polytope-databases 20170220.2__py3-none-any.whl

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.
@@ -0,0 +1,249 @@
1
+ """Packaged SageMath databases of two- and three-dimensional polytopes.
2
+
3
+ The public helpers return :mod:`importlib.resources` ``Traversable`` objects or
4
+ context managers for real filesystem paths. The package performs no network
5
+ access and does not depend on SageMath.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import os
12
+ import operator
13
+ import shutil
14
+ from contextlib import contextmanager
15
+ from importlib import resources
16
+ from importlib.resources.abc import Traversable
17
+ from pathlib import Path
18
+ from tempfile import TemporaryDirectory
19
+ from typing import IO, Iterator, Mapping, Union
20
+
21
+ __version__ = "20170220.2"
22
+
23
+ DATA_FILES = (
24
+ "Full2d/zzdb.info",
25
+ "Full2d/zzdb.v03",
26
+ "Full2d/zzdb.v04",
27
+ "Full2d/zzdb.v05",
28
+ "Full2d/zzdb.v06",
29
+ "Full3d/zzdb.info",
30
+ "Full3d/zzdb.v04",
31
+ "Full3d/zzdb.v05",
32
+ "Full3d/zzdb.v06",
33
+ "Full3d/zzdb.v07",
34
+ "Full3d/zzdb.v08",
35
+ "Full3d/zzdb.v09",
36
+ "Full3d/zzdb.v10",
37
+ "Full3d/zzdb.v11",
38
+ "Full3d/zzdb.v12",
39
+ "Full3d/zzdb.v13",
40
+ "reflexive_polytopes_2d",
41
+ "reflexive_polytopes_3d",
42
+ )
43
+
44
+ DATA_SHA256: Mapping[str, str] = {
45
+ "Full2d/zzdb.info": "719ff58ca68984379be5962772983de912a8d74037173ed5c965268c135adaac",
46
+ "Full2d/zzdb.v03": "dde5ff0e7fd5c109d0aca7c01d1e2660e5f31af1199e8584d37cf9b878354b2c",
47
+ "Full2d/zzdb.v04": "0e81c83a04f4eb45e4cc393b36923e55844ddc4d7a23c8e01fb0095d1b760371",
48
+ "Full2d/zzdb.v05": "b7f853e6fc6e10c3362a6e4c9eb63ddca72c1832481ce06bd6d4629bb58bcb35",
49
+ "Full2d/zzdb.v06": "1aef85f64ccf4318bc3f25c20a4f5f3f1c635bebc36772d89c95ac639340c575",
50
+ "Full3d/zzdb.info": "b76c164ca39e018c62a2387443ff7940edba86615c13409c92e82094cf12e241",
51
+ "Full3d/zzdb.v04": "15545d51cc41c1dc70e543e5471cb14eff480da792a520c9d6041efef699a591",
52
+ "Full3d/zzdb.v05": "a787c47c6db5077bf54110957bc1ceb9538170aa0cd1e50c399814ea86e61c5b",
53
+ "Full3d/zzdb.v06": "1f86ff7cb8478fdf768547f848179da4f73587d5bd77672498a241596a42abe9",
54
+ "Full3d/zzdb.v07": "5aa55925b1eb46309bb7c70ce8dd2da3c2ae137390375ba79eac003c4ca65dc9",
55
+ "Full3d/zzdb.v08": "97ff70bff251043cea9978112de9c604ed6a5624438c3ee47876fd2aab601a78",
56
+ "Full3d/zzdb.v09": "d770b9ee7b1be356c451e9e6d77249d9afd59329b52ff34d4dd1e0cff58d6995",
57
+ "Full3d/zzdb.v10": "44d193a4765baa0fe442301a5e1b65f909d76d2c6980b9f140214909a4cc734c",
58
+ "Full3d/zzdb.v11": "696051521ff2a732d3c0e401b77922362eef5475158c84c1bb31a7533fdecd7c",
59
+ "Full3d/zzdb.v12": "92a9a3bcbf31f415bd45b3e1ee5516e0e318d5d63d0538b83d1712f5889e410c",
60
+ "Full3d/zzdb.v13": "f36361bf277890f4c84559520e36022449c53280d363edd883cd4fabe0d71577",
61
+ "reflexive_polytopes_2d": "f0e47311eb365f700e2a03a6b061fee85d44f1d3937acff32876723f47ebedb4",
62
+ "reflexive_polytopes_3d": "1d590ab17bb166084d87467123c7c9ff189dd15b42e4bf4d5df6790ffd10fed3",
63
+ }
64
+
65
+
66
+ def data_root() -> Traversable:
67
+ """Return the root of the packaged data as a Traversable resource."""
68
+
69
+ return resources.files(__package__).joinpath("data")
70
+
71
+
72
+ def _resource_parts(parts: tuple[Union[str, os.PathLike[str]], ...]) -> tuple[str, ...]:
73
+ if not parts:
74
+ raise ValueError("at least one relative resource name is required")
75
+ result = []
76
+ for value in parts:
77
+ part = os.fspath(value)
78
+ if (
79
+ not part
80
+ or part in {".", ".."}
81
+ or os.path.isabs(part)
82
+ or "/" in part
83
+ or "\\" in part
84
+ ):
85
+ raise ValueError(f"invalid resource path component: {part!r}")
86
+ result.append(part)
87
+ return tuple(result)
88
+
89
+
90
+ def resource(*parts: Union[str, os.PathLike[str]]) -> Traversable:
91
+ """Return one packaged resource.
92
+
93
+ Each argument must be one relative path component. For example,
94
+ ``resource("Full3d", "zzdb.info")`` returns the PALP metadata file.
95
+ """
96
+
97
+ target = data_root().joinpath(*_resource_parts(parts))
98
+ if not (target.is_file() or target.is_dir()):
99
+ raise FileNotFoundError("/".join(os.fspath(part) for part in parts))
100
+ return target
101
+
102
+
103
+ def open_resource(
104
+ *parts: Union[str, os.PathLike[str]],
105
+ mode: str = "rb",
106
+ encoding: str | None = None,
107
+ errors: str | None = None,
108
+ newline: str | None = None,
109
+ ) -> IO:
110
+ """Open a packaged resource for reading.
111
+
112
+ Text mode defaults to UTF-8. Write and update modes are rejected because
113
+ installed package resources are immutable.
114
+ """
115
+
116
+ if any(flag in mode for flag in "wax+") or "r" not in mode:
117
+ raise ValueError("package resources can only be opened for reading")
118
+ target = resource(*parts)
119
+ if not target.is_file():
120
+ raise IsADirectoryError("/".join(os.fspath(part) for part in parts))
121
+ if "b" in mode:
122
+ if any(value is not None for value in (encoding, errors, newline)):
123
+ raise ValueError("encoding, errors, and newline require text mode")
124
+ return target.open(mode)
125
+ return target.open(
126
+ mode,
127
+ encoding=encoding or "utf-8",
128
+ errors=errors,
129
+ newline=newline,
130
+ )
131
+
132
+
133
+ def _copy_directory(source: Traversable, destination: Path) -> None:
134
+ destination.mkdir()
135
+ for child in source.iterdir():
136
+ output = destination / child.name
137
+ if child.is_dir():
138
+ _copy_directory(child, output)
139
+ elif child.is_file():
140
+ with child.open("rb") as input_stream, output.open("wb") as output_stream:
141
+ shutil.copyfileobj(input_stream, output_stream)
142
+
143
+
144
+ @contextmanager
145
+ def resource_path(*parts: Union[str, os.PathLike[str]]) -> Iterator[Path]:
146
+ """Yield a real filesystem path for a packaged file or directory.
147
+
148
+ Keep the context open while using the path. A temporary copy is created
149
+ when an import loader does not expose resources directly on the filesystem.
150
+ """
151
+
152
+ target = resource(*parts)
153
+ if isinstance(target, Path):
154
+ yield target
155
+ return
156
+ if target.is_file():
157
+ with resources.as_file(target) as path:
158
+ yield path
159
+ return
160
+ with TemporaryDirectory(prefix="polytope-databases-") as temporary:
161
+ path = Path(temporary) / target.name
162
+ _copy_directory(target, path)
163
+ yield path
164
+
165
+
166
+ def _dimension(value: object) -> int:
167
+ if isinstance(value, bool):
168
+ raise ValueError("dimension must be 2 or 3")
169
+ try:
170
+ dimension = operator.index(value) # type: ignore[arg-type]
171
+ except TypeError as error:
172
+ raise ValueError("dimension must be 2 or 3") from error
173
+ if dimension not in (2, 3):
174
+ raise ValueError("dimension must be 2 or 3")
175
+ return dimension
176
+
177
+
178
+ def reflexive_polytopes(dim: object) -> Traversable:
179
+ """Return the plain-text reflexive-polytope catalogue for dimension 2 or 3."""
180
+
181
+ return resource(f"reflexive_polytopes_{_dimension(dim)}d")
182
+
183
+
184
+ def open_reflexive_polytopes(dim: object, *, encoding: str = "ascii") -> IO:
185
+ """Open a reflexive-polytope catalogue as a text stream."""
186
+
187
+ return open_resource(
188
+ f"reflexive_polytopes_{_dimension(dim)}d", mode="r", encoding=encoding
189
+ )
190
+
191
+
192
+ @contextmanager
193
+ def reflexive_polytopes_path(dim: object) -> Iterator[Path]:
194
+ """Yield a real filesystem path to a plain-text polytope catalogue."""
195
+
196
+ with resource_path(f"reflexive_polytopes_{_dimension(dim)}d") as path:
197
+ yield path
198
+
199
+
200
+ def palp_database(dim: object) -> Traversable:
201
+ """Return the PALP database directory for dimension 2 or 3."""
202
+
203
+ return resource(f"Full{_dimension(dim)}d")
204
+
205
+
206
+ @contextmanager
207
+ def palp_database_path(dim: object) -> Iterator[Path]:
208
+ """Yield a real filesystem path to a PALP database directory."""
209
+
210
+ with resource_path(f"Full{_dimension(dim)}d") as path:
211
+ yield path
212
+
213
+
214
+ def verify_data() -> None:
215
+ """Raise an exception unless all packaged data matches the release manifest."""
216
+
217
+ actual_files = []
218
+ for directory in ("Full2d", "Full3d"):
219
+ actual_files.extend(
220
+ f"{directory}/{item.name}"
221
+ for item in resource(directory).iterdir()
222
+ if item.is_file()
223
+ )
224
+ actual_files.extend(
225
+ name for name in ("reflexive_polytopes_2d", "reflexive_polytopes_3d")
226
+ if resource(name).is_file()
227
+ )
228
+ if tuple(sorted(actual_files)) != tuple(sorted(DATA_FILES)):
229
+ raise RuntimeError("packaged data file manifest does not match DATA_FILES")
230
+ for name, expected in DATA_SHA256.items():
231
+ digest = hashlib.sha256(resource(*name.split("/")).read_bytes()).hexdigest()
232
+ if digest != expected:
233
+ raise RuntimeError(f"checksum mismatch for {name}: {digest}")
234
+
235
+
236
+ __all__ = [
237
+ "DATA_FILES",
238
+ "DATA_SHA256",
239
+ "data_root",
240
+ "open_reflexive_polytopes",
241
+ "open_resource",
242
+ "palp_database",
243
+ "palp_database_path",
244
+ "reflexive_polytopes",
245
+ "reflexive_polytopes_path",
246
+ "resource",
247
+ "resource_path",
248
+ "verify_data",
249
+ ]
@@ -0,0 +1,10 @@
1
+ 2 4 6 3 5 10 4 0 20 0 0 0 0
2
+
3
+ 3 2
4
+ 1 1 2 2
5
+ 4 1
6
+ 2 4
7
+ 5 1
8
+ 2 2
9
+ 6 1
10
+ 3 1
Binary file
Binary file
@@ -0,0 +1 @@
1
+ �d
@@ -0,0 +1 @@
1
+ \Na
@@ -0,0 +1,22 @@
1
+ 3 10 13 10 43 2199 79 0 11549 0 0 0 0
2
+
3
+ 4 4
4
+ 2 8 3 5 4 11 5 3
5
+ 5 5
6
+ 2 1 3 82 4 43 5 34 6 2
7
+ 6 6
8
+ 3 45 4 149 5 142 6 45 7 3 8 1
9
+ 7 6
10
+ 3 14 4 129 5 310 6 85 7 22 8 5
11
+ 8 5
12
+ 4 34 5 163 6 269 7 48 8 18
13
+ 9 5
14
+ 5 48 6 215 7 63 8 26 9 1
15
+ 10 6
16
+ 5 50 6 58 7 4 8 13 9 7 10 1
17
+ 11 3
18
+ 6 22 7 12 8 1
19
+ 12 2
20
+ 6 4 7 1
21
+ 13 1
22
+ 7 2
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1 @@
1
+ �aq����Ǝ�!���b������"\o�Q��ǐ�Ŀ��B�4�1���[����*�� -�� ��� ψ� �e5� �y��o�n6[�n,�.o��K����^}�|�에3=s�M�|e(��*
@@ -0,0 +1 @@
1
+ O/�6�1���|%P��j{ywx`����Swx(}�
@@ -0,0 +1 @@
1
+ �D���8lP�e�
@@ -0,0 +1,80 @@
1
+ 3 2
2
+ 1 0
3
+ 0 1
4
+ -1 -1
5
+ 3 2
6
+ 1 0
7
+ 0 1
8
+ -2 -1
9
+ 4 2
10
+ 1 0
11
+ -1 0
12
+ 0 1
13
+ 1 -1
14
+ 4 2
15
+ 1 0
16
+ 0 1
17
+ 0 -1
18
+ -1 0
19
+ 4 2
20
+ 1 0
21
+ 0 1
22
+ -1 -1
23
+ -1 1
24
+ 5 2
25
+ 1 0
26
+ 0 1
27
+ 0 -1
28
+ -1 0
29
+ 1 1
30
+ 3 2
31
+ 1 0
32
+ 0 1
33
+ -3 -2
34
+ 4 2
35
+ 1 0
36
+ 0 1
37
+ 0 -1
38
+ -2 1
39
+ 5 2
40
+ 1 0
41
+ 0 1
42
+ 0 -1
43
+ -1 1
44
+ -1 -1
45
+ 6 2
46
+ 1 0
47
+ 0 1
48
+ 1 -1
49
+ -1 1
50
+ 0 -1
51
+ -1 0
52
+ 4 2
53
+ 1 0
54
+ 0 1
55
+ -1 1
56
+ -1 -2
57
+ 5 2
58
+ 1 0
59
+ 0 1
60
+ -1 1
61
+ 1 -1
62
+ -1 -1
63
+ 3 2
64
+ 1 0
65
+ 1 2
66
+ -3 -2
67
+ 4 2
68
+ 1 0
69
+ 0 1
70
+ -2 1
71
+ 1 -2
72
+ 4 2
73
+ 1 0
74
+ 1 2
75
+ -1 -2
76
+ -1 0
77
+ 3 2
78
+ 1 0
79
+ 1 3
80
+ -2 -3