forked from ObjectProfile/PythonBridge
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathPBProxyObject.class.st
More file actions
150 lines (125 loc) · 4.09 KB
/
PBProxyObject.class.st
File metadata and controls
150 lines (125 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
Class {
#name : #PBProxyObject,
#superclass : #PBObject,
#instVars : [
'pythonClass',
'application'
],
#category : #'PythonBridge-Core'
}
{ #category : #accessing }
PBProxyObject class >> pythonClass [
"Return the Python class/type name that I am a mirror of.
Fully qualified name unless it is one of the builtins."
"The default is to return PBProxyObject which is no actual Python class,
see #pythonClass:pythonVar:application:superclasses: for how this maps to me"
"Subclasses can override this to request the creation of a different mirror instance"
^ 'PBProxyObject'
]
{ #category : #'instance creation' }
PBProxyObject class >> pythonClass: pythonClass pythonVar: pyVar application: application superclasses: supers [
| proxyClass proxyClasses |
proxyClasses := (self allSubclasses
collect: [ :each | each pythonClass -> each ]) asDictionary.
proxyClass := proxyClasses
at: pythonClass
ifAbsent: [ supers
detect: [ :sup | proxyClasses includesKey: sup ]
ifFound: [ :sup | proxyClasses at: sup ]
ifNone: [ PBProxyObject ] ].
^ proxyClass new
pythonVariable: pyVar;
pythonClass: pythonClass;
application: application;
yourself
]
{ #category : #accessing }
PBProxyObject >> application [
^ application
]
{ #category : #accessing }
PBProxyObject >> application: anObject [
application := anObject
]
{ #category : #accessing }
PBProxyObject >> applicationClass [
^ self application class
]
{ #category : #converting }
PBProxyObject >> asJsonDictionary [
"Answer the receiver as a Dictionary"
^ {
#__pyclass__ -> pythonClass.
#__pyid__ -> pythonVariable name } asDictionary.
]
{ #category : #accessing }
PBProxyObject >> attributeAt: attributeName [
"Answer the value of the named attribute in the Python object that I represent"
^ self newCommandFactory
<< (self => attributeName);
sendAndWait
]
{ #category : #accessing }
PBProxyObject >> callMethod: methodName [
"Call methodName on the Python object that I represent and return the result"
^ self callMethod: methodName withArgs: #()
]
{ #category : #accessing }
PBProxyObject >> callMethod: methodName withArgs: arguments [
"Call methodName with arguments on the Python object that I represent and return the result"
^ self newCommandFactory
<< (self => methodName callWith: arguments);
sendAndWait
]
{ #category : #hooks }
PBProxyObject >> createObject [
self shouldNotImplement
]
{ #category : #accessing }
PBProxyObject >> doesNotUnderstand: aMessage [
"PBProxyObjects attempt to forward unimplemented messages to python with the following semantics:
1) Unary selectors are first tried as attribute of the python object.
2) If the attribute is a method, it is called and the value returned, otherwise the attribute value
is returned
3) If a keyword message is sent, we attempt to call a method on the python object with only the first keyword as the method name and all the arguments.
4) If any of this fails, we simply fall back to DNU
"
| sel |
sel := aMessage selector.
[ | val method args |
sel isKeyword
ifTrue: [ method := aMessage selector keywords first copyWithout: $:.
args := aMessage arguments.
^ self callMethod: method withArgs: args ]
ifFalse: [ val := self attributeAt: sel.
^ ((val class == PBProxyObject or: [ val class inheritsFrom: PBProxyObject ])
and: [ val pythonClass = 'method' ])
ifTrue: [ self callMethod: sel ]
ifFalse: [ val ] ] ] on: Exception do: [ ].
^ super doesNotUnderstand: aMessage
]
{ #category : #accessing }
PBProxyObject >> languageLinkSerializable [
^ self asJsonDictionary
]
{ #category : #printing }
PBProxyObject >> printOn: str [
str
<< (pythonClass asString first isVowel ifTrue: ['an '] ifFalse: ['a ']);
<< pythonClass asString;
<< ' (Proxy)'
]
{ #category : #accessing }
PBProxyObject >> pythonClass [
"Return the Python class/type name that I am a mirror of.
Fully qualified name unless it is one of the builtins."
^ pythonClass
]
{ #category : #accessing }
PBProxyObject >> pythonClass: anObject [
pythonClass := anObject
]
{ #category : #accessing }
PBProxyObject >> pythonVariable: pyVar [
pythonVariable := pyVar
]