-
-
Notifications
You must be signed in to change notification settings - Fork 68
/
protocols.clj
169 lines (117 loc) · 3.94 KB
/
protocols.clj
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
(ns libpython-clj.python.protocols
"Protocols to help generalize the python bindings. There is a clear distinction
made between building a bridging type and thus allowing communication between the
two systems and building a complete copy of the datastructure of one system in
another. Generic objects must only bridge but if we know more about the object
(like it implements java.util.Map) then we can implement either a bridge or a
copy.
Atomic objects:
* numbers
* booleans
* strings-convertible things like strings, keywords, symbols
Standard containers:
* list
* map
* set
* tuple (persistent vector of length less than 8)")
(defprotocol PPythonType
(get-python-type [item]
"Return a keyword that describes the python datatype of this object."))
(defn python-type
[item]
(if item
(get-python-type item)
:none-type))
(defprotocol PCopyToPython
(->python [item options]
"Copy this item into a python representation. Must never return nil.
Items may fallback to as-python if copying is untenable."))
(defprotocol PBridgeToPython
(as-python [item options]
"Aside from atom types, this means the object represented by a zero copy python
mirror. May return nil. This convertible to pointers get converted
to numpy implementations that share the backing store."))
(defprotocol PCopyToJVM
(->jvm [item options]
"Copy the python object into the jvm leaving no references. This not copying
are converted into a {:type :pyobject-address} pairs."))
(defprotocol PBridgeToJVM
(as-jvm [item options]
"Return a pyobject implementation that wraps the python object."))
(extend-type Object
PBridgeToPython
(as-python [item options] nil)
PCopyToJVM
(->jvm [item options] item)
PBridgeToJVM
(as-jvm [item options] item))
(extend-type Object
PBridgeToJVM
(as-jvm [item options] item))
(defprotocol PPyObject
(dir [item]
"Get sorted list of all attribute names.")
(has-attr? [item item-name])
(get-attr [item item-name])
(set-attr! [item item-name item-value])
(callable? [item])
(has-item? [item item-name])
(get-item [item item-name])
(set-item! [item item-name item-value]))
(defprotocol PPyAttMap
(att-type-map [item]
"Get hashmap of att name to keyword datatype."))
(extend-type Object
PPyAttMap
(att-type-map [item]
() (->> (dir item)
(map (juxt identity (comp python-type
(partial get-attr item))))
(into (sorted-map)))))
(defprotocol PyCall
(do-call-fn [callable arglist kw-arg-map]))
(defn call
[callable & args]
(do-call-fn callable args nil))
(defn call-kw
[callable arglist kw-args]
(do-call-fn callable arglist kw-args))
(defn call-attr
"Call an object attribute"
[item att-name & args]
(-> (get-attr item att-name)
(do-call-fn args nil)))
(defn call-attr-kw
[item att-name arglist kw-map]
(-> (get-attr item att-name)
(do-call-fn arglist kw-map)))
(defprotocol PPyObjLength
"Call the __len__ attribute."
(len [item]))
(extend-type Object
PPyObjLength
(len [item]
(-> (call-attr item "__len__")
(->jvm {}))))
(defprotocol PPyObjectBridgeToMap
(as-map [item]
"Return a Map implementation using __getitem__, __setitem__. Note that it may be
incomplete especially if the object has no 'keys' attribute."))
(defprotocol PPyObjectBridgeToList
(as-list [item]
"Return a List implementation using __getitem__, __setitem__."))
(defprotocol PJvmToNumpyBridge
(as-numpy [item options]
"Never copy data, operation returns nil of would require copy."))
(defprotocol PJvmToNumpy
(->numpy [item options]
"Never return nil. Copy or otherwise, numpy or bust."))
(defprotocol PPyObjectBridgeToTensor
(as-tensor [item]
"Return a tech.v2.tensor object from the item that shares the data backing store."))
(defmulti pyobject->jvm
(fn [pyobj]
(python-type pyobj)))
(defmulti pyobject-as-jvm
(fn [pyobj]
(python-type pyobj)))