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.
Files changed (29) hide show
  1. {pkg_about-2.0.1 → pkg_about-2.0.2}/CHANGES.rst +6 -1
  2. {pkg_about-2.0.1 → pkg_about-2.0.2}/PKG-INFO +10 -5
  3. {pkg_about-2.0.1 → pkg_about-2.0.2}/pyproject.toml +41 -19
  4. {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about/_about.py +63 -49
  5. {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/PKG-INFO +10 -5
  6. {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/requires.txt +3 -3
  7. pkg_about-2.0.2/tests/test_main.py +99 -0
  8. pkg_about-2.0.1/tests/test_main.py +0 -75
  9. {pkg_about-2.0.1 → pkg_about-2.0.2}/.readthedocs.yml +0 -0
  10. {pkg_about-2.0.1 → pkg_about-2.0.2}/LICENSE +0 -0
  11. {pkg_about-2.0.1 → pkg_about-2.0.2}/MANIFEST.in +0 -0
  12. {pkg_about-2.0.1 → pkg_about-2.0.2}/README.rst +0 -0
  13. {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/CHANGES.rst +0 -0
  14. {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/README.rst +0 -0
  15. {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/_static/.keep +0 -0
  16. {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/_templates/.keep +0 -0
  17. {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/conf.py +0 -0
  18. {pkg_about-2.0.1 → pkg_about-2.0.2}/docs/index.rst +0 -0
  19. {pkg_about-2.0.1 → pkg_about-2.0.2}/setup.cfg +0 -0
  20. {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about/__about__.py +0 -0
  21. {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about/__init__.py +0 -0
  22. {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about/py.typed +0 -0
  23. {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/SOURCES.txt +0 -0
  24. {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/dependency_links.txt +0 -0
  25. {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/top_level.txt +0 -0
  26. {pkg_about-2.0.1 → pkg_about-2.0.2}/src/pkg_about.egg-info/zip-safe +0 -0
  27. {pkg_about-2.0.1 → pkg_about-2.0.2}/tests/__init__.py +0 -0
  28. {pkg_about-2.0.1 → pkg_about-2.0.2}/tests/__main__.py +0 -0
  29. {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.1 (2025-09-08)
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.1
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.2.1; python_version < "3.11"
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.0; extra == "doc"
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.1.0; extra == "test"
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.1 (2025-09-08)
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.30.2']
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.1'
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.2.1 ; python_version < "3.11"',
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.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.1.0',
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.30.2',
181
- 'virtualenv>=20.34.0',
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.2',
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.10.6',
256
+ 'coverage>=7.11.0',
237
257
  'covdefaults>=2.3.0',
238
- 'diff-cover>=9.6.0',
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','--ignore','.tox','--ignore','build','--ignore','dist'],
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.17.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.0.0',
310
- 'flake8-deprecated>=2.2.1',
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
- def about(package: str | None = None) -> None:
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 = dict(
39
+ pkg_metadata = adict(
27
40
  __title__ = metadata["Name"],
28
41
  __version__ = str(version),
29
- __version_info__ = type("version_info", (), dict(
30
- major=version.major,
31
- minor=version.minor,
32
- micro=version.micro,
33
- releaselevel=release_levels[
34
- version.pre[0] if version.pre else
35
- "dev" if version.dev else
36
- "post" if version.post else
37
- "local" if version.local else
38
- "final"],
39
- serial=(version.pre[1] if version.pre else
40
- version.dev or version.post
41
- or version.local or 0))),
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["__all__"] = list(pkg_metadata.keys())
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) -> type:
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
- class about:
99
- __slots__ = ()
100
- __module__ = 'pkg_about'
101
- __title__ = metadata["name"]
102
- __version__ = str(version)
103
- __version_info__ = type("version_info", (), dict(
104
- major=version.major,
105
- minor=version.minor,
106
- micro=version.micro,
107
- releaselevel=release_levels[
108
- version.pre[0] if version.pre else
109
- "dev" if version.dev else
110
- "post" if version.post else
111
- "local" if version.local else
112
- "final"],
113
- serial=(version.pre[1] if version.pre else
114
- version.dev or version.post
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"] = about
150
+ pkg_globals["about"] = pkg_metadata
137
151
  pkg_globals.setdefault("__all__", [])
138
152
  pkg_globals["__all__"].append("about")
139
- return about
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.1
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.2.1; python_version < "3.11"
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.0; extra == "doc"
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.1.0; extra == "test"
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.1 (2025-09-08)
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.2.1
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.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.1.0
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