llnl-ssapy-data 0.1.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018, Lawrence Livermore National Security, LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,7 @@
1
+ include LICENSE
2
+ include NOTICE
3
+ include README.rst
4
+ include src/ssapy_data/manifest.json
5
+ graft src/ssapy_data/data
6
+ prune **/__pycache__
7
+ global-exclude *.py[cod]
@@ -0,0 +1,7 @@
1
+ This work was produced under the auspices of the U.S. Department of Energy by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344.
2
+
3
+ This work was prepared as an account of work sponsored by an agency of the United States Government. Neither the United States Government nor Lawrence Livermore National Security, LLC, nor any of their employees makes any warranty, expressed or implied, or assumes any legal liability or responsibility for the accuracy, completeness, or usefulness of any information, apparatus, product, or process disclosed, or represents that its use would not infringe privately owned rights.
4
+
5
+ Reference herein to any specific commercial product, process, or service by trade name, trademark, manufacturer, or otherwise does not necessarily constitute or imply its endorsement, recommendation, or favoring by the United States Government or Lawrence Livermore National Security, LLC.
6
+
7
+ The views and opinions of authors expressed herein do not necessarily state or reflect those of the United States Government or Lawrence Livermore National Security, LLC, and shall not be used for advertising or product endorsement purposes.
@@ -0,0 +1,162 @@
1
+ Metadata-Version: 2.4
2
+ Name: llnl-ssapy-data
3
+ Version: 0.1.0
4
+ Summary: Packaged data resources for SSAPy and SSAPy Toolkit
5
+ Author-email: LLNL SSAPy Software Team <yeagerastro@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/llnl/SSAPy-Data
8
+ Project-URL: Repository, https://github.com/llnl/SSAPy-Data
9
+ Project-URL: Issues, https://github.com/llnl/SSAPy-Data/issues
10
+ Keywords: ssapy,astrodynamics,orbital-mechanics,data
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/x-rst
23
+ License-File: LICENSE
24
+ License-File: NOTICE
25
+ Provides-Extra: dev
26
+ Requires-Dist: build; extra == "dev"
27
+ Requires-Dist: pytest; extra == "dev"
28
+ Requires-Dist: twine; extra == "dev"
29
+ Dynamic: license-file
30
+
31
+ SSAPy-Data
32
+ ==========
33
+
34
+ SSAPy-Data stores reusable data resources for `SSAPy <https://github.com/llnl/SSAPy>`_
35
+ and `SSAPy Toolkit <https://github.com/llnl/SSAPy-Toolkit>`_. The repository is
36
+ packaged as the ``llnl-ssapy-data`` Python distribution and exposes the
37
+ ``ssapy_data`` import package. Data files live under ``src/ssapy_data/data`` so
38
+ users can receive required data through normal ``pip`` installation without Git
39
+ LFS, git submodules, or runtime GitHub downloads.
40
+
41
+ The initial package intentionally does not duplicate data already packaged by
42
+ base SSAPy. New SSAPy Toolkit datasets should be added here when they are needed
43
+ by toolkit functions and are not already available from the base ``llnl-ssapy``
44
+ wheel.
45
+
46
+ Installation
47
+ ------------
48
+
49
+ Install from a local clone in editable mode:
50
+
51
+ .. code-block:: bash
52
+
53
+ pip install -e .
54
+
55
+ Build the wheel and source distribution:
56
+
57
+ .. code-block:: bash
58
+
59
+ python -m build
60
+ ls -lh dist/
61
+
62
+ Using packaged data
63
+ -------------------
64
+
65
+ Access packaged data with ``importlib.resources`` helpers exposed by
66
+ ``ssapy_data``:
67
+
68
+ .. code-block:: python
69
+
70
+ from ssapy_data import data_path, read_text
71
+
72
+ gravity_header = read_text("egm84.egm")
73
+
74
+ with data_path("Earth_graphics/ne_50m_ocean.shp") as path:
75
+ print(path)
76
+
77
+ ``data_path`` yields a real filesystem path for libraries that require paths.
78
+ Use the path only inside the context manager because zipped wheels may extract
79
+ resources to temporary locations.
80
+
81
+ Adding data
82
+ -----------
83
+
84
+ Add new reusable data below ``src/ssapy_data/data``. Preserve source filenames
85
+ when possible, and use subdirectories when a dataset has multiple sidecar files.
86
+ Do not add files already packaged by base SSAPy unless a later migration
87
+ explicitly moves that dependency here.
88
+ After adding, replacing, or removing data, regenerate the manifest:
89
+
90
+ .. code-block:: bash
91
+
92
+ python scripts/update_manifest.py
93
+ python -m pytest
94
+ python -m build
95
+
96
+ The manifest records each packaged file path, byte count, and SHA-256 digest in
97
+ ``src/ssapy_data/manifest.json``. Pull requests that change data should also
98
+ update the source/provenance notes in this README when the dataset source or
99
+ license differs from the existing entries.
100
+
101
+ Size guidance
102
+ -------------
103
+
104
+ The initial wheel contains only the package helpers and a data-directory README.
105
+ Before adding large datasets, estimate the built wheel size with:
106
+
107
+ .. code-block:: bash
108
+
109
+ python -m build --wheel
110
+ ls -lh dist/*.whl
111
+
112
+ If a future dataset pushes the wheel above PyPI limits, split the data into a
113
+ separate companion package rather than using Git LFS in SSAPy Toolkit.
114
+
115
+ Publishing
116
+ ----------
117
+
118
+ The repository publishes ``llnl-ssapy-data`` to PyPI through GitHub Actions and
119
+ PyPI trusted publishing. Configure PyPI before creating the first release:
120
+
121
+ * Create a PyPI trusted publisher, or pending publisher, for project
122
+ ``llnl-ssapy-data``.
123
+ * Set the owner to ``llnl`` and repository to ``SSAPy-Data``.
124
+ * Set the workflow filename to ``publish.yml``.
125
+ * Set the GitHub environment to ``pypi``.
126
+
127
+ After PyPI trust is configured, publish by creating a GitHub release whose tag
128
+ matches the version in ``pyproject.toml``, for example ``v0.1.0``. The
129
+ ``Publish to PyPI`` workflow builds a clean wheel and source distribution, runs
130
+ tests, checks the manifest, and uploads through OpenID Connect (OIDC). No PyPI
131
+ API token is required.
132
+
133
+ Data provenance
134
+ ---------------
135
+
136
+ Each data pull request should document the source URL, license, retrieval date,
137
+ and any preprocessing steps for new packaged datasets. Candidate sources include:
138
+
139
+ * Earth gravity fields:
140
+ `ICGEM time-variable gravity fields <http://icgem.gfz-potsdam.de/tom_longtime>`_
141
+ * Other celestial bodies:
142
+ `ICGEM celestial gravity fields <http://icgem.gfz-potsdam.de/tom_celestial>`_
143
+
144
+ Code of Conduct
145
+ ---------------
146
+
147
+ Please note that SSAPy-Data has a
148
+ `Code of Conduct <https://github.com/LLNL/SSAPy-Data/blob/main/CODE_OF_CONDUCT.md>`_.
149
+ By participating in the SSAPy-Data community, you agree to abide by its rules.
150
+
151
+ License
152
+ -------
153
+
154
+ SSAPy-Data is distributed under the terms of the MIT license. All new
155
+ contributions must be made under the MIT license.
156
+
157
+ See the `license <https://github.com/LLNL/SSAPy-Data/blob/main/LICENSE>`_ and
158
+ `NOTICE <https://github.com/LLNL/SSAPy-Data/blob/main/NOTICE>`_ for details.
159
+
160
+ SPDX-License-Identifier: MIT
161
+
162
+ LLNL-CODE-862420
@@ -0,0 +1,132 @@
1
+ SSAPy-Data
2
+ ==========
3
+
4
+ SSAPy-Data stores reusable data resources for `SSAPy <https://github.com/llnl/SSAPy>`_
5
+ and `SSAPy Toolkit <https://github.com/llnl/SSAPy-Toolkit>`_. The repository is
6
+ packaged as the ``llnl-ssapy-data`` Python distribution and exposes the
7
+ ``ssapy_data`` import package. Data files live under ``src/ssapy_data/data`` so
8
+ users can receive required data through normal ``pip`` installation without Git
9
+ LFS, git submodules, or runtime GitHub downloads.
10
+
11
+ The initial package intentionally does not duplicate data already packaged by
12
+ base SSAPy. New SSAPy Toolkit datasets should be added here when they are needed
13
+ by toolkit functions and are not already available from the base ``llnl-ssapy``
14
+ wheel.
15
+
16
+ Installation
17
+ ------------
18
+
19
+ Install from a local clone in editable mode:
20
+
21
+ .. code-block:: bash
22
+
23
+ pip install -e .
24
+
25
+ Build the wheel and source distribution:
26
+
27
+ .. code-block:: bash
28
+
29
+ python -m build
30
+ ls -lh dist/
31
+
32
+ Using packaged data
33
+ -------------------
34
+
35
+ Access packaged data with ``importlib.resources`` helpers exposed by
36
+ ``ssapy_data``:
37
+
38
+ .. code-block:: python
39
+
40
+ from ssapy_data import data_path, read_text
41
+
42
+ gravity_header = read_text("egm84.egm")
43
+
44
+ with data_path("Earth_graphics/ne_50m_ocean.shp") as path:
45
+ print(path)
46
+
47
+ ``data_path`` yields a real filesystem path for libraries that require paths.
48
+ Use the path only inside the context manager because zipped wheels may extract
49
+ resources to temporary locations.
50
+
51
+ Adding data
52
+ -----------
53
+
54
+ Add new reusable data below ``src/ssapy_data/data``. Preserve source filenames
55
+ when possible, and use subdirectories when a dataset has multiple sidecar files.
56
+ Do not add files already packaged by base SSAPy unless a later migration
57
+ explicitly moves that dependency here.
58
+ After adding, replacing, or removing data, regenerate the manifest:
59
+
60
+ .. code-block:: bash
61
+
62
+ python scripts/update_manifest.py
63
+ python -m pytest
64
+ python -m build
65
+
66
+ The manifest records each packaged file path, byte count, and SHA-256 digest in
67
+ ``src/ssapy_data/manifest.json``. Pull requests that change data should also
68
+ update the source/provenance notes in this README when the dataset source or
69
+ license differs from the existing entries.
70
+
71
+ Size guidance
72
+ -------------
73
+
74
+ The initial wheel contains only the package helpers and a data-directory README.
75
+ Before adding large datasets, estimate the built wheel size with:
76
+
77
+ .. code-block:: bash
78
+
79
+ python -m build --wheel
80
+ ls -lh dist/*.whl
81
+
82
+ If a future dataset pushes the wheel above PyPI limits, split the data into a
83
+ separate companion package rather than using Git LFS in SSAPy Toolkit.
84
+
85
+ Publishing
86
+ ----------
87
+
88
+ The repository publishes ``llnl-ssapy-data`` to PyPI through GitHub Actions and
89
+ PyPI trusted publishing. Configure PyPI before creating the first release:
90
+
91
+ * Create a PyPI trusted publisher, or pending publisher, for project
92
+ ``llnl-ssapy-data``.
93
+ * Set the owner to ``llnl`` and repository to ``SSAPy-Data``.
94
+ * Set the workflow filename to ``publish.yml``.
95
+ * Set the GitHub environment to ``pypi``.
96
+
97
+ After PyPI trust is configured, publish by creating a GitHub release whose tag
98
+ matches the version in ``pyproject.toml``, for example ``v0.1.0``. The
99
+ ``Publish to PyPI`` workflow builds a clean wheel and source distribution, runs
100
+ tests, checks the manifest, and uploads through OpenID Connect (OIDC). No PyPI
101
+ API token is required.
102
+
103
+ Data provenance
104
+ ---------------
105
+
106
+ Each data pull request should document the source URL, license, retrieval date,
107
+ and any preprocessing steps for new packaged datasets. Candidate sources include:
108
+
109
+ * Earth gravity fields:
110
+ `ICGEM time-variable gravity fields <http://icgem.gfz-potsdam.de/tom_longtime>`_
111
+ * Other celestial bodies:
112
+ `ICGEM celestial gravity fields <http://icgem.gfz-potsdam.de/tom_celestial>`_
113
+
114
+ Code of Conduct
115
+ ---------------
116
+
117
+ Please note that SSAPy-Data has a
118
+ `Code of Conduct <https://github.com/LLNL/SSAPy-Data/blob/main/CODE_OF_CONDUCT.md>`_.
119
+ By participating in the SSAPy-Data community, you agree to abide by its rules.
120
+
121
+ License
122
+ -------
123
+
124
+ SSAPy-Data is distributed under the terms of the MIT license. All new
125
+ contributions must be made under the MIT license.
126
+
127
+ See the `license <https://github.com/LLNL/SSAPy-Data/blob/main/LICENSE>`_ and
128
+ `NOTICE <https://github.com/LLNL/SSAPy-Data/blob/main/NOTICE>`_ for details.
129
+
130
+ SPDX-License-Identifier: MIT
131
+
132
+ LLNL-CODE-862420
@@ -0,0 +1,53 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "llnl-ssapy-data"
7
+ version = "0.1.0"
8
+ description = "Packaged data resources for SSAPy and SSAPy Toolkit"
9
+ readme = "README.rst"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE", "NOTICE"]
13
+ authors = [
14
+ { name = "LLNL SSAPy Software Team", email = "yeagerastro@gmail.com" },
15
+ ]
16
+ keywords = ["ssapy", "astrodynamics", "orbital-mechanics", "data"]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Intended Audience :: Science/Research",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3 :: Only",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Topic :: Scientific/Engineering :: Astronomy",
28
+ ]
29
+
30
+ dependencies = []
31
+
32
+ [project.optional-dependencies]
33
+ dev = [
34
+ "build",
35
+ "pytest",
36
+ "twine",
37
+ ]
38
+
39
+ [project.urls]
40
+ Homepage = "https://github.com/llnl/SSAPy-Data"
41
+ Repository = "https://github.com/llnl/SSAPy-Data"
42
+ Issues = "https://github.com/llnl/SSAPy-Data/issues"
43
+
44
+ [tool.setuptools]
45
+ package-dir = { "" = "src" }
46
+ packages = { find = { where = ["src"] } }
47
+ include-package-data = true
48
+
49
+ [tool.setuptools.package-data]
50
+ ssapy_data = ["manifest.json", "data/*", "data/**/*"]
51
+
52
+ [tool.pytest.ini_options]
53
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,162 @@
1
+ Metadata-Version: 2.4
2
+ Name: llnl-ssapy-data
3
+ Version: 0.1.0
4
+ Summary: Packaged data resources for SSAPy and SSAPy Toolkit
5
+ Author-email: LLNL SSAPy Software Team <yeagerastro@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/llnl/SSAPy-Data
8
+ Project-URL: Repository, https://github.com/llnl/SSAPy-Data
9
+ Project-URL: Issues, https://github.com/llnl/SSAPy-Data/issues
10
+ Keywords: ssapy,astrodynamics,orbital-mechanics,data
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/x-rst
23
+ License-File: LICENSE
24
+ License-File: NOTICE
25
+ Provides-Extra: dev
26
+ Requires-Dist: build; extra == "dev"
27
+ Requires-Dist: pytest; extra == "dev"
28
+ Requires-Dist: twine; extra == "dev"
29
+ Dynamic: license-file
30
+
31
+ SSAPy-Data
32
+ ==========
33
+
34
+ SSAPy-Data stores reusable data resources for `SSAPy <https://github.com/llnl/SSAPy>`_
35
+ and `SSAPy Toolkit <https://github.com/llnl/SSAPy-Toolkit>`_. The repository is
36
+ packaged as the ``llnl-ssapy-data`` Python distribution and exposes the
37
+ ``ssapy_data`` import package. Data files live under ``src/ssapy_data/data`` so
38
+ users can receive required data through normal ``pip`` installation without Git
39
+ LFS, git submodules, or runtime GitHub downloads.
40
+
41
+ The initial package intentionally does not duplicate data already packaged by
42
+ base SSAPy. New SSAPy Toolkit datasets should be added here when they are needed
43
+ by toolkit functions and are not already available from the base ``llnl-ssapy``
44
+ wheel.
45
+
46
+ Installation
47
+ ------------
48
+
49
+ Install from a local clone in editable mode:
50
+
51
+ .. code-block:: bash
52
+
53
+ pip install -e .
54
+
55
+ Build the wheel and source distribution:
56
+
57
+ .. code-block:: bash
58
+
59
+ python -m build
60
+ ls -lh dist/
61
+
62
+ Using packaged data
63
+ -------------------
64
+
65
+ Access packaged data with ``importlib.resources`` helpers exposed by
66
+ ``ssapy_data``:
67
+
68
+ .. code-block:: python
69
+
70
+ from ssapy_data import data_path, read_text
71
+
72
+ gravity_header = read_text("egm84.egm")
73
+
74
+ with data_path("Earth_graphics/ne_50m_ocean.shp") as path:
75
+ print(path)
76
+
77
+ ``data_path`` yields a real filesystem path for libraries that require paths.
78
+ Use the path only inside the context manager because zipped wheels may extract
79
+ resources to temporary locations.
80
+
81
+ Adding data
82
+ -----------
83
+
84
+ Add new reusable data below ``src/ssapy_data/data``. Preserve source filenames
85
+ when possible, and use subdirectories when a dataset has multiple sidecar files.
86
+ Do not add files already packaged by base SSAPy unless a later migration
87
+ explicitly moves that dependency here.
88
+ After adding, replacing, or removing data, regenerate the manifest:
89
+
90
+ .. code-block:: bash
91
+
92
+ python scripts/update_manifest.py
93
+ python -m pytest
94
+ python -m build
95
+
96
+ The manifest records each packaged file path, byte count, and SHA-256 digest in
97
+ ``src/ssapy_data/manifest.json``. Pull requests that change data should also
98
+ update the source/provenance notes in this README when the dataset source or
99
+ license differs from the existing entries.
100
+
101
+ Size guidance
102
+ -------------
103
+
104
+ The initial wheel contains only the package helpers and a data-directory README.
105
+ Before adding large datasets, estimate the built wheel size with:
106
+
107
+ .. code-block:: bash
108
+
109
+ python -m build --wheel
110
+ ls -lh dist/*.whl
111
+
112
+ If a future dataset pushes the wheel above PyPI limits, split the data into a
113
+ separate companion package rather than using Git LFS in SSAPy Toolkit.
114
+
115
+ Publishing
116
+ ----------
117
+
118
+ The repository publishes ``llnl-ssapy-data`` to PyPI through GitHub Actions and
119
+ PyPI trusted publishing. Configure PyPI before creating the first release:
120
+
121
+ * Create a PyPI trusted publisher, or pending publisher, for project
122
+ ``llnl-ssapy-data``.
123
+ * Set the owner to ``llnl`` and repository to ``SSAPy-Data``.
124
+ * Set the workflow filename to ``publish.yml``.
125
+ * Set the GitHub environment to ``pypi``.
126
+
127
+ After PyPI trust is configured, publish by creating a GitHub release whose tag
128
+ matches the version in ``pyproject.toml``, for example ``v0.1.0``. The
129
+ ``Publish to PyPI`` workflow builds a clean wheel and source distribution, runs
130
+ tests, checks the manifest, and uploads through OpenID Connect (OIDC). No PyPI
131
+ API token is required.
132
+
133
+ Data provenance
134
+ ---------------
135
+
136
+ Each data pull request should document the source URL, license, retrieval date,
137
+ and any preprocessing steps for new packaged datasets. Candidate sources include:
138
+
139
+ * Earth gravity fields:
140
+ `ICGEM time-variable gravity fields <http://icgem.gfz-potsdam.de/tom_longtime>`_
141
+ * Other celestial bodies:
142
+ `ICGEM celestial gravity fields <http://icgem.gfz-potsdam.de/tom_celestial>`_
143
+
144
+ Code of Conduct
145
+ ---------------
146
+
147
+ Please note that SSAPy-Data has a
148
+ `Code of Conduct <https://github.com/LLNL/SSAPy-Data/blob/main/CODE_OF_CONDUCT.md>`_.
149
+ By participating in the SSAPy-Data community, you agree to abide by its rules.
150
+
151
+ License
152
+ -------
153
+
154
+ SSAPy-Data is distributed under the terms of the MIT license. All new
155
+ contributions must be made under the MIT license.
156
+
157
+ See the `license <https://github.com/LLNL/SSAPy-Data/blob/main/LICENSE>`_ and
158
+ `NOTICE <https://github.com/LLNL/SSAPy-Data/blob/main/NOTICE>`_ for details.
159
+
160
+ SPDX-License-Identifier: MIT
161
+
162
+ LLNL-CODE-862420
@@ -0,0 +1,16 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ NOTICE
4
+ README.rst
5
+ pyproject.toml
6
+ src/llnl_ssapy_data.egg-info/PKG-INFO
7
+ src/llnl_ssapy_data.egg-info/SOURCES.txt
8
+ src/llnl_ssapy_data.egg-info/dependency_links.txt
9
+ src/llnl_ssapy_data.egg-info/requires.txt
10
+ src/llnl_ssapy_data.egg-info/top_level.txt
11
+ src/ssapy_data/__init__.py
12
+ src/ssapy_data/_manifest.py
13
+ src/ssapy_data/_resources.py
14
+ src/ssapy_data/manifest.json
15
+ src/ssapy_data/data/README.md
16
+ tests/test_package_data.py
@@ -0,0 +1,5 @@
1
+
2
+ [dev]
3
+ build
4
+ pytest
5
+ twine
@@ -0,0 +1,30 @@
1
+ """Packaged data resources for SSAPy and SSAPy Toolkit."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from ._manifest import manifest, manifest_entries
6
+ from ._resources import (
7
+ DataResourceNotFoundError,
8
+ data_path,
9
+ data_resource,
10
+ iter_data_files,
11
+ open_binary,
12
+ open_text,
13
+ read_binary,
14
+ read_text,
15
+ )
16
+
17
+ __version__ = "0.1.0"
18
+
19
+ __all__ = [
20
+ "DataResourceNotFoundError",
21
+ "data_path",
22
+ "data_resource",
23
+ "iter_data_files",
24
+ "manifest",
25
+ "manifest_entries",
26
+ "open_binary",
27
+ "open_text",
28
+ "read_binary",
29
+ "read_text",
30
+ ]
@@ -0,0 +1,23 @@
1
+ """Manifest helpers for packaged SSAPy data."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from importlib.resources import files
7
+ from typing import Any
8
+
9
+ PACKAGE = "ssapy_data"
10
+ MANIFEST_NAME = "manifest.json"
11
+
12
+
13
+ def manifest() -> dict[str, Any]:
14
+ """Return the packaged data manifest."""
15
+
16
+ resource = files(PACKAGE).joinpath(MANIFEST_NAME)
17
+ return json.loads(resource.read_text(encoding="utf-8"))
18
+
19
+
20
+ def manifest_entries() -> list[dict[str, Any]]:
21
+ """Return file entries from the packaged data manifest."""
22
+
23
+ return list(manifest()["files"])
@@ -0,0 +1,165 @@
1
+ """Resource helpers for data packaged in ``ssapy_data`` wheels."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from contextlib import contextmanager
6
+ from importlib.resources import as_file, files
7
+ try:
8
+ from importlib.resources.abc import Traversable
9
+ except ImportError: # Python 3.10
10
+ from importlib.abc import Traversable
11
+ from os import PathLike
12
+ from pathlib import Path, PurePosixPath
13
+ from typing import Iterator
14
+
15
+ DATA_ROOT = "data"
16
+ PACKAGE = "ssapy_data"
17
+
18
+
19
+ class DataResourceNotFoundError(FileNotFoundError):
20
+ """Raised when a requested packaged data resource is absent."""
21
+
22
+
23
+ def data_resource(
24
+ relative_path: str | PathLike[str] = "",
25
+ *,
26
+ data_root: str | PathLike[str] = DATA_ROOT,
27
+ must_exist: bool = True,
28
+ ) -> Traversable:
29
+ """Return an ``importlib.resources`` object for packaged SSAPy data.
30
+
31
+ Parameters
32
+ ----------
33
+ relative_path
34
+ POSIX-style path below ``data_root``. Absolute paths and ``..`` traversal
35
+ are rejected.
36
+ data_root
37
+ Directory inside ``ssapy_data`` that contains data resources.
38
+ must_exist
39
+ If ``True``, raise :class:`DataResourceNotFoundError` when the resource
40
+ is missing.
41
+ """
42
+
43
+ resource = files(PACKAGE)
44
+ for part in _safe_parts(data_root):
45
+ resource = resource.joinpath(part)
46
+ for part in _safe_parts(relative_path):
47
+ resource = resource.joinpath(part)
48
+
49
+ if must_exist and not resource.exists():
50
+ requested = _display_path(data_root, relative_path)
51
+ raise DataResourceNotFoundError(
52
+ f"Data resource '{requested}' was not found in package '{PACKAGE}'."
53
+ )
54
+
55
+ return resource
56
+
57
+
58
+ @contextmanager
59
+ def data_path(
60
+ relative_path: str | PathLike[str],
61
+ *,
62
+ data_root: str | PathLike[str] = DATA_ROOT,
63
+ ) -> Iterator[Path]:
64
+ """Yield a filesystem path for a packaged data file.
65
+
66
+ Use this when a downstream library requires a real path instead of a file
67
+ object. The yielded path may be a temporary extraction path for zipped wheels,
68
+ so callers should use it only inside the context manager.
69
+ """
70
+
71
+ resource = data_resource(relative_path, data_root=data_root)
72
+ if not resource.is_file():
73
+ requested = _display_path(data_root, relative_path)
74
+ raise DataResourceNotFoundError(f"Data resource '{requested}' is not a file.")
75
+
76
+ with as_file(resource) as path:
77
+ yield path
78
+
79
+
80
+ @contextmanager
81
+ def open_binary(relative_path: str | PathLike[str], *, data_root: str | PathLike[str] = DATA_ROOT):
82
+ """Open a packaged data file in binary mode."""
83
+
84
+ resource = data_resource(relative_path, data_root=data_root)
85
+ if not resource.is_file():
86
+ requested = _display_path(data_root, relative_path)
87
+ raise DataResourceNotFoundError(f"Data resource '{requested}' is not a file.")
88
+
89
+ with resource.open("rb") as file_handle:
90
+ yield file_handle
91
+
92
+
93
+ @contextmanager
94
+ def open_text(
95
+ relative_path: str | PathLike[str],
96
+ *,
97
+ data_root: str | PathLike[str] = DATA_ROOT,
98
+ encoding: str = "utf-8",
99
+ ):
100
+ """Open a packaged data file in text mode."""
101
+
102
+ resource = data_resource(relative_path, data_root=data_root)
103
+ if not resource.is_file():
104
+ requested = _display_path(data_root, relative_path)
105
+ raise DataResourceNotFoundError(f"Data resource '{requested}' is not a file.")
106
+
107
+ with resource.open("r", encoding=encoding) as file_handle:
108
+ yield file_handle
109
+
110
+
111
+ def read_binary(relative_path: str | PathLike[str], *, data_root: str | PathLike[str] = DATA_ROOT) -> bytes:
112
+ """Read a packaged binary data file."""
113
+
114
+ with open_binary(relative_path, data_root=data_root) as file_handle:
115
+ return file_handle.read()
116
+
117
+
118
+ def read_text(
119
+ relative_path: str | PathLike[str],
120
+ *,
121
+ data_root: str | PathLike[str] = DATA_ROOT,
122
+ encoding: str = "utf-8",
123
+ ) -> str:
124
+ """Read a packaged text data file."""
125
+
126
+ with open_text(relative_path, data_root=data_root, encoding=encoding) as file_handle:
127
+ return file_handle.read()
128
+
129
+
130
+ def iter_data_files(relative_path: str | PathLike[str] = "") -> Iterator[Traversable]:
131
+ """Yield packaged data files recursively below ``relative_path``."""
132
+
133
+ root = data_resource(relative_path)
134
+ if root.is_file():
135
+ yield root
136
+ return
137
+
138
+ for child in sorted(root.iterdir(), key=lambda item: item.name):
139
+ if child.is_file():
140
+ yield child
141
+ elif child.is_dir():
142
+ child_relative = _display_path(relative_path, child.name)
143
+ yield from iter_data_files(child_relative)
144
+
145
+
146
+ def _safe_parts(path: str | PathLike[str]) -> tuple[str, ...]:
147
+ path_string = str(path)
148
+ if path_string in {"", "."}:
149
+ return ()
150
+
151
+ pure_path = PurePosixPath(path_string)
152
+ if pure_path.is_absolute():
153
+ raise ValueError(f"Packaged data paths must be relative, got '{path_string}'.")
154
+
155
+ parts = tuple(part for part in pure_path.parts if part not in {"", "."})
156
+ if ".." in parts:
157
+ raise ValueError(f"Packaged data paths cannot contain '..', got '{path_string}'.")
158
+ return parts
159
+
160
+
161
+ def _display_path(*paths: str | PathLike[str]) -> str:
162
+ parts: list[str] = []
163
+ for path in paths:
164
+ parts.extend(_safe_parts(path))
165
+ return "/".join(parts)
@@ -0,0 +1,9 @@
1
+ # SSAPy Data Payload Directory
2
+
3
+ Add new reusable datasets for SSAPy Toolkit under this directory. Do not add data already packaged by base SSAPy unless a later migration explicitly moves that dependency here.
4
+
5
+ After changing files here, run:
6
+
7
+ ```bash
8
+ python scripts/update_manifest.py
9
+ ```
@@ -0,0 +1,12 @@
1
+ {
2
+ "data_root": "data",
3
+ "files": [
4
+ {
5
+ "bytes": 289,
6
+ "path": "README.md",
7
+ "sha256": "b860d6a1e800c0ee4f7bd9c493e22de75545fd37f087db8b9a015a690e8b7ae1"
8
+ }
9
+ ],
10
+ "generated_by": "scripts/update_manifest.py",
11
+ "schema_version": 1
12
+ }
@@ -0,0 +1,61 @@
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ from pathlib import Path
5
+
6
+ import pytest
7
+
8
+ from ssapy_data import (
9
+ DataResourceNotFoundError,
10
+ data_path,
11
+ data_resource,
12
+ iter_data_files,
13
+ manifest,
14
+ read_binary,
15
+ read_text,
16
+ )
17
+
18
+
19
+ def test_known_resources_are_packaged():
20
+ assert data_resource("README.md").is_file()
21
+
22
+
23
+ def test_text_and_binary_read_helpers():
24
+ text = read_text("README.md")
25
+ assert "SSAPy Data Payload Directory" in text
26
+ assert read_binary("README.md").startswith(b"# SSAPy Data")
27
+
28
+
29
+ def test_data_path_yields_filesystem_path():
30
+ with data_path("README.md") as path:
31
+ assert path.exists()
32
+ assert path.name == "README.md"
33
+ assert path.stat().st_size > 0
34
+
35
+
36
+ def test_manifest_matches_packaged_files():
37
+ payload = manifest()
38
+ entries = payload["files"]
39
+ entry_paths = {entry["path"] for entry in entries}
40
+ actual_paths = {resource.name for resource in iter_data_files()}
41
+
42
+ assert payload["schema_version"] == 1
43
+ assert payload["data_root"] == "data"
44
+ assert entry_paths == {"README.md"}
45
+ assert actual_paths == {"README.md"}
46
+
47
+ for entry in entries:
48
+ resource = data_resource(entry["path"])
49
+ with data_path(entry["path"]) as path:
50
+ assert path.stat().st_size == entry["bytes"]
51
+ assert hashlib.sha256(path.read_bytes()).hexdigest() == entry["sha256"]
52
+ assert resource.is_file()
53
+
54
+
55
+ def test_missing_and_unsafe_paths_are_rejected():
56
+ with pytest.raises(DataResourceNotFoundError, match="missing.dat"):
57
+ data_resource("missing.dat")
58
+ with pytest.raises(ValueError, match="must be relative"):
59
+ data_resource("/earth.png")
60
+ with pytest.raises(ValueError, match="cannot contain"):
61
+ data_resource("Earth_graphics/../earth.png")