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.
Files changed (28) hide show
  1. {pkl-python-0.1.11 → pkl-python-0.1.12}/PKG-INFO +2 -2
  2. {pkl-python-0.1.11 → pkl-python-0.1.12}/README.md +1 -1
  3. pkl-python-0.1.12/pkl/VERSION +1 -0
  4. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/__init__.py +5 -3
  5. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/evaluator_manager.py +17 -8
  6. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/parser.py +28 -68
  7. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/server.py +1 -2
  8. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl_python.egg-info/PKG-INFO +2 -2
  9. pkl-python-0.1.11/pkl/VERSION +0 -1
  10. {pkl-python-0.1.11 → pkl-python-0.1.12}/LICENSE +0 -0
  11. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/evaluator_options.py +0 -0
  12. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/msgapi.py +0 -0
  13. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/reader.py +0 -0
  14. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl/utils.py +0 -0
  15. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl_python.egg-info/SOURCES.txt +0 -0
  16. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl_python.egg-info/dependency_links.txt +0 -0
  17. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl_python.egg-info/requires.txt +0 -0
  18. {pkl-python-0.1.11 → pkl-python-0.1.12}/pkl_python.egg-info/top_level.txt +0 -0
  19. {pkl-python-0.1.11 → pkl-python-0.1.12}/pyproject.toml +0 -0
  20. {pkl-python-0.1.11 → pkl-python-0.1.12}/scripts/download_binary.py +0 -0
  21. {pkl-python-0.1.11 → pkl-python-0.1.12}/scripts/eval.py +0 -0
  22. {pkl-python-0.1.11 → pkl-python-0.1.12}/setup.cfg +0 -0
  23. {pkl-python-0.1.11 → pkl-python-0.1.12}/setup.py +0 -0
  24. {pkl-python-0.1.11 → pkl-python-0.1.12}/tests/test_evaluator_manager.py +0 -0
  25. {pkl-python-0.1.11 → pkl-python-0.1.12}/tests/test_load.py +0 -0
  26. {pkl-python-0.1.11 → pkl-python-0.1.12}/tests/test_parser.py +0 -0
  27. {pkl-python-0.1.11 → pkl-python-0.1.12}/tests/test_readers.py +0 -0
  28. {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.11
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 PKLL to load a PKL module:
65
+ Here's how you can start using `pkl-python` to load a PKL module:
66
66
 
67
67
  ```python
68
68
  import pkl
@@ -15,7 +15,7 @@ pip install pkl-python
15
15
  ```
16
16
 
17
17
  ### Basic Usage
18
- Here's how you can start using PKLL to load a PKL module:
18
+ Here's how you can start using `pkl-python` to load a PKL module:
19
19
 
20
20
  ```python
21
21
  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(parser=parser, debug=debug) as manager:
89
+ with EvaluatorManager(debug=debug) as manager:
90
90
  if (Path(project_dir) / "PklProject").exists():
91
- evaluator = manager.new_project_evaluator(project_dir, evaluator_options)
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._manager._parser.parse(decoded)
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, pkl_command: Optional[List[str]] = None, *, parser=None, debug=False
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(self, project_dir: str, options: EvaluatorOptions):
294
- project_evaluator = self.new_evaluator(PreconfiguredOptions())
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 Any, List, Literal
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: Any
50
- second: Any
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._dataclass_cache = {}
124
- self._namedtuple_cache = {
125
- "__Pair__": namedtuple("Pair", ["first", "second"]),
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._dataclass_cache:
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._dataclass_cache[class_name] = dynamic_class
159
- dynamic_class = self._dataclass_cache[class_name]
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._force_render:
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
- if result_type == ResultType.DATACLASS:
183
- dynamic_class = self.get_dataclass_class(class_name, members.keys())
184
- res = dynamic_class(*members.values())
185
- return res
186
- elif result_type == ResultType.NAMEDTUPLE:
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
- raise ValueError(f"invalid result_type: '{result_type}'")
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
- if self._pair_result_type == ResultType.DATACLASS:
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
- if self._datasize_result_type == ResultType.DATACLASS:
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
- if self._intseq_result_type == ResultType.DATACLASS:
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
- if self._datasize_result_type == ResultType.DATACLASS:
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.11
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 PKLL to load a PKL module:
65
+ Here's how you can start using `pkl-python` to load a PKL module:
66
66
 
67
67
  ```python
68
68
  import pkl
@@ -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