pkg-about 2.0.1__tar.gz → 2.0.2__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.
- {pkg_about-2.0.1 → pkg_about-2.0.2}/CHANGES.rst +6 -1
- {pkg_about-2.0.1 → pkg_about-2.0.2}/PKG-INFO +10 -5
- {pkg_about-2.0.1 → pkg_about-2.0.2}/pyproject.toml +41 -19
- {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about/_about.py +63 -49
- {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/PKG-INFO +10 -5
- {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/requires.txt +3 -3
- pkg_about-2.0.2/tests/test_main.py +99 -0
- pkg_about-2.0.1/tests/test_main.py +0 -75
- {pkg_about-2.0.1 → pkg_about-2.0.2}/.readthedocs.yml +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/LICENSE +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/MANIFEST.in +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/README.rst +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/CHANGES.rst +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/README.rst +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/_static/.keep +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/_templates/.keep +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/conf.py +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/index.rst +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/setup.cfg +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about/__about__.py +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about/__init__.py +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about/py.typed +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/SOURCES.txt +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/dependency_links.txt +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/top_level.txt +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/zip-safe +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/tests/__init__.py +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/tests/__main__.py +0 -0
- {pkg_about-2.0.1 → pkg_about-2.0.2}/tests/data/setup.cfg +0 -0
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
-
2.0.
|
|
4
|
+
2.0.2 (2025-10-10)
|
|
5
5
|
------------------
|
|
6
|
+
- | Now about() and about_from_setup() return an instance of the adict
|
|
7
|
+
| dictionary with about info (but backward compatibility is preserved).
|
|
8
|
+
- | Now the __version_info__ field has a namedtuple type 'version_info'
|
|
9
|
+
| instead of a class (but backward compatibility is preserved).
|
|
6
10
|
- | Workaround for the tox error when pyproject.toml and setup.cfg
|
|
7
11
|
| files coexist.
|
|
8
12
|
- Mark the package as typed.
|
|
13
|
+
- Add tox's tool.tox.env.cleanup testenv.
|
|
9
14
|
- Setup (dependencies) update.
|
|
10
15
|
|
|
11
16
|
1.5.0 (2025-09-01)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pkg_about
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: Shares Python package metadata at runtime.
|
|
5
5
|
Author: Adam Karpierz
|
|
6
6
|
Author-email: adam@karpierz.net
|
|
@@ -35,7 +35,7 @@ Description-Content-Type: text/x-rst; charset=UTF-8
|
|
|
35
35
|
License-File: LICENSE
|
|
36
36
|
Requires-Dist: setuptools>=80.9.0
|
|
37
37
|
Requires-Dist: packaging>=25.0.0
|
|
38
|
-
Requires-Dist: tomli>=2.
|
|
38
|
+
Requires-Dist: tomli>=2.3.0; python_version < "3.11"
|
|
39
39
|
Provides-Extra: doc
|
|
40
40
|
Requires-Dist: Sphinx>=8.1.3; extra == "doc"
|
|
41
41
|
Requires-Dist: sphinx-autodoc-typehints>=3.0.1; extra == "doc"
|
|
@@ -43,12 +43,12 @@ Requires-Dist: sphinx-toolbox>=4.0.0; extra == "doc"
|
|
|
43
43
|
Requires-Dist: sphinx-tabs>=3.4.5; extra == "doc"
|
|
44
44
|
Requires-Dist: sphinx-copybutton>=0.5.2; extra == "doc"
|
|
45
45
|
Requires-Dist: sphinxcontrib-spelling>=8.0.1; extra == "doc"
|
|
46
|
-
Requires-Dist: sphinx-lint>=1.0.
|
|
46
|
+
Requires-Dist: sphinx-lint>=1.0.1; extra == "doc"
|
|
47
47
|
Requires-Dist: restructuredtext-lint>=1.4.0; extra == "doc"
|
|
48
48
|
Requires-Dist: nbsphinx>=0.9.7; extra == "doc"
|
|
49
49
|
Provides-Extra: test
|
|
50
50
|
Requires-Dist: deepdiff>=8.6.1; extra == "test"
|
|
51
|
-
Requires-Dist: rich>=14.
|
|
51
|
+
Requires-Dist: rich>=14.2.0; extra == "test"
|
|
52
52
|
Dynamic: license-file
|
|
53
53
|
|
|
54
54
|
pkg_about
|
|
@@ -145,11 +145,16 @@ Authors
|
|
|
145
145
|
Changelog
|
|
146
146
|
=========
|
|
147
147
|
|
|
148
|
-
2.0.
|
|
148
|
+
2.0.2 (2025-10-10)
|
|
149
149
|
------------------
|
|
150
|
+
- | Now about() and about_from_setup() return an instance of the adict
|
|
151
|
+
| dictionary with about info (but backward compatibility is preserved).
|
|
152
|
+
- | Now the __version_info__ field has a namedtuple type 'version_info'
|
|
153
|
+
| instead of a class (but backward compatibility is preserved).
|
|
150
154
|
- | Workaround for the tox error when pyproject.toml and setup.cfg
|
|
151
155
|
| files coexist.
|
|
152
156
|
- Mark the package as typed.
|
|
157
|
+
- Add tox's tool.tox.env.cleanup testenv.
|
|
153
158
|
- Setup (dependencies) update.
|
|
154
159
|
|
|
155
160
|
1.5.0 (2025-09-01)
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
[build-system]
|
|
5
5
|
build-backend = 'setuptools.build_meta'
|
|
6
|
-
requires = ['setuptools>=80.9.0', 'packaging>=25.0.0', 'tox>=4.
|
|
6
|
+
requires = ['setuptools>=80.9.0', 'packaging>=25.0.0', 'tox>=4.32.0']
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = 'pkg_about'
|
|
10
|
-
version = '2.0.
|
|
10
|
+
version = '2.0.2'
|
|
11
11
|
description = 'Shares Python package metadata at runtime.'
|
|
12
12
|
authors = [
|
|
13
13
|
{ name = 'Adam Karpierz' },
|
|
@@ -48,7 +48,7 @@ dependencies = [
|
|
|
48
48
|
# mandatory
|
|
49
49
|
'setuptools>=80.9.0',
|
|
50
50
|
'packaging>=25.0.0',
|
|
51
|
-
'tomli>=2.
|
|
51
|
+
'tomli>=2.3.0 ; python_version < "3.11"',
|
|
52
52
|
# others
|
|
53
53
|
]
|
|
54
54
|
dynamic = ['readme']
|
|
@@ -59,13 +59,13 @@ optional-dependencies.'doc' = [
|
|
|
59
59
|
'sphinx-tabs>=3.4.5', # don't touch! sphinx-toolbox requires <3.4.7
|
|
60
60
|
'sphinx-copybutton>=0.5.2',
|
|
61
61
|
'sphinxcontrib-spelling>=8.0.1',
|
|
62
|
-
'sphinx-lint>=1.0.
|
|
62
|
+
'sphinx-lint>=1.0.1',
|
|
63
63
|
'restructuredtext-lint>=1.4.0',
|
|
64
64
|
'nbsphinx>=0.9.7',
|
|
65
65
|
]
|
|
66
66
|
optional-dependencies.'test' = [
|
|
67
67
|
'deepdiff>=8.6.1',
|
|
68
|
-
'rich>=14.
|
|
68
|
+
'rich>=14.2.0',
|
|
69
69
|
]
|
|
70
70
|
|
|
71
71
|
[project.scripts]
|
|
@@ -124,6 +124,8 @@ report.exclude_also = [
|
|
|
124
124
|
'''if\s+__name__.*\s*==\s*['"]__main__['"]\s*:''',
|
|
125
125
|
'^\s*@unittest\.skip\(',
|
|
126
126
|
'^\s*@unittest\.skipIf\(sys\.platform\.startswith\("win"\)',
|
|
127
|
+
'^\s*@unittest\.skipIf\(is_windows,',
|
|
128
|
+
'^\s*@unittest\.skipIf\(is_cpython,',
|
|
127
129
|
'if typing.TYPE_CHECKING:',
|
|
128
130
|
]
|
|
129
131
|
report.omit = [
|
|
@@ -177,12 +179,13 @@ env_list = [{replace='ref',of=['tool','tox','labels','py'],extend=true},
|
|
|
177
179
|
skip_missing_interpreters = true
|
|
178
180
|
requires = [
|
|
179
181
|
{replace='ref',of=['tool','tox','_','base','deps'],extend=true},
|
|
180
|
-
'tox>=4.
|
|
181
|
-
'virtualenv>=20.
|
|
182
|
+
'tox>=4.32.0',
|
|
183
|
+
'virtualenv>=20.35.4',
|
|
182
184
|
]
|
|
183
185
|
[tool.tox.labels]
|
|
184
186
|
py = ['py310','py311','py312','py313','py314', 'pypy310','pypy311']
|
|
185
|
-
prepare = ['prepare']
|
|
187
|
+
prepare = ['cleanup', 'prepare']
|
|
188
|
+
cleanup = ['cleanup']
|
|
186
189
|
coverage = ['coverage']
|
|
187
190
|
typing = ['typing']
|
|
188
191
|
lint = ['lint']
|
|
@@ -193,7 +196,7 @@ deploy = [{replace='ref',of=['tool','tox','labels','build'],extend=true}, 'publi
|
|
|
193
196
|
[tool.tox._.base]
|
|
194
197
|
base_python = ['python3.13']
|
|
195
198
|
deps = [
|
|
196
|
-
'pip>=25.
|
|
199
|
+
'pip>=25.3',
|
|
197
200
|
'setuptools>=80.9.0',
|
|
198
201
|
]
|
|
199
202
|
package_subdir = 'pkg_about'
|
|
@@ -211,18 +214,35 @@ deps = [
|
|
|
211
214
|
]
|
|
212
215
|
|
|
213
216
|
[tool.tox.env.'prepare']
|
|
217
|
+
depends = ['cleanup']
|
|
214
218
|
base_python = {replace='ref',of=['tool','tox','_','base','base_python']}
|
|
215
219
|
skip_install = true
|
|
216
|
-
allowlist_externals = [
|
|
217
|
-
'cmd',
|
|
218
|
-
'.build',
|
|
219
|
-
]
|
|
220
|
+
allowlist_externals = ['cmd', '.build']
|
|
220
221
|
commands = [
|
|
221
222
|
['cmd','/C','if','exist','.build.cmd','.build.cmd'],
|
|
222
223
|
]
|
|
223
224
|
extras = []
|
|
224
225
|
deps = []
|
|
225
226
|
|
|
227
|
+
[tool.tox.env.'cleanup']
|
|
228
|
+
base_python = {replace='ref',of=['tool','tox','_','base','base_python']}
|
|
229
|
+
skip_install = true
|
|
230
|
+
no_package = true
|
|
231
|
+
env_log_dir = '{env:TMP_DIR}{/}tox.env.{env_name}-{env:PYTHONHASHSEED}{/}log'
|
|
232
|
+
env_tmp_dir = '{env:TMP_DIR}{/}tox.env.{env_name}-{env:PYTHONHASHSEED}{/}tmp'
|
|
233
|
+
allowlist_externals = ['cmd', '.clean']
|
|
234
|
+
commands = [
|
|
235
|
+
['cmd','/C','if','exist','.clean.cmd','.clean.cmd','2>','nul'],
|
|
236
|
+
['{env_python}','-W','ignore','-c',"import shutil ; shutil.rmtree('build', ignore_errors=True)"],
|
|
237
|
+
['{env_python}','-W','ignore','-c',"import shutil ; shutil.rmtree('dist', ignore_errors=True)"],
|
|
238
|
+
['{env_python}','-W','ignore','-c',"import shutil,glob ; [shutil.rmtree(item) for item in glob.glob('src/*.egg-info')]"],
|
|
239
|
+
['{env_python}','-W','ignore','-c',"import shutil,glob ; [shutil.rmtree(item) for item in glob.glob('**/__pycache__', recursive=True)]"],
|
|
240
|
+
['{env_python}','-W','ignore','-c',"import shutil,glob ; [shutil.rmtree(item) for item in glob.glob('**/.mypy_cache', recursive=True)]"],
|
|
241
|
+
['cmd','/C','if','exist','.tox','rmdir','/S/Q','.tox','2>','nul'],
|
|
242
|
+
]
|
|
243
|
+
extras = []
|
|
244
|
+
deps = []
|
|
245
|
+
|
|
226
246
|
[tool.tox.env.'coverage']
|
|
227
247
|
base_python = {replace='ref',of=['tool','tox','_','base','base_python']}
|
|
228
248
|
commands = [
|
|
@@ -233,15 +253,15 @@ commands = [
|
|
|
233
253
|
]
|
|
234
254
|
deps = [
|
|
235
255
|
{replace='ref',of=['tool','tox','env_run_base','deps'],extend=true},
|
|
236
|
-
'coverage>=7.
|
|
256
|
+
'coverage>=7.11.0',
|
|
237
257
|
'covdefaults>=2.3.0',
|
|
238
|
-
'diff-cover>=9.
|
|
258
|
+
'diff-cover>=9.7.1',
|
|
239
259
|
]
|
|
240
260
|
|
|
241
261
|
[tool.tox.env.'docs']
|
|
242
262
|
base_python = {replace='ref',of=['tool','tox','_','base','base_python']}
|
|
243
263
|
commands = [
|
|
244
|
-
['{env_python}','-m','sphinxlint','
|
|
264
|
+
['{env_python}','-m','sphinxlint','-i','#arch','-i','.tox','-i','build','-i','dist','-i','.mypy_cache'],
|
|
245
265
|
#['{env_python}','-m','sphinx.apidoc','-f','{env_site_packages_dir}/{[tool.tox._.base]package_subdir}'],
|
|
246
266
|
['{env_python}','-m','sphinx.cmd.build','-W','-a','-b','html','-E','./docs','./build/docs/html'],
|
|
247
267
|
['{env_python}','-m','sphinx.cmd.build','-W','-a','-b','linkcheck','./docs','./build/docs/html'],
|
|
@@ -256,12 +276,14 @@ deps = [
|
|
|
256
276
|
depends = [{replace='ref',of=['tool','tox','labels','py'],extend=true}, 'docs']
|
|
257
277
|
base_python = {replace='ref',of=['tool','tox','_','base','base_python']}
|
|
258
278
|
commands = [
|
|
279
|
+
['{env_python}','-m','check_manifest','-v'],
|
|
259
280
|
['{env_python}','-m','build'],
|
|
260
281
|
# check out for PyPi
|
|
261
282
|
['{env_python}','-m','twine','check','dist/*'],
|
|
262
283
|
]
|
|
263
284
|
deps = [
|
|
264
285
|
{replace='ref',of=['tool','tox','env_run_base','deps'],extend=true},
|
|
286
|
+
'check-manifest>=0.51',
|
|
265
287
|
'build>=1.3.0',
|
|
266
288
|
'twine>=6.2.0',
|
|
267
289
|
]
|
|
@@ -288,7 +310,7 @@ commands = [
|
|
|
288
310
|
extras = []
|
|
289
311
|
deps = [
|
|
290
312
|
{replace='ref',of=['tool','tox','_','base','deps'],extend=true},
|
|
291
|
-
'mypy>=1.
|
|
313
|
+
'mypy>=1.18.2',
|
|
292
314
|
'mypy_extensions>=1.1.0',
|
|
293
315
|
'types-setuptools>=80.9.0.20250822',
|
|
294
316
|
]
|
|
@@ -306,6 +328,6 @@ deps = [
|
|
|
306
328
|
'flake8-pyproject>=1.2.3',
|
|
307
329
|
'flake8-docstrings>=1.7.0',
|
|
308
330
|
'pep8-naming>=0.15.1',
|
|
309
|
-
'flake8-builtins>=3.
|
|
310
|
-
'flake8-deprecated>=2.
|
|
331
|
+
'flake8-builtins>=3.1.0',
|
|
332
|
+
'flake8-deprecated>=2.3.0',
|
|
311
333
|
]
|
|
@@ -5,9 +5,22 @@ __all__ = ('about', 'about_from_setup')
|
|
|
5
5
|
|
|
6
6
|
from typing import Any
|
|
7
7
|
from pathlib import Path
|
|
8
|
+
from collections import namedtuple
|
|
8
9
|
|
|
10
|
+
version_info = namedtuple("version_info",
|
|
11
|
+
["major", "minor", "micro", "releaselevel", "serial"],
|
|
12
|
+
module="pkg_about")
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
|
|
15
|
+
class __adict(dict[str, Any]):
|
|
16
|
+
__getattr__ = dict.__getitem__
|
|
17
|
+
__setattr__ = dict.__setitem__
|
|
18
|
+
__delattr__ = dict.__delitem__
|
|
19
|
+
__copy__ = lambda self: self.__class__(self)
|
|
20
|
+
copy = lambda self: self.copy()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def about(package: str | None = None) -> __adict:
|
|
11
24
|
import sys
|
|
12
25
|
from packaging.version import parse as parse_version
|
|
13
26
|
from importlib.metadata import metadata as get_metadata
|
|
@@ -20,25 +33,25 @@ def about(package: str | None = None) -> None:
|
|
|
20
33
|
project_urls = {item.partition(",")[0].strip():
|
|
21
34
|
item.partition(",")[2].lstrip()
|
|
22
35
|
for item in metadata.get_all("Project-URL") or []}
|
|
23
|
-
release_levels = __release_levels
|
|
36
|
+
adict, release_levels = __adict, __release_levels
|
|
24
37
|
metadata_get = metadata.get # type: ignore[attr-defined]
|
|
25
38
|
|
|
26
|
-
pkg_metadata =
|
|
39
|
+
pkg_metadata = adict(
|
|
27
40
|
__title__ = metadata["Name"],
|
|
28
41
|
__version__ = str(version),
|
|
29
|
-
__version_info__ =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
__version_info__ = version_info(
|
|
43
|
+
major=version.major,
|
|
44
|
+
minor=version.minor,
|
|
45
|
+
micro=version.micro,
|
|
46
|
+
releaselevel=release_levels[
|
|
47
|
+
version.pre[0] if version.pre else
|
|
48
|
+
"dev" if version.dev else
|
|
49
|
+
"post" if version.post else
|
|
50
|
+
"local" if version.local else
|
|
51
|
+
"final"],
|
|
52
|
+
serial=(version.pre[1] if version.pre else
|
|
53
|
+
version.dev or version.post
|
|
54
|
+
or version.local or 0)),
|
|
42
55
|
__summary__ = metadata_get("Summary"),
|
|
43
56
|
__uri__ = (metadata_get("Home-page")
|
|
44
57
|
or project_urls.get("Home-page")
|
|
@@ -55,10 +68,12 @@ def about(package: str | None = None) -> None:
|
|
|
55
68
|
)
|
|
56
69
|
|
|
57
70
|
pkg_globals.update(pkg_metadata)
|
|
58
|
-
pkg_globals
|
|
71
|
+
pkg_globals.setdefault("__all__", [])
|
|
72
|
+
pkg_globals["__all__"] += list(pkg_metadata.keys())
|
|
73
|
+
return pkg_metadata
|
|
59
74
|
|
|
60
75
|
|
|
61
|
-
def about_from_setup(package_path: Path | str | None = None) ->
|
|
76
|
+
def about_from_setup(package_path: Path | str | None = None) -> __adict:
|
|
62
77
|
import sys
|
|
63
78
|
from pathlib import Path
|
|
64
79
|
from packaging.version import parse as parse_version
|
|
@@ -93,50 +108,49 @@ def about_from_setup(package_path: Path | str | None = None) -> type:
|
|
|
93
108
|
with pyproject_path.open("rb") as file:
|
|
94
109
|
metadata.update(tomllib.load(file).get("project", {}))
|
|
95
110
|
version = parse_version(metadata["version"])
|
|
96
|
-
get, release_levels = __get, __release_levels
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
or version.local or 0)))
|
|
116
|
-
__summary__ = get(metadata, "description")
|
|
111
|
+
adict, get, release_levels = __adict, __get, __release_levels
|
|
112
|
+
|
|
113
|
+
pkg_metadata = adict(
|
|
114
|
+
__title__ = metadata["name"],
|
|
115
|
+
__version__ = str(version),
|
|
116
|
+
__version_info__ = version_info(
|
|
117
|
+
major=version.major,
|
|
118
|
+
minor=version.minor,
|
|
119
|
+
micro=version.micro,
|
|
120
|
+
releaselevel=release_levels[
|
|
121
|
+
version.pre[0] if version.pre else
|
|
122
|
+
"dev" if version.dev else
|
|
123
|
+
"post" if version.post else
|
|
124
|
+
"local" if version.local else
|
|
125
|
+
"final"],
|
|
126
|
+
serial=(version.pre[1] if version.pre else
|
|
127
|
+
version.dev or version.post
|
|
128
|
+
or version.local or 0)),
|
|
129
|
+
__summary__ = get(metadata, "description"),
|
|
117
130
|
__uri__ = (get(metadata, "urls", "Home-page")
|
|
118
131
|
or get(metadata, "urls", "Homepage")
|
|
119
132
|
or get(metadata, "urls", "Home")
|
|
120
|
-
or get(metadata, "url"))
|
|
133
|
+
or get(metadata, "url")),
|
|
121
134
|
__author__ = (get(metadata, "authors", 0, "name")
|
|
122
|
-
or get(metadata, "author"))
|
|
135
|
+
or get(metadata, "author")),
|
|
123
136
|
__email__ = (get(metadata, "authors", 1, "email")
|
|
124
|
-
or get(metadata, "author_email"))
|
|
137
|
+
or get(metadata, "author_email")),
|
|
125
138
|
__author_email__ = (get(metadata, "authors", 1, "email")
|
|
126
|
-
or get(metadata, "author_email"))
|
|
139
|
+
or get(metadata, "author_email")),
|
|
127
140
|
__maintainer__ = (get(metadata, "maintainers", 0, "name")
|
|
128
|
-
or get(metadata, "maintainer"))
|
|
141
|
+
or get(metadata, "maintainer")),
|
|
129
142
|
__maintainer_email__ = (get(metadata, "maintainers", 1, "email")
|
|
130
|
-
or get(metadata, "maintainer_email"))
|
|
143
|
+
or get(metadata, "maintainer_email")),
|
|
131
144
|
__license__ = (get(metadata, "license", "text")
|
|
132
|
-
or get(metadata, "license"))
|
|
145
|
+
or get(metadata, "license")),
|
|
133
146
|
__copyright__ = (get(metadata, "authors", 0, "name")
|
|
134
|
-
or get(metadata, "author"))
|
|
147
|
+
or get(metadata, "author")),
|
|
148
|
+
)
|
|
135
149
|
|
|
136
|
-
pkg_globals["about"] =
|
|
150
|
+
pkg_globals["about"] = pkg_metadata
|
|
137
151
|
pkg_globals.setdefault("__all__", [])
|
|
138
152
|
pkg_globals["__all__"].append("about")
|
|
139
|
-
return
|
|
153
|
+
return pkg_metadata
|
|
140
154
|
|
|
141
155
|
|
|
142
156
|
def __get(metadata: Any, *keys: Any) -> Any:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pkg_about
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: Shares Python package metadata at runtime.
|
|
5
5
|
Author: Adam Karpierz
|
|
6
6
|
Author-email: adam@karpierz.net
|
|
@@ -35,7 +35,7 @@ Description-Content-Type: text/x-rst; charset=UTF-8
|
|
|
35
35
|
License-File: LICENSE
|
|
36
36
|
Requires-Dist: setuptools>=80.9.0
|
|
37
37
|
Requires-Dist: packaging>=25.0.0
|
|
38
|
-
Requires-Dist: tomli>=2.
|
|
38
|
+
Requires-Dist: tomli>=2.3.0; python_version < "3.11"
|
|
39
39
|
Provides-Extra: doc
|
|
40
40
|
Requires-Dist: Sphinx>=8.1.3; extra == "doc"
|
|
41
41
|
Requires-Dist: sphinx-autodoc-typehints>=3.0.1; extra == "doc"
|
|
@@ -43,12 +43,12 @@ Requires-Dist: sphinx-toolbox>=4.0.0; extra == "doc"
|
|
|
43
43
|
Requires-Dist: sphinx-tabs>=3.4.5; extra == "doc"
|
|
44
44
|
Requires-Dist: sphinx-copybutton>=0.5.2; extra == "doc"
|
|
45
45
|
Requires-Dist: sphinxcontrib-spelling>=8.0.1; extra == "doc"
|
|
46
|
-
Requires-Dist: sphinx-lint>=1.0.
|
|
46
|
+
Requires-Dist: sphinx-lint>=1.0.1; extra == "doc"
|
|
47
47
|
Requires-Dist: restructuredtext-lint>=1.4.0; extra == "doc"
|
|
48
48
|
Requires-Dist: nbsphinx>=0.9.7; extra == "doc"
|
|
49
49
|
Provides-Extra: test
|
|
50
50
|
Requires-Dist: deepdiff>=8.6.1; extra == "test"
|
|
51
|
-
Requires-Dist: rich>=14.
|
|
51
|
+
Requires-Dist: rich>=14.2.0; extra == "test"
|
|
52
52
|
Dynamic: license-file
|
|
53
53
|
|
|
54
54
|
pkg_about
|
|
@@ -145,11 +145,16 @@ Authors
|
|
|
145
145
|
Changelog
|
|
146
146
|
=========
|
|
147
147
|
|
|
148
|
-
2.0.
|
|
148
|
+
2.0.2 (2025-10-10)
|
|
149
149
|
------------------
|
|
150
|
+
- | Now about() and about_from_setup() return an instance of the adict
|
|
151
|
+
| dictionary with about info (but backward compatibility is preserved).
|
|
152
|
+
- | Now the __version_info__ field has a namedtuple type 'version_info'
|
|
153
|
+
| instead of a class (but backward compatibility is preserved).
|
|
150
154
|
- | Workaround for the tox error when pyproject.toml and setup.cfg
|
|
151
155
|
| files coexist.
|
|
152
156
|
- Mark the package as typed.
|
|
157
|
+
- Add tox's tool.tox.env.cleanup testenv.
|
|
153
158
|
- Setup (dependencies) update.
|
|
154
159
|
|
|
155
160
|
1.5.0 (2025-09-01)
|
|
@@ -2,7 +2,7 @@ setuptools>=80.9.0
|
|
|
2
2
|
packaging>=25.0.0
|
|
3
3
|
|
|
4
4
|
[:python_version < "3.11"]
|
|
5
|
-
tomli>=2.
|
|
5
|
+
tomli>=2.3.0
|
|
6
6
|
|
|
7
7
|
[doc]
|
|
8
8
|
Sphinx>=8.1.3
|
|
@@ -11,10 +11,10 @@ sphinx-toolbox>=4.0.0
|
|
|
11
11
|
sphinx-tabs>=3.4.5
|
|
12
12
|
sphinx-copybutton>=0.5.2
|
|
13
13
|
sphinxcontrib-spelling>=8.0.1
|
|
14
|
-
sphinx-lint>=1.0.
|
|
14
|
+
sphinx-lint>=1.0.1
|
|
15
15
|
restructuredtext-lint>=1.4.0
|
|
16
16
|
nbsphinx>=0.9.7
|
|
17
17
|
|
|
18
18
|
[test]
|
|
19
19
|
deepdiff>=8.6.1
|
|
20
|
-
rich>=14.
|
|
20
|
+
rich>=14.2.0
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Copyright (c) 2020 Adam Karpierz
|
|
2
|
+
# SPDX-License-Identifier: Zlib
|
|
3
|
+
|
|
4
|
+
import unittest
|
|
5
|
+
import sys
|
|
6
|
+
import os
|
|
7
|
+
import stat
|
|
8
|
+
import shutil
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from . import test_dir
|
|
12
|
+
|
|
13
|
+
import pkg_about
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MainTestCase(unittest.TestCase):
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def is_namedtuple_instance(obj):
|
|
20
|
+
return (isinstance(obj, tuple) and
|
|
21
|
+
hasattr(obj, '_fields') and
|
|
22
|
+
isinstance(obj._fields, tuple) and
|
|
23
|
+
all(isinstance(field, str) for field in obj._fields))
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def setUpClass(cls):
|
|
27
|
+
pyproject_path = Path(__file__).resolve().parent.parent/"pyproject.toml"
|
|
28
|
+
if sys.version_info >= (3, 11):
|
|
29
|
+
import tomllib
|
|
30
|
+
else: # pragma: no cover
|
|
31
|
+
import tomli as tomllib
|
|
32
|
+
with pyproject_path.open("rb") as file:
|
|
33
|
+
metadata = tomllib.load(file).get("project", {})
|
|
34
|
+
cls.version_expected = metadata["version"]
|
|
35
|
+
version_parts = cls.version_expected.split(".")
|
|
36
|
+
cls.version_major_expected = int(version_parts[0])
|
|
37
|
+
cls.version_minor_expected = int(version_parts[1])
|
|
38
|
+
cls.version_micro_expected = int(version_parts[2])
|
|
39
|
+
|
|
40
|
+
def test_about(self):
|
|
41
|
+
about = pkg_about.about("pkg_about")
|
|
42
|
+
self.assertIsInstance(about, dict)
|
|
43
|
+
self.assertIs(__title__, about.__title__)
|
|
44
|
+
self.assertEqual(about.__title__, "pkg_about")
|
|
45
|
+
self.assertIs(__version__, about.__version__)
|
|
46
|
+
self.assertEqual(about.__version__, self.version_expected)
|
|
47
|
+
self.assertIs(__version_info__, about.__version_info__)
|
|
48
|
+
self.assertTrue(self.is_namedtuple_instance(about.__version_info__))
|
|
49
|
+
self.assertEqual(about.__version_info__.major, self.version_major_expected)
|
|
50
|
+
self.assertEqual(about.__version_info__.minor, self.version_minor_expected)
|
|
51
|
+
self.assertEqual(about.__version_info__.micro, self.version_micro_expected)
|
|
52
|
+
self.assertEqual(about.__version_info__.releaselevel, "final")
|
|
53
|
+
self.assertEqual(about.__version_info__.serial, 0)
|
|
54
|
+
self.assertIs(__summary__, about.__summary__)
|
|
55
|
+
self.assertEqual(about.__summary__, "Shares Python package metadata at runtime.")
|
|
56
|
+
self.assertIs(__uri__, about.__uri__)
|
|
57
|
+
self.assertEqual(about.__uri__, "https://pypi.org/project/pkg-about/")
|
|
58
|
+
self.assertIs(__author__, about.__author__)
|
|
59
|
+
self.assertEqual(about.__author__, "Adam Karpierz")
|
|
60
|
+
self.assertIs(__email__, about.__email__)
|
|
61
|
+
self.assertEqual(about.__email__, "adam@karpierz.net")
|
|
62
|
+
self.assertIs(__author_email__, about.__author_email__)
|
|
63
|
+
self.assertEqual(about.__author_email__, "adam@karpierz.net")
|
|
64
|
+
self.assertIs(__maintainer__, about.__maintainer__)
|
|
65
|
+
self.assertEqual(about.__maintainer__, "Adam Karpierz")
|
|
66
|
+
self.assertIs(__maintainer_email__, about.__maintainer_email__)
|
|
67
|
+
self.assertEqual(about.__maintainer_email__, "adam@karpierz.net")
|
|
68
|
+
self.assertIs(__license__, about.__license__)
|
|
69
|
+
self.assertEqual(about.__license__, "Zlib")
|
|
70
|
+
self.assertIs(__copyright__, about.__copyright__)
|
|
71
|
+
self.assertEqual(about.__copyright__, __author__)
|
|
72
|
+
|
|
73
|
+
def test_about_from_setup(self):
|
|
74
|
+
package_path = Path(__file__).resolve().parent.parent
|
|
75
|
+
setup_cfg = shutil.copy(test_dir/"data/setup.cfg", package_path/"setup.cfg")
|
|
76
|
+
try:
|
|
77
|
+
ret_about = pkg_about.about_from_setup(package_path)
|
|
78
|
+
self.assertIs(ret_about, about)
|
|
79
|
+
self.assertIsInstance(about, dict)
|
|
80
|
+
self.assertEqual(about.__title__, "pkg_about")
|
|
81
|
+
self.assertEqual(about.__version__, self.version_expected)
|
|
82
|
+
self.assertTrue(self.is_namedtuple_instance(about.__version_info__))
|
|
83
|
+
self.assertEqual(about.__version_info__.major, self.version_major_expected)
|
|
84
|
+
self.assertEqual(about.__version_info__.minor, self.version_minor_expected)
|
|
85
|
+
self.assertEqual(about.__version_info__.micro, self.version_micro_expected)
|
|
86
|
+
self.assertEqual(about.__version_info__.releaselevel, "final")
|
|
87
|
+
self.assertEqual(about.__version_info__.serial, 0)
|
|
88
|
+
self.assertEqual(about.__summary__, "Shares Python package metadata at runtime.")
|
|
89
|
+
self.assertEqual(about.__uri__, "https://pypi.org/project/pkg-about/")
|
|
90
|
+
self.assertEqual(about.__author__, "Adam Karpierz")
|
|
91
|
+
self.assertEqual(about.__email__, "adam@karpierz.net")
|
|
92
|
+
self.assertEqual(about.__author_email__, "adam@karpierz.net")
|
|
93
|
+
self.assertEqual(about.__maintainer__, "Adam Karpierz")
|
|
94
|
+
self.assertEqual(about.__maintainer_email__, "adam@karpierz.net")
|
|
95
|
+
self.assertEqual(about.__license__, "Zlib")
|
|
96
|
+
self.assertEqual(about.__copyright__, about.__author__)
|
|
97
|
+
finally:
|
|
98
|
+
os.chmod(setup_cfg, stat.S_IWRITE)
|
|
99
|
+
setup_cfg.unlink()
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2020 Adam Karpierz
|
|
2
|
-
# SPDX-License-Identifier: Zlib
|
|
3
|
-
|
|
4
|
-
import unittest
|
|
5
|
-
import sys
|
|
6
|
-
import os
|
|
7
|
-
import stat
|
|
8
|
-
import shutil
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
|
|
11
|
-
from . import test_dir
|
|
12
|
-
|
|
13
|
-
import pkg_about
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class MainTestCase(unittest.TestCase):
|
|
17
|
-
|
|
18
|
-
@classmethod
|
|
19
|
-
def setUpClass(cls):
|
|
20
|
-
pyproject_path = Path(__file__).resolve().parent.parent/"pyproject.toml"
|
|
21
|
-
if sys.version_info >= (3, 11):
|
|
22
|
-
import tomllib
|
|
23
|
-
else: # pragma: no cover
|
|
24
|
-
import tomli as tomllib
|
|
25
|
-
with pyproject_path.open("rb") as file:
|
|
26
|
-
metadata = tomllib.load(file).get("project", {})
|
|
27
|
-
cls.version_expected = metadata["version"]
|
|
28
|
-
version_parts = cls.version_expected.split(".")
|
|
29
|
-
cls.version_major_expected = int(version_parts[0])
|
|
30
|
-
cls.version_minor_expected = int(version_parts[1])
|
|
31
|
-
cls.version_micro_expected = int(version_parts[2])
|
|
32
|
-
|
|
33
|
-
def test_about(self):
|
|
34
|
-
pkg_about.about("pkg_about")
|
|
35
|
-
self.assertEqual(__title__, "pkg_about")
|
|
36
|
-
self.assertEqual(__version__, self.version_expected)
|
|
37
|
-
self.assertEqual(__version_info__.major, self.version_major_expected)
|
|
38
|
-
self.assertEqual(__version_info__.minor, self.version_minor_expected)
|
|
39
|
-
self.assertEqual(__version_info__.micro, self.version_micro_expected)
|
|
40
|
-
self.assertEqual(__version_info__.releaselevel, "final")
|
|
41
|
-
self.assertEqual(__version_info__.serial, 0)
|
|
42
|
-
self.assertEqual(__summary__, "Shares Python package metadata at runtime.")
|
|
43
|
-
self.assertEqual(__uri__, "https://pypi.org/project/pkg-about/")
|
|
44
|
-
self.assertEqual(__author__, "Adam Karpierz")
|
|
45
|
-
self.assertEqual(__email__, "adam@karpierz.net")
|
|
46
|
-
self.assertEqual(__author_email__, "adam@karpierz.net")
|
|
47
|
-
self.assertEqual(__maintainer__, "Adam Karpierz")
|
|
48
|
-
self.assertEqual(__maintainer_email__, "adam@karpierz.net")
|
|
49
|
-
self.assertEqual(__license__, "Zlib")
|
|
50
|
-
self.assertEqual(__copyright__, __author__)
|
|
51
|
-
|
|
52
|
-
def test_about_from_setup(self):
|
|
53
|
-
package_path = Path(__file__).resolve().parent.parent
|
|
54
|
-
setup_cfg = shutil.copy(test_dir/"data/setup.cfg", package_path/"setup.cfg")
|
|
55
|
-
try:
|
|
56
|
-
pkg_about.about_from_setup(package_path)
|
|
57
|
-
self.assertEqual(about.__title__, "pkg_about")
|
|
58
|
-
self.assertEqual(about.__version__, self.version_expected)
|
|
59
|
-
self.assertEqual(about.__version_info__.major, self.version_major_expected)
|
|
60
|
-
self.assertEqual(about.__version_info__.minor, self.version_minor_expected)
|
|
61
|
-
self.assertEqual(about.__version_info__.micro, self.version_micro_expected)
|
|
62
|
-
self.assertEqual(about.__version_info__.releaselevel, "final")
|
|
63
|
-
self.assertEqual(about.__version_info__.serial, 0)
|
|
64
|
-
self.assertEqual(about.__summary__, "Shares Python package metadata at runtime.")
|
|
65
|
-
self.assertEqual(about.__uri__, "https://pypi.org/project/pkg-about/")
|
|
66
|
-
self.assertEqual(about.__author__, "Adam Karpierz")
|
|
67
|
-
self.assertEqual(about.__email__, "adam@karpierz.net")
|
|
68
|
-
self.assertEqual(about.__author_email__, "adam@karpierz.net")
|
|
69
|
-
self.assertEqual(about.__maintainer__, "Adam Karpierz")
|
|
70
|
-
self.assertEqual(about.__maintainer_email__, "adam@karpierz.net")
|
|
71
|
-
self.assertEqual(about.__license__, "Zlib")
|
|
72
|
-
self.assertEqual(about.__copyright__, about.__author__)
|
|
73
|
-
finally:
|
|
74
|
-
os.chmod(setup_cfg, stat.S_IWRITE)
|
|
75
|
-
setup_cfg.unlink()
|
|
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
|
|
File without changes
|
|
File without changes
|