pkl-python 0.1.11__tar.gz → 0.1.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pkl-python-0.1.11 → pkl-python-0.1.12}/PKG-INFO +2 -2
- {pkl-python-0.1.11 → pkl-python-0.1.12}/README.md +1 -1
- pkl-python-0.1.12/pkl/VERSION +1 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/__init__.py +5 -3
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/evaluator_manager.py +17 -8
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/parser.py +28 -68
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/server.py +1 -2
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl_python.egg-info/PKG-INFO +2 -2
- pkl-python-0.1.11/pkl/VERSION +0 -1
- {pkl-python-0.1.11 → pkl-python-0.1.12}/LICENSE +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/evaluator_options.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/msgapi.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/reader.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/utils.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl_python.egg-info/SOURCES.txt +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl_python.egg-info/dependency_links.txt +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl_python.egg-info/requires.txt +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl_python.egg-info/top_level.txt +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/pyproject.toml +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/scripts/download_binary.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/scripts/eval.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/setup.cfg +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/setup.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/tests/test_evaluator_manager.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/tests/test_load.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/tests/test_parser.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/tests/test_readers.py +0 -0
- {pkl-python-0.1.11 → pkl-python-0.1.12}/tests/test_server.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pkl-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.12
|
|
4
4
|
Summary: Python library for Apple's PKL.
|
|
5
5
|
Author-email: Jungwoo Yang <jwyang0213@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -62,7 +62,7 @@ pip install pkl-python
|
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
### Basic Usage
|
|
65
|
-
Here's how you can start using
|
|
65
|
+
Here's how you can start using `pkl-python` to load a PKL module:
|
|
66
66
|
|
|
67
67
|
```python
|
|
68
68
|
import pkl
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.12
|
|
@@ -86,11 +86,13 @@ def load(
|
|
|
86
86
|
if project_dir is PKL_DEFAULT:
|
|
87
87
|
project_dir = _search_project_dir(str(module_uri))
|
|
88
88
|
|
|
89
|
-
with EvaluatorManager(
|
|
89
|
+
with EvaluatorManager(debug=debug) as manager:
|
|
90
90
|
if (Path(project_dir) / "PklProject").exists():
|
|
91
|
-
evaluator = manager.new_project_evaluator(
|
|
91
|
+
evaluator = manager.new_project_evaluator(
|
|
92
|
+
project_dir, evaluator_options, parser=parser
|
|
93
|
+
)
|
|
92
94
|
else:
|
|
93
|
-
evaluator = manager.new_evaluator(evaluator_options)
|
|
95
|
+
evaluator = manager.new_evaluator(evaluator_options, parser=parser)
|
|
94
96
|
config = evaluator.evaluate_expression(source, expr)
|
|
95
97
|
return config
|
|
96
98
|
|
|
@@ -45,6 +45,8 @@ class Evaluator:
|
|
|
45
45
|
manager: "EvaluatorManager",
|
|
46
46
|
resource_readers: Optional[List[ResourceReader]] = None,
|
|
47
47
|
module_readers: Optional[List[ModuleReader]] = None,
|
|
48
|
+
*,
|
|
49
|
+
parser=None,
|
|
48
50
|
):
|
|
49
51
|
self.evaluatorId = evaluatorId
|
|
50
52
|
self.pending_requests = {}
|
|
@@ -55,6 +57,8 @@ class Evaluator:
|
|
|
55
57
|
self.resource_readers = resource_readers or []
|
|
56
58
|
self.module_readers = module_readers or []
|
|
57
59
|
|
|
60
|
+
self.parser = parser or Parser()
|
|
61
|
+
|
|
58
62
|
def _get_requestId(self):
|
|
59
63
|
res = self._prev_requestId + 1
|
|
60
64
|
self._prev_requestId = res
|
|
@@ -79,7 +83,7 @@ class Evaluator:
|
|
|
79
83
|
def evaluate_expression(self, source: ModuleSource, expr: Optional[str]):
|
|
80
84
|
binary_res = self._evaluate_expression_raw(source, expr)
|
|
81
85
|
decoded = msgpack.unpackb(binary_res, strict_map_key=False)
|
|
82
|
-
parsed = self.
|
|
86
|
+
parsed = self.parser.parse(decoded)
|
|
83
87
|
return parsed
|
|
84
88
|
|
|
85
89
|
def _evaluate_expression_raw(self, source: ModuleSource, expr: Optional[str]):
|
|
@@ -100,7 +104,7 @@ class Evaluator:
|
|
|
100
104
|
response: EvaluateResponse = self._manager.receive(requestId)
|
|
101
105
|
|
|
102
106
|
if response.error is not None:
|
|
103
|
-
raise PklError(response.error)
|
|
107
|
+
raise PklError("\n" + response.error)
|
|
104
108
|
return response.result
|
|
105
109
|
|
|
106
110
|
def evaluate_module(self, source: ModuleSource):
|
|
@@ -214,7 +218,10 @@ class Evaluator:
|
|
|
214
218
|
|
|
215
219
|
class EvaluatorManager:
|
|
216
220
|
def __init__(
|
|
217
|
-
self,
|
|
221
|
+
self,
|
|
222
|
+
pkl_command: Optional[List[str]] = None,
|
|
223
|
+
*,
|
|
224
|
+
debug=False,
|
|
218
225
|
):
|
|
219
226
|
self._evaluators: Dict[int, Evaluator] = {}
|
|
220
227
|
self._closed = False
|
|
@@ -223,7 +230,6 @@ class EvaluatorManager:
|
|
|
223
230
|
self._server = PKLServer(pkl_command, debug=debug)
|
|
224
231
|
|
|
225
232
|
self._prev_id = -100
|
|
226
|
-
self._parser = parser or Parser()
|
|
227
233
|
|
|
228
234
|
def send(self, msg: OutgoingMessage):
|
|
229
235
|
obj = msg.to_json()
|
|
@@ -258,7 +264,7 @@ class EvaluatorManager:
|
|
|
258
264
|
self._evaluators[decoded.evaluatorId].handle_request(decoded)
|
|
259
265
|
|
|
260
266
|
def new_evaluator(
|
|
261
|
-
self, options: EvaluatorOptions, project: Optional[Project] = None
|
|
267
|
+
self, options: EvaluatorOptions, project: Optional[Project] = None, parser=None
|
|
262
268
|
):
|
|
263
269
|
if self._closed:
|
|
264
270
|
raise ValueError("Server closed")
|
|
@@ -286,14 +292,17 @@ class EvaluatorManager:
|
|
|
286
292
|
self,
|
|
287
293
|
resource_readers=options.resourceReaders,
|
|
288
294
|
module_readers=options.moduleReaders,
|
|
295
|
+
parser=parser,
|
|
289
296
|
)
|
|
290
297
|
self._evaluators[response.evaluatorId] = evaluator
|
|
291
298
|
return evaluator
|
|
292
299
|
|
|
293
|
-
def new_project_evaluator(
|
|
294
|
-
|
|
300
|
+
def new_project_evaluator(
|
|
301
|
+
self, project_dir: str, options: EvaluatorOptions, parser=None
|
|
302
|
+
):
|
|
303
|
+
project_evaluator = self.new_evaluator(PreconfiguredOptions(), parser=parser)
|
|
295
304
|
project = load_project_from_evaluator(project_evaluator, project_dir)
|
|
296
|
-
evaluator = self.new_evaluator(options, project)
|
|
305
|
+
evaluator = self.new_evaluator(options, project, parser)
|
|
297
306
|
return evaluator
|
|
298
307
|
|
|
299
308
|
def _get_start_requestId(self):
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
import types
|
|
3
|
-
from collections import namedtuple
|
|
4
3
|
from dataclasses import dataclass, make_dataclass
|
|
5
4
|
from datetime import timedelta
|
|
6
5
|
from enum import Enum, auto
|
|
7
|
-
from typing import
|
|
6
|
+
from typing import Generic, List, Literal, TypeVar
|
|
8
7
|
|
|
9
8
|
# create module for lookup
|
|
10
9
|
_lookup_module = types.ModuleType(__name__ + "._lookup")
|
|
@@ -44,10 +43,14 @@ CODE_ENTRY = 0x11
|
|
|
44
43
|
CODE_ELEMENT = 0x12
|
|
45
44
|
|
|
46
45
|
|
|
46
|
+
T1 = TypeVar("T1")
|
|
47
|
+
T2 = TypeVar("T2")
|
|
48
|
+
|
|
49
|
+
|
|
47
50
|
@dataclass
|
|
48
|
-
class Pair:
|
|
49
|
-
first:
|
|
50
|
-
second:
|
|
51
|
+
class Pair(Generic[T1, T2]):
|
|
52
|
+
first: T1
|
|
53
|
+
second: T2
|
|
51
54
|
|
|
52
55
|
|
|
53
56
|
@dataclass
|
|
@@ -94,13 +97,8 @@ class Regex:
|
|
|
94
97
|
class Parser:
|
|
95
98
|
def __init__(
|
|
96
99
|
self,
|
|
100
|
+
namespace=None,
|
|
97
101
|
force_render=False,
|
|
98
|
-
*,
|
|
99
|
-
typed_dynamic_result_type=ResultType.DATACLASS,
|
|
100
|
-
pair_result_type=ResultType.DATACLASS,
|
|
101
|
-
datasize_result_type=ResultType.DATACLASS,
|
|
102
|
-
regex_result_type=ResultType.DATACLASS,
|
|
103
|
-
intseq_result_type=ResultType.DATACLASS,
|
|
104
102
|
):
|
|
105
103
|
self.type_handlers = {
|
|
106
104
|
CODE_TYPED_DYNAMIC: self.parse_typed_dynamic,
|
|
@@ -120,18 +118,9 @@ class Parser:
|
|
|
120
118
|
CODE_ENTRY: self.parse_entry,
|
|
121
119
|
CODE_ELEMENT: self.parse_element,
|
|
122
120
|
}
|
|
123
|
-
self.
|
|
124
|
-
self.
|
|
125
|
-
|
|
126
|
-
"__DataSize__": namedtuple("DataSize", ["value", "unit"]),
|
|
127
|
-
"__Regex__": namedtuple("Regex", ["pattern"]),
|
|
128
|
-
}
|
|
129
|
-
self._force_render = force_render
|
|
130
|
-
self._typed_dynamic_result_type = typed_dynamic_result_type
|
|
131
|
-
self._pair_result_type = pair_result_type
|
|
132
|
-
self._datasize_result_type = datasize_result_type
|
|
133
|
-
self._regex_result_type = regex_result_type
|
|
134
|
-
self._intseq_result_type = intseq_result_type
|
|
121
|
+
self.namespace = namespace
|
|
122
|
+
self.dataclass_cache = {}
|
|
123
|
+
self.force_render = force_render
|
|
135
124
|
|
|
136
125
|
def parse(self, obj):
|
|
137
126
|
return self.handle_type(obj)
|
|
@@ -151,12 +140,12 @@ class Parser:
|
|
|
151
140
|
return obj
|
|
152
141
|
|
|
153
142
|
def get_dataclass_class(self, class_name: str, keys: List[str]):
|
|
154
|
-
if class_name not in self.
|
|
143
|
+
if class_name not in self.dataclass_cache:
|
|
155
144
|
dynamic_class = make_dataclass(class_name, keys)
|
|
156
145
|
dynamic_class.__module__ = _lookup_module.__name__
|
|
157
146
|
setattr(_lookup_module, class_name, dynamic_class)
|
|
158
|
-
self.
|
|
159
|
-
dynamic_class = self.
|
|
147
|
+
self.dataclass_cache[class_name] = dynamic_class
|
|
148
|
+
dynamic_class = self.dataclass_cache[class_name]
|
|
160
149
|
return dynamic_class
|
|
161
150
|
|
|
162
151
|
def parse_typed_dynamic(self, obj):
|
|
@@ -166,7 +155,7 @@ class Parser:
|
|
|
166
155
|
property_list = list(map(self.handle_type, members))
|
|
167
156
|
|
|
168
157
|
if CODE_ELEMENT in member_types: # has element
|
|
169
|
-
if len(member_types) > 1 and not self.
|
|
158
|
+
if len(member_types) > 1 and not self.force_render:
|
|
170
159
|
raise ValueError(
|
|
171
160
|
"Cannot render object with both elements and properties/entries.\n"
|
|
172
161
|
"\tUse 'force_render=True'"
|
|
@@ -177,19 +166,16 @@ class Parser:
|
|
|
177
166
|
|
|
178
167
|
# only properties and entries
|
|
179
168
|
members = {k: v for m in property_list for k, v in m.items()}
|
|
180
|
-
result_type = self._typed_dynamic_result_type
|
|
181
169
|
class_name = full_class_name.split("#")[-1].split(".")[-1]
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
res = namedtuple(class_name, members.keys())(*members.values())
|
|
188
|
-
return res
|
|
189
|
-
elif result_type == ResultType.DICTIONARY:
|
|
190
|
-
return {full_class_name: members}
|
|
170
|
+
|
|
171
|
+
if self.namespace is not None:
|
|
172
|
+
if class_name not in self.namespace:
|
|
173
|
+
raise ValueError(f"'namespace' provided but '{class_name}' not found")
|
|
174
|
+
clazz = self.namespace[class_name]
|
|
191
175
|
else:
|
|
192
|
-
|
|
176
|
+
clazz = self.get_dataclass_class(class_name, members.keys())
|
|
177
|
+
res = clazz(*members.values())
|
|
178
|
+
return res
|
|
193
179
|
|
|
194
180
|
def parse_map(self, obj):
|
|
195
181
|
members = obj[1]
|
|
@@ -213,42 +199,16 @@ class Parser:
|
|
|
213
199
|
return Duration(value, unit)
|
|
214
200
|
|
|
215
201
|
def parse_pair(self, obj):
|
|
216
|
-
|
|
217
|
-
return Pair(obj[1], obj[2])
|
|
218
|
-
elif self._pair_result_type == ResultType.NAMEDTUPLE:
|
|
219
|
-
return self._namedtuple_cache["__Pair__"](obj[1], obj[2])
|
|
220
|
-
elif self._pair_result_type == ResultType.LIST:
|
|
221
|
-
return [obj[1], obj[2]]
|
|
222
|
-
elif self._pair_result_type == ResultType.TUPLE:
|
|
223
|
-
return (obj[1], obj[2])
|
|
224
|
-
else:
|
|
225
|
-
raise ValueError(f"ResultType '{self._pair_result_type}' not supported")
|
|
202
|
+
return Pair(obj[1], obj[2])
|
|
226
203
|
|
|
227
204
|
def parse_datasize(self, obj):
|
|
228
|
-
|
|
229
|
-
return DataSize(obj[1], obj[2])
|
|
230
|
-
elif self._datasize_result_type == ResultType.NAMEDTUPLE:
|
|
231
|
-
return self._namedtuple_cache["__DataSize__"](obj[1], obj[2])
|
|
232
|
-
elif self._datasize_result_type == ResultType.TUPLE:
|
|
233
|
-
return (obj[1], obj[2])
|
|
234
|
-
else:
|
|
235
|
-
raise ValueError(f"ResultType '{self._datasize_result_type}' not supported")
|
|
205
|
+
return DataSize(obj[1], obj[2])
|
|
236
206
|
|
|
237
207
|
def parse_intseq(self, obj):
|
|
238
|
-
|
|
239
|
-
return IntSeq(obj[1], obj[2], obj[3])
|
|
240
|
-
elif self._intseq_result_type == ResultType.RANGE:
|
|
241
|
-
return range(obj[1], obj[2], obj[3])
|
|
242
|
-
else:
|
|
243
|
-
raise ValueError(f"ResultType '{self._intseq_result_type}' not supported")
|
|
208
|
+
return IntSeq(obj[1], obj[2], obj[3])
|
|
244
209
|
|
|
245
210
|
def parse_regex(self, obj):
|
|
246
|
-
|
|
247
|
-
return Regex(obj[1])
|
|
248
|
-
elif self._datasize_result_type == ResultType.NAMEDTUPLE:
|
|
249
|
-
return self._namedtuple_cache["__Regex__"](obj[1])
|
|
250
|
-
else:
|
|
251
|
-
raise ValueError(f"ResultType '{self._datasize_result_type}' not supported")
|
|
211
|
+
return Regex(obj[1])
|
|
252
212
|
|
|
253
213
|
def parse_class(self, obj):
|
|
254
214
|
return
|
|
@@ -129,12 +129,11 @@ class PKLServer:
|
|
|
129
129
|
return msg
|
|
130
130
|
|
|
131
131
|
def _receive(self, stream):
|
|
132
|
-
msg = self._read(stream)
|
|
133
132
|
while True:
|
|
134
|
-
self.unpacker.feed(msg)
|
|
135
133
|
for unpacked in self.unpacker:
|
|
136
134
|
return unpacked
|
|
137
135
|
msg = self._read(stream)
|
|
136
|
+
self.unpacker.feed(msg)
|
|
138
137
|
|
|
139
138
|
def receive(self):
|
|
140
139
|
if self.closed:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pkl-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.12
|
|
4
4
|
Summary: Python library for Apple's PKL.
|
|
5
5
|
Author-email: Jungwoo Yang <jwyang0213@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -62,7 +62,7 @@ pip install pkl-python
|
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
### Basic Usage
|
|
65
|
-
Here's how you can start using
|
|
65
|
+
Here's how you can start using `pkl-python` to load a PKL module:
|
|
66
66
|
|
|
67
67
|
```python
|
|
68
68
|
import pkl
|
pkl-python-0.1.11/pkl/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.1.11
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|