pkl-python 0.1.14__tar.gz → 0.1.16__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 (32) hide show
  1. {pkl-python-0.1.14 → pkl_python-0.1.16}/PKG-INFO +9 -8
  2. {pkl-python-0.1.14 → pkl_python-0.1.16}/README.md +7 -6
  3. {pkl-python-0.1.14 → pkl_python-0.1.16}/pyproject.toml +13 -2
  4. pkl_python-0.1.16/src/pkl/VERSION +1 -0
  5. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl/__init__.py +35 -15
  6. pkl_python-0.1.16/src/pkl/binary_manager.py +185 -0
  7. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl/server.py +6 -62
  8. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl_python.egg-info/PKG-INFO +9 -8
  9. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl_python.egg-info/SOURCES.txt +2 -1
  10. pkl_python-0.1.16/tests/test_binary.py +61 -0
  11. {pkl-python-0.1.14 → pkl_python-0.1.16}/tests/test_load.py +5 -0
  12. pkl-python-0.1.14/setup.py +0 -74
  13. pkl-python-0.1.14/src/pkl/VERSION +0 -1
  14. {pkl-python-0.1.14 → pkl_python-0.1.16}/LICENSE +0 -0
  15. {pkl-python-0.1.14 → pkl_python-0.1.16}/setup.cfg +0 -0
  16. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl/evaluator_manager.py +0 -0
  17. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl/evaluator_options.py +0 -0
  18. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl/msgapi.py +0 -0
  19. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl/parser.py +0 -0
  20. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl/reader.py +0 -0
  21. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl/utils.py +0 -0
  22. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl_gen_python.py +0 -0
  23. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl_python.egg-info/dependency_links.txt +0 -0
  24. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl_python.egg-info/entry_points.txt +0 -0
  25. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl_python.egg-info/requires.txt +0 -0
  26. {pkl-python-0.1.14 → pkl_python-0.1.16}/src/pkl_python.egg-info/top_level.txt +0 -0
  27. {pkl-python-0.1.14 → pkl_python-0.1.16}/tests/test_evaluator_manager.py +0 -0
  28. {pkl-python-0.1.14 → pkl_python-0.1.16}/tests/test_fixtures.py +0 -0
  29. {pkl-python-0.1.14 → pkl_python-0.1.16}/tests/test_parser.py +0 -0
  30. {pkl-python-0.1.14 → pkl_python-0.1.16}/tests/test_readers.py +0 -0
  31. {pkl-python-0.1.14 → pkl_python-0.1.16}/tests/test_server.py +0 -0
  32. {pkl-python-0.1.14 → pkl_python-0.1.16}/tests/test_trace.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pkl-python
3
- Version: 0.1.14
3
+ Version: 0.1.16
4
4
  Summary: Python library for Apple's PKL.
5
5
  Author-email: Jungwoo Yang <jwyang0213@gmail.com>
6
6
  License: MIT License
@@ -31,7 +31,7 @@ Project-URL: Source, https://github.com/jw-y/pkl-python
31
31
  Classifier: Programming Language :: Python :: 3
32
32
  Classifier: License :: OSI Approved :: MIT License
33
33
  Classifier: Operating System :: OS Independent
34
- Requires-Python: >=3.7
34
+ Requires-Python: >=3.8
35
35
  Description-Content-Type: text/markdown
36
36
  License-File: LICENSE
37
37
  Requires-Dist: msgpack>=1.0.8
@@ -68,6 +68,7 @@ Here's how you can start using `pkl-python` to load a PKL module:
68
68
  import pkl
69
69
 
70
70
  config = pkl.load("path/to/pkl/example_module.pkl")
71
+ config = pkl.loads("a: Int = 1 + 1")
71
72
  ```
72
73
 
73
74
  ### Code Generation
@@ -78,10 +79,6 @@ However, codegen lets you expect contents of pkl files within Python modules.
78
79
  pkl-gen-python path/to/pkl/example_module.pkl
79
80
  ```
80
81
 
81
- ### Status
82
- * Evaluator API: functional
83
- * Code Generation: functional, but needs refining
84
-
85
82
  ### TODO
