omdev 0.0.0.dev16__tar.gz → 0.0.0.dev18__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.
Potentially problematic release.
This version of omdev might be problematic. Click here for more details.
- {omdev-0.0.0.dev16/omdev.egg-info → omdev-0.0.0.dev18}/PKG-INFO +2 -2
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/__about__.py +2 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/cmake.py +7 -23
- omdev-0.0.0.dev18/omdev/cexts/magic.py +7 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/scan.py +5 -6
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/pyproject/cli.py +9 -7
- omdev-0.0.0.dev18/omdev/pyproject/pkg.py +380 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/scripts/pyproject.py +310 -90
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/toml/writer.py +4 -1
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18/omdev.egg-info}/PKG-INFO +2 -2
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev.egg-info/SOURCES.txt +22 -21
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev.egg-info/requires.txt +1 -1
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/pyproject.toml +2 -2
- omdev-0.0.0.dev16/omdev/pyproject/pkg.py +0 -227
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/LICENSE +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/README.rst +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/amalg/amalg.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/bracepy.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/__init__.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/util.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/_distutils/version.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/build.py +0 -0
- {omdev-0.0.0.dev16/omdev/exts → omdev-0.0.0.dev18/omdev/cexts}/importhook.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/classdot.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/findimports.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/findmagic.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/interp/providers.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/interp/pyenv.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/interp/standalone.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/interp/system.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/mypy/__init__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/precheck/__init__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/precheck/precheck.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/pyproject/__main__.py +0 -0
- /omdev-0.0.0.dev16/omdev/pyproject/ext.py → /omdev-0.0.0.dev18/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/scripts/execrss.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/tokens.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/toml/__init__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/toml/parser.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/tools/dockertools.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/tools/gittools.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/tools/revisions.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/tools/traceimport.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/versioning/__init__.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/versioning/specifiers.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/versioning/versions.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev/wheelfile.py +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev16 → omdev-0.0.0.dev18}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev18
|
|
4
4
|
Summary: omdev
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Classifier: Operating System :: POSIX
|
|
13
13
|
Requires-Python: ~=3.12
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
|
15
|
+
Requires-Dist: omlish==0.0.0.dev18
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
|
18
18
|
Requires-Dist: cffi~=1.17; extra == "all"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
FIXME:
|
|
3
3
|
- debug tables don't handle symlinks
|
|
4
|
+
- use relapths in cml.txt
|
|
4
5
|
|
|
5
6
|
TODO:
|
|
6
7
|
- symlink headers, included src files (hamt_impl, ...)
|
|
@@ -37,6 +38,7 @@ from omlish import logs
|
|
|
37
38
|
|
|
38
39
|
from .. import cmake
|
|
39
40
|
from .. import findmagic
|
|
41
|
+
from .magic import CextMagic
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
log = logging.getLogger(__name__)
|
|
@@ -45,12 +47,6 @@ log = logging.getLogger(__name__)
|
|
|
45
47
|
##
|
|
46
48
|
|
|
47
49
|
|
|
48
|
-
MAGIC = '@omdev-ext'
|
|
49
|
-
MAGIC_COMMENT = f'// {MAGIC}'
|
|
50
|
-
|
|
51
|
-
FILE_EXTENSIONS = ('c', 'cc', 'cpp')
|
|
52
|
-
|
|
53
|
-
|
|
54
50
|
def _sep_str_grps(*ls: ta.Sequence[str]) -> list[str]:
|
|
55
51
|
o = []
|
|
56
52
|
for i, l in enumerate(ls):
|
|
@@ -87,7 +83,7 @@ class CmakeProjectGen:
|
|
|
87
83
|
|
|
88
84
|
@lang.cached_function
|
|
89
85
|
def cmake_dir(self) -> str:
|
|
90
|
-
cmake_dir = os.path.join(self.prj_root, 'cmake')
|
|
86
|
+
cmake_dir = os.path.join(self.prj_root, 'cmake', self.prj_name())
|
|
91
87
|
if os.path.exists(cmake_dir):
|
|
92
88
|
for e in os.listdir(cmake_dir):
|
|
93
89
|
if e == '.idea':
|
|
@@ -98,7 +94,7 @@ class CmakeProjectGen:
|
|
|
98
94
|
else:
|
|
99
95
|
shutil.rmtree(ep)
|
|
100
96
|
else:
|
|
101
|
-
os.
|
|
97
|
+
os.makedirs(cmake_dir)
|
|
102
98
|
return cmake_dir
|
|
103
99
|
|
|
104
100
|
#
|
|
@@ -109,17 +105,6 @@ class CmakeProjectGen:
|
|
|
109
105
|
|
|
110
106
|
#
|
|
111
107
|
|
|
112
|
-
def write_idea_name(self) -> None:
|
|
113
|
-
idea_dir = os.path.join(self.cmake_dir(), '.idea')
|
|
114
|
-
if not os.path.isdir(idea_dir):
|
|
115
|
-
os.mkdir(idea_dir)
|
|
116
|
-
idea_name_file = os.path.join(idea_dir, '.name')
|
|
117
|
-
if not os.path.isfile(idea_name_file):
|
|
118
|
-
with open(idea_name_file, 'w') as f:
|
|
119
|
-
f.write(self.prj_name())
|
|
120
|
-
|
|
121
|
-
#
|
|
122
|
-
|
|
123
108
|
@dc.dataclass(frozen=True, kw_only=True)
|
|
124
109
|
class PyInfo:
|
|
125
110
|
venv_exe: str
|
|
@@ -153,8 +138,8 @@ class CmakeProjectGen:
|
|
|
153
138
|
out.extend(
|
|
154
139
|
findmagic.find_magic(
|
|
155
140
|
[e],
|
|
156
|
-
[MAGIC_COMMENT],
|
|
157
|
-
FILE_EXTENSIONS,
|
|
141
|
+
[CextMagic.MAGIC_COMMENT],
|
|
142
|
+
CextMagic.FILE_EXTENSIONS,
|
|
158
143
|
),
|
|
159
144
|
)
|
|
160
145
|
else:
|
|
@@ -224,7 +209,7 @@ class CmakeProjectGen:
|
|
|
224
209
|
[
|
|
225
210
|
' '.join([
|
|
226
211
|
'COMMAND ${CMAKE_COMMAND} -E ',
|
|
227
|
-
f'copy $<TARGET_FILE_NAME:{ext_name}>
|
|
212
|
+
f'copy $<TARGET_FILE_NAME:{ext_name}> ../../../{os.path.dirname(ext_src)}/{so_name}',
|
|
228
213
|
]),
|
|
229
214
|
'COMMAND_EXPAND_LISTS',
|
|
230
215
|
],
|
|
@@ -311,7 +296,6 @@ class CmakeProjectGen:
|
|
|
311
296
|
|
|
312
297
|
self.cmake_dir()
|
|
313
298
|
self.write_git_ignore()
|
|
314
|
-
self.write_idea_name()
|
|
315
299
|
|
|
316
300
|
out = io.StringIO()
|
|
317
301
|
clg = self._CmakeListsGen(self, out)
|
|
@@ -5,18 +5,17 @@ import typing as ta
|
|
|
5
5
|
|
|
6
6
|
from omlish import logs
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
log = logging.getLogger(__name__)
|
|
8
|
+
from .magic import CextMagic
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
log = logging.getLogger(__name__)
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
def scan_one(
|
|
16
15
|
input_path: str,
|
|
17
16
|
**kwargs: ta.Any,
|
|
18
17
|
) -> None:
|
|
19
|
-
if not any(input_path.endswith(fx) for fx in
|
|
18
|
+
if not any(input_path.endswith('.' + fx) for fx in CextMagic.FILE_EXTENSIONS):
|
|
20
19
|
return
|
|
21
20
|
|
|
22
21
|
with open(input_path, 'rb') as f:
|
|
@@ -27,9 +26,9 @@ def scan_one(
|
|
|
27
26
|
except UnicodeDecodeError:
|
|
28
27
|
return
|
|
29
28
|
|
|
30
|
-
sls = [l for l in src.splitlines() if l.startswith(
|
|
29
|
+
sls = [l for l in src.splitlines() if l.startswith(CextMagic.MAGIC_COMMENT)]
|
|
31
30
|
for sl in sls:
|
|
32
|
-
sas = sl[len(
|
|
31
|
+
sas = sl[len(CextMagic.MAGIC_COMMENT):].split() # noqa
|
|
33
32
|
|
|
34
33
|
log.info('Found ext: %s', input_path)
|
|
35
34
|
|
|
@@ -301,10 +301,10 @@ def _pkg_cmd(args) -> None:
|
|
|
301
301
|
raise Exception('must specify command')
|
|
302
302
|
|
|
303
303
|
elif cmd == 'gen':
|
|
304
|
-
|
|
304
|
+
pkgs_root = os.path.join('.pkg')
|
|
305
305
|
|
|
306
|
-
if os.path.exists(
|
|
307
|
-
shutil.rmtree(
|
|
306
|
+
if os.path.exists(pkgs_root):
|
|
307
|
+
shutil.rmtree(pkgs_root)
|
|
308
308
|
|
|
309
309
|
build_output_dir = 'dist'
|
|
310
310
|
run_build = bool(args.build)
|
|
@@ -319,11 +319,13 @@ def _pkg_cmd(args) -> None:
|
|
|
319
319
|
ex.submit(functools.partial(
|
|
320
320
|
PyprojectPackageGenerator(
|
|
321
321
|
dir_name,
|
|
322
|
-
|
|
322
|
+
pkgs_root,
|
|
323
323
|
).gen,
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
324
|
+
PyprojectPackageGenerator.GenOpts(
|
|
325
|
+
run_build=run_build,
|
|
326
|
+
build_output_dir=build_output_dir,
|
|
327
|
+
add_revision=add_revision,
|
|
328
|
+
),
|
|
327
329
|
))
|
|
328
330
|
for dir_name in run.cfg().pkgs
|
|
329
331
|
]
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- ext scanning
|
|
4
|
+
- __revision__
|
|
5
|
+
- entry_points
|
|
6
|
+
|
|
7
|
+
https://setuptools.pypa.io/en/latest/references/keywords.html
|
|
8
|
+
https://packaging.python.org/en/latest/specifications/pyproject-toml
|
|
9
|
+
|
|
10
|
+
How to build a C extension in keeping with PEP 517, i.e. with pyproject.toml instead of setup.py?
|
|
11
|
+
https://stackoverflow.com/a/66479252
|
|
12
|
+
|
|
13
|
+
https://github.com/pypa/sampleproject/blob/db5806e0a3204034c51b1c00dde7d5eb3fa2532e/setup.py
|
|
14
|
+
|
|
15
|
+
https://pip.pypa.io/en/stable/cli/pip_install/#vcs-support
|
|
16
|
+
vcs+protocol://repo_url/#egg=pkg&subdirectory=pkg_dir
|
|
17
|
+
'git+https://github.com/wrmsr/omlish@master#subdirectory=.pip/omlish'
|
|
18
|
+
"""
|
|
19
|
+
# ruff: noqa: UP006 UP007
|
|
20
|
+
import abc
|
|
21
|
+
import dataclasses as dc
|
|
22
|
+
import importlib
|
|
23
|
+
import os.path
|
|
24
|
+
import shutil
|
|
25
|
+
import subprocess
|
|
26
|
+
import sys
|
|
27
|
+
import types
|
|
28
|
+
import typing as ta
|
|
29
|
+
|
|
30
|
+
from omlish.lite.cached import cached_nullary
|
|
31
|
+
from omlish.lite.logs import log
|
|
32
|
+
|
|
33
|
+
from ..cexts.magic import CextMagic
|
|
34
|
+
from ..findmagic import find_magic
|
|
35
|
+
from ..toml.writer import TomlWriter
|
|
36
|
+
from ..tools.revisions import GitRevisionAdder
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class BasePyprojectPackageGenerator(abc.ABC):
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
dir_name: str,
|
|
46
|
+
pkgs_root: str,
|
|
47
|
+
*,
|
|
48
|
+
pkg_suffix: str = '',
|
|
49
|
+
) -> None:
|
|
50
|
+
super().__init__()
|
|
51
|
+
self._dir_name = dir_name
|
|
52
|
+
self._pkgs_root = pkgs_root
|
|
53
|
+
self._pkg_suffix = pkg_suffix
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
|
|
57
|
+
@cached_nullary
|
|
58
|
+
def about(self) -> types.ModuleType:
|
|
59
|
+
return importlib.import_module(f'{self._dir_name}.__about__')
|
|
60
|
+
|
|
61
|
+
#
|
|
62
|
+
|
|
63
|
+
@cached_nullary
|
|
64
|
+
def _pkg_dir(self) -> str:
|
|
65
|
+
pkg_dir: str = os.path.join(self._pkgs_root, self._dir_name + self._pkg_suffix)
|
|
66
|
+
if os.path.isdir(pkg_dir):
|
|
67
|
+
shutil.rmtree(pkg_dir)
|
|
68
|
+
os.makedirs(pkg_dir)
|
|
69
|
+
return pkg_dir
|
|
70
|
+
|
|
71
|
+
#
|
|
72
|
+
|
|
73
|
+
_GIT_IGNORE: ta.Sequence[str] = [
|
|
74
|
+
'/*.egg-info/',
|
|
75
|
+
'/dist',
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
def _write_git_ignore(self) -> None:
|
|
79
|
+
with open(os.path.join(self._pkg_dir(), '.gitignore'), 'w') as f:
|
|
80
|
+
f.write('\n'.join(self._GIT_IGNORE))
|
|
81
|
+
|
|
82
|
+
#
|
|
83
|
+
|
|
84
|
+
def _symlink_source_dir(self) -> None:
|
|
85
|
+
os.symlink(
|
|
86
|
+
os.path.relpath(self._dir_name, self._pkg_dir()),
|
|
87
|
+
os.path.join(self._pkg_dir(), self._dir_name),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
#
|
|
91
|
+
|
|
92
|
+
@cached_nullary
|
|
93
|
+
def project_cls(self) -> type:
|
|
94
|
+
return self.about().Project
|
|
95
|
+
|
|
96
|
+
@cached_nullary
|
|
97
|
+
def setuptools_cls(self) -> type:
|
|
98
|
+
return self.about().Setuptools
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def _build_cls_dct(cls: type) -> ta.Dict[str, ta.Any]: # noqa
|
|
102
|
+
dct = {}
|
|
103
|
+
for b in reversed(cls.__mro__):
|
|
104
|
+
for k, v in b.__dict__.items():
|
|
105
|
+
if k.startswith('_'):
|
|
106
|
+
continue
|
|
107
|
+
dct[k] = v
|
|
108
|
+
return dct
|
|
109
|
+
|
|
110
|
+
@staticmethod
|
|
111
|
+
def _move_dict_key(
|
|
112
|
+
sd: ta.Dict[str, ta.Any],
|
|
113
|
+
sk: str,
|
|
114
|
+
dd: ta.Dict[str, ta.Any],
|
|
115
|
+
dk: str,
|
|
116
|
+
) -> None:
|
|
117
|
+
if sk in sd:
|
|
118
|
+
dd[dk] = sd.pop(sk)
|
|
119
|
+
|
|
120
|
+
@dc.dataclass(frozen=True)
|
|
121
|
+
class Specs:
|
|
122
|
+
pyproject: ta.Dict[str, ta.Any]
|
|
123
|
+
setuptools: ta.Dict[str, ta.Any]
|
|
124
|
+
|
|
125
|
+
def build_specs(self) -> Specs:
|
|
126
|
+
return self.Specs(
|
|
127
|
+
self._build_cls_dct(self.project_cls()),
|
|
128
|
+
self._build_cls_dct(self.setuptools_cls()),
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
#
|
|
132
|
+
|
|
133
|
+
@abc.abstractmethod
|
|
134
|
+
def _write_file_contents(self) -> None:
|
|
135
|
+
raise NotImplementedError
|
|
136
|
+
|
|
137
|
+
#
|
|
138
|
+
|
|
139
|
+
_STANDARD_FILES: ta.Sequence[str] = [
|
|
140
|
+
'LICENSE',
|
|
141
|
+
'README.rst',
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
def _symlink_standard_files(self) -> None:
|
|
145
|
+
for fn in self._STANDARD_FILES:
|
|
146
|
+
if os.path.exists(fn):
|
|
147
|
+
os.symlink(os.path.relpath(fn, self._pkg_dir()), os.path.join(self._pkg_dir(), fn))
|
|
148
|
+
|
|
149
|
+
#
|
|
150
|
+
|
|
151
|
+
def _run_build(
|
|
152
|
+
self,
|
|
153
|
+
build_output_dir: ta.Optional[str] = None,
|
|
154
|
+
*,
|
|
155
|
+
add_revision: bool = False,
|
|
156
|
+
) -> None:
|
|
157
|
+
subprocess.check_call(
|
|
158
|
+
[
|
|
159
|
+
sys.executable,
|
|
160
|
+
'-m',
|
|
161
|
+
'build',
|
|
162
|
+
],
|
|
163
|
+
cwd=self._pkg_dir(),
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
dist_dir = os.path.join(self._pkg_dir(), 'dist')
|
|
167
|
+
|
|
168
|
+
if add_revision:
|
|
169
|
+
GitRevisionAdder().add_to(dist_dir)
|
|
170
|
+
|
|
171
|
+
if build_output_dir is not None:
|
|
172
|
+
for fn in os.listdir(dist_dir):
|
|
173
|
+
shutil.copyfile(os.path.join(dist_dir, fn), os.path.join(build_output_dir, fn))
|
|
174
|
+
|
|
175
|
+
#
|
|
176
|
+
|
|
177
|
+
@dc.dataclass(frozen=True)
|
|
178
|
+
class GenOpts:
|
|
179
|
+
run_build: bool = False
|
|
180
|
+
build_output_dir: ta.Optional[str] = None
|
|
181
|
+
add_revision: bool = False
|
|
182
|
+
|
|
183
|
+
def gen(self, opts: GenOpts = GenOpts()) -> str:
|
|
184
|
+
log.info('Generating pyproject package: %s -> %s (%s)', self._dir_name, self._pkgs_root, self._pkg_suffix)
|
|
185
|
+
|
|
186
|
+
self._pkg_dir()
|
|
187
|
+
self._write_git_ignore()
|
|
188
|
+
self._symlink_source_dir()
|
|
189
|
+
self._write_file_contents()
|
|
190
|
+
self._symlink_standard_files()
|
|
191
|
+
|
|
192
|
+
if opts.run_build:
|
|
193
|
+
self._run_build(
|
|
194
|
+
opts.build_output_dir,
|
|
195
|
+
add_revision=opts.add_revision,
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
return self._pkg_dir()
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
#
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class PyprojectPackageGenerator(BasePyprojectPackageGenerator):
|
|
205
|
+
|
|
206
|
+
#
|
|
207
|
+
|
|
208
|
+
@dc.dataclass(frozen=True)
|
|
209
|
+
class FileContents:
|
|
210
|
+
pyproject_dct: ta.Mapping[str, ta.Any]
|
|
211
|
+
manifest_in: ta.Optional[ta.Sequence[str]]
|
|
212
|
+
|
|
213
|
+
@cached_nullary
|
|
214
|
+
def file_contents(self) -> FileContents:
|
|
215
|
+
specs = self.build_specs()
|
|
216
|
+
|
|
217
|
+
#
|
|
218
|
+
|
|
219
|
+
pyp_dct = {}
|
|
220
|
+
|
|
221
|
+
pyp_dct['build-system'] = {
|
|
222
|
+
'requires': ['setuptools'],
|
|
223
|
+
'build-backend': 'setuptools.build_meta',
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
prj = specs.pyproject
|
|
227
|
+
prj['name'] += self._pkg_suffix
|
|
228
|
+
|
|
229
|
+
pyp_dct['project'] = prj
|
|
230
|
+
|
|
231
|
+
self._move_dict_key(prj, 'optional_dependencies', pyp_dct, extrask := 'project.optional-dependencies')
|
|
232
|
+
if (extras := pyp_dct.get(extrask)):
|
|
233
|
+
pyp_dct[extrask] = {
|
|
234
|
+
'all': [
|
|
235
|
+
e
|
|
236
|
+
for lst in extras.values()
|
|
237
|
+
for e in lst
|
|
238
|
+
],
|
|
239
|
+
**extras,
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
#
|
|
243
|
+
|
|
244
|
+
st = specs.setuptools
|
|
245
|
+
pyp_dct['tool.setuptools'] = st
|
|
246
|
+
|
|
247
|
+
st.pop('cexts', None)
|
|
248
|
+
|
|
249
|
+
self._move_dict_key(st, 'find_packages', pyp_dct, 'tool.setuptools.packages.find')
|
|
250
|
+
|
|
251
|
+
mani_in = st.pop('manifest_in', None)
|
|
252
|
+
|
|
253
|
+
#
|
|
254
|
+
|
|
255
|
+
return self.FileContents(
|
|
256
|
+
pyp_dct,
|
|
257
|
+
mani_in,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
def _write_file_contents(self) -> None:
|
|
261
|
+
fc = self.file_contents()
|
|
262
|
+
|
|
263
|
+
with open(os.path.join(self._pkg_dir(), 'pyproject.toml'), 'w') as f:
|
|
264
|
+
TomlWriter(f).write_root(fc.pyproject_dct)
|
|
265
|
+
|
|
266
|
+
if fc.manifest_in:
|
|
267
|
+
with open(os.path.join(self._pkg_dir(), 'MANIFEST.in'), 'w') as f:
|
|
268
|
+
f.write('\n'.join(fc.manifest_in)) # noqa
|
|
269
|
+
|
|
270
|
+
#
|
|
271
|
+
|
|
272
|
+
def gen(self, opts: BasePyprojectPackageGenerator.GenOpts = BasePyprojectPackageGenerator.GenOpts()) -> str:
|
|
273
|
+
ret = super().gen(opts)
|
|
274
|
+
|
|
275
|
+
if self.build_specs().setuptools.get('cexts'):
|
|
276
|
+
_PyprojectCextPackageGenerator(
|
|
277
|
+
self._dir_name,
|
|
278
|
+
self._pkgs_root,
|
|
279
|
+
pkg_suffix='-cext',
|
|
280
|
+
).gen(opts)
|
|
281
|
+
|
|
282
|
+
return ret
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
#
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
|
|
289
|
+
|
|
290
|
+
#
|
|
291
|
+
|
|
292
|
+
@cached_nullary
|
|
293
|
+
def find_cext_srcs(self) -> ta.Sequence[str]:
|
|
294
|
+
return sorted(find_magic(
|
|
295
|
+
[self._dir_name],
|
|
296
|
+
[CextMagic.MAGIC_COMMENT],
|
|
297
|
+
CextMagic.FILE_EXTENSIONS,
|
|
298
|
+
))
|
|
299
|
+
|
|
300
|
+
#
|
|
301
|
+
|
|
302
|
+
@dc.dataclass(frozen=True)
|
|
303
|
+
class FileContents:
|
|
304
|
+
pyproject_dct: ta.Mapping[str, ta.Any]
|
|
305
|
+
setup_py: str
|
|
306
|
+
|
|
307
|
+
@cached_nullary
|
|
308
|
+
def file_contents(self) -> FileContents:
|
|
309
|
+
specs = self.build_specs()
|
|
310
|
+
|
|
311
|
+
#
|
|
312
|
+
|
|
313
|
+
pyp_dct = {}
|
|
314
|
+
|
|
315
|
+
pyp_dct['build-system'] = {
|
|
316
|
+
'requires': ['setuptools'],
|
|
317
|
+
'build-backend': 'setuptools.build_meta',
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
prj = specs.pyproject
|
|
321
|
+
prj['dependencies'] = [f'{prj["name"]} == {prj["version"]}']
|
|
322
|
+
prj['name'] += self._pkg_suffix
|
|
323
|
+
prj.pop('optional_dependencies', None)
|
|
324
|
+
|
|
325
|
+
pyp_dct['project'] = prj
|
|
326
|
+
|
|
327
|
+
#
|
|
328
|
+
|
|
329
|
+
st = specs.setuptools
|
|
330
|
+
pyp_dct['tool.setuptools'] = st
|
|
331
|
+
|
|
332
|
+
st.pop('cexts', None)
|
|
333
|
+
st.pop('find_packages', None)
|
|
334
|
+
st.pop('manifest_in', None)
|
|
335
|
+
|
|
336
|
+
pyp_dct['tool.setuptools.packages.find'] = {
|
|
337
|
+
'include': [],
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
#
|
|
341
|
+
|
|
342
|
+
ext_lines = []
|
|
343
|
+
|
|
344
|
+
for ext_src in self.find_cext_srcs():
|
|
345
|
+
ext_name = ext_src.rpartition('.')[0].replace(os.sep, '.')
|
|
346
|
+
ext_lines.extend([
|
|
347
|
+
'st.Extension(',
|
|
348
|
+
f" name='{ext_name}',",
|
|
349
|
+
f" sources=['{ext_src}'],",
|
|
350
|
+
" extra_compile_args=['-std=c++20'],",
|
|
351
|
+
'),',
|
|
352
|
+
])
|
|
353
|
+
|
|
354
|
+
src = '\n'.join([
|
|
355
|
+
'import setuptools as st',
|
|
356
|
+
'',
|
|
357
|
+
'',
|
|
358
|
+
'st.setup(',
|
|
359
|
+
' ext_modules=[',
|
|
360
|
+
*[' ' + l for l in ext_lines],
|
|
361
|
+
' ]',
|
|
362
|
+
')',
|
|
363
|
+
'',
|
|
364
|
+
])
|
|
365
|
+
|
|
366
|
+
#
|
|
367
|
+
|
|
368
|
+
return self.FileContents(
|
|
369
|
+
pyp_dct,
|
|
370
|
+
src,
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
def _write_file_contents(self) -> None:
|
|
374
|
+
fc = self.file_contents()
|
|
375
|
+
|
|
376
|
+
with open(os.path.join(self._pkg_dir(), 'pyproject.toml'), 'w') as f:
|
|
377
|
+
TomlWriter(f).write_root(fc.pyproject_dct)
|
|
378
|
+
|
|
379
|
+
with open(os.path.join(self._pkg_dir(), 'setup.py'), 'w') as f:
|
|
380
|
+
f.write(fc.setup_py)
|