partis-pyproj 0.1.4__py3-none-any.whl → 0.1.6__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.
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/__init__.py +9 -1
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/_legacy_setup.py +11 -11
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/_nonprintable.py +4 -3
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/backend.py +44 -37
- partis_pyproj-0.1.6.data/purelib/partis/pyproj/builder/builder.py +351 -0
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/builder/cargo.py +2 -2
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/builder/cmake.py +9 -15
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/builder/meson.py +5 -13
- partis_pyproj-0.1.6.data/purelib/partis/pyproj/builder/process.py +42 -0
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/dist_file/__init__.py +1 -1
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/dist_file/dist_base.py +75 -86
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/dist_file/dist_binary.py +6 -24
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/dist_file/dist_copy.py +7 -18
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/dist_file/dist_source.py +4 -21
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/dist_file/dist_targz.py +5 -12
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/dist_file/dist_zip.py +5 -14
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/file.py +2 -1
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/legacy.py +3 -2
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/load_module.py +7 -6
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/norms.py +35 -31
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/path/__init__.py +2 -1
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/path/match.py +42 -35
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/path/pattern.py +60 -54
- partis_pyproj-0.1.6.data/purelib/partis/pyproj/path/utils.py +94 -0
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/pep.py +36 -35
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/pkginfo.py +7 -16
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/pptoml.py +125 -120
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/pyproj.py +47 -36
- partis_pyproj-0.1.6.data/purelib/partis/pyproj/template.py +229 -0
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/validate.py +273 -268
- partis_pyproj-0.1.6.dist-info/METADATA +500 -0
- partis_pyproj-0.1.6.dist-info/RECORD +37 -0
- partis_pyproj-0.1.4.data/purelib/partis/pyproj/builder/builder.py +0 -267
- partis_pyproj-0.1.4.data/purelib/partis/pyproj/builder/process.py +0 -75
- partis_pyproj-0.1.4.data/purelib/partis/pyproj/path/utils.py +0 -40
- partis_pyproj-0.1.4.dist-info/METADATA +0 -51
- partis_pyproj-0.1.4.dist-info/RECORD +0 -36
- {partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/builder/__init__.py +0 -0
- {partis_pyproj-0.1.4.dist-info → partis_pyproj-0.1.6.dist-info}/LICENSE.txt +0 -0
- {partis_pyproj-0.1.4.dist-info → partis_pyproj-0.1.6.dist-info}/WHEEL +0 -0
- {partis_pyproj-0.1.4.dist-info → partis_pyproj-0.1.6.dist-info}/entry_points.txt +0 -0
- {partis_pyproj-0.1.4.dist-info → partis_pyproj-0.1.6.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
#===============================================================================
|
3
3
|
from .validate import (
|
4
4
|
ValidationError,
|
5
5
|
ValidationWarning,
|
@@ -10,6 +10,7 @@ from .validate import (
|
|
10
10
|
as_list )
|
11
11
|
|
12
12
|
from .norms import (
|
13
|
+
marker_evaluated,
|
13
14
|
scalar,
|
14
15
|
scalar_list,
|
15
16
|
empty_str,
|
@@ -59,6 +60,13 @@ from .path import (
|
|
59
60
|
combine_ignore_patterns,
|
60
61
|
contains )
|
61
62
|
|
63
|
+
from .template import (
|
64
|
+
Template,
|
65
|
+
Namespace,
|
66
|
+
template_substitute,
|
67
|
+
TemplateError,
|
68
|
+
NamespaceError)
|
69
|
+
|
62
70
|
from .dist_file import (
|
63
71
|
dist_base,
|
64
72
|
dist_zip,
|
{partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/_legacy_setup.py
RENAMED
@@ -15,7 +15,7 @@ import tempfile
|
|
15
15
|
from argparse import RawTextHelpFormatter
|
16
16
|
logger = logging.getLogger(__name__)
|
17
17
|
|
18
|
-
|
18
|
+
#===============================================================================
|
19
19
|
def egg_info( args ):
|
20
20
|
|
21
21
|
logger.warning(
|
@@ -26,13 +26,13 @@ def egg_info( args ):
|
|
26
26
|
if not dir.exists():
|
27
27
|
dir.mkdir(parents=True, exist_ok = True)
|
28
28
|
|
29
|
-
with open(dir.joinpath('PKG-INFO'), 'wb' ) as fp:
|
29
|
+
with open(dir.joinpath('PKG-INFO'), 'wb' ) as fp:
|
30
30
|
fp.write( PKG_INFO )
|
31
31
|
|
32
|
-
with open( dir.joinpath('setup_requires.txt'), 'wb' ) as fp:
|
32
|
+
with open( dir.joinpath('setup_requires.txt'), 'wb' ) as fp:
|
33
33
|
fp.write( b'' )
|
34
34
|
|
35
|
-
with open( dir.joinpath('requires.txt'), 'wb' ) as fp:
|
35
|
+
with open( dir.joinpath('requires.txt'), 'wb' ) as fp:
|
36
36
|
fp.write( REQUIRES )
|
37
37
|
|
38
38
|
with open( dir.joinpath('SOURCES.txt'), 'wb' ) as fp:
|
@@ -50,7 +50,7 @@ def egg_info( args ):
|
|
50
50
|
with open( dir.joinpath('not-zip-safe'), 'wb' ) as fp:
|
51
51
|
fp.write( b'' )
|
52
52
|
|
53
|
-
|
53
|
+
#===============================================================================
|
54
54
|
def bdist_wheel( args ):
|
55
55
|
|
56
56
|
logger.warning(
|
@@ -63,7 +63,7 @@ def bdist_wheel( args ):
|
|
63
63
|
backend.build_wheel(
|
64
64
|
wheel_directory = args.dist_dir or args.bdist_dir or '.' )
|
65
65
|
|
66
|
-
|
66
|
+
#===============================================================================
|
67
67
|
def install( args ):
|
68
68
|
|
69
69
|
logger.warning(
|
@@ -91,13 +91,13 @@ def install( args ):
|
|
91
91
|
'-m',
|
92
92
|
'pip',
|
93
93
|
'install',
|
94
|
-
tmpdir.joinpath(wheel_name) ])
|
94
|
+
tmpdir.joinpath(wheel_name) ])
|
95
95
|
|
96
|
-
|
96
|
+
#===============================================================================
|
97
97
|
def dummy( args ):
|
98
98
|
pass
|
99
99
|
|
100
|
-
|
100
|
+
#===============================================================================
|
101
101
|
def main():
|
102
102
|
|
103
103
|
logging.basicConfig(
|
@@ -185,7 +185,7 @@ def main():
|
|
185
185
|
args.func( args )
|
186
186
|
|
187
187
|
|
188
|
-
|
188
|
+
#===============================================================================
|
189
189
|
# NOTE: these are templated literal values substituded by the backend when
|
190
190
|
# building the source distribution
|
191
191
|
|
@@ -205,7 +205,7 @@ TOP_LEVEL = {top_level}
|
|
205
205
|
|
206
206
|
ENTRY_POINTS = {entry_points}
|
207
207
|
|
208
|
-
|
208
|
+
#===============================================================================
|
209
209
|
|
210
210
|
if __name__ == "__main__":
|
211
211
|
exit( main() )
|
{partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/_nonprintable.py
RENAMED
@@ -1,7 +1,8 @@
|
|
1
|
+
from __future__ import annotations
|
1
2
|
import sys
|
2
3
|
import re
|
3
4
|
|
4
|
-
|
5
|
+
#===============================================================================
|
5
6
|
def _gen_nonprintable():
|
6
7
|
test = ''
|
7
8
|
|
@@ -28,7 +29,7 @@ def _gen_nonprintable():
|
|
28
29
|
|
29
30
|
return ns, test
|
30
31
|
|
31
|
-
|
32
|
+
#===============================================================================
|
32
33
|
def gen_nonprintable():
|
33
34
|
"""Method used to generate a regex for matchiing all non-printable unicode
|
34
35
|
characters, except for newlines '\\n' and tabs '\\t'.
|
@@ -79,6 +80,6 @@ def gen_nonprintable():
|
|
79
80
|
|
80
81
|
return nonprintable
|
81
82
|
|
82
|
-
|
83
|
+
#===============================================================================
|
83
84
|
if __name__ == '__main__':
|
84
85
|
print( gen_nonprintable() )
|
@@ -1,8 +1,13 @@
|
|
1
|
+
from __future__ import annotations
|
1
2
|
import os
|
2
3
|
import os.path as osp
|
3
4
|
import sys
|
4
5
|
import shutil
|
5
6
|
import logging
|
7
|
+
from logging import (
|
8
|
+
basicConfig,
|
9
|
+
getLogger,
|
10
|
+
Logger)
|
6
11
|
import tempfile
|
7
12
|
import re
|
8
13
|
|
@@ -24,34 +29,18 @@ from . import (
|
|
24
29
|
dist_binary_wheel,
|
25
30
|
dist_source_targz )
|
26
31
|
|
27
|
-
|
28
|
-
class UnsupportedOperation( Exception ):
|
29
|
-
"""
|
30
|
-
Note
|
31
|
-
----
|
32
|
-
If the backend cannot produce an dist because a dependency is missing,
|
33
|
-
or for another well understood reason, it should raise an exception of a
|
34
|
-
specific type which it makes available as UnsupportedOperation on the
|
35
|
-
backend object.
|
36
|
-
|
37
|
-
See Also
|
38
|
-
--------
|
39
|
-
* https://www.python.org/dev/peps/pep-0517/
|
40
|
-
"""
|
41
|
-
pass
|
42
|
-
|
43
|
-
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
32
|
+
#===============================================================================
|
44
33
|
def backend_init(
|
45
|
-
root = '
|
46
|
-
config_settings = None,
|
47
|
-
logger = None ):
|
34
|
+
root: str|Path = '',
|
35
|
+
config_settings: dict|None = None,
|
36
|
+
logger: Logger|None = None ):
|
48
37
|
"""Called to inialialize the backend upon a call to one of the hooks
|
49
38
|
|
50
39
|
Parameters
|
51
40
|
----------
|
52
|
-
root :
|
41
|
+
root :
|
53
42
|
Directory containing 'pyproject.toml'
|
54
|
-
logger :
|
43
|
+
logger :
|
55
44
|
Logger to use
|
56
45
|
|
57
46
|
Returns
|
@@ -59,28 +48,30 @@ def backend_init(
|
|
59
48
|
PyProjBase
|
60
49
|
"""
|
61
50
|
|
62
|
-
logger = logger or logging.getLogger( __name__ )
|
63
|
-
|
64
|
-
pyproj = PyProjBase(
|
65
|
-
root = root,
|
66
|
-
config_settings = config_settings,
|
67
|
-
logger = logger )
|
68
|
-
|
69
51
|
# NOTE: this is mainly used for debugging, since front-ends don't seem to have
|
70
52
|
# an option to set logging level for the backend.
|
71
|
-
|
72
|
-
|
73
|
-
|
53
|
+
root_logger = getLogger()
|
54
|
+
|
55
|
+
if not root_logger.handlers:
|
56
|
+
basicConfig(
|
74
57
|
level = logging.INFO,
|
75
58
|
format = "{message}",
|
76
59
|
style = "{" )
|
77
60
|
|
61
|
+
root = Path(root)
|
62
|
+
logger = logger or getLogger( __name__ )
|
63
|
+
|
64
|
+
pyproj = PyProjBase(
|
65
|
+
root = root,
|
66
|
+
config_settings = config_settings,
|
67
|
+
logger = logger )
|
68
|
+
|
78
69
|
return pyproj
|
79
70
|
|
80
71
|
|
81
72
|
#-----------------------------------------------------------------------------
|
82
73
|
def get_requires_for_build_sdist(
|
83
|
-
config_settings = None ):
|
74
|
+
config_settings: dict|None = None ):
|
84
75
|
"""
|
85
76
|
Note
|
86
77
|
----
|
@@ -99,7 +90,7 @@ def get_requires_for_build_sdist(
|
|
99
90
|
#-----------------------------------------------------------------------------
|
100
91
|
def build_sdist(
|
101
92
|
dist_directory,
|
102
|
-
config_settings = None ):
|
93
|
+
config_settings: dict|None = None ):
|
103
94
|
"""
|
104
95
|
Note
|
105
96
|
----
|
@@ -130,7 +121,7 @@ def build_sdist(
|
|
130
121
|
|
131
122
|
#-----------------------------------------------------------------------------
|
132
123
|
def get_requires_for_build_wheel(
|
133
|
-
config_settings = None ):
|
124
|
+
config_settings: dict|None = None ):
|
134
125
|
"""
|
135
126
|
Note
|
136
127
|
----
|
@@ -169,7 +160,7 @@ def get_requires_for_build_wheel(
|
|
169
160
|
#-----------------------------------------------------------------------------
|
170
161
|
def prepare_metadata_for_build_wheel(
|
171
162
|
metadata_directory,
|
172
|
-
config_settings = None ):
|
163
|
+
config_settings: dict|None = None ):
|
173
164
|
"""
|
174
165
|
Note
|
175
166
|
----
|
@@ -204,7 +195,7 @@ def prepare_metadata_for_build_wheel(
|
|
204
195
|
#-----------------------------------------------------------------------------
|
205
196
|
def build_wheel(
|
206
197
|
wheel_directory,
|
207
|
-
config_settings = None,
|
198
|
+
config_settings: dict|None = None,
|
208
199
|
metadata_directory = None ):
|
209
200
|
"""
|
210
201
|
Note
|
@@ -255,3 +246,19 @@ def build_wheel(
|
|
255
246
|
# config_settings = None,
|
256
247
|
# metadata_directory = None ):
|
257
248
|
# pass
|
249
|
+
|
250
|
+
#===============================================================================
|
251
|
+
class UnsupportedOperation( Exception ):
|
252
|
+
"""
|
253
|
+
Note
|
254
|
+
----
|
255
|
+
If the backend cannot produce an dist because a dependency is missing,
|
256
|
+
or for another well understood reason, it should raise an exception of a
|
257
|
+
specific type which it makes available as UnsupportedOperation on the
|
258
|
+
backend object.
|
259
|
+
|
260
|
+
See Also
|
261
|
+
--------
|
262
|
+
* https://www.python.org/dev/peps/pep-0517/
|
263
|
+
"""
|
264
|
+
pass
|
@@ -0,0 +1,351 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
import os
|
3
|
+
import os.path as osp
|
4
|
+
import sys
|
5
|
+
import sysconfig
|
6
|
+
import re
|
7
|
+
from copy import copy
|
8
|
+
import shutil
|
9
|
+
import subprocess
|
10
|
+
from logging import Logger
|
11
|
+
from pathlib import Path
|
12
|
+
|
13
|
+
from ..file import tail
|
14
|
+
from ..validate import (
|
15
|
+
validating,
|
16
|
+
ValidationError,
|
17
|
+
ValidPathError,
|
18
|
+
FileOutsideRootError )
|
19
|
+
|
20
|
+
from ..load_module import EntryPoint
|
21
|
+
|
22
|
+
from ..path import (
|
23
|
+
subdir,
|
24
|
+
resolve)
|
25
|
+
|
26
|
+
from ..template import (
|
27
|
+
template_substitute,
|
28
|
+
Namespace)
|
29
|
+
from ..pptoml import pyproj_targets
|
30
|
+
|
31
|
+
ERROR_REC = re.compile(r"error:", re.I)
|
32
|
+
|
33
|
+
#===============================================================================
|
34
|
+
class BuildCommandError(ValidationError):
|
35
|
+
pass
|
36
|
+
|
37
|
+
#===============================================================================
|
38
|
+
class Builder:
|
39
|
+
"""Run build setup, compile, install commands
|
40
|
+
|
41
|
+
Parameters
|
42
|
+
----------
|
43
|
+
root:
|
44
|
+
Path to root project directory
|
45
|
+
targets:
|
46
|
+
logger:
|
47
|
+
|
48
|
+
"""
|
49
|
+
#-----------------------------------------------------------------------------
|
50
|
+
def __init__(self,
|
51
|
+
pyproj,
|
52
|
+
root: str | Path,
|
53
|
+
targets: pyproj_targets,
|
54
|
+
logger: Logger):
|
55
|
+
|
56
|
+
root = resolve(Path(root))
|
57
|
+
|
58
|
+
self.pyproj = pyproj
|
59
|
+
self.root = root
|
60
|
+
# isolate (shallow) changes to targets
|
61
|
+
self.targets = [copy(v) for v in targets]
|
62
|
+
self.clean_dirs = [False]*len(self.targets)
|
63
|
+
self.logger = logger
|
64
|
+
self.namespace = Namespace({
|
65
|
+
'root': root,
|
66
|
+
'pptoml': pyproj.pptoml,
|
67
|
+
'project': pyproj.project,
|
68
|
+
'pyproj': pyproj.pyproj,
|
69
|
+
'config_settings': pyproj.config_settings,
|
70
|
+
'targets': targets,
|
71
|
+
'env': os.environ,
|
72
|
+
'config_vars': sysconfig.get_config_vars()},
|
73
|
+
root=root)
|
74
|
+
|
75
|
+
#-----------------------------------------------------------------------------
|
76
|
+
def __enter__(self):
|
77
|
+
return self
|
78
|
+
|
79
|
+
#-----------------------------------------------------------------------------
|
80
|
+
def __exit__(self, type, value, traceback):
|
81
|
+
self.build_clean()
|
82
|
+
|
83
|
+
# do not handle any exceptions here
|
84
|
+
return False
|
85
|
+
|
86
|
+
#-----------------------------------------------------------------------------
|
87
|
+
def build_targets(self):
|
88
|
+
for i, target in enumerate(self.targets):
|
89
|
+
if not target.enabled:
|
90
|
+
self.logger.info(f"Skipping targets[{i}], disabled for environment markers")
|
91
|
+
continue
|
92
|
+
|
93
|
+
# each target isolated (shallow) changes to namespace
|
94
|
+
namespace = copy(self.namespace)
|
95
|
+
|
96
|
+
# check paths
|
97
|
+
for k in ('work_dir', 'src_dir', 'build_dir', 'prefix'):
|
98
|
+
with validating(key = f"tool.pyproj.targets[{i}].{k}"):
|
99
|
+
rel_path = target[k]
|
100
|
+
rel_path = template_substitute(rel_path, namespace)
|
101
|
+
|
102
|
+
if rel_path.is_absolute():
|
103
|
+
abs_path = rel_path
|
104
|
+
else:
|
105
|
+
abs_path = self.root/rel_path
|
106
|
+
|
107
|
+
abs_path = resolve(abs_path)
|
108
|
+
|
109
|
+
if not subdir(self.root, abs_path, check=False):
|
110
|
+
raise FileOutsideRootError(
|
111
|
+
f"Must be within project root directory:"
|
112
|
+
f"file = \"{abs_path}\", root = \"{self.root}\"")
|
113
|
+
|
114
|
+
if k in ('build_dir', 'prefix') and subdir(abs_path, self.root, check=False):
|
115
|
+
raise ValidPathError(
|
116
|
+
f"'{k}' cannot be project root directory:"
|
117
|
+
f"file = \"{abs_path}\", root = \"{self.root}\"")
|
118
|
+
|
119
|
+
target[k] = abs_path
|
120
|
+
namespace[k] = abs_path
|
121
|
+
|
122
|
+
src_dir = target.src_dir
|
123
|
+
build_dir = target.build_dir
|
124
|
+
prefix = target.prefix
|
125
|
+
work_dir = target.work_dir
|
126
|
+
|
127
|
+
with validating(key = f"tool.pyproj.targets[{i}].src_dir"):
|
128
|
+
if not src_dir.exists():
|
129
|
+
raise ValidPathError(f"Source directory not found: {src_dir}")
|
130
|
+
|
131
|
+
if not src_dir.is_dir():
|
132
|
+
raise ValidPathError(f"Source directory not a directory: {src_dir}")
|
133
|
+
|
134
|
+
with validating(key = f"tool.pyproj.targets[{i}]"):
|
135
|
+
if subdir(build_dir, prefix, check=False):
|
136
|
+
raise ValidPathError(
|
137
|
+
f"'prefix' cannot be inside 'build_dir', which will be cleaned: {build_dir} > {prefix}")
|
138
|
+
|
139
|
+
build_dirty = build_dir.exists() and any(build_dir.iterdir())
|
140
|
+
|
141
|
+
if target.build_clean and build_dirty:
|
142
|
+
raise ValidPathError(
|
143
|
+
f"'build_dir' is not empty, please remove manually."
|
144
|
+
f" If this was intended, set 'build_clean = false': {build_dir}")
|
145
|
+
|
146
|
+
# create output directories
|
147
|
+
for k in ['build_dir', 'prefix']:
|
148
|
+
with validating(key = f"tool.pyproj.targets[{i}].{k}"):
|
149
|
+
target[k].mkdir(parents=True, exist_ok=True)
|
150
|
+
|
151
|
+
with validating(key = f"tool.pyproj.targets[{i}].options"):
|
152
|
+
# original target options remain until evaluated
|
153
|
+
options = target.options
|
154
|
+
|
155
|
+
# top-level options updated in order of appearance
|
156
|
+
_options = {}
|
157
|
+
namespace['options'] = _options
|
158
|
+
|
159
|
+
for k,v in options.items():
|
160
|
+
v = template_substitute(v, namespace)
|
161
|
+
# update target
|
162
|
+
options[k] = v
|
163
|
+
# update
|
164
|
+
_options[k] = v
|
165
|
+
|
166
|
+
with validating(key = f"tool.pyproj.targets[{i}].env"):
|
167
|
+
# original target options remain until evaluated
|
168
|
+
env = target.env
|
169
|
+
|
170
|
+
# top-level options updated in order of appearance
|
171
|
+
# copy of environment dict, each target isolated changes
|
172
|
+
_env = copy(namespace['env'])
|
173
|
+
namespace['env'] = _env
|
174
|
+
|
175
|
+
for k,v in env.items():
|
176
|
+
v = template_substitute(v, namespace)
|
177
|
+
env[k] = v
|
178
|
+
_env[k] = v
|
179
|
+
|
180
|
+
for attr in ['setup_args', 'compile_args', 'install_args']:
|
181
|
+
with validating(key = f"tool.pyproj.targets[{i}].{attr}"):
|
182
|
+
value = target[attr]
|
183
|
+
value = template_substitute(value, namespace)
|
184
|
+
|
185
|
+
target[attr] = value
|
186
|
+
namespace[attr] = value
|
187
|
+
|
188
|
+
entry_point = EntryPoint(
|
189
|
+
pyproj = self,
|
190
|
+
root = self.root,
|
191
|
+
name = f"tool.pyproj.targets[{i}]",
|
192
|
+
logger = self.logger,
|
193
|
+
entry = target.entry)
|
194
|
+
|
195
|
+
log_dir = self.root/'build'/'logs'
|
196
|
+
|
197
|
+
log_dir.mkdir(parents=True, exist_ok=True)
|
198
|
+
|
199
|
+
runner = ProcessRunner(
|
200
|
+
logger=self.logger,
|
201
|
+
log_dir=log_dir,
|
202
|
+
target_name=f"target_{i:02d}",
|
203
|
+
env=_env)
|
204
|
+
|
205
|
+
self.logger.info('\n'.join([
|
206
|
+
f"targets[{i}]:",
|
207
|
+
f" work_dir: {work_dir}",
|
208
|
+
f" src_dir: {src_dir}",
|
209
|
+
f" build_dir: {build_dir}",
|
210
|
+
f" prefix: {prefix}",
|
211
|
+
f" log_dir: {log_dir}",
|
212
|
+
" options: " + ('\n' if target.options else 'none') + '\n'.join([
|
213
|
+
f" {k}: {v}" for k,v in target.options.items()]),
|
214
|
+
" env: " + ('\n' if target.env else 'default') + '\n'.join([
|
215
|
+
f" {k}: {v}" for k,v in target.env.items()])]))
|
216
|
+
|
217
|
+
cwd = os.getcwd()
|
218
|
+
|
219
|
+
# allow cleaning once the target is validated
|
220
|
+
self.clean_dirs[i] = True
|
221
|
+
|
222
|
+
try:
|
223
|
+
os.chdir(work_dir)
|
224
|
+
|
225
|
+
entry_point(
|
226
|
+
options = target.options,
|
227
|
+
work_dir = work_dir,
|
228
|
+
src_dir = src_dir,
|
229
|
+
build_dir = build_dir,
|
230
|
+
prefix = prefix,
|
231
|
+
setup_args = target.setup_args,
|
232
|
+
compile_args = target.compile_args,
|
233
|
+
install_args = target.install_args,
|
234
|
+
build_clean = not build_dirty,
|
235
|
+
runner = runner)
|
236
|
+
|
237
|
+
finally:
|
238
|
+
os.chdir(cwd)
|
239
|
+
|
240
|
+
#-----------------------------------------------------------------------------
|
241
|
+
def build_clean(self):
|
242
|
+
for i, (target, clean) in enumerate(zip(self.targets, self.clean_dirs)):
|
243
|
+
if not clean:
|
244
|
+
continue
|
245
|
+
|
246
|
+
build_dir = target.build_dir
|
247
|
+
|
248
|
+
if build_dir is not None and build_dir.exists() and target.build_clean:
|
249
|
+
self.logger.info(f"Removing build dir: {build_dir}")
|
250
|
+
shutil.rmtree(build_dir)
|
251
|
+
|
252
|
+
#===============================================================================
|
253
|
+
class ProcessRunner:
|
254
|
+
#-----------------------------------------------------------------------------
|
255
|
+
def __init__(self,
|
256
|
+
logger,
|
257
|
+
log_dir: Path,
|
258
|
+
target_name: str,
|
259
|
+
env: dict):
|
260
|
+
|
261
|
+
self.logger = logger
|
262
|
+
self.log_dir = log_dir
|
263
|
+
self.target_name = target_name
|
264
|
+
self.commands = {}
|
265
|
+
self.env = env
|
266
|
+
|
267
|
+
#-----------------------------------------------------------------------------
|
268
|
+
def run(self, args: list, env: dict = None):
|
269
|
+
if len(args) == 0:
|
270
|
+
raise ValueError(f"Command for {self.target_name} is empty.")
|
271
|
+
|
272
|
+
cmd_exec = args[0]
|
273
|
+
cmd_exec_src = shutil.which(cmd_exec)
|
274
|
+
|
275
|
+
if cmd_exec_src is None:
|
276
|
+
raise ValueError(
|
277
|
+
f"Executable does not exist or has in-sufficient permissions: {cmd_exec}")
|
278
|
+
|
279
|
+
cmd_exec_src = resolve(Path(cmd_exec_src))
|
280
|
+
cmd_name = cmd_exec_src.name
|
281
|
+
args = [str(cmd_exec_src)]+args[1:]
|
282
|
+
|
283
|
+
cmd_hist = self.commands.setdefault(cmd_exec_src, [])
|
284
|
+
cmd_idx = len(cmd_hist)
|
285
|
+
cmd_hist.append(args)
|
286
|
+
|
287
|
+
run_name = re.sub(r'[^\w]+', "_", cmd_name)
|
288
|
+
run_id = f"{self.target_name}.{run_name}.{cmd_idx:02d}"
|
289
|
+
|
290
|
+
stdout_file = self.log_dir/f"{run_id}.log"
|
291
|
+
|
292
|
+
try:
|
293
|
+
self.logger.info(f"Running {run_id!r}: "+' '.join(args))
|
294
|
+
|
295
|
+
with open(stdout_file, 'wb') as fp:
|
296
|
+
subprocess.run(
|
297
|
+
args,
|
298
|
+
shell=False,
|
299
|
+
stdout=fp,
|
300
|
+
stderr=subprocess.STDOUT,
|
301
|
+
check=True,
|
302
|
+
env=self.env)
|
303
|
+
|
304
|
+
except subprocess.CalledProcessError as e:
|
305
|
+
|
306
|
+
|
307
|
+
num_windows = 20
|
308
|
+
window_size = 5
|
309
|
+
with open(stdout_file, 'rb') as fp:
|
310
|
+
lines = [
|
311
|
+
(lineno,line)
|
312
|
+
for lineno,line in enumerate(fp.read().decode('utf-8', errors='replace').splitlines())]
|
313
|
+
|
314
|
+
suspect_linenos = [
|
315
|
+
lineno
|
316
|
+
for lineno,line in lines
|
317
|
+
if ERROR_REC.search(line)]
|
318
|
+
|
319
|
+
# suspect_linenos = suspect_linenos[:num_windows]
|
320
|
+
|
321
|
+
extra = [
|
322
|
+
'\n'.join(
|
323
|
+
[f"{'':-<70}",f"{'':>4}⋮"]
|
324
|
+
+[f"{j:>4d}| {line}" for j,line in lines[i:i+window_size]]
|
325
|
+
+[f"{'':>4}⋮"])
|
326
|
+
for i in suspect_linenos]
|
327
|
+
|
328
|
+
m = len(lines)-num_windows
|
329
|
+
|
330
|
+
if suspect_linenos:
|
331
|
+
m = max(m, suspect_linenos[-1])
|
332
|
+
|
333
|
+
last_lines = lines[m:]
|
334
|
+
|
335
|
+
if last_lines:
|
336
|
+
extra += [
|
337
|
+
f"{'':-<70}",
|
338
|
+
f"Last {len(last_lines)} lines of command output:",
|
339
|
+
f"{'':>4}⋮"]
|
340
|
+
|
341
|
+
extra += [
|
342
|
+
f"{j:>4d}| {line}"
|
343
|
+
for j,line in last_lines]
|
344
|
+
|
345
|
+
extra += [
|
346
|
+
f"{'END':>4}| [See log file: {stdout_file}]",
|
347
|
+
f"{'':-<70}",]
|
348
|
+
|
349
|
+
raise BuildCommandError(
|
350
|
+
str(e),
|
351
|
+
extra='\n'.join(extra)) from None
|
{partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/builder/cargo.py
RENAMED
@@ -13,7 +13,7 @@ from ..validate import (
|
|
13
13
|
ValidPathError,
|
14
14
|
FileOutsideRootError )
|
15
15
|
|
16
|
-
|
16
|
+
#===============================================================================
|
17
17
|
def cargo(
|
18
18
|
pyproj: PyProjBase,
|
19
19
|
logger: Logger,
|
@@ -31,7 +31,7 @@ def cargo(
|
|
31
31
|
"""
|
32
32
|
|
33
33
|
if not shutil.which('cargo'):
|
34
|
-
raise ValueError(
|
34
|
+
raise ValueError("The 'cargo' program not found.")
|
35
35
|
|
36
36
|
if setup_args or install_args:
|
37
37
|
raise ValueError(
|
{partis_pyproj-0.1.4.data → partis_pyproj-0.1.6.data}/purelib/partis/pyproj/builder/cmake.py
RENAMED
@@ -1,25 +1,19 @@
|
|
1
|
-
import
|
2
|
-
import os.path as osp
|
3
|
-
import tempfile
|
1
|
+
from __future__ import annotations
|
4
2
|
import shutil
|
5
|
-
import subprocess
|
6
3
|
|
7
|
-
|
8
|
-
validating,
|
9
|
-
ValidationError,
|
10
|
-
ValidPathError,
|
11
|
-
FileOutsideRootError )
|
12
|
-
|
13
|
-
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
4
|
+
#===============================================================================
|
14
5
|
def cmake_option_arg(k, v):
|
15
6
|
"""Convert python key-value pair to cmake ``-Dkey=value`` option
|
16
7
|
"""
|
8
|
+
typename = ''
|
9
|
+
|
17
10
|
if isinstance(v, bool):
|
11
|
+
typename = ':BOOL'
|
18
12
|
v = ({True: 'ON', False: 'OFF'})[v]
|
19
13
|
|
20
|
-
return f'-D{k}={v}'
|
14
|
+
return f'-D{k}{typename}={v}'
|
21
15
|
|
22
|
-
|
16
|
+
#===============================================================================
|
23
17
|
def cmake(
|
24
18
|
pyproj,
|
25
19
|
logger,
|
@@ -50,10 +44,10 @@ def cmake(
|
|
50
44
|
"""
|
51
45
|
|
52
46
|
if not shutil.which('cmake'):
|
53
|
-
raise ValueError(
|
47
|
+
raise ValueError("The 'cmake' program not found.")
|
54
48
|
|
55
49
|
if not shutil.which('ninja'):
|
56
|
-
raise ValueError(
|
50
|
+
raise ValueError("The 'ninja' program not found.")
|
57
51
|
|
58
52
|
# TODO: ensure any paths in setup_args are normalized
|
59
53
|
if not build_clean:
|