86
83
  * [x] (codgen) pip binary installation
87
84
  * [ ] (codgen) gatherer depth-first ordering
@@ -89,7 +86,6 @@ pkl-gen-python path/to/pkl/example_module.pkl
89
86
 
90
87
 
91
88
  ## Advanced Features
92
- For details on the parameters, refer [Message Passing API](https://pkl-lang.org/main/current/bindings-specification/message-passing-api.html).
93
89
 
94
90
  ```python
95
91
  import pkl
@@ -100,6 +96,11 @@ config = pkl.load(None, module_text="a: Int = 1 + 1")
100
96
  config = pkl.load("./tests/types.pkl", debug=True)
101
97
  ```
102
98
 
99
+ ### `pkl.load` Parameters Detail
100
+ For details on the parameters, refer
101
+ * [`pkl eval`](https://pkl-lang.org/main/current/pkl-cli/index.html#command-eval)
102
+ * [Message Passing API](https://pkl-lang.org/main/current/bindings-specification/message-passing-api.html).
103
+
103
104
  ### Custom Readers
104
105
  It is possible to add module or resource or module readers:
105
106
  ```python
@@ -123,7 +124,7 @@ opts = PreconfiguredOptions(
123
124
  moduleReaders=[TestModuleReader("customfs", True, True, True)]
124
125
  )
125
126
  opts.allowedModules.append("customfs:")
126
- config = pkl.load("./tests/myModule.pkl", evaluator_options=opts)
127
+ config = pkl.load("./tests/pkls/myModule.pkl", evaluator_options=opts)
127
128
  ```
128
129
 
129
130
  ## Appendix
@@ -21,6 +21,7 @@ Here's how you can start using `pkl-python` to load a PKL module:
21
21
  import pkl
22
22
 
23
23
  config = pkl.load("path/to/pkl/example_module.pkl")
24
+ config = pkl.loads("a: Int = 1 + 1")
24
25
  ```
25
26
 
26
27
  ### Code Generation
@@ -31,10 +32,6 @@ However, codegen lets you expect contents of pkl files within Python modules.
31
32
  pkl-gen-python path/to/pkl/example_module.pkl
32
33
  ```
33
34
 
34
- ### Status
35
- * Evaluator API: functional
36
- * Code Generation: functional, but needs refining
37
-
38
35
  ### TODO
39
36
  * [x] (codgen) pip binary installation
40
37
  * [ ] (codgen) gatherer depth-first ordering
@@ -42,7 +39,6 @@ pkl-gen-python path/to/pkl/example_module.pkl
42
39
 
43
40
 
44
41
  ## Advanced Features
45
- For details on the parameters, refer [Message Passing API](https://pkl-lang.org/main/current/bindings-specification/message-passing-api.html).
46
42
 
47
43
  ```python
48
44
  import pkl
@@ -53,6 +49,11 @@ config = pkl.load(None, module_text="a: Int = 1 + 1")
53
49
  config = pkl.load("./tests/types.pkl", debug=True)
54
50
  ```
55
51
 
52
+ ### `pkl.load` Parameters Detail
53
+ For details on the parameters, refer
54
+ * [`pkl eval`](https://pkl-lang.org/main/current/pkl-cli/index.html#command-eval)
55
+ * [Message Passing API](https://pkl-lang.org/main/current/bindings-specification/message-passing-api.html).
56
+
56
57
  ### Custom Readers
57
58
  It is possible to add module or resource or module readers:
58
59
  ```python
@@ -76,7 +77,7 @@ opts = PreconfiguredOptions(
76
77
  moduleReaders=[TestModuleReader("customfs", True, True, True)]
77
78
  )
78
79
  opts.allowedModules.append("customfs:")
79
- config = pkl.load("./tests/myModule.pkl", evaluator_options=opts)
80
+ config = pkl.load("./tests/pkls/myModule.pkl", evaluator_options=opts)
80
81
  ```
81
82
 
82
83
  ## Appendix
@@ -1,5 +1,5 @@
1
1
  [build-system]
2
- requires = ["setuptools>=42", "wheel"]
2
+ requires = ["setuptools>=42", "wheel", "msgpack", "requests"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
@@ -11,7 +11,7 @@ authors = [
11
11
  ]
12
12
  license = { file = "LICENSE" }
13
13
  readme = "README.md"
14
- requires-python = ">=3.7"
14
+ requires-python = ">=3.8"
15
15
  classifiers = [
16
16
  "Programming Language :: Python :: 3",
17
17
  "License :: OSI Approved :: MIT License",
@@ -64,3 +64,14 @@ exclude = ["codegen/snippet-tests/output/*"]
64
64
 
65
65
  [tool.pytest.ini_options]
66
66
  addopts = "-ra -q"
67
+
68
+
69
+ [tool.cibuildwheel]
70
+ build = [
71
+ "*-macosx_x86_64",
72
+ "*-macosx_arm64",
73
+ "*-manylinux_aarch64",
74
+ "*-manylinux_x86_64",
75
+ #"*-musllinux_x86_64",
76
+ "*-win_amd64",
77
+ ]
@@ -0,0 +1 @@
1
+ 0.1.16
@@ -14,23 +14,15 @@ with open(os.path.join(os.path.dirname(__file__), "VERSION"), "r") as _f:
14
14
  __version__ = _f.read().strip()
15
15
 
16
16
 
17
- class PklDefaultType:
18
- def __repr__(self):
19
- return "<PklDefault>"
20
-
21
-
22
- PKL_DEFAULT = PklDefaultType()
23
-
24
-
25
17
  def _search_project_dir(module_path: str) -> str:
26
18
  cur_path = Path(module_path).parent.absolute()
19
+ root_path = cur_path.root
20
+
27
21
  while not (cur_path / "PklProject").exists():
28
- cur_path = cur_path.parent
29
- if str(cur_path) == "/":
22
+ if cur_path == cur_path.parent or cur_path == root_path:
30
23
  break
24
+ cur_path = cur_path.parent
31
25
 
32
- if str(cur_path) == "/":
33
- cur_path = Path(module_path).parent
34
26
  return str(cur_path.absolute())
35
27
 
36
28
 
@@ -54,7 +46,7 @@ def load(
54
46
  *,
55
47
  module_text: Optional[str] = None,
56
48
  expr: Optional[str] = None,
57
- project_dir: str = PKL_DEFAULT,
49
+ project_dir: Optional[str] = None,
58
50
  evaluator_options: EvaluatorOptions = PreconfiguredOptions(),
59
51
  parser=None,
60
52
  debug=False,
@@ -69,7 +61,7 @@ def load(
69
61
  If None, the module is loaded from the specified URI.
70
62
  expr (Optional[str], None): Optionally, a Pkl expression to be evaluated
71
63
  within the loaded module. If None, the entire module is evaluated.
72
- project_dir (str, PKL_DEFAULT): The project directory to use for this command.
64
+ project_dir (Optional[str], None): The project directory to use for this command.
73
65
  By default, searches up from the working directory for a PklProject file.
74
66
  evaluator_options (EvaluatorOptions, PreconfiguredOptions()):
75
67
  extra options for evaluator
@@ -88,7 +80,7 @@ def load(
88
80
 
89
81
  source = _parse_module_uri(module_uri, module_text)
90
82
 
91
- if project_dir is PKL_DEFAULT:
83
+ if project_dir is None:
92
84
  project_dir = _search_project_dir(str(module_uri))
93
85
 
94
86
  with EvaluatorManager(debug=debug) as manager:
@@ -102,8 +94,36 @@ def load(
102
94
  return config
103
95
 
104
96
 
97
+ def loads(
98
+ module_text: Optional[str],
99
+ *,
100
+ expr: Optional[str] = None,
101
+ project_dir: Optional[str] = None,
102
+ evaluator_options: EvaluatorOptions = PreconfiguredOptions(),
103
+ parser=None,
104
+ debug=False,
105
+ **kwargs,
106
+ ):
107
+ """
108
+ This function is a specialized version of `load` that defaults `module_uri` to None.
109
+
110
+ {load.__doc__}
111
+ """
112
+ return load(
113
+ module_uri=None,
114
+ module_text=module_text,
115
+ expr=expr,
116
+ project_dir=project_dir,
117
+ evaluator_options=evaluator_options,
118
+ parser=parser,
119
+ debug=debug,
120
+ **kwargs,
121
+ )
122
+
123
+
105
124
  __all__ = [
106
125
  "load",
126
+ "loads",
107
127
  "Evaluator",
108
128
  "EvaluatorManager",
109
129
  "EvaluatorOptions",
@@ -0,0 +1,185 @@
1
+ import argparse
2
+ import os
3
+ import platform
4
+ import stat
5
+ import subprocess
6
+ from functools import cache
7
+ from pathlib import Path
8
+
9
+ import requests
10
+
11
+ ARM_BINARIES = {
12
+ "darwin": "pkl-macos-aarch64",
13
+ "linux": "pkl-linux-aarch64",
14
+ }
15
+ AMD64_BINARIES = {
16
+ "darwin": "pkl-macos-amd64",
17
+ "linux": "pkl-linux-amd64",
18
+ "alpine-linux": "pkl-alpine-linux-amd64",
19
+ "windows": "pkl-windows-amd64.exe",
20
+ }
21
+ # PKL_VERSION = "0.26.3"
22
+ # BASE_PATH = "https://github.com/apple/pkl/releases/download/"
23
+
24
+
25
+ class BinaryManager:
26
+ def __init__(self, download_binary=True):
27
+ binary_fp = self.is_command_available() or self._downloaded_binary_path()
28
+ need_to_download = binary_fp is None
29
+ if download_binary and need_to_download:
30
+ binary_dir = self._default_bin_dir()
31
+ binary_url: str = self._determine_binary_url()
32
+ binary_fp = self.download_binary(binary_dir, binary_url)
33
+
34
+ self.binary_path = binary_fp
35
+
36
+ # self.binary_dir: Path = binary_dir or self._default_bin_dir()
37
+ # self.binary_name: str = binary_name or self._determine_binary_name()
38
+ # self.binary_path: Path = self.binary_dir / self.binary_name
39
+ # self.binary_base_url = BASE_PATH + PKL_VERSION + "/"
40
+ # self.binary_url = self.binary_base_url + self.binary_path.name
41
+
42
+ def _downloaded_binary_path(self):
43
+ binary_dir: Path = self._default_bin_dir()
44
+ if not binary_dir.exists():
45
+ return None
46
+ ls = list(binary_dir.iterdir())
47
+
48
+ if len(ls) == 0:
49
+ return None
50
+ elif len(ls) == 1:
51
+ return Path(ls[0])
52
+ else:
53
+ raise Exception("Something went wrong")
54
+
55
+ @cache
56
+ def get_latest_pkl_release_urls(self):
57
+ url = "https://api.github.com/repos/apple/pkl/releases/latest"
58
+ response = requests.get(url)
59
+ release = response.json()
60
+ assets = release["assets"]
61
+ urls = {a["name"]: a["browser_download_url"] for a in assets}
62
+ return urls
63
+
64
+ def is_command_available(self):
65
+ """
66
+ Check if a command is available in the system's PATH.
67
+ """
68
+ try:
69
+ if platform.system() == "Windows":
70
+ result = subprocess.run(
71
+ ["where", "pkl"],
72
+ check=True,
73
+ stdout=subprocess.PIPE,
74
+ stderr=subprocess.PIPE,
75
+ )
76
+ else:
77
+ result = subprocess.run(
78
+ ["which", "pkl"],
79
+ check=True,
80
+ stdout=subprocess.PIPE,
81
+ stderr=subprocess.PIPE,
82
+ )
83
+ return result.stdout.decode().splitlines()[0].strip()
84
+ except subprocess.CalledProcessError:
85
+ return None
86
+
87
+ def download_binary(self, binary_dir: Path, binary_url: str):
88
+ binary_dir.mkdir(exist_ok=True, parents=True)
89
+ return self._download_and_save_binary(binary_url, binary_dir)
90
+
91
+ def get_binary_filepath(self):
92
+ return str(self.binary_path)
93
+
94
+ def detect_system(self):
95
+ def is_alpine_linux():
96
+ return os.path.isfile("/etc/alpine-release")
97
+
98
+ def detect_processor_architecture():
99
+ architecture = platform.machine().lower()
100
+ if "arm" in architecture or "aarch64" in architecture:
101
+ return "ARM"
102
+ elif "x86_64" in architecture or "amd64" in architecture:
103
+ return "AMD64"
104
+ else:
105
+ return None
106
+
107
+ os_name = platform.system().lower()
108
+ if os_name == "linux" and is_alpine_linux():
109
+ os_name = "alpine-linux"
110
+ arch = detect_processor_architecture()
111
+ return os_name, arch
112
+
113
+ def _determine_binary_url(self) -> str:
114
+ os_name, arch = self.detect_system()
115
+ if arch == "ARM":
116
+ bin_name = ARM_BINARIES.get(os_name)
117
+ else:
118
+ bin_name = AMD64_BINARIES.get(os_name)
119
+
120
+ if bin_name is None:
121
+ raise OSError(
122
+ f"No compatible binary found for your system: {os_name}, {arch}"
123
+ )
124
+ name_to_url_map = self.get_latest_pkl_release_urls()
125
+ url = name_to_url_map[bin_name]
126
+ return url
127
+
128
+ @classmethod
129
+ def _default_bin_dir(cls) -> Path:
130
+ bin_dir = Path(__file__).parent / "bin"
131
+ return bin_dir
132
+
133
+ """
134
+ def download_all_binary(self):
135
+ download_dir = self._default_bin_dir()
136
+ download_dir.mkdir(exist_ok=True)
137
+ for filename in BINARIES.values():
138
+ url = self.binary_base_url + filename
139
+ self._download_and_save_binary(url, download_dir)
140
+ """
141
+
142
+ @classmethod
143
+ def _fetch_binary(cls, url):
144
+ response = requests.get(url)
145
+ response.raise_for_status()
146
+ return response.content
147
+
148
+ @classmethod
149
+ def _download_and_save_binary(
150
+ cls, url, target_dir: Path, filename=None, skip_exists=True
151
+ ) -> Path:
152
+ assert target_dir.is_dir()
153
+ content = cls._fetch_binary(url)
154
+
155
+ default_filename = Path(url).name
156
+ binary_fp = target_dir / (filename or default_filename)
157
+
158
+ if skip_exists and binary_fp.exists():
159
+ return binary_fp
160
+
161
+ with open(binary_fp, "wb") as f:
162
+ f.write(content)
163
+ print(f"Successfully installed {binary_fp}")
164
+ os.chmod(binary_fp, os.stat(binary_fp).st_mode | stat.S_IXUSR)
165
+ return binary_fp
166
+
167
+ def check(self):
168
+ cmd = [self.binary_path, "-v"]
169
+ result = subprocess.run(cmd, capture_output=True, text=True)
170
+ stdout = result.stdout
171
+ return stdout
172
+
173
+
174
+ def main():
175
+ parser = argparse.ArgumentParser()
176
+ parser.add_argument("--binary_dir")
177
+ args = parser.parse_args()
178
+
179
+ binary_dir = Path(args.binary_dir)
180
+ manager = BinaryManager(binary_dir=binary_dir)
181
+ manager.download_all_binary()
182
+
183
+
184
+ if __name__ == "__main__":
185
+ main()
@@ -1,23 +1,9 @@
1
1
  import atexit
2
2
  import os
3
- import platform
4
3
  import signal
5
- import stat
6
4
  import subprocess
7
- from pathlib import Path
8
5
 
9
6
  import msgpack
10
- import requests
11
-
12
- BINARIES = {
13
- ("darwin", "64bit"): "pkl-macos-amd64",
14
- ("darwin", "aarch64"): "pkl-macos-aarch64",
15
- ("linux", "64bit"): "pkl-linux-amd64",
16
- ("linux", "aarch64"): "pkl-linux-aarch64",
17
- ("linux", "64bit", "alpine"): "pkl-alpine-linux-amd64",
18
- }
19
- PKL_VERSION = "0.25.3"
20
- BASE_PATH = "https://github.com/apple/pkl/releases/download/"
21
7
 
22
8
 
23
9
  def preexec_function():
@@ -25,53 +11,6 @@ def preexec_function():
25
11
  signal.signal(signal.SIGHUP, signal.SIG_IGN)
26
12
 
27
13
 
28
- def detect_system():
29
- os_name = platform.system().lower()
30
- arch, _ = platform.architecture()
31
- return os_name, arch
32
-
33
-
34
- def is_alpine_linux():
35
- return os.path.isfile("/etc/alpine-release")
36
-
37
-
38
- def execute_binary(binary_path):
39
- subprocess.run([binary_path, "server"], check=True)
40
-
41
-
42
- def download_binary(file, target_fp):
43
- url = BASE_PATH + PKL_VERSION + "/" + file
44
- response = requests.get(url)
45
- with open(target_fp, "wb") as f:
46
- f.write(response.content)
47
-
48
-
49
- def get_binary_path():
50
- os_name, arch = detect_system()
51
- if os_name == "linux" and is_alpine_linux():
52
- os_name = "alpine"
53
- binary_key = (os_name, arch)
54
- if binary_key == ("linux", "64bit") and is_alpine_linux():
55
- binary_key += ("alpine",)
56
- bin_file = BINARIES.get(binary_key)
57
-
58
- if bin_file is None:
59
- raise OSError("No compatible binary found for your system.")
60
-
61
- bin_parent_path = (Path("~/.pkl/bin/") / PKL_VERSION).expanduser()
62
- binary_path = bin_parent_path / bin_file
63
-
64
- if not binary_path.exists():
65
- binary_path.parent.mkdir(exist_ok=True, parents=True)
66
- download_binary(bin_file, binary_path)
67
-
68
- current_permissions = os.stat(binary_path).st_mode
69
- new_permissions = current_permissions | stat.S_IXUSR
70
- os.chmod(binary_path, new_permissions)
71
-
72
- return binary_path
73
-
74
-
75
14
  _PROCESSES = []
76
15
 
77
16
 
@@ -86,7 +25,12 @@ atexit.register(terminate_processes)
86
25
 
87
26
  class PKLServer:
88
27
  def __init__(self, cmd=None, debug=False):
89
- self.cmd = cmd or [get_binary_path(), "server"]
28
+ from pkl.binary_manager import BinaryManager
29
+
30
+ manager = BinaryManager()
31
+ binary_path = manager.get_binary_filepath()
32
+
33
+ self.cmd = cmd or [binary_path, "server"]
90
34
  self.next_request_id = 1
91
35
  self.unpacker = msgpack.Unpacker()
92
36
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pkl-python
3
- Version: 0.1.14
3
+ Version: 0.1.16
4
4
  Summary: Python library for Apple's PKL.
5
5
  Author-email: Jungwoo Yang <jwyang0213@gmail.com>
6
6
  License: MIT License
@@ -31,7 +31,7 @@ Project-URL: Source, https://github.com/jw-y/pkl-python
31
31
  Classifier: Programming Language :: Python :: 3
32
32
  Classifier: License :: OSI Approved :: MIT License
33
33
  Classifier: Operating System :: OS Independent
34
- Requires-Python: >=3.7
34
+ Requires-Python: >=3.8
35
35
  Description-Content-Type: text/markdown
36
36
  License-File: LICENSE
37
37
  Requires-Dist: msgpack>=1.0.8
@@ -68,6 +68,7 @@ Here's how you can start using `pkl-python` to load a PKL module:
68
68
  import pkl
69
69
 
70
70
  config = pkl.load("path/to/pkl/example_module.pkl")
71
+ config = pkl.loads("a: Int = 1 + 1")
71
72
  ```
72
73
 
73
74
  ### Code Generation
@@ -78,10 +79,6 @@ However, codegen lets you expect contents of pkl files within Python modules.
78
79
  pkl-gen-python path/to/pkl/example_module.pkl
79
80
  ```
80
81
 
81
- ### Status
82
- * Evaluator API: functional
83
- * Code Generation: functional, but needs refining
84
-
85
82
  ### TODO
86
83
  * [x] (codgen) pip binary installation
87
84
  * [ ] (codgen) gatherer depth-first ordering
@@ -89,7 +86,6 @@ pkl-gen-python path/to/pkl/example_module.pkl
89
86
 
90
87
 
91
88
  ## Advanced Features
92
- For details on the parameters, refer [Message Passing API](https://pkl-lang.org/main/current/bindings-specification/message-passing-api.html).
93
89
 
94
90
  ```python
95
91
  import pkl
@@ -100,6 +96,11 @@ config = pkl.load(None, module_text="a: Int = 1 + 1")
100
96
  config = pkl.load("./tests/types.pkl", debug=True)
101
97
  ```
102
98
 
99
+ ### `pkl.load` Parameters Detail
100
+ For details on the parameters, refer
101
+ * [`pkl eval`](https://pkl-lang.org/main/current/pkl-cli/index.html#command-eval)
102
+ * [Message Passing API](https://pkl-lang.org/main/current/bindings-specification/message-passing-api.html).
103
+
103
104
  ### Custom Readers
104
105
  It is possible to add module or resource or module readers:
105
106
  ```python
@@ -123,7 +124,7 @@ opts = PreconfiguredOptions(
123
124
  moduleReaders=[TestModuleReader("customfs", True, True, True)]
124
125
  )
125
126
  opts.allowedModules.append("customfs:")
126
- config = pkl.load("./tests/myModule.pkl", evaluator_options=opts)
127
+ config = pkl.load("./tests/pkls/myModule.pkl", evaluator_options=opts)
127
128
  ```
128
129
 
129
130
  ## Appendix
@@ -1,10 +1,10 @@
1
1
  LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
- setup.py
5
4
  src/pkl_gen_python.py
6
5
  src/pkl/VERSION
7
6
  src/pkl/__init__.py
7
+ src/pkl/binary_manager.py
8
8
  src/pkl/evaluator_manager.py
9
9
  src/pkl/evaluator_options.py
10
10
  src/pkl/msgapi.py
@@ -18,6 +18,7 @@ src/pkl_python.egg-info/dependency_links.txt
18
18
  src/pkl_python.egg-info/entry_points.txt
19
19
  src/pkl_python.egg-info/requires.txt
20
20
  src/pkl_python.egg-info/top_level.txt
21
+ tests/test_binary.py
21
22
  tests/test_evaluator_manager.py
22
23
  tests/test_fixtures.py
23
24
  tests/test_load.py
@@ -0,0 +1,61 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ import pytest
5
+
6
+ import pkl
7
+ from pkl.binary_manager import BinaryManager
8
+
9
+
10
+ def remove_pkl_from_path(monkeypatch):
11
+ manager = BinaryManager()
12
+ path = manager.is_command_available()
13
+ if path is None:
14
+ return
15
+ path = path.rsplit("/", 1)[0]
16
+ original_path = os.environ.get("PATH", "")
17
+ paths = original_path.split(os.pathsep)
18
+ paths = [p for p in paths if path not in p]
19
+ monkeypatch.setenv("PATH", os.pathsep.join(paths))
20
+
21
+
22
+ def remove_pkl_binary():
23
+ path = Path(pkl.__file__)
24
+ ls = list((path.parent / "bin").iterdir())
25
+ if len(ls) == 0:
26
+ return
27
+ assert len(ls) == 1
28
+ binary_path = ls[0]
29
+ os.remove(binary_path)
30
+ return binary_path
31
+
32
+
33
+ def test_latest_release():
34
+ manager = BinaryManager()
35
+ urls = manager.get_latest_pkl_release_urls()
36
+ assert len(urls) == 7
37
+
38
+
39
+ def test_without_download_binary():
40
+ manager = BinaryManager()
41
+ output = manager.check()
42
+ assert output.lower().startswith("pkl")
43
+
44
+
45
+ def test_download_binary(monkeypatch: pytest.MonkeyPatch):
46
+ remove_pkl_binary()
47
+ remove_pkl_from_path(monkeypatch)
48
+ manager = BinaryManager()
49
+ output = manager.check()
50
+ assert output.lower().startswith("pkl")
51
+
52
+ removed = remove_pkl_binary()
53
+ assert manager.binary_path == removed
54
+
55
+
56
+ def test_binary_file_exists():
57
+ manager = BinaryManager()
58
+ manager.is_command_available()
59
+
60
+ fp = manager.get_binary_filepath()
61
+ assert os.path.exists(fp), f"Binary file not found at {fp}"
@@ -5,6 +5,11 @@ def test_load():
5
5
  _ = pkl.load("./tests/pkls/types.pkl")
6
6
 
7
7
 
8
+ def test_loads():
9
+ config = pkl.loads("a: Int = 1 + 1")
10
+ assert config.a == 2
11
+
12
+
8
13
  def test_load_expr():
9
14
  config = pkl.load("./tests/pkls/types.pkl", expr="datasize")
10
15
  assert config.__class__.__name__ == "DataSize"
@@ -1,74 +0,0 @@
1
- import os
2
- import platform
3
- import stat
4
- from pathlib import Path
5
-
6
- import setuptools
7
- from setuptools.command.install import install
8
-
9
- BINARIES = {
10
- ("darwin", "64bit"): "pkl-macos-amd64",
11
- ("darwin", "aarch64"): "pkl-macos-aarch64",
12
- ("linux", "64bit"): "pkl-linux-amd64",
13
- ("linux", "aarch64"): "pkl-linux-aarch64",
14
- ("linux", "64bit", "alpine"): "pkl-alpine-linux-amd64",
15
- }
16
- PKL_VERSION = "0.25.3"
17
- BASE_PATH = "https://github.com/apple/pkl/releases/download/"
18
-
19
-
20
- def detect_system():
21
- os_name = platform.system().lower()
22
- arch, _ = platform.architecture()
23
- return os_name, arch
24
-
25
-
26
- def is_alpine_linux():
27
- return os.path.isfile("/etc/alpine-release")
28
-
29
-
30
- def download_binary(file, target_fp):
31
- import requests
32
-
33
- url = BASE_PATH + PKL_VERSION + "/" + file
34
- response = requests.get(url)
35
- with open(target_fp, "wb") as f:
36
- f.write(response.content)
37
-
38
-
39
- def get_binary_path():
40
- os_name, arch = detect_system()
41
- if os_name == "linux" and is_alpine_linux():
42
- os_name = "alpine"
43
- binary_key = (os_name, arch)
44
- if binary_key == ("linux", "64bit") and is_alpine_linux():
45
- binary_key += ("alpine",)
46
- bin_file = BINARIES.get(binary_key)
47
-
48
- if bin_file is None:
49
- raise OSError("No compatible binary found for your system.")
50
-
51
- bin_parent_path = (Path("~/.pkl/bin/") / PKL_VERSION).expanduser()
52
- binary_path = bin_parent_path / bin_file
53
-
54
- if not binary_path.exists():
55
- binary_path.parent.mkdir(exist_ok=True, parents=True)
56
- download_binary(bin_file, binary_path)
57
-
58
- current_permissions = os.stat(binary_path).st_mode
59
- new_permissions = current_permissions | stat.S_IXUSR
60
- os.chmod(binary_path, new_permissions)
61
-
62
- return binary_path
63
-
64
-
65
- class CustomInstallCommand(install):
66
- def run(self):
67
- get_binary_path()
68
- install.run(self)
69
-
70
-
71
- setuptools.setup(
72
- cmdclass={"install": CustomInstallCommand},
73
- setup_requires=["requests"],
74
- )
@@ -1 +0,0 @@
1
- 0.1.14
File without changes
File without changes