Skip to content

Commit a02d8fe

Browse files
split up code and migrate to hatch
1 parent e91f456 commit a02d8fe

File tree

9 files changed

+105
-99
lines changed

9 files changed

+105
-99
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
src/apipkg/version.py
1+
src/apipkg/_version.py
22
__pycache__
33
*.egg-info
44
.pytest_cache/
55
.eggs/
66
.tox/
7+
dist/

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ repos:
3030
rev: v2.32.1
3131
hooks:
3232
- id: pyupgrade
33+
args: [--py37-plus]
3334
- repo: https://github.com/asottile/setup-cfg-fmt
3435
rev: v1.20.1
3536
hooks:

CHANGELOG

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
2+
3.0.0
3+
-----
4+
* add support for python 3.11 and drop dead pythons (thanks hukgo)
5+
* migrate to hatch
6+
17
2.1.1
28
-----
39

pyproject.toml

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,48 @@
11
[build-system]
2-
requires = ["setuptools>=41.2.0", "wheel", "setuptools_scm>3"]
2+
requires = [
3+
"hatchling>=0.24.0", "hatch-vcs"
4+
]
5+
build-backend = "hatchling.build"
36

7+
[project]
8+
name = "apipkg"
9+
description = "apipkg: namespace control and lazy-import mechanism"
10+
readme = "README.rst"
11+
license = "MIT"
12+
requires-python = ">=3.7"
13+
authors = [
14+
{ name = "holger krekel" },
15+
]
16+
classifiers = [
17+
"Development Status :: 4 - Beta",
18+
"Intended Audience :: Developers",
19+
"License :: OSI Approved :: MIT License",
20+
"Operating System :: MacOS :: MacOS X",
21+
"Operating System :: Microsoft :: Windows",
22+
"Operating System :: POSIX",
23+
"Programming Language :: Python",
24+
"Programming Language :: Python :: Implementation :: CPython",
25+
"Programming Language :: Python :: 3",
26+
"Programming Language :: Python :: 3 :: Only",
27+
"Programming Language :: Python :: 3.7",
28+
"Programming Language :: Python :: 3.8",
29+
"Programming Language :: Python :: 3.9",
30+
"Programming Language :: Python :: 3.10",
31+
"Topic :: Software Development :: Libraries",
32+
]
33+
dynamic = [
34+
"version",
35+
]
436

37+
[project.urls]
38+
Homepage = "https://github.com/pytest-dev/apipkg"
539

6-
[tool.setuptools_scm]
7-
write_to = "src/apipkg/version.py"
40+
[tool.hatch.version]
41+
source = "vcs"
42+
43+
[tool.hatch.build.targets.sdist]
44+
include = [
45+
"/src",
46+
]
47+
[tool.hatch.build.hooks.vcs]
48+
version-file = "src/apipkg/_version.py"

setup.cfg

Lines changed: 0 additions & 47 deletions
This file was deleted.

