From f9442e23de0e0c9a09042e07581fa7726e40dc5c Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Fri, 8 Jan 2021 10:25:58 +0100 Subject: [PATCH 01/63] Use github://feenkcom/OSSubprocess/repository --- src/BaselineOfPythonBridge/BaselineOfPythonBridge.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BaselineOfPythonBridge/BaselineOfPythonBridge.class.st b/src/BaselineOfPythonBridge/BaselineOfPythonBridge.class.st index d7b02ea..9150220 100644 --- a/src/BaselineOfPythonBridge/BaselineOfPythonBridge.class.st +++ b/src/BaselineOfPythonBridge/BaselineOfPythonBridge.class.st @@ -12,7 +12,7 @@ BaselineOfPythonBridge >> baseline: spec [ do: [ spec baseline: 'OSSubprocess' - with: [ spec repository: 'github://pharo-contributions/OSSubprocess:v1.0.0/repository' ]. + with: [ spec repository: 'github://feenkcom/OSSubprocess/repository' ]. spec baseline: 'Python3Generator' with: [ spec repository: 'github://juliendelplanque/Python3Generator:v2.0.0/repository' ]. From b47dc56d41cbe63fb181b355333afdd990bca1fa Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Fri, 15 Jan 2021 08:19:02 +0100 Subject: [PATCH 02/63] Allow the runtime directory to be used without the repository present. --- .../PBPharoPlatform.class.st | 28 +++++++++++++++---- src/PythonBridge/PBAbstractProcess.class.st | 4 +-- src/PythonBridge/PBApplication.class.st | 16 ++++++++++- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/PythonBridge-Pharo/PBPharoPlatform.class.st b/src/PythonBridge-Pharo/PBPharoPlatform.class.st index 024332c..a50c1d6 100644 --- a/src/PythonBridge-Pharo/PBPharoPlatform.class.st +++ b/src/PythonBridge-Pharo/PBPharoPlatform.class.st @@ -54,12 +54,14 @@ PBPharoPlatform >> defaultMessageBrokerClass [ { #category : #hooks } PBPharoPlatform >> ensureApplicationSymlinks: application [ | appFolder | - appFolder := self folderForApplication: application. - self ensureFolderSymlinkFor: appFolder. - self ensurePBridge: (self folderForApplication: application class baseApplication) symlinkIn: appFolder + + appFolder := self runtimeFolderForApplication: application. + appFolder exists ifFalse: + [ self ensureFolderSymlinkFor: appFolder. + self ensurePBridge: (self folderForApplication: application class baseApplication) symlinkIn: appFolder ] ] -{ #category : #'as yet unclassified' } +{ #category : #private } PBPharoPlatform >> ensureEnvironmentForApp: anApplication [ self ensureApplicationSymlinks: anApplication. self installEnvironmentForApp: anApplication. @@ -99,7 +101,7 @@ PBPharoPlatform >> forceInstallEnvironmentForApp: application [ command: '/bin/bash'; addAllEnvVariablesFromParentWithoutOverride; arguments: (Array - with: ((self folderForApplication: application) / 'install_env.sh') fullName); + with: ((self runtimeFolderForApplication: application) / 'install_env.sh') fullName); terminateOnShutdown; runAndWait. (proc exitStatus = 0 or: [ proc exitStatus < -1000 or: [ proc exitStatus > SmallInteger maxVal ] ]) ifFalse: [ @@ -109,7 +111,7 @@ PBPharoPlatform >> forceInstallEnvironmentForApp: application [ { #category : #utils } PBPharoPlatform >> installEnvironmentForApp: application [ | folder | - folder := self folderForApplication: application. + folder := self runtimeFolderForApplication: application. (folder / '.venv') exists ifFalse: [ self forceInstallEnvironmentForApp: application ] ] @@ -119,6 +121,20 @@ PBPharoPlatform >> newRandomName [ ^ 'pb' , UUID new asString36 ] +{ #category : #accessing } +PBPharoPlatform >> runtimeFolder [ + "Answer the directory where the PythonBridge runtime files are located" + + ^ FileLocator imageDirectory / 'PythonBridge' +] + +{ #category : #accessing } +PBPharoPlatform >> runtimeFolderForApplication: application [ + "Answer the directory where the PythonBridge runtime files are located" + + ^ FileLocator imageDirectory / application runtimeDirectory +] + { #category : #private } PBPharoPlatform >> signalPipenvCreateEnvFailed [ " diff --git a/src/PythonBridge/PBAbstractProcess.class.st b/src/PythonBridge/PBAbstractProcess.class.st index 8066e27..db8c8ad 100644 --- a/src/PythonBridge/PBAbstractProcess.class.st +++ b/src/PythonBridge/PBAbstractProcess.class.st @@ -26,7 +26,7 @@ PBAbstractProcess class >> platform [ PBAbstractProcess class >> settings: settings application: application [ ^ self settings: settings - workingDirectory: (PBPlatform current folderForApplication: application) + workingDirectory: (PBPlatform current runtimeFolderForApplication: application) debugMode: application class debugMode ] @@ -49,7 +49,7 @@ PBAbstractProcess class >> settings: settings workingDirectory: fileRef debugMod { #category : #hooks } PBAbstractProcess class >> workingDirectory [ - ^ self platform folderForApplication: PBApplication + ^ self platform runtimeFolderForApplication: PBApplication ] { #category : #accessing } diff --git a/src/PythonBridge/PBApplication.class.st b/src/PythonBridge/PBApplication.class.st index 0c0e451..1189ad1 100644 --- a/src/PythonBridge/PBApplication.class.st +++ b/src/PythonBridge/PBApplication.class.st @@ -61,7 +61,7 @@ PBApplication class >> platform [ { #category : #'python hooks file' } PBApplication class >> repositoryFileReference [ - ^ self platform folderForApplication: self + ^ self platform runtimeFolderForApplication: self ] { #category : #instructions } @@ -73,6 +73,13 @@ PBApplication class >> resetUniqueInstance [ uniqueInstance := nil ] +{ #category : #accessing } +PBApplication class >> runtimeDirectory [ + "This is the directory basename where the runtime files are located" + + ^ 'PythonBridge' +] + { #category : #instructions } PBApplication class >> send: obj [ self assert: self isRunning. @@ -215,6 +222,13 @@ PBApplication >> registerObject: aPythonObject [ self executionHandler registerObject: aPythonObject ] +{ #category : #accessing } +PBApplication >> runtimeDirectory [ + "This is the directory basename where the runtime files are located" + + ^ self class runtimeDirectory +] + { #category : #instructions } PBApplication >> send: aCommand [ self isRunning ifFalse: [ Error signal: 'Bridge not running.' ]. From f9950f384a5a5aef1d29070875b7f6bc7790d3f4 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Fri, 15 Jan 2021 09:35:32 +0100 Subject: [PATCH 03/63] Create the symbolic link for the module --- src/PythonBridge-Pharo/PBPharoPlatform.class.st | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PythonBridge-Pharo/PBPharoPlatform.class.st b/src/PythonBridge-Pharo/PBPharoPlatform.class.st index a50c1d6..5842c75 100644 --- a/src/PythonBridge-Pharo/PBPharoPlatform.class.st +++ b/src/PythonBridge-Pharo/PBPharoPlatform.class.st @@ -56,9 +56,9 @@ PBPharoPlatform >> ensureApplicationSymlinks: application [ | appFolder | appFolder := self runtimeFolderForApplication: application. - appFolder exists ifFalse: - [ self ensureFolderSymlinkFor: appFolder. - self ensurePBridge: (self folderForApplication: application class baseApplication) symlinkIn: appFolder ] + appFolder exists ifTrue: [ ^ self ]. + self ensureFolderSymlinkFor: (self folderForApplication: application). + self ensurePBridge: (self folderForApplication: application class baseApplication) symlinkIn: appFolder. ] { #category : #private } From ce4af542042e835ddf2c5e8d4dc6f4f2d03af0a0 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Fri, 15 Jan 2021 09:35:46 +0100 Subject: [PATCH 04/63] Pass remote exceptions back to the calling process --- src/PythonBridge/PBExecutionHandler.class.st | 9 +++------ src/PythonBridge/PBPromise.class.st | 6 ++++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/PythonBridge/PBExecutionHandler.class.st b/src/PythonBridge/PBExecutionHandler.class.st index fb58fb1..e38a318 100644 --- a/src/PythonBridge/PBExecutionHandler.class.st +++ b/src/PythonBridge/PBExecutionHandler.class.st @@ -137,12 +137,9 @@ PBExecutionHandler >> registerPromiseForCommand: aCommand [ { #category : #'as yet unclassified' } PBExecutionHandler >> safeTriggerDebugger: error [ - | sem | - sem := Semaphore new. - [ [ self triggerDebugger: error ] ensure: [ sem signal ] ] - on: PBPythonError fork: [ :e | PBPlatform current uiManager spawnDebuggerOnException: e ]. - sem wait. - ^ error proceedAction: error defaultProceedAction + + [ promiseRegistry signalPromiseId: error command id with: error ] fork. + ] { #category : #'private protocol' } diff --git a/src/PythonBridge/PBPromise.class.st b/src/PythonBridge/PBPromise.class.st index 3d867be..4147eff 100644 --- a/src/PythonBridge/PBPromise.class.st +++ b/src/PythonBridge/PBPromise.class.st @@ -68,7 +68,9 @@ PBPromise >> value [ { #category : #signalling } PBPromise >> waitForValue [ - self isSignaled ifTrue: [ ^ self value ]. - semaphore wait. + + self isSignaled ifFalse: [ semaphore wait ]. + (value isKindOf: Exception) ifTrue: + [ value copy signal ]. ^ self value ] From 4245e1e4ea215b29108929100c9c9ec8eb71095a Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Fri, 15 Jan 2021 14:58:13 +0100 Subject: [PATCH 05/63] Use #isSuccess to check the OS process status in PBPharoPlatform>>forceInstallEnvironment --- src/PythonBridge-Pharo/PBPharoPlatform.class.st | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PythonBridge-Pharo/PBPharoPlatform.class.st b/src/PythonBridge-Pharo/PBPharoPlatform.class.st index 5842c75..d6f317e 100644 --- a/src/PythonBridge-Pharo/PBPharoPlatform.class.st +++ b/src/PythonBridge-Pharo/PBPharoPlatform.class.st @@ -104,8 +104,7 @@ PBPharoPlatform >> forceInstallEnvironmentForApp: application [ with: ((self runtimeFolderForApplication: application) / 'install_env.sh') fullName); terminateOnShutdown; runAndWait. - (proc exitStatus = 0 or: [ proc exitStatus < -1000 or: [ proc exitStatus > SmallInteger maxVal ] ]) ifFalse: [ - self signalPipenvCreateEnvFailed ] + proc isSuccess ifFalse: [ self signalPipenvCreateEnvFailed ]. ] { #category : #utils } From 91bc338599639f5ddbe6a4f9e1d83e2b81c9be93 Mon Sep 17 00:00:00 2001 From: Konrad Hinsen Date: Sun, 17 Jan 2021 19:38:16 +0100 Subject: [PATCH 06/63] Run installation script with pipenv on PATH --- src/PythonBridge-Pharo/PBPharoPlatform.class.st | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/PythonBridge-Pharo/PBPharoPlatform.class.st b/src/PythonBridge-Pharo/PBPharoPlatform.class.st index d6f317e..b4cb262 100644 --- a/src/PythonBridge-Pharo/PBPharoPlatform.class.st +++ b/src/PythonBridge-Pharo/PBPharoPlatform.class.st @@ -99,11 +99,17 @@ PBPharoPlatform >> forceInstallEnvironmentForApp: application [ self assert: PBPharoPipenvProcess pipenvPath isEmptyOrNil not description: 'pipenv is apparently not accessible at a standard location. Please, have a look at the Troubleshooting section of https://objectprofile.github.io/PythonBridge/pages/pharo-installation'. proc := OSSUnixSubprocess new command: '/bin/bash'; - addAllEnvVariablesFromParentWithoutOverride; - arguments: (Array - with: ((self runtimeFolderForApplication: application) / 'install_env.sh') fullName); - terminateOnShutdown; - runAndWait. + addAllEnvVariablesFromParentWithoutOverride. + proc + environmentAt: 'PATH' + put: (PBPharoPipenvProcess pipenvPath + asFileReference parent fullName), + ':', (proc envVariables at: 'PATH'). + proc + arguments: (Array + with: ((self runtimeFolderForApplication: application) / 'install_env.sh') fullName); + terminateOnShutdown; + runAndWait. proc isSuccess ifFalse: [ self signalPipenvCreateEnvFailed ]. ] From f2f11cc52fcf9b7ad7d5d0fd0b193479bc59f997 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Fri, 22 Jan 2021 12:02:50 +0100 Subject: [PATCH 07/63] Add pipenvPath and workingDirectory to PBSettings --- src/PythonBridge/PBSettings.class.st | 30 +++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/PythonBridge/PBSettings.class.st b/src/PythonBridge/PBSettings.class.st index f2c7ca0..a9895a7 100644 --- a/src/PythonBridge/PBSettings.class.st +++ b/src/PythonBridge/PBSettings.class.st @@ -3,7 +3,9 @@ Class { #superclass : #Object, #instVars : [ 'pharoSocketAddress', - 'pythonSocketAddress' + 'pythonSocketAddress', + 'pipenvPath', + 'workingDirectory' ], #category : #'PythonBridge-Platform' } @@ -26,6 +28,19 @@ PBSettings >> pharoSocketAddress: anObject [ pharoSocketAddress := anObject ] +{ #category : #accessing } +PBSettings >> pipenvPath [ + ^ pipenvPath +] + +{ #category : #accessing } +PBSettings >> pipenvPath: aFileReference [ + + pipenvPath := aFileReference + pipenvPath ifNil: [ ^ self ]. + self assert: [ pipenvPath exists ]. +] + { #category : #accessing } PBSettings >> pythonSocketAddress [ ^ pythonSocketAddress @@ -35,3 +50,16 @@ PBSettings >> pythonSocketAddress [ PBSettings >> pythonSocketAddress: anObject [ pythonSocketAddress := anObject ] + +{ #category : #accessing } +PBSettings >> workingDirectory [ + ^ workingDirectory +] + +{ #category : #accessing } +PBSettings >> workingDirectory: aFileReference [ + + workingDirectory := aFileReference. + workingDirectory ifNil: [ ^ self ]. + self assert: [ workingDirectory exists ]. +] From 39be56bb6c842fe374656d0691722c73dbbb3920 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Mon, 25 Jan 2021 08:23:09 +0100 Subject: [PATCH 08/63] Allow the server installation / working directory to be specified. --- .../PBPharoPlatform.class.st | 39 +++++++++++++++++-- src/PythonBridge/PBCommandQueue.class.st | 27 ++++++------- src/PythonBridge/PBPythonHandler.class.st | 6 +++ 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/PythonBridge-Pharo/PBPharoPlatform.class.st b/src/PythonBridge-Pharo/PBPharoPlatform.class.st index b4cb262..09dc243 100644 --- a/src/PythonBridge-Pharo/PBPharoPlatform.class.st +++ b/src/PythonBridge-Pharo/PBPharoPlatform.class.st @@ -34,6 +34,25 @@ PBPharoPlatform class >> weakRegistryClass [ ^ PBPharoWeakRegistry ] +{ #category : #private } +PBPharoPlatform >> copyApplicationTo: appFolder application: application [ + "Copy the PythonBridge runtime environment to the specified folder" + | srcDir | + + srcDir := FileLocator imageDirectory / 'PythonBridge'. + srcDir exists ifFalse: + [ srcDir := self folderForApplication: application ]. + srcDir exists ifFalse: + [ self error: 'Unable to locate PythonBridge runtime files' ]. + srcDir children do: [ :child | + "#copyAllTo: doesn't handle symbolic links. + This makes assumptions about the folder structure to avoid copying the symlink. + Don't copy symlinks for now and create it later" + child isSymlink ifFalse: + [ child copyAllTo: appFolder / child basename ] ]. + +] + { #category : #'private - symlinks' } PBPharoPlatform >> createSymlinkFor: originalFile on: targetFile [ OSSUnixSubprocess new @@ -51,19 +70,30 @@ PBPharoPlatform >> defaultMessageBrokerClass [ ^ self class socketMessageBrokerClass ] +{ #category : #hooks } +PBPharoPlatform >> ensureApplicationDirectory: application [ + | appFolder | + + appFolder := self runtimeFolderForApplication: application. + (appFolder / 'PythonBridge') exists ifTrue: [ ^ self ]. + self copyApplicationTo: appFolder application: application. + self ensurePBridge: (self folderForApplication: application class baseApplication) symlinkIn: appFolder. +] + { #category : #hooks } PBPharoPlatform >> ensureApplicationSymlinks: application [ | appFolder | appFolder := self runtimeFolderForApplication: application. - appFolder exists ifTrue: [ ^ self ]. + (appFolder / 'PythonBridge') exists ifTrue: [ ^ self ]. self ensureFolderSymlinkFor: (self folderForApplication: application). self ensurePBridge: (self folderForApplication: application class baseApplication) symlinkIn: appFolder. ] { #category : #private } PBPharoPlatform >> ensureEnvironmentForApp: anApplication [ - self ensureApplicationSymlinks: anApplication. + + self ensureApplicationDirectory: anApplication. self installEnvironmentForApp: anApplication. ] @@ -80,7 +110,7 @@ PBPharoPlatform >> ensurePBridge: pbridgeFolder symlinkIn: aFolder [ | symlinkRef | symlinkRef := aFolder / 'PythonBridge'. symlinkRef exists ifFalse: [ - self createSymlinkFor: pbridgeFolder on: symlinkRef ]. + self createSymlinkFor: aFolder on: symlinkRef ]. ] { #category : #utils } @@ -137,7 +167,8 @@ PBPharoPlatform >> runtimeFolder [ PBPharoPlatform >> runtimeFolderForApplication: application [ "Answer the directory where the PythonBridge runtime files are located" - ^ FileLocator imageDirectory / application runtimeDirectory + ^ application settings workingDirectory ifNil: + [ FileLocator imageDirectory / application runtimeDirectory ] ] { #category : #private } diff --git a/src/PythonBridge/PBCommandQueue.class.st b/src/PythonBridge/PBCommandQueue.class.st index 16a6f62..90d0915 100644 --- a/src/PythonBridge/PBCommandQueue.class.st +++ b/src/PythonBridge/PBCommandQueue.class.st @@ -67,19 +67,20 @@ PBCommandQueue >> finishCommand: aCommand [ { #category : #accessing } PBCommandQueue >> finishCommandId: id [ | commandIndex | - self currentCommand ifNotNil: [ :command | - command id = id - ifTrue: [ - self cleanIndex: currentIndex. - currentIndex := currentIndex + 1. - ^ true ] ]. - commandIndex := innerCollection detectIndex: [ :command | command id = id ]. - commandIndex > currentIndex - ifTrue: [ - currentIndex := commandIndex + 1. - self log: (PBErrorLog message: 'Out of sync command queue. Pharo is delayed.') ] - ifFalse: [ - self log: (PBErrorLog message: 'Out of sync command queue. Python is delayed.') ]. + self currentCommand + ifNotNil: [ :command | + command id = id + ifTrue: [ self cleanIndex: currentIndex. + currentIndex := currentIndex + 1. + ^ true ] ]. + commandIndex := innerCollection + detectIndex: [ :command | command id = id ]. + commandIndex > currentIndex + ifTrue: [ currentIndex := commandIndex + 1. + self + trace: (PBErrorLog message: 'Out of sync command queue. Pharo is delayed.') ] + ifFalse: [ self + log: (PBErrorLog message: 'Out of sync command queue. Python is delayed.') ]. self cleanIndex: commandIndex. ^ false ] diff --git a/src/PythonBridge/PBPythonHandler.class.st b/src/PythonBridge/PBPythonHandler.class.st index 04d70d4..95e5d70 100644 --- a/src/PythonBridge/PBPythonHandler.class.st +++ b/src/PythonBridge/PBPythonHandler.class.st @@ -38,3 +38,9 @@ PBPythonHandler >> start [ PBPythonHandler >> stop [ ^ process stop ] + +{ #category : #accessing } +PBPythonHandler >> workingDirectory: aFileReference [ + + process workingDirectory: aFileReference +] From 06fca29f6ecc42d0c3daa21a0faae207bbdbdc5d Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Mon, 25 Jan 2021 11:30:31 +0100 Subject: [PATCH 09/63] PBPharoPlatform handle application directory located in image directory. --- src/PythonBridge-Pharo/PBPharoPlatform.class.st | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/PythonBridge-Pharo/PBPharoPlatform.class.st b/src/PythonBridge-Pharo/PBPharoPlatform.class.st index 09dc243..b38beed 100644 --- a/src/PythonBridge-Pharo/PBPharoPlatform.class.st +++ b/src/PythonBridge-Pharo/PBPharoPlatform.class.st @@ -40,7 +40,7 @@ PBPharoPlatform >> copyApplicationTo: appFolder application: application [ | srcDir | srcDir := FileLocator imageDirectory / 'PythonBridge'. - srcDir exists ifFalse: + (srcDir exists and: [ srcDir ~= appFolder ]) ifFalse: [ srcDir := self folderForApplication: application ]. srcDir exists ifFalse: [ self error: 'Unable to locate PythonBridge runtime files' ]. @@ -76,6 +76,7 @@ PBPharoPlatform >> ensureApplicationDirectory: application [ appFolder := self runtimeFolderForApplication: application. (appFolder / 'PythonBridge') exists ifTrue: [ ^ self ]. + appFolder ensureCreateDirectory. self copyApplicationTo: appFolder application: application. self ensurePBridge: (self folderForApplication: application class baseApplication) symlinkIn: appFolder. ] From 2bc0c000d0f3b388dea3e6d15af62ff1870afb33 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Mon, 25 Jan 2021 11:31:34 +0100 Subject: [PATCH 10/63] Remove unused PBPharoPlatform>>ensureApplicationSymlinks: --- src/PythonBridge-Pharo/PBPharoPlatform.class.st | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/PythonBridge-Pharo/PBPharoPlatform.class.st b/src/PythonBridge-Pharo/PBPharoPlatform.class.st index b38beed..305c47a 100644 --- a/src/PythonBridge-Pharo/PBPharoPlatform.class.st +++ b/src/PythonBridge-Pharo/PBPharoPlatform.class.st @@ -81,16 +81,6 @@ PBPharoPlatform >> ensureApplicationDirectory: application [ self ensurePBridge: (self folderForApplication: application class baseApplication) symlinkIn: appFolder. ] -{ #category : #hooks } -PBPharoPlatform >> ensureApplicationSymlinks: application [ - | appFolder | - - appFolder := self runtimeFolderForApplication: application. - (appFolder / 'PythonBridge') exists ifTrue: [ ^ self ]. - self ensureFolderSymlinkFor: (self folderForApplication: application). - self ensurePBridge: (self folderForApplication: application class baseApplication) symlinkIn: appFolder. -] - { #category : #private } PBPharoPlatform >> ensureEnvironmentForApp: anApplication [ From f97b46adb15842b6c4d7654a04d0729f951ac3c5 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Tue, 26 Jan 2021 12:45:31 +0100 Subject: [PATCH 11/63] Use the specified directory when installin the environment in PBPharoPlatform --- src/PythonBridge-Pharo/PBPharoPlatform.class.st | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PythonBridge-Pharo/PBPharoPlatform.class.st b/src/PythonBridge-Pharo/PBPharoPlatform.class.st index 305c47a..d103c56 100644 --- a/src/PythonBridge-Pharo/PBPharoPlatform.class.st +++ b/src/PythonBridge-Pharo/PBPharoPlatform.class.st @@ -120,6 +120,7 @@ PBPharoPlatform >> forceInstallEnvironmentForApp: application [ self assert: PBPharoPipenvProcess pipenvPath isEmptyOrNil not description: 'pipenv is apparently not accessible at a standard location. Please, have a look at the Troubleshooting section of https://objectprofile.github.io/PythonBridge/pages/pharo-installation'. proc := OSSUnixSubprocess new command: '/bin/bash'; + workingDirectory: (self runtimeFolderForApplication: application) fullName; addAllEnvVariablesFromParentWithoutOverride. proc environmentAt: 'PATH' From 0be62a616f4ec00429d2e60a9692c8b064992507 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Tue, 26 Jan 2021 12:46:06 +0100 Subject: [PATCH 12/63] Don't rely on the global command factory for every instance of PBApplication --- src/PythonBridge/PBApplication.class.st | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PythonBridge/PBApplication.class.st b/src/PythonBridge/PBApplication.class.st index 1189ad1..96be79d 100644 --- a/src/PythonBridge/PBApplication.class.st +++ b/src/PythonBridge/PBApplication.class.st @@ -91,6 +91,7 @@ PBApplication class >> start [ self isRunning ifTrue: [ Error signal: 'Keras already running.' ]. self stop. uniqueInstance := self new. + PBCF reset. uniqueInstance commandFactory reset. uniqueInstance start ] @@ -248,10 +249,9 @@ PBApplication >> settings: anObject [ { #category : #accessing } PBApplication >> start [ self handlers do: #start. - self commandFactory reset. self waitInitialization. self postInitialization. - self commandFactory send. + self newCommandFactory send. ] { #category : #'as yet unclassified' } From f793d0aaf0e711a8f152a312e690bb0adfdd7da6 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Tue, 26 Jan 2021 17:06:37 +0100 Subject: [PATCH 13/63] PBPharoPlatform: copy runtime files keeping file attributes --- .../PBPharoPlatform.class.st | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/PythonBridge-Pharo/PBPharoPlatform.class.st b/src/PythonBridge-Pharo/PBPharoPlatform.class.st index d103c56..0136775 100644 --- a/src/PythonBridge-Pharo/PBPharoPlatform.class.st +++ b/src/PythonBridge-Pharo/PBPharoPlatform.class.st @@ -37,19 +37,34 @@ PBPharoPlatform class >> weakRegistryClass [ { #category : #private } PBPharoPlatform >> copyApplicationTo: appFolder application: application [ "Copy the PythonBridge runtime environment to the specified folder" - | srcDir | + | srcDir cpCommand proc pbSymLink | srcDir := FileLocator imageDirectory / 'PythonBridge'. (srcDir exists and: [ srcDir ~= appFolder ]) ifFalse: [ srcDir := self folderForApplication: application ]. srcDir exists ifFalse: [ self error: 'Unable to locate PythonBridge runtime files' ]. - srcDir children do: [ :child | - "#copyAllTo: doesn't handle symbolic links. - This makes assumptions about the folder structure to avoid copying the symlink. - Don't copy symlinks for now and create it later" - child isSymlink ifFalse: - [ child copyAllTo: appFolder / child basename ] ]. + + "Copy the runtime directory" + cpCommand := String streamContents: [ :stream | + stream + << 'cp -ar '; + << srcDir fullName; + << '/* '; + << appFolder fullName; + << '/' ]. + proc := OSSUnixSubprocess new + shellCommand: cpCommand; + runAndWait. + proc isSuccess ifFalse: + [ self error: 'Unable to install PythonBridge runtime' ]. + "Remove the existing symlink, which probably points to the source folder. + FileReference>>delete doesn't handle symbolic links, so use the lower layer" + pbSymLink := (appFolder / 'PythonBridge') resolve. + pbSymLink exists ifTrue: + [ pbSymLink isSymlink + ifTrue: [ self removeFile: pbSymLink ] + ifFalse: [ self error: 'PythonBridge should be a symbolic link' ] ]. ] @@ -148,6 +163,20 @@ PBPharoPlatform >> newRandomName [ ^ 'pb' , UUID new asString36 ] +{ #category : #'private - symlinks' } +PBPharoPlatform >> removeFile: aFileReference [ + "Use the OS rm command to remove the specified file. + Required since the file system primitive doesn't seem to handle symbolic links" + | proc | + + proc := OSSUnixSubprocess new + command: 'rm'; + arguments: { aFileReference fullName }; + runAndWait. + proc isSuccess ifFalse: + [ self error: 'Unable to remove: ', aFileReference fullName ] +] + { #category : #accessing } PBPharoPlatform >> runtimeFolder [ "Answer the directory where the PythonBridge runtime files are located" From ac62e1272379e6615b64141db3bd763e7edf5902 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Wed, 3 Feb 2021 10:16:14 +0100 Subject: [PATCH 14/63] PBSettings>>pipenvPath: typo --- src/PythonBridge/PBSettings.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PythonBridge/PBSettings.class.st b/src/PythonBridge/PBSettings.class.st index a9895a7..56945da 100644 --- a/src/PythonBridge/PBSettings.class.st +++ b/src/PythonBridge/PBSettings.class.st @@ -36,7 +36,7 @@ PBSettings >> pipenvPath [ { #category : #accessing } PBSettings >> pipenvPath: aFileReference [ - pipenvPath := aFileReference + pipenvPath := aFileReference. pipenvPath ifNil: [ ^ self ]. self assert: [ pipenvPath exists ]. ] From be1251925f652f3e267ea5751a5325c11d3f6232 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Mon, 8 Feb 2021 13:06:27 +0100 Subject: [PATCH 15/63] PBPharoPipenvProcess>>resolvePipenvPath signalPipenvNotFound fix --- src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st b/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st index c4cfe73..0bb0088 100644 --- a/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st +++ b/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st @@ -30,14 +30,17 @@ PBPharoPipenvProcess class >> platform [ { #category : #initialization } PBPharoPipenvProcess class >> resolvePipenvPath [ - ^ (OSSUnixSubprocess new + | path | + + (OSSUnixSubprocess new command: '/usr/bin/which'; - arguments: (Array with: 'pipenv'); + arguments: (Array with: 'pipenvno'); addAllEnvVariablesFromParentWithoutOverride; redirectStdout; terminateOnShutdown; - runAndWaitOnExitDo: [ :command :outString | ^ outString trim ]) - ifEmpty: [ self signalPipenvNotFound ] + runAndWaitOnExitDo: [ :command :outString | path := outString trim ]). + path ifEmpty: [ self signalPipenvNotFound ]. + ^ path ] { #category : #initialization } From 998547cc245e22dc61c0802d96e07abcdc6c31b8 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Mon, 8 Feb 2021 13:13:22 +0100 Subject: [PATCH 16/63] Pipenv path typo --- src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st b/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st index 0bb0088..48ff3fe 100644 --- a/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st +++ b/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st @@ -34,7 +34,7 @@ PBPharoPipenvProcess class >> resolvePipenvPath [ (OSSUnixSubprocess new command: '/usr/bin/which'; - arguments: (Array with: 'pipenvno'); + arguments: (Array with: 'pipenv'); addAllEnvVariablesFromParentWithoutOverride; redirectStdout; terminateOnShutdown; From 310b24a4e904bf020f1374efd942c3ab71febf1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20Chi=C8=99?= Date: Mon, 8 Feb 2021 16:06:26 +0100 Subject: [PATCH 17/63] Load the v17 tag for NeoJSON --- src/BaselineOfPythonBridge/BaselineOfPythonBridge.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BaselineOfPythonBridge/BaselineOfPythonBridge.class.st b/src/BaselineOfPythonBridge/BaselineOfPythonBridge.class.st index 9150220..4067b61 100644 --- a/src/BaselineOfPythonBridge/BaselineOfPythonBridge.class.st +++ b/src/BaselineOfPythonBridge/BaselineOfPythonBridge.class.st @@ -18,7 +18,7 @@ BaselineOfPythonBridge >> baseline: spec [ with: [ spec repository: 'github://juliendelplanque/Python3Generator:v2.0.0/repository' ]. spec baseline: 'NeoJSON' with: [ spec - repository: 'github://svenvc/NeoJSON/repository' ]. + repository: 'github://svenvc/NeoJSON:v17/repository' ]. spec baseline: 'MessagePack' with: [ spec repository: 'github://msgpack/msgpack-smalltalk:v1.3.1/repository' ]. From b009fea5dd7edaf0a636c9dcb8db3361151879f0 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Tue, 9 Feb 2021 08:51:21 +0100 Subject: [PATCH 18/63] Deprecation auto-rewrite --- src/PythonBridge/PBCommandQueue.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PythonBridge/PBCommandQueue.class.st b/src/PythonBridge/PBCommandQueue.class.st index 90d0915..46d49f4 100644 --- a/src/PythonBridge/PBCommandQueue.class.st +++ b/src/PythonBridge/PBCommandQueue.class.st @@ -80,7 +80,7 @@ PBCommandQueue >> finishCommandId: id [ self trace: (PBErrorLog message: 'Out of sync command queue. Pharo is delayed.') ] ifFalse: [ self - log: (PBErrorLog message: 'Out of sync command queue. Python is delayed.') ]. + trace: (PBErrorLog message: 'Out of sync command queue. Python is delayed.') ]. self cleanIndex: commandIndex. ^ false ] From bfedd9fd7a13e87a0515dc300907590353de9c8e Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Wed, 10 Feb 2021 12:51:45 +0100 Subject: [PATCH 19/63] Use the pipenvPath specified in settings --- src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st | 10 ++++++---- src/PythonBridge/PBSettings.class.st | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st b/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st index 48ff3fe..9f808cb 100644 --- a/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st +++ b/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st @@ -19,8 +19,8 @@ PBPharoPipenvProcess class >> pipenvPath [ ] { #category : #initialization } -PBPharoPipenvProcess class >> pipenvPath: aString [ - PipenvPath := aString +PBPharoPipenvProcess class >> pipenvPath: aFileReference [ + PipenvPath := aFileReference ] { #category : #accessing } @@ -40,7 +40,7 @@ PBPharoPipenvProcess class >> resolvePipenvPath [ terminateOnShutdown; runAndWaitOnExitDo: [ :command :outString | path := outString trim ]). path ifEmpty: [ self signalPipenvNotFound ]. - ^ path + ^ path asFileReference ] { #category : #initialization } @@ -85,8 +85,10 @@ PBPharoPipenvProcess >> isRunning [ { #category : #private } PBPharoPipenvProcess >> newProcess [ | newProcess | + newProcess := OSSUnixSubprocess new - command: self class pipenvPath; + command: (settings pipenvPath ifNil: + [ self class pipenvPath ]) fullName; arguments: self processArguments; workingDirectory: self workingDirectory fullName; addAllEnvVariablesFromParentWithoutOverride; diff --git a/src/PythonBridge/PBSettings.class.st b/src/PythonBridge/PBSettings.class.st index 56945da..a2bf8cb 100644 --- a/src/PythonBridge/PBSettings.class.st +++ b/src/PythonBridge/PBSettings.class.st @@ -36,9 +36,10 @@ PBSettings >> pipenvPath [ { #category : #accessing } PBSettings >> pipenvPath: aFileReference [ - pipenvPath := aFileReference. + pipenvPath := aFileReference asFileReference. pipenvPath ifNil: [ ^ self ]. - self assert: [ pipenvPath exists ]. + self assert: [ pipenvPath exists ] + description: pipenvPath fullName, ' doesn''t exist'. ] { #category : #accessing } From 72b54eb68a824ae1a490a6e789a39c67f4355902 Mon Sep 17 00:00:00 2001 From: Alistair Grant Date: Thu, 11 Feb 2021 08:04:59 +0100 Subject: [PATCH 20/63] Enable the pipenvPath and working directory to be set in PBSettings --- .../PBPharoPipenvProcess.class.st | 17 ++++++++++++----- src/PythonBridge-Pharo/PBPharoPlatform.class.st | 17 +++++++++++++---- src/PythonBridge/PBProcessTest.class.st | 7 +++---- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st b/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st index 9f808cb..9e0bce9 100644 --- a/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st +++ b/src/PythonBridge-Pharo/PBPharoPipenvProcess.class.st @@ -13,9 +13,9 @@ Class { { #category : #initialization } PBPharoPipenvProcess class >> pipenvPath [ - ^ PipenvPath isEmptyOrNil - ifTrue: [ PipenvPath := self resolvePipenvPath ] - ifFalse: [ PipenvPath ] + ^ PipenvPath + ifNil: [ PipenvPath := self resolvePipenvPath ] + ifNotNil: [ PipenvPath ] ] { #category : #initialization } @@ -28,6 +28,13 @@ PBPharoPipenvProcess class >> platform [ ^ PBPharoPlatform current ] +{ #category : #initialization } +PBPharoPipenvProcess class >> reset [ +