omdev 0.0.0.dev17__py3-none-any.whl → 0.0.0.dev19__py3-none-any.whl
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/__about__.py +2 -0
- omdev/cexts/cmake.py +7 -23
- omdev/cexts/magic.py +7 -0
- omdev/cexts/scan.py +5 -6
- omdev/pyproject/cli.py +9 -7
- omdev/pyproject/pkg.py +244 -83
- omdev/scripts/interp.py +1 -1
- omdev/scripts/pyproject.py +320 -92
- omdev/toml/writer.py +4 -1
- {omdev-0.0.0.dev17.dist-info → omdev-0.0.0.dev19.dist-info}/METADATA +2 -2
- {omdev-0.0.0.dev17.dist-info → omdev-0.0.0.dev19.dist-info}/RECORD +15 -14
- /omdev/pyproject/{ext.py → cexts.py} +0 -0
- {omdev-0.0.0.dev17.dist-info → omdev-0.0.0.dev19.dist-info}/LICENSE +0 -0
- {omdev-0.0.0.dev17.dist-info → omdev-0.0.0.dev19.dist-info}/WHEEL +0 -0
- {omdev-0.0.0.dev17.dist-info → omdev-0.0.0.dev19.dist-info}/top_level.txt +0 -0
omdev/__about__.py
CHANGED
omdev/cexts/cmake.py
CHANGED
|
@@ -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-cext'
|
|
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)
|
omdev/cexts/magic.py
ADDED
omdev/cexts/scan.py
CHANGED
|
@@ -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
|
|
omdev/pyproject/cli.py
CHANGED
|
@@ -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
|
]
|
omdev/pyproject/pkg.py
CHANGED
|
@@ -4,6 +4,14 @@ TODO:
|
|
|
4
4
|
- __revision__
|
|
5
5
|
- entry_points
|
|
6
6
|
|
|
7
|
+
** NOTE **
|
|
8
|
+
setuptools now (2024/09/02) has experimental support for extensions in pure pyproject.toml - but we still want a
|
|
9
|
+
separate '-cext' package
|
|
10
|
+
https://setuptools.pypa.io/en/latest/userguide/ext_modules.html
|
|
11
|
+
https://github.com/pypa/setuptools/commit/1a9d87308dc0d8aabeaae0dce989b35dfb7699f0#diff-61d113525e9cc93565799a4bb8b34a68e2945b8a3f7d90c81380614a4ea39542R7-R8
|
|
12
|
+
|
|
13
|
+
--
|
|
14
|
+
|
|
7
15
|
https://setuptools.pypa.io/en/latest/references/keywords.html
|
|
8
16
|
https://packaging.python.org/en/latest/specifications/pyproject-toml
|
|
9
17
|
|
|
@@ -15,8 +23,9 @@ https://github.com/pypa/sampleproject/blob/db5806e0a3204034c51b1c00dde7d5eb3fa25
|
|
|
15
23
|
https://pip.pypa.io/en/stable/cli/pip_install/#vcs-support
|
|
16
24
|
vcs+protocol://repo_url/#egg=pkg&subdirectory=pkg_dir
|
|
17
25
|
'git+https://github.com/wrmsr/omlish@master#subdirectory=.pip/omlish'
|
|
18
|
-
"""
|
|
26
|
+
""" # noqa
|
|
19
27
|
# ruff: noqa: UP006 UP007
|
|
28
|
+
import abc
|
|
20
29
|
import dataclasses as dc
|
|
21
30
|
import importlib
|
|
22
31
|
import os.path
|
|
@@ -29,19 +38,27 @@ import typing as ta
|
|
|
29
38
|
from omlish.lite.cached import cached_nullary
|
|
30
39
|
from omlish.lite.logs import log
|
|
31
40
|
|
|
41
|
+
from ..cexts.magic import CextMagic
|
|
42
|
+
from ..findmagic import find_magic
|
|
32
43
|
from ..toml.writer import TomlWriter
|
|
33
44
|
from ..tools.revisions import GitRevisionAdder
|
|
34
45
|
|
|
35
46
|
|
|
36
|
-
|
|
47
|
+
#
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class BasePyprojectPackageGenerator(abc.ABC):
|
|
37
51
|
def __init__(
|
|
38
52
|
self,
|
|
39
53
|
dir_name: str,
|
|
40
|
-
|
|
54
|
+
pkgs_root: str,
|
|
55
|
+
*,
|
|
56
|
+
pkg_suffix: str = '',
|
|
41
57
|
) -> None:
|
|
42
58
|
super().__init__()
|
|
43
59
|
self._dir_name = dir_name
|
|
44
|
-
self.
|
|
60
|
+
self._pkgs_root = pkgs_root
|
|
61
|
+
self._pkg_suffix = pkg_suffix
|
|
45
62
|
|
|
46
63
|
#
|
|
47
64
|
|
|
@@ -49,48 +66,44 @@ class PyprojectPackageGenerator:
|
|
|
49
66
|
def about(self) -> types.ModuleType:
|
|
50
67
|
return importlib.import_module(f'{self._dir_name}.__about__')
|
|
51
68
|
|
|
52
|
-
@cached_nullary
|
|
53
|
-
def project_cls(self) -> type:
|
|
54
|
-
return self.about().Project
|
|
55
|
-
|
|
56
|
-
@cached_nullary
|
|
57
|
-
def setuptools_cls(self) -> type:
|
|
58
|
-
return self.about().Setuptools
|
|
59
|
-
|
|
60
69
|
#
|
|
61
70
|
|
|
62
71
|
@cached_nullary
|
|
63
|
-
def
|
|
64
|
-
|
|
65
|
-
if os.path.isdir(
|
|
66
|
-
shutil.rmtree(
|
|
67
|
-
os.makedirs(
|
|
68
|
-
return
|
|
72
|
+
def _pkg_dir(self) -> str:
|
|
73
|
+
pkg_dir: str = os.path.join(self._pkgs_root, self._dir_name + self._pkg_suffix)
|
|
74
|
+
if os.path.isdir(pkg_dir):
|
|
75
|
+
shutil.rmtree(pkg_dir)
|
|
76
|
+
os.makedirs(pkg_dir)
|
|
77
|
+
return pkg_dir
|
|
69
78
|
|
|
70
79
|
#
|
|
71
80
|
|
|
81
|
+
_GIT_IGNORE: ta.Sequence[str] = [
|
|
82
|
+
'/*.egg-info/',
|
|
83
|
+
'/dist',
|
|
84
|
+
]
|
|
85
|
+
|
|
72
86
|
def _write_git_ignore(self) -> None:
|
|
73
|
-
|
|
74
|
-
'
|
|
75
|
-
'/dist',
|
|
76
|
-
]
|
|
77
|
-
with open(os.path.join(self._build_dir(), '.gitignore'), 'w') as f:
|
|
78
|
-
f.write('\n'.join(git_ignore))
|
|
87
|
+
with open(os.path.join(self._pkg_dir(), '.gitignore'), 'w') as f:
|
|
88
|
+
f.write('\n'.join(self._GIT_IGNORE))
|
|
79
89
|
|
|
80
90
|
#
|
|
81
91
|
|
|
82
92
|
def _symlink_source_dir(self) -> None:
|
|
83
93
|
os.symlink(
|
|
84
|
-
os.path.relpath(self._dir_name, self.
|
|
85
|
-
os.path.join(self.
|
|
94
|
+
os.path.relpath(self._dir_name, self._pkg_dir()),
|
|
95
|
+
os.path.join(self._pkg_dir(), self._dir_name),
|
|
86
96
|
)
|
|
87
97
|
|
|
88
98
|
#
|
|
89
99
|
|
|
90
|
-
@
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
@cached_nullary
|
|
101
|
+
def project_cls(self) -> type:
|
|
102
|
+
return self.about().Project
|
|
103
|
+
|
|
104
|
+
@cached_nullary
|
|
105
|
+
def setuptools_cls(self) -> type:
|
|
106
|
+
return self.about().Setuptools
|
|
94
107
|
|
|
95
108
|
@staticmethod
|
|
96
109
|
def _build_cls_dct(cls: type) -> ta.Dict[str, ta.Any]: # noqa
|
|
@@ -112,18 +125,115 @@ class PyprojectPackageGenerator:
|
|
|
112
125
|
if sk in sd:
|
|
113
126
|
dd[dk] = sd.pop(sk)
|
|
114
127
|
|
|
128
|
+
@dc.dataclass(frozen=True)
|
|
129
|
+
class Specs:
|
|
130
|
+
pyproject: ta.Dict[str, ta.Any]
|
|
131
|
+
setuptools: ta.Dict[str, ta.Any]
|
|
132
|
+
|
|
133
|
+
def build_specs(self) -> Specs:
|
|
134
|
+
return self.Specs(
|
|
135
|
+
self._build_cls_dct(self.project_cls()),
|
|
136
|
+
self._build_cls_dct(self.setuptools_cls()),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
#
|
|
140
|
+
|
|
141
|
+
@abc.abstractmethod
|
|
142
|
+
def _write_file_contents(self) -> None:
|
|
143
|
+
raise NotImplementedError
|
|
144
|
+
|
|
145
|
+
#
|
|
146
|
+
|
|
147
|
+
_STANDARD_FILES: ta.Sequence[str] = [
|
|
148
|
+
'LICENSE',
|
|
149
|
+
'README.rst',
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
def _symlink_standard_files(self) -> None:
|
|
153
|
+
for fn in self._STANDARD_FILES:
|
|
154
|
+
if os.path.exists(fn):
|
|
155
|
+
os.symlink(os.path.relpath(fn, self._pkg_dir()), os.path.join(self._pkg_dir(), fn))
|
|
156
|
+
|
|
157
|
+
#
|
|
158
|
+
|
|
159
|
+
def _run_build(
|
|
160
|
+
self,
|
|
161
|
+
build_output_dir: ta.Optional[str] = None,
|
|
162
|
+
*,
|
|
163
|
+
add_revision: bool = False,
|
|
164
|
+
) -> None:
|
|
165
|
+
subprocess.check_call(
|
|
166
|
+
[
|
|
167
|
+
sys.executable,
|
|
168
|
+
'-m',
|
|
169
|
+
'build',
|
|
170
|
+
],
|
|
171
|
+
cwd=self._pkg_dir(),
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
dist_dir = os.path.join(self._pkg_dir(), 'dist')
|
|
175
|
+
|
|
176
|
+
if add_revision:
|
|
177
|
+
GitRevisionAdder().add_to(dist_dir)
|
|
178
|
+
|
|
179
|
+
if build_output_dir is not None:
|
|
180
|
+
for fn in os.listdir(dist_dir):
|
|
181
|
+
shutil.copyfile(os.path.join(dist_dir, fn), os.path.join(build_output_dir, fn))
|
|
182
|
+
|
|
183
|
+
#
|
|
184
|
+
|
|
185
|
+
@dc.dataclass(frozen=True)
|
|
186
|
+
class GenOpts:
|
|
187
|
+
run_build: bool = False
|
|
188
|
+
build_output_dir: ta.Optional[str] = None
|
|
189
|
+
add_revision: bool = False
|
|
190
|
+
|
|
191
|
+
def gen(self, opts: GenOpts = GenOpts()) -> str:
|
|
192
|
+
log.info('Generating pyproject package: %s -> %s (%s)', self._dir_name, self._pkgs_root, self._pkg_suffix)
|
|
193
|
+
|
|
194
|
+
self._pkg_dir()
|
|
195
|
+
self._write_git_ignore()
|
|
196
|
+
self._symlink_source_dir()
|
|
197
|
+
self._write_file_contents()
|
|
198
|
+
self._symlink_standard_files()
|
|
199
|
+
|
|
200
|
+
if opts.run_build:
|
|
201
|
+
self._run_build(
|
|
202
|
+
opts.build_output_dir,
|
|
203
|
+
add_revision=opts.add_revision,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
return self._pkg_dir()
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
#
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class PyprojectPackageGenerator(BasePyprojectPackageGenerator):
|
|
213
|
+
|
|
214
|
+
#
|
|
215
|
+
|
|
216
|
+
@dc.dataclass(frozen=True)
|
|
217
|
+
class FileContents:
|
|
218
|
+
pyproject_dct: ta.Mapping[str, ta.Any]
|
|
219
|
+
manifest_in: ta.Optional[ta.Sequence[str]]
|
|
220
|
+
|
|
115
221
|
@cached_nullary
|
|
116
222
|
def file_contents(self) -> FileContents:
|
|
117
|
-
|
|
223
|
+
specs = self.build_specs()
|
|
118
224
|
|
|
119
225
|
#
|
|
120
226
|
|
|
227
|
+
pyp_dct = {}
|
|
228
|
+
|
|
121
229
|
pyp_dct['build-system'] = {
|
|
122
230
|
'requires': ['setuptools'],
|
|
123
231
|
'build-backend': 'setuptools.build_meta',
|
|
124
232
|
}
|
|
125
233
|
|
|
126
|
-
prj =
|
|
234
|
+
prj = specs.pyproject
|
|
235
|
+
prj['name'] += self._pkg_suffix
|
|
236
|
+
|
|
127
237
|
pyp_dct['project'] = prj
|
|
128
238
|
|
|
129
239
|
self._move_dict_key(prj, 'optional_dependencies', pyp_dct, extrask := 'project.optional-dependencies')
|
|
@@ -139,9 +249,11 @@ class PyprojectPackageGenerator:
|
|
|
139
249
|
|
|
140
250
|
#
|
|
141
251
|
|
|
142
|
-
st =
|
|
252
|
+
st = specs.setuptools
|
|
143
253
|
pyp_dct['tool.setuptools'] = st
|
|
144
254
|
|
|
255
|
+
st.pop('cexts', None)
|
|
256
|
+
|
|
145
257
|
self._move_dict_key(st, 'find_packages', pyp_dct, 'tool.setuptools.packages.find')
|
|
146
258
|
|
|
147
259
|
mani_in = st.pop('manifest_in', None)
|
|
@@ -156,72 +268,121 @@ class PyprojectPackageGenerator:
|
|
|
156
268
|
def _write_file_contents(self) -> None:
|
|
157
269
|
fc = self.file_contents()
|
|
158
270
|
|
|
159
|
-
with open(os.path.join(self.
|
|
271
|
+
with open(os.path.join(self._pkg_dir(), 'pyproject.toml'), 'w') as f:
|
|
160
272
|
TomlWriter(f).write_root(fc.pyproject_dct)
|
|
161
273
|
|
|
162
274
|
if fc.manifest_in:
|
|
163
|
-
with open(os.path.join(self.
|
|
275
|
+
with open(os.path.join(self._pkg_dir(), 'MANIFEST.in'), 'w') as f:
|
|
164
276
|
f.write('\n'.join(fc.manifest_in)) # noqa
|
|
165
277
|
|
|
166
278
|
#
|
|
167
279
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
'README.rst',
|
|
171
|
-
]
|
|
280
|
+
def gen(self, opts: BasePyprojectPackageGenerator.GenOpts = BasePyprojectPackageGenerator.GenOpts()) -> str:
|
|
281
|
+
ret = super().gen(opts)
|
|
172
282
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
283
|
+
if self.build_specs().setuptools.get('cexts'):
|
|
284
|
+
_PyprojectCextPackageGenerator(
|
|
285
|
+
self._dir_name,
|
|
286
|
+
self._pkgs_root,
|
|
287
|
+
pkg_suffix='-cext',
|
|
288
|
+
).gen(opts)
|
|
177
289
|
|
|
178
|
-
|
|
290
|
+
return ret
|
|
179
291
|
|
|
180
|
-
def _run_build(
|
|
181
|
-
self,
|
|
182
|
-
build_output_dir: ta.Optional[str] = None,
|
|
183
|
-
*,
|
|
184
|
-
add_revision: bool = False,
|
|
185
|
-
) -> None:
|
|
186
|
-
subprocess.check_call(
|
|
187
|
-
[
|
|
188
|
-
sys.executable,
|
|
189
|
-
'-m',
|
|
190
|
-
'build',
|
|
191
|
-
],
|
|
192
|
-
cwd=self._build_dir(),
|
|
193
|
-
)
|
|
194
292
|
|
|
195
|
-
|
|
293
|
+
#
|
|
196
294
|
|
|
197
|
-
if add_revision:
|
|
198
|
-
GitRevisionAdder().add_to(dist_dir)
|
|
199
295
|
|
|
200
|
-
|
|
201
|
-
for fn in os.listdir(dist_dir):
|
|
202
|
-
shutil.copyfile(os.path.join(dist_dir, fn), os.path.join(build_output_dir, fn))
|
|
296
|
+
class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
|
|
203
297
|
|
|
204
298
|
#
|
|
205
299
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
log.info('Generating pyproject package: %s -> %s', self._dir_name, self._build_root)
|
|
300
|
+
@cached_nullary
|
|
301
|
+
def find_cext_srcs(self) -> ta.Sequence[str]:
|
|
302
|
+
return sorted(find_magic(
|
|
303
|
+
[self._dir_name],
|
|
304
|
+
[CextMagic.MAGIC_COMMENT],
|
|
305
|
+
CextMagic.FILE_EXTENSIONS,
|
|
306
|
+
))
|
|
214
307
|
|
|
215
|
-
|
|
216
|
-
self._write_git_ignore()
|
|
217
|
-
self._symlink_source_dir()
|
|
218
|
-
self._write_file_contents()
|
|
219
|
-
self._symlink_standard_files()
|
|
308
|
+
#
|
|
220
309
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
310
|
+
@dc.dataclass(frozen=True)
|
|
311
|
+
class FileContents:
|
|
312
|
+
pyproject_dct: ta.Mapping[str, ta.Any]
|
|
313
|
+
setup_py: str
|
|
314
|
+
|
|
315
|
+
@cached_nullary
|
|
316
|
+
def file_contents(self) -> FileContents:
|
|
317
|
+
specs = self.build_specs()
|
|
318
|
+
|
|
319
|
+
#
|
|
320
|
+
|
|
321
|
+
pyp_dct = {}
|
|
322
|
+
|
|
323
|
+
pyp_dct['build-system'] = {
|
|
324
|
+
'requires': ['setuptools'],
|
|
325
|
+
'build-backend': 'setuptools.build_meta',
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
prj = specs.pyproject
|
|
329
|
+
prj['dependencies'] = [f'{prj["name"]} == {prj["version"]}']
|
|
330
|
+
prj['name'] += self._pkg_suffix
|
|
331
|
+
prj.pop('optional_dependencies', None)
|
|
332
|
+
|
|
333
|
+
pyp_dct['project'] = prj
|
|
334
|
+
|
|
335
|
+
#
|
|
336
|
+
|
|
337
|
+
st = specs.setuptools
|
|
338
|
+
pyp_dct['tool.setuptools'] = st
|
|
339
|
+
|
|
340
|
+
st.pop('cexts', None)
|
|
341
|
+
st.pop('find_packages', None)
|
|
342
|
+
st.pop('manifest_in', None)
|
|
343
|
+
|
|
344
|
+
pyp_dct['tool.setuptools.packages.find'] = {
|
|
345
|
+
'include': [],
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
#
|
|
349
|
+
|
|
350
|
+
ext_lines = []
|
|
351
|
+
|
|
352
|
+
for ext_src in self.find_cext_srcs():
|
|
353
|
+
ext_name = ext_src.rpartition('.')[0].replace(os.sep, '.')
|
|
354
|
+
ext_lines.extend([
|
|
355
|
+
'st.Extension(',
|
|
356
|
+
f" name='{ext_name}',",
|
|
357
|
+
f" sources=['{ext_src}'],",
|
|
358
|
+
" extra_compile_args=['-std=c++20'],",
|
|
359
|
+
'),',
|
|
360
|
+
])
|
|
361
|
+
|
|
362
|
+
src = '\n'.join([
|
|
363
|
+
'import setuptools as st',
|
|
364
|
+
'',
|
|
365
|
+
'',
|
|
366
|
+
'st.setup(',
|
|
367
|
+
' ext_modules=[',
|
|
368
|
+
*[' ' + l for l in ext_lines],
|
|
369
|
+
' ]',
|
|
370
|
+
')',
|
|
371
|
+
'',
|
|
372
|
+
])
|
|
373
|
+
|
|
374
|
+
#
|
|
375
|
+
|
|
376
|
+
return self.FileContents(
|
|
377
|
+
pyp_dct,
|
|
378
|
+
src,
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
def _write_file_contents(self) -> None:
|
|
382
|
+
fc = self.file_contents()
|
|
383
|
+
|
|
384
|
+
with open(os.path.join(self._pkg_dir(), 'pyproject.toml'), 'w') as f:
|
|
385
|
+
TomlWriter(f).write_root(fc.pyproject_dct)
|
|
226
386
|
|
|
227
|
-
|
|
387
|
+
with open(os.path.join(self._pkg_dir(), 'setup.py'), 'w') as f:
|
|
388
|
+
f.write(fc.setup_py)
|
omdev/scripts/interp.py
CHANGED
|
@@ -1206,7 +1206,7 @@ class JsonLogFormatter(logging.Formatter):
|
|
|
1206
1206
|
STANDARD_LOG_FORMAT_PARTS = [
|
|
1207
1207
|
('asctime', '%(asctime)-15s'),
|
|
1208
1208
|
('process', 'pid=%(process)-6s'),
|
|
1209
|
-
('thread', 'tid=%(thread)-
|
|
1209
|
+
('thread', 'tid=%(thread)-10x'),
|
|
1210
1210
|
('levelname', '%(levelname)-8s'),
|
|
1211
1211
|
('name', '%(name)s'),
|
|
1212
1212
|
('separator', '::'),
|
omdev/scripts/pyproject.py
CHANGED
|
@@ -86,6 +86,71 @@ UnparsedVersionVar = ta.TypeVar('UnparsedVersionVar', bound=UnparsedVersion)
|
|
|
86
86
|
CallableVersionOperator = ta.Callable[['Version', str], bool]
|
|
87
87
|
|
|
88
88
|
|
|
89
|
+
########################################
|
|
90
|
+
# ../../cexts/magic.py
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class CextMagic:
|
|
94
|
+
MAGIC = '@omdev-cext'
|
|
95
|
+
MAGIC_COMMENT = f'// {MAGIC}'
|
|
96
|
+
|
|
97
|
+
FILE_EXTENSIONS = ('c', 'cc', 'cpp')
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
########################################
|
|
101
|
+
# ../../findmagic.py
|
|
102
|
+
# @omlish-script
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def compile_magic_pat(m: str) -> re.Pattern:
|
|
106
|
+
return re.compile('^' + re.escape(m) + r'($|(\s.*))')
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def find_magic(
|
|
110
|
+
roots: ta.Sequence[str],
|
|
111
|
+
magics: ta.Sequence[str],
|
|
112
|
+
exts: ta.Sequence[str],
|
|
113
|
+
*,
|
|
114
|
+
py: bool = False,
|
|
115
|
+
) -> ta.Iterator[str]:
|
|
116
|
+
if not magics:
|
|
117
|
+
raise Exception('Must specify magics')
|
|
118
|
+
if not exts:
|
|
119
|
+
raise Exception('Must specify extensions')
|
|
120
|
+
|
|
121
|
+
pats = [compile_magic_pat(m) for m in magics]
|
|
122
|
+
|
|
123
|
+
for root in roots:
|
|
124
|
+
for dp, dns, fns in os.walk(root): # noqa
|
|
125
|
+
for fn in fns:
|
|
126
|
+
if not any(fn.endswith(f'.{x}') for x in exts):
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
fp = os.path.join(dp, fn)
|
|
130
|
+
try:
|
|
131
|
+
with open(fp) as f:
|
|
132
|
+
src = f.read()
|
|
133
|
+
except UnicodeDecodeError:
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
if not any(
|
|
137
|
+
any(pat.fullmatch(l) for pat in pats)
|
|
138
|
+
for l in src.splitlines()
|
|
139
|
+
):
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
if py:
|
|
143
|
+
if fn == '__init__.py':
|
|
144
|
+
out = dp.replace(os.sep, '.')
|
|
145
|
+
elif fn.endswith('.py'):
|
|
146
|
+
out = fp[:-3].replace(os.sep, '.')
|
|
147
|
+
else:
|
|
148
|
+
out = fp
|
|
149
|
+
else:
|
|
150
|
+
out = fp
|
|
151
|
+
yield out
|
|
152
|
+
|
|
153
|
+
|
|
89
154
|
########################################
|
|
90
155
|
# ../../toml/parser.py
|
|
91
156
|
# SPDX-License-Identifier: MIT
|
|
@@ -1003,7 +1068,10 @@ class TomlWriter:
|
|
|
1003
1068
|
elif isinstance(obj, ta.Mapping):
|
|
1004
1069
|
self.write_inline_table(obj)
|
|
1005
1070
|
elif isinstance(obj, ta.Sequence):
|
|
1006
|
-
|
|
1071
|
+
if not obj:
|
|
1072
|
+
self.write_inline_array(obj)
|
|
1073
|
+
else:
|
|
1074
|
+
self.write_array(obj)
|
|
1007
1075
|
else:
|
|
1008
1076
|
raise TypeError(obj)
|
|
1009
1077
|
|
|
@@ -2405,7 +2473,7 @@ class JsonLogFormatter(logging.Formatter):
|
|
|
2405
2473
|
STANDARD_LOG_FORMAT_PARTS = [
|
|
2406
2474
|
('asctime', '%(asctime)-15s'),
|
|
2407
2475
|
('process', 'pid=%(process)-6s'),
|
|
2408
|
-
('thread', 'tid=%(thread)-
|
|
2476
|
+
('thread', 'tid=%(thread)-10x'),
|
|
2409
2477
|
('levelname', '%(levelname)-8s'),
|
|
2410
2478
|
('name', '%(name)s'),
|
|
2411
2479
|
('separator', '::'),
|
|
@@ -3320,6 +3388,14 @@ TODO:
|
|
|
3320
3388
|
- __revision__
|
|
3321
3389
|
- entry_points
|
|
3322
3390
|
|
|
3391
|
+
** NOTE **
|
|
3392
|
+
setuptools now (2024/09/02) has experimental support for extensions in pure pyproject.toml - but we still want a
|
|
3393
|
+
separate '-cext' package
|
|
3394
|
+
https://setuptools.pypa.io/en/latest/userguide/ext_modules.html
|
|
3395
|
+
https://github.com/pypa/setuptools/commit/1a9d87308dc0d8aabeaae0dce989b35dfb7699f0#diff-61d113525e9cc93565799a4bb8b34a68e2945b8a3f7d90c81380614a4ea39542R7-R8
|
|
3396
|
+
|
|
3397
|
+
--
|
|
3398
|
+
|
|
3323
3399
|
https://setuptools.pypa.io/en/latest/references/keywords.html
|
|
3324
3400
|
https://packaging.python.org/en/latest/specifications/pyproject-toml
|
|
3325
3401
|
|
|
@@ -3331,19 +3407,25 @@ https://github.com/pypa/sampleproject/blob/db5806e0a3204034c51b1c00dde7d5eb3fa25
|
|
|
3331
3407
|
https://pip.pypa.io/en/stable/cli/pip_install/#vcs-support
|
|
3332
3408
|
vcs+protocol://repo_url/#egg=pkg&subdirectory=pkg_dir
|
|
3333
3409
|
'git+https://github.com/wrmsr/omlish@master#subdirectory=.pip/omlish'
|
|
3334
|
-
"""
|
|
3410
|
+
""" # noqa
|
|
3335
3411
|
# ruff: noqa: UP006 UP007
|
|
3336
3412
|
|
|
3337
3413
|
|
|
3338
|
-
|
|
3414
|
+
#
|
|
3415
|
+
|
|
3416
|
+
|
|
3417
|
+
class BasePyprojectPackageGenerator(abc.ABC):
|
|
3339
3418
|
def __init__(
|
|
3340
3419
|
self,
|
|
3341
3420
|
dir_name: str,
|
|
3342
|
-
|
|
3421
|
+
pkgs_root: str,
|
|
3422
|
+
*,
|
|
3423
|
+
pkg_suffix: str = '',
|
|
3343
3424
|
) -> None:
|
|
3344
3425
|
super().__init__()
|
|
3345
3426
|
self._dir_name = dir_name
|
|
3346
|
-
self.
|
|
3427
|
+
self._pkgs_root = pkgs_root
|
|
3428
|
+
self._pkg_suffix = pkg_suffix
|
|
3347
3429
|
|
|
3348
3430
|
#
|
|
3349
3431
|
|
|
@@ -3351,48 +3433,44 @@ class PyprojectPackageGenerator:
|
|
|
3351
3433
|
def about(self) -> types.ModuleType:
|
|
3352
3434
|
return importlib.import_module(f'{self._dir_name}.__about__')
|
|
3353
3435
|
|
|
3354
|
-
@cached_nullary
|
|
3355
|
-
def project_cls(self) -> type:
|
|
3356
|
-
return self.about().Project
|
|
3357
|
-
|
|
3358
|
-
@cached_nullary
|
|
3359
|
-
def setuptools_cls(self) -> type:
|
|
3360
|
-
return self.about().Setuptools
|
|
3361
|
-
|
|
3362
3436
|
#
|
|
3363
3437
|
|
|
3364
3438
|
@cached_nullary
|
|
3365
|
-
def
|
|
3366
|
-
|
|
3367
|
-
if os.path.isdir(
|
|
3368
|
-
shutil.rmtree(
|
|
3369
|
-
os.makedirs(
|
|
3370
|
-
return
|
|
3439
|
+
def _pkg_dir(self) -> str:
|
|
3440
|
+
pkg_dir: str = os.path.join(self._pkgs_root, self._dir_name + self._pkg_suffix)
|
|
3441
|
+
if os.path.isdir(pkg_dir):
|
|
3442
|
+
shutil.rmtree(pkg_dir)
|
|
3443
|
+
os.makedirs(pkg_dir)
|
|
3444
|
+
return pkg_dir
|
|
3371
3445
|
|
|
3372
3446
|
#
|
|
3373
3447
|
|
|
3448
|
+
_GIT_IGNORE: ta.Sequence[str] = [
|
|
3449
|
+
'/*.egg-info/',
|
|
3450
|
+
'/dist',
|
|
3451
|
+
]
|
|
3452
|
+
|
|
3374
3453
|
def _write_git_ignore(self) -> None:
|
|
3375
|
-
|
|
3376
|
-
'
|
|
3377
|
-
'/dist',
|
|
3378
|
-
]
|
|
3379
|
-
with open(os.path.join(self._build_dir(), '.gitignore'), 'w') as f:
|
|
3380
|
-
f.write('\n'.join(git_ignore))
|
|
3454
|
+
with open(os.path.join(self._pkg_dir(), '.gitignore'), 'w') as f:
|
|
3455
|
+
f.write('\n'.join(self._GIT_IGNORE))
|
|
3381
3456
|
|
|
3382
3457
|
#
|
|
3383
3458
|
|
|
3384
3459
|
def _symlink_source_dir(self) -> None:
|
|
3385
3460
|
os.symlink(
|
|
3386
|
-
os.path.relpath(self._dir_name, self.
|
|
3387
|
-
os.path.join(self.
|
|
3461
|
+
os.path.relpath(self._dir_name, self._pkg_dir()),
|
|
3462
|
+
os.path.join(self._pkg_dir(), self._dir_name),
|
|
3388
3463
|
)
|
|
3389
3464
|
|
|
3390
3465
|
#
|
|
3391
3466
|
|
|
3392
|
-
@
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3467
|
+
@cached_nullary
|
|
3468
|
+
def project_cls(self) -> type:
|
|
3469
|
+
return self.about().Project
|
|
3470
|
+
|
|
3471
|
+
@cached_nullary
|
|
3472
|
+
def setuptools_cls(self) -> type:
|
|
3473
|
+
return self.about().Setuptools
|
|
3396
3474
|
|
|
3397
3475
|
@staticmethod
|
|
3398
3476
|
def _build_cls_dct(cls: type) -> ta.Dict[str, ta.Any]: # noqa
|
|
@@ -3414,18 +3492,115 @@ class PyprojectPackageGenerator:
|
|
|
3414
3492
|
if sk in sd:
|
|
3415
3493
|
dd[dk] = sd.pop(sk)
|
|
3416
3494
|
|
|
3495
|
+
@dc.dataclass(frozen=True)
|
|
3496
|
+
class Specs:
|
|
3497
|
+
pyproject: ta.Dict[str, ta.Any]
|
|
3498
|
+
setuptools: ta.Dict[str, ta.Any]
|
|
3499
|
+
|
|
3500
|
+
def build_specs(self) -> Specs:
|
|
3501
|
+
return self.Specs(
|
|
3502
|
+
self._build_cls_dct(self.project_cls()),
|
|
3503
|
+
self._build_cls_dct(self.setuptools_cls()),
|
|
3504
|
+
)
|
|
3505
|
+
|
|
3506
|
+
#
|
|
3507
|
+
|
|
3508
|
+
@abc.abstractmethod
|
|
3509
|
+
def _write_file_contents(self) -> None:
|
|
3510
|
+
raise NotImplementedError
|
|
3511
|
+
|
|
3512
|
+
#
|
|
3513
|
+
|
|
3514
|
+
_STANDARD_FILES: ta.Sequence[str] = [
|
|
3515
|
+
'LICENSE',
|
|
3516
|
+
'README.rst',
|
|
3517
|
+
]
|
|
3518
|
+
|
|
3519
|
+
def _symlink_standard_files(self) -> None:
|
|
3520
|
+
for fn in self._STANDARD_FILES:
|
|
3521
|
+
if os.path.exists(fn):
|
|
3522
|
+
os.symlink(os.path.relpath(fn, self._pkg_dir()), os.path.join(self._pkg_dir(), fn))
|
|
3523
|
+
|
|
3524
|
+
#
|
|
3525
|
+
|
|
3526
|
+
def _run_build(
|
|
3527
|
+
self,
|
|
3528
|
+
build_output_dir: ta.Optional[str] = None,
|
|
3529
|
+
*,
|
|
3530
|
+
add_revision: bool = False,
|
|
3531
|
+
) -> None:
|
|
3532
|
+
subprocess.check_call(
|
|
3533
|
+
[
|
|
3534
|
+
sys.executable,
|
|
3535
|
+
'-m',
|
|
3536
|
+
'build',
|
|
3537
|
+
],
|
|
3538
|
+
cwd=self._pkg_dir(),
|
|
3539
|
+
)
|
|
3540
|
+
|
|
3541
|
+
dist_dir = os.path.join(self._pkg_dir(), 'dist')
|
|
3542
|
+
|
|
3543
|
+
if add_revision:
|
|
3544
|
+
GitRevisionAdder().add_to(dist_dir)
|
|
3545
|
+
|
|
3546
|
+
if build_output_dir is not None:
|
|
3547
|
+
for fn in os.listdir(dist_dir):
|
|
3548
|
+
shutil.copyfile(os.path.join(dist_dir, fn), os.path.join(build_output_dir, fn))
|
|
3549
|
+
|
|
3550
|
+
#
|
|
3551
|
+
|
|
3552
|
+
@dc.dataclass(frozen=True)
|
|
3553
|
+
class GenOpts:
|
|
3554
|
+
run_build: bool = False
|
|
3555
|
+
build_output_dir: ta.Optional[str] = None
|
|
3556
|
+
add_revision: bool = False
|
|
3557
|
+
|
|
3558
|
+
def gen(self, opts: GenOpts = GenOpts()) -> str:
|
|
3559
|
+
log.info('Generating pyproject package: %s -> %s (%s)', self._dir_name, self._pkgs_root, self._pkg_suffix)
|
|
3560
|
+
|
|
3561
|
+
self._pkg_dir()
|
|
3562
|
+
self._write_git_ignore()
|
|
3563
|
+
self._symlink_source_dir()
|
|
3564
|
+
self._write_file_contents()
|
|
3565
|
+
self._symlink_standard_files()
|
|
3566
|
+
|
|
3567
|
+
if opts.run_build:
|
|
3568
|
+
self._run_build(
|
|
3569
|
+
opts.build_output_dir,
|
|
3570
|
+
add_revision=opts.add_revision,
|
|
3571
|
+
)
|
|
3572
|
+
|
|
3573
|
+
return self._pkg_dir()
|
|
3574
|
+
|
|
3575
|
+
|
|
3576
|
+
#
|
|
3577
|
+
|
|
3578
|
+
|
|
3579
|
+
class PyprojectPackageGenerator(BasePyprojectPackageGenerator):
|
|
3580
|
+
|
|
3581
|
+
#
|
|
3582
|
+
|
|
3583
|
+
@dc.dataclass(frozen=True)
|
|
3584
|
+
class FileContents:
|
|
3585
|
+
pyproject_dct: ta.Mapping[str, ta.Any]
|
|
3586
|
+
manifest_in: ta.Optional[ta.Sequence[str]]
|
|
3587
|
+
|
|
3417
3588
|
@cached_nullary
|
|
3418
3589
|
def file_contents(self) -> FileContents:
|
|
3419
|
-
|
|
3590
|
+
specs = self.build_specs()
|
|
3420
3591
|
|
|
3421
3592
|
#
|
|
3422
3593
|
|
|
3594
|
+
pyp_dct = {}
|
|
3595
|
+
|
|
3423
3596
|
pyp_dct['build-system'] = {
|
|
3424
3597
|
'requires': ['setuptools'],
|
|
3425
3598
|
'build-backend': 'setuptools.build_meta',
|
|
3426
3599
|
}
|
|
3427
3600
|
|
|
3428
|
-
prj =
|
|
3601
|
+
prj = specs.pyproject
|
|
3602
|
+
prj['name'] += self._pkg_suffix
|
|
3603
|
+
|
|
3429
3604
|
pyp_dct['project'] = prj
|
|
3430
3605
|
|
|
3431
3606
|
self._move_dict_key(prj, 'optional_dependencies', pyp_dct, extrask := 'project.optional-dependencies')
|
|
@@ -3441,9 +3616,11 @@ class PyprojectPackageGenerator:
|
|
|
3441
3616
|
|
|
3442
3617
|
#
|
|
3443
3618
|
|
|
3444
|
-
st =
|
|
3619
|
+
st = specs.setuptools
|
|
3445
3620
|
pyp_dct['tool.setuptools'] = st
|
|
3446
3621
|
|
|
3622
|
+
st.pop('cexts', None)
|
|
3623
|
+
|
|
3447
3624
|
self._move_dict_key(st, 'find_packages', pyp_dct, 'tool.setuptools.packages.find')
|
|
3448
3625
|
|
|
3449
3626
|
mani_in = st.pop('manifest_in', None)
|
|
@@ -3458,75 +3635,124 @@ class PyprojectPackageGenerator:
|
|
|
3458
3635
|
def _write_file_contents(self) -> None:
|
|
3459
3636
|
fc = self.file_contents()
|
|
3460
3637
|
|
|
3461
|
-
with open(os.path.join(self.
|
|
3638
|
+
with open(os.path.join(self._pkg_dir(), 'pyproject.toml'), 'w') as f:
|
|
3462
3639
|
TomlWriter(f).write_root(fc.pyproject_dct)
|
|
3463
3640
|
|
|
3464
3641
|
if fc.manifest_in:
|
|
3465
|
-
with open(os.path.join(self.
|
|
3642
|
+
with open(os.path.join(self._pkg_dir(), 'MANIFEST.in'), 'w') as f:
|
|
3466
3643
|
f.write('\n'.join(fc.manifest_in)) # noqa
|
|
3467
3644
|
|
|
3468
3645
|
#
|
|
3469
3646
|
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
'README.rst',
|
|
3473
|
-
]
|
|
3647
|
+
def gen(self, opts: BasePyprojectPackageGenerator.GenOpts = BasePyprojectPackageGenerator.GenOpts()) -> str:
|
|
3648
|
+
ret = super().gen(opts)
|
|
3474
3649
|
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3650
|
+
if self.build_specs().setuptools.get('cexts'):
|
|
3651
|
+
_PyprojectCextPackageGenerator(
|
|
3652
|
+
self._dir_name,
|
|
3653
|
+
self._pkgs_root,
|
|
3654
|
+
pkg_suffix='-cext',
|
|
3655
|
+
).gen(opts)
|
|
3479
3656
|
|
|
3480
|
-
|
|
3657
|
+
return ret
|
|
3481
3658
|
|
|
3482
|
-
def _run_build(
|
|
3483
|
-
self,
|
|
3484
|
-
build_output_dir: ta.Optional[str] = None,
|
|
3485
|
-
*,
|
|
3486
|
-
add_revision: bool = False,
|
|
3487
|
-
) -> None:
|
|
3488
|
-
subprocess.check_call(
|
|
3489
|
-
[
|
|
3490
|
-
sys.executable,
|
|
3491
|
-
'-m',
|
|
3492
|
-
'build',
|
|
3493
|
-
],
|
|
3494
|
-
cwd=self._build_dir(),
|
|
3495
|
-
)
|
|
3496
3659
|
|
|
3497
|
-
|
|
3660
|
+
#
|
|
3498
3661
|
|
|
3499
|
-
if add_revision:
|
|
3500
|
-
GitRevisionAdder().add_to(dist_dir)
|
|
3501
3662
|
|
|
3502
|
-
|
|
3503
|
-
for fn in os.listdir(dist_dir):
|
|
3504
|
-
shutil.copyfile(os.path.join(dist_dir, fn), os.path.join(build_output_dir, fn))
|
|
3663
|
+
class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
|
|
3505
3664
|
|
|
3506
3665
|
#
|
|
3507
3666
|
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
log.info('Generating pyproject package: %s -> %s', self._dir_name, self._build_root)
|
|
3667
|
+
@cached_nullary
|
|
3668
|
+
def find_cext_srcs(self) -> ta.Sequence[str]:
|
|
3669
|
+
return sorted(find_magic(
|
|
3670
|
+
[self._dir_name],
|
|
3671
|
+
[CextMagic.MAGIC_COMMENT],
|
|
3672
|
+
CextMagic.FILE_EXTENSIONS,
|
|
3673
|
+
))
|
|
3516
3674
|
|
|
3517
|
-
|
|
3518
|
-
self._write_git_ignore()
|
|
3519
|
-
self._symlink_source_dir()
|
|
3520
|
-
self._write_file_contents()
|
|
3521
|
-
self._symlink_standard_files()
|
|
3675
|
+
#
|
|
3522
3676
|
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3677
|
+
@dc.dataclass(frozen=True)
|
|
3678
|
+
class FileContents:
|
|
3679
|
+
pyproject_dct: ta.Mapping[str, ta.Any]
|
|
3680
|
+
setup_py: str
|
|
3681
|
+
|
|
3682
|
+
@cached_nullary
|
|
3683
|
+
def file_contents(self) -> FileContents:
|
|
3684
|
+
specs = self.build_specs()
|
|
3685
|
+
|
|
3686
|
+
#
|
|
3687
|
+
|
|
3688
|
+
pyp_dct = {}
|
|
3689
|
+
|
|
3690
|
+
pyp_dct['build-system'] = {
|
|
3691
|
+
'requires': ['setuptools'],
|
|
3692
|
+
'build-backend': 'setuptools.build_meta',
|
|
3693
|
+
}
|
|
3694
|
+
|
|
3695
|
+
prj = specs.pyproject
|
|
3696
|
+
prj['dependencies'] = [f'{prj["name"]} == {prj["version"]}']
|
|
3697
|
+
prj['name'] += self._pkg_suffix
|
|
3698
|
+
prj.pop('optional_dependencies', None)
|
|
3699
|
+
|
|
3700
|
+
pyp_dct['project'] = prj
|
|
3701
|
+
|
|
3702
|
+
#
|
|
3703
|
+
|
|
3704
|
+
st = specs.setuptools
|
|
3705
|
+
pyp_dct['tool.setuptools'] = st
|
|
3706
|
+
|
|
3707
|
+
st.pop('cexts', None)
|
|
3708
|
+
st.pop('find_packages', None)
|
|
3709
|
+
st.pop('manifest_in', None)
|
|
3710
|
+
|
|
3711
|
+
pyp_dct['tool.setuptools.packages.find'] = {
|
|
3712
|
+
'include': [],
|
|
3713
|
+
}
|
|
3714
|
+
|
|
3715
|
+
#
|
|
3716
|
+
|
|
3717
|
+
ext_lines = []
|
|
3718
|
+
|
|
3719
|
+
for ext_src in self.find_cext_srcs():
|
|
3720
|
+
ext_name = ext_src.rpartition('.')[0].replace(os.sep, '.')
|
|
3721
|
+
ext_lines.extend([
|
|
3722
|
+
'st.Extension(',
|
|
3723
|
+
f" name='{ext_name}',",
|
|
3724
|
+
f" sources=['{ext_src}'],",
|
|
3725
|
+
" extra_compile_args=['-std=c++20'],",
|
|
3726
|
+
'),',
|
|
3727
|
+
])
|
|
3728
|
+
|
|
3729
|
+
src = '\n'.join([
|
|
3730
|
+
'import setuptools as st',
|
|
3731
|
+
'',
|
|
3732
|
+
'',
|
|
3733
|
+
'st.setup(',
|
|
3734
|
+
' ext_modules=[',
|
|
3735
|
+
*[' ' + l for l in ext_lines],
|
|
3736
|
+
' ]',
|
|
3737
|
+
')',
|
|
3738
|
+
'',
|
|
3739
|
+
])
|
|
3740
|
+
|
|
3741
|
+
#
|
|
3742
|
+
|
|
3743
|
+
return self.FileContents(
|
|
3744
|
+
pyp_dct,
|
|
3745
|
+
src,
|
|
3746
|
+
)
|
|
3747
|
+
|
|
3748
|
+
def _write_file_contents(self) -> None:
|
|
3749
|
+
fc = self.file_contents()
|
|
3750
|
+
|
|
3751
|
+
with open(os.path.join(self._pkg_dir(), 'pyproject.toml'), 'w') as f:
|
|
3752
|
+
TomlWriter(f).write_root(fc.pyproject_dct)
|
|
3528
3753
|
|
|
3529
|
-
|
|
3754
|
+
with open(os.path.join(self._pkg_dir(), 'setup.py'), 'w') as f:
|
|
3755
|
+
f.write(fc.setup_py)
|
|
3530
3756
|
|
|
3531
3757
|
|
|
3532
3758
|
########################################
|
|
@@ -4363,10 +4589,10 @@ def _pkg_cmd(args) -> None:
|
|
|
4363
4589
|
raise Exception('must specify command')
|
|
4364
4590
|
|
|
4365
4591
|
elif cmd == 'gen':
|
|
4366
|
-
|
|
4592
|
+
pkgs_root = os.path.join('.pkg')
|
|
4367
4593
|
|
|
4368
|
-
if os.path.exists(
|
|
4369
|
-
shutil.rmtree(
|
|
4594
|
+
if os.path.exists(pkgs_root):
|
|
4595
|
+
shutil.rmtree(pkgs_root)
|
|
4370
4596
|
|
|
4371
4597
|
build_output_dir = 'dist'
|
|
4372
4598
|
run_build = bool(args.build)
|
|
@@ -4381,11 +4607,13 @@ def _pkg_cmd(args) -> None:
|
|
|
4381
4607
|
ex.submit(functools.partial(
|
|
4382
4608
|
PyprojectPackageGenerator(
|
|
4383
4609
|
dir_name,
|
|
4384
|
-
|
|
4610
|
+
pkgs_root,
|
|
4385
4611
|
).gen,
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4612
|
+
PyprojectPackageGenerator.GenOpts(
|
|
4613
|
+
run_build=run_build,
|
|
4614
|
+
build_output_dir=build_output_dir,
|
|
4615
|
+
add_revision=add_revision,
|
|
4616
|
+
),
|
|
4389
4617
|
))
|
|
4390
4618
|
for dir_name in run.cfg().pkgs
|
|
4391
4619
|
]
|
omdev/toml/writer.py
CHANGED
|
@@ -99,6 +99,9 @@ class TomlWriter:
|
|
|
99
99
|
elif isinstance(obj, ta.Mapping):
|
|
100
100
|
self.write_inline_table(obj)
|
|
101
101
|
elif isinstance(obj, ta.Sequence):
|
|
102
|
-
|
|
102
|
+
if not obj:
|
|
103
|
+
self.write_inline_array(obj)
|
|
104
|
+
else:
|
|
105
|
+
self.write_array(obj)
|
|
103
106
|
else:
|
|
104
107
|
raise TypeError(obj)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev19
|
|
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.dev19
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: pycparser ~=2.22 ; extra == 'all'
|
|
18
18
|
Requires-Dist: cffi ~=1.17 ; extra == 'all'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
omdev/__about__.py,sha256=
|
|
1
|
+
omdev/__about__.py,sha256=x1427IilNX73BS7VDiNwnCFDuzGfPVPoRvJze6stnsE,802
|
|
2
2
|
omdev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
omdev/bracepy.py,sha256=HwBK5XmlOsF_juTel25fRLJK9vHSJCWXuCc-OZlevRQ,2619
|
|
4
4
|
omdev/classdot.py,sha256=urN5Pzd2ooAwnfkH0z-muQxdO90IMo-sX2WB-A37lVU,1533
|
|
@@ -12,9 +12,10 @@ omdev/amalg/__main__.py,sha256=OE1udULO1g4McUbeg1CoHbSm4hbQ2kcE3ffEGxlnPh4,69
|
|
|
12
12
|
omdev/amalg/amalg.py,sha256=YEyH097MZop-f1qobZJW__srtyLFS3rI7M2MaRtshKg,13057
|
|
13
13
|
omdev/cexts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
omdev/cexts/build.py,sha256=zViF1wYx6z5ACyifgNjlCAVoPAMCKpTr_VoAvwtmvtY,1013
|
|
15
|
-
omdev/cexts/cmake.py,sha256=
|
|
15
|
+
omdev/cexts/cmake.py,sha256=WrH5l3WnamyVEcMMjxkX87bNT7O7ZWX-docajc7XwAg,9726
|
|
16
16
|
omdev/cexts/importhook.py,sha256=nljqEuPopuh10DPeSrIYKmkV4z-Wk5Q7WpUid1JEmkg,3530
|
|
17
|
-
omdev/cexts/
|
|
17
|
+
omdev/cexts/magic.py,sha256=LhC31I2GiCq3NRU5dpy_9do6IVjhdGu58uPPFffQx5Q,135
|
|
18
|
+
omdev/cexts/scan.py,sha256=_U5DX9ksHP1845PdGxWh4Rf1a6x_sG1MH3uL_hwBnKY,1669
|
|
18
19
|
omdev/cexts/_distutils/__init__.py,sha256=c1zImtnPh3uY8BUTV4RLKtGKqTPx3c_pBbhA6tPtNsE,297
|
|
19
20
|
omdev/cexts/_distutils/build_ext.py,sha256=STHl9Rq2KeWJ3dQ8j8LwIQ-vFc4-3XsYWQ8Qc5_VByU,13833
|
|
20
21
|
omdev/cexts/_distutils/dir_util.py,sha256=xxfAIPHbjlh-aW9OX6UGDrXiXfB5biG4xEC5RA6oszM,2882
|
|
@@ -47,17 +48,17 @@ omdev/precheck/__main__.py,sha256=wKF_2KP2Yn1hKDEOCGR_fm5zu9UHMWCZtuEmWjpprrU,72
|
|
|
47
48
|
omdev/precheck/precheck.py,sha256=2yTjNGvjPYf3QxUBbCbehBYYuB8gDR_dYSTrlNCs9qU,8322
|
|
48
49
|
omdev/pyproject/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
49
50
|
omdev/pyproject/__main__.py,sha256=gFhR9DikwDZk0LqgdR3qq_aXQHThUOPllDmHDOfnFAU,67
|
|
50
|
-
omdev/pyproject/
|
|
51
|
+
omdev/pyproject/cexts.py,sha256=x13piOOnNrYbA17qZLDVuR0p1sqhgEwpk4FtImX-klM,4281
|
|
52
|
+
omdev/pyproject/cli.py,sha256=RnRj8zfGGUcLJ-oiQS90gR2O0XAH4iwNSX5JIDWzM4U,10004
|
|
51
53
|
omdev/pyproject/configs.py,sha256=MFHnmpMjlwxw74-SyX1Q1qNQ4ptwTXEzDGkeUcGY0mA,2822
|
|
52
|
-
omdev/pyproject/
|
|
53
|
-
omdev/pyproject/pkg.py,sha256=YrnqZK-b2qJh6kSkvYjZ19F39NU0kpbth1FYItpFZ80,5977
|
|
54
|
+
omdev/pyproject/pkg.py,sha256=_uPJNU9i3zbtZ8yw6h0ZTEGtEVJp07EacdHFs3jMMHM,9862
|
|
54
55
|
omdev/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
56
|
omdev/scripts/execrss.py,sha256=HzDNmwXOO8fMwIRXw9q8CUnVfLFCQASyU2tfY_y2Vf8,324
|
|
56
|
-
omdev/scripts/interp.py,sha256=
|
|
57
|
-
omdev/scripts/pyproject.py,sha256=
|
|
57
|
+
omdev/scripts/interp.py,sha256=fLO1WXW6_3zr6VlyM9om7RNRtG1yj2TPZpNHOYKfk98,63069
|
|
58
|
+
omdev/scripts/pyproject.py,sha256=3-skV2FFYDPI2TeXQ9DzfS_BFBjmghFFhVcPVLHVlac,139733
|
|
58
59
|
omdev/toml/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
59
60
|
omdev/toml/parser.py,sha256=84bn09uhYHwQGyfww6Rw6y1RxPAE_HDltODOSakcqDM,29186
|
|
60
|
-
omdev/toml/writer.py,sha256=
|
|
61
|
+
omdev/toml/writer.py,sha256=dwz_Qw8z5Z_nmWpXqch63W6S_j6n256erb7AGFTVzB4,2872
|
|
61
62
|
omdev/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
63
|
omdev/tools/dockertools.py,sha256=3844AhUst6kYo2xKNn-2Npi-f6r4rocxEOx0tHjE0dk,2063
|
|
63
64
|
omdev/tools/gittools.py,sha256=zPy2D5WDs-CbwT86_T_hbaq5yCuss5e-ouUccXC6xlg,578
|
|
@@ -67,8 +68,8 @@ omdev/tools/traceimport.py,sha256=oDry9CwIv5h96wSaTVKJ0qQ5vMGxYE5oBtfF-GYNLJs,13
|
|
|
67
68
|
omdev/versioning/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
68
69
|
omdev/versioning/specifiers.py,sha256=6Odf9e6farwlPRsD_YqwTfYKG-BXn_dIcKtqfkhfodI,17432
|
|
69
70
|
omdev/versioning/versions.py,sha256=ei2eopEsJq3zSMJmezK1nzZgikgCdxFtnF3f69nCRZQ,12246
|
|
70
|
-
omdev-0.0.0.
|
|
71
|
-
omdev-0.0.0.
|
|
72
|
-
omdev-0.0.0.
|
|
73
|
-
omdev-0.0.0.
|
|
74
|
-
omdev-0.0.0.
|
|
71
|
+
omdev-0.0.0.dev19.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
|
72
|
+
omdev-0.0.0.dev19.dist-info/METADATA,sha256=k0Elh8TPD7dB1z2dwbDPyQ_-GUOLna4LW_oPSYlmNB0,1126
|
|
73
|
+
omdev-0.0.0.dev19.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
|
74
|
+
omdev-0.0.0.dev19.dist-info/top_level.txt,sha256=1nr7j30fEWgLYHW3lGR9pkdHkb7knv1U1ES1XRNVQ6k,6
|
|
75
|
+
omdev-0.0.0.dev19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|