setup.py

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/apipkg/__init__.py

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
66
(c) holger krekel, 2009 - MIT license
77
"""
8+
from __future__ import annotations
9+
810
import functools
9-
import os
1011
import sys
1112
import threading
1213
from types import ModuleType
1314

14-
from .version import version as __version__ # NOQA:F401
15-
15+
from ._importing import _py_abspath
16+
from ._importing import distribution_version as distribution_version
17+
from ._version import version as __version__ # NOQA:F401
1618

1719
_PRESERVED_MODULE_ATTRS = {
1820
"__file__",
@@ -26,31 +28,6 @@
2628
}
2729

2830

29-
def _py_abspath(path):
30-
"""
31-
special version of abspath
32-
that will leave paths from jython jars alone
33-
"""
34-
if path.startswith("__pyclasspath__"):
35-
36-
return path
37-
else:
38-
return os.path.abspath(path)
39-
40-
41-
def distribution_version(name):
42-
"""try to get the version of the named distribution,
43-
returs None on failure"""
44-
from pkg_resources import get_distribution, DistributionNotFound
45-
46-
try:
47-
dist = get_distribution(name)
48-
except DistributionNotFound:
49-
pass
50-
else:
51-
return dist.version
52-
53-
5431
def initpkg(pkgname, exportdefs, attr=None, eager=False):
5532
"""initialize given package from the export definitions."""
5633
attr = attr or {}
@@ -101,7 +78,7 @@ def _initpkg(mod, pkgname, exportdefs, attr=None):
10178
return mod
10279

10380

104-
def importobj(modpath, attrname):
81+
def importobj(modpath: str, attrname: str) -> object:
10582
"""imports a module, then resolves the attrname on it"""
10683
module = __import__(modpath, None, None, ["__doc__"])
10784
if not attrname:
@@ -116,8 +93,6 @@ def importobj(modpath, attrname):
11693

11794
def _synchronized(wrapped_function):
11895
"""Decorator to synchronise __getattr__ calls."""
119-
if threading is None:
120-
return wrapped_function
12196

12297
# Lock shared between all instances of ApiModule to avoid possible deadlocks
12398
lock = threading.RLock()
@@ -133,17 +108,19 @@ def synchronized_wrapper_function(*args, **kwargs):
133108
class ApiModule(ModuleType):
134109
"""the magical lazy-loading module standing"""
135110

136-
def __docget(self):
111+
def __docget(self) -> str | None:
137112
try:
138113
return self.__doc
139114
except AttributeError:
140115
if "__doc__" in self.__map__:
141116
return self.__makeattr("__doc__")
117+
else:
118+
return None
142119

143-
def __docset(self, value):
120+
def __docset(self, value: str) -> None:
144121
self.__doc = value
145122

146-
__doc__ = property(__docget, __docset)
123+
__doc__ = property(__docget, __docset) # type: ignore
147124

148125
def __init__(self, name, importspec, implprefix=None, attr=None):
149126
self.__name__ = name
@@ -240,16 +217,19 @@ def __dict__(self):
240217
return dict
241218

242219

243-
def AliasModule(modname, modpath, attrname=None):
244-
mod = []
220+
def AliasModule(modname: str, modpath: str, attrname: str | None=None):
221+
mod: object | None = None
245222

246-
def getmod():
247-
if not mod:
248-
x = importobj(modpath, None)
223+
def getmod() -> object:
224+
nonlocal mod
225+
if mod is None:
226+
imported = importobj(modpath, None)
249227
if attrname is not None:
250-
x = getattr(x, attrname)
251-
mod.append(x)
252-
return mod[0]
228+
mod = getattr(imported, attrname)
229+
else:
230+
mod = imported
231+
232+
return mod
253233

254234
x = modpath + ("." + attrname if attrname else "")
255235
repr_result = f"<AliasModule {modname!r} for {x!r}>"

src/apipkg/_importing.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from __future__ import annotations
2+
import os
3+
import sys
4+
5+
6+
def _py_abspath(path: str) -> str:
7+
"""
8+
special version of abspath
9+
that will leave paths from jython jars alone
10+
"""
11+
if path.startswith("__pyclasspath__"):
12+
return path
13+
else:
14+
return os.path.abspath(path)
15+
16+
17+
def distribution_version(name: str) -> str | None:
18+
"""try to get the version of the named distribution,
19+
returns None on failure"""
20+
if sys.version_info >= (3, 8):
21+
from importlib.metadata import PackageNotFoundError, version
22+
else:
23+
from importlib_metadata import PackageNotFoundError, version
24+
try:
25+
return version(name)
26+
except PackageNotFoundError:
27+
return None
28+
29+

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tox]
22
envlist=py37,py38,py39,py310,py311
3-
3+
isolated_build = True
44
[testenv]
55
deps=pytest
66
commands=pytest []

0 commit comments

Comments
 (0)