cmeel 0.46.0__tar.gz → 0.47.1__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 cmeel might be problematic. Click here for more details.

@@ -1,18 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cmeel
3
- Version: 0.46.0
3
+ Version: 0.47.1
4
4
  Summary: Create Wheel from CMake projects
5
5
  Home-page: https://github.com/cmake-wheel/cmeel
6
6
  License: BSD-2-Clause
7
7
  Author: Guilhem Saurel
8
8
  Author-email: guilhem.saurel@laas.fr
9
- Requires-Python: >=3.7,<4.0
9
+ Requires-Python: >=3.8,<4.0
10
10
  Classifier: License :: OSI Approved :: BSD License
11
11
  Classifier: Operating System :: MacOS
12
12
  Classifier: Operating System :: POSIX :: Linux
13
13
  Classifier: Programming Language :: C++
14
14
  Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.7
16
15
  Classifier: Programming Language :: Python :: 3.8
17
16
  Classifier: Programming Language :: Python :: 3.9
18
17
  Classifier: Programming Language :: Python :: 3.10
@@ -21,11 +20,11 @@ Classifier: Topic :: Software Development :: Build Tools
21
20
  Classifier: Topic :: System :: Archiving :: Packaging
22
21
  Classifier: Topic :: System :: Software Distribution
23
22
  Provides-Extra: build
24
- Requires-Dist: cmake (>=3.22.3,<4.0.0) ; extra == "build"
25
- Requires-Dist: importlib-metadata (>=6.0.0,<7.0.0) ; python_version < "3.8"
26
- Requires-Dist: packaging (>=23.0,<24.0) ; extra == "build"
23
+ Requires-Dist: cmake (>=3.27.0,<4.0.0) ; extra == "build"
24
+ Requires-Dist: git-archive-all (>=1.23.1,<2.0.0) ; extra == "build"
25
+ Requires-Dist: packaging (>=23.1,<24.0) ; extra == "build"
27
26
  Requires-Dist: tomli (>=2.0.1,<3.0.0) ; python_version < "3.11"
28
- Requires-Dist: wheel (>=0.38.4,<0.41.0) ; extra == "build"
27
+ Requires-Dist: wheel (>=0.41.0,<0.42.0) ; extra == "build"
29
28
  Project-URL: Documentation, https://cmeel.readthedocs.io/
30
29
  Project-URL: changelog, https://github.com/cmake-wheel/cmeel/blob/main/CHANGELOG.md
31
30
  Description-Content-Type: text/markdown
@@ -55,7 +54,7 @@ https://matrix.to/#/#cmake-wheel:matrix.org
55
54
 
56
55
  ## Basic idea
57
56
 
58
- Glue between PEP 517 `build_wheel` function and modern CMake standard project configuration / build / test / install
57
+ Glue between PEP 517 & 660 entry points and modern CMake standard project configuration / build / test / install
59
58
 
60
59
  This Install in `${PYTHON_SITELIB}/cmeel.prefix/`:
61
60
  - As there is a dot, it is not a valid python module name, so no risk of importing anything there by mistake
@@ -23,7 +23,7 @@ https://matrix.to/#/#cmake-wheel:matrix.org
23
23
 
24
24
  ## Basic idea
25
25
 
26
- Glue between PEP 517 `build_wheel` function and modern CMake standard project configuration / build / test / install
26
+ Glue between PEP 517 & 660 entry points and modern CMake standard project configuration / build / test / install
27
27
 
28
28
  This Install in `${PYTHON_SITELIB}/cmeel.prefix/`:
29
29
  - As there is a dot, it is not a valid python module name, so no risk of importing anything there by mistake
@@ -1,9 +1,6 @@
1
1
  """Cmeel module."""
2
2
 
3
- try:
4
- from importlib.metadata import metadata
5
- except ImportError: # Python < 3.8
6
- from importlib_metadata import metadata # type: ignore
3
+ from importlib.metadata import metadata
7
4
 
8
5
  __metadata__ = metadata("cmeel")
9
6
  __project_name__ = __metadata__["name"]
@@ -6,6 +6,7 @@ import os
6
6
  import pathlib
7
7
  import sys
8
8
 
9
+ from . import __version__
9
10
  from .docker import add_docker_arguments, docker_build
10
11
  from .env import add_paths_arguments, get_paths
11
12
  from .release import add_release_arguments, release
@@ -42,6 +43,9 @@ def parse_args() -> argparse.Namespace:
42
43
  add_docker_arguments(subparsers)
43
44
  add_release_arguments(subparsers)
44
45
 
46
+ ver = subparsers.add_parser("version", help="print current cmeel version.")
47
+ ver.set_defaults(cmd="version")
48
+
45
49
  args = parser.parse_args()
46
50
 
47
51
  if args.verbose == 0:
@@ -50,7 +54,7 @@ def parse_args() -> argparse.Namespace:
50
54
  level = 30 - 10 * args.verbose
51
55
  logging.basicConfig(level=level)
52
56
 
53
- LOG.debug("parsed arguments :%s", args)
57
+ LOG.debug("parsed arguments: %s", args)
54
58
 
55
59
  if "cmd" in args:
56
60
  LOG.debug("running subcommand %s", args.cmd)
@@ -65,8 +69,10 @@ def main():
65
69
  args = parse_args()
66
70
  if args.cmd == "docker":
67
71
  docker_build(**vars(args))
68
- if args.cmd == "release":
72
+ elif args.cmd == "release":
69
73
  release(**vars(args))
74
+ elif args.cmd == "version":
75
+ print(f"This is cmeel version {__version__}")
70
76
  else:
71
77
  print(get_paths(**vars(args)))
72
78
 
@@ -0,0 +1,31 @@
1
+ """PEP 517 & 660 entry points."""
2
+
3
+ import logging
4
+ import os
5
+
6
+ from .impl import build_impl
7
+ from .sdist import sdist_impl
8
+
9
+ LOG = logging.getLogger("cmeel")
10
+
11
+
12
+ def build_editable(
13
+ wheel_directory,
14
+ config_settings=None,
15
+ metadata_directory=None,
16
+ ) -> str:
17
+ """Build an editable wheel: main entry point for PEP 660."""
18
+ LOG.info("cmeel build editable")
19
+ os.environ["CMAKE_INSTALL_MODE"] = "ABS_SYMLINK"
20
+ return build_impl(wheel_directory, editable=True)
21
+
22
+
23
+ def build_wheel(wheel_directory, config_settings=None, metadata_directory=None) -> str:
24
+ """Build a binary wheel: main entry point for PEP 517."""
25
+ LOG.info("cmeel build wheel")
26
+ return build_impl(wheel_directory, editable=False)
27
+
28
+
29
+ def build_sdist(sdist_directory, config_settings=None) -> str:
30
+ """Generate a gzipped distribution tarball."""
31
+ return sdist_impl(sdist_directory)
@@ -3,6 +3,6 @@ import os
3
3
  import sys
4
4
 
5
5
  CMEEL_PREFIX = "cmeel.prefix"
6
- SITELIB = os.sep.join(
6
+ SITELIB = os.sep.join( # noqa: PTH118
7
7
  ["lib", "python" + ".".join(sys.version.split(".")[:2]), "site-packages"],
8
8
  )
@@ -0,0 +1,200 @@
1
+ """Implementation of the main build function."""
2
+
3
+ import logging
4
+ import os
5
+ import re
6
+ import sys
7
+ from pathlib import Path
8
+ from subprocess import check_call, check_output
9
+
10
+ try:
11
+ import tomllib # type: ignore
12
+ except ModuleNotFoundError:
13
+ import tomli as tomllib # type: ignore
14
+
15
+ from . import __version__
16
+ from .config import cmeel_config
17
+ from .consts import CMEEL_PREFIX, SITELIB
18
+ from .metadata import metadata
19
+ from .utils import (
20
+ deprecate_build_system,
21
+ ensure_relocatable,
22
+ expose_bin,
23
+ get_tag,
24
+ launch_tests,
25
+ log_pip,
26
+ normalize,
27
+ patch,
28
+ )
29
+
30
+ LOG = logging.getLogger("cmeel.impl")
31
+
32
+
33
+ def build_impl(wheel_directory, editable=False) -> str:
34
+ """Run CMake configure / build / test / install steps, and pack the wheel."""
35
+ logging.basicConfig(level=cmeel_config.log_level.upper())
36
+ LOG.info("CMake Wheel in editable mode" if editable else "CMake Wheel")
37
+ LOG.info("cmeel version %s" % __version__)
38
+ log_pip()
39
+
40
+ prefix = Path() / "build-editable" if editable else cmeel_config.temp_dir
41
+ build = prefix / "bld"
42
+ wheel_dir = prefix / "whl"
43
+ install = (prefix if editable else wheel_dir) / CMEEL_PREFIX
44
+
45
+ LOG.info("load conf from pyproject.toml")
46
+ with Path("pyproject.toml").open("rb") as f:
47
+ pyproject = tomllib.load(f)
48
+
49
+ conf = pyproject["project"]
50
+ conf["name"] = normalize(conf["name"])
51
+ distribution = f"{conf['name'].replace('-', '_')}-{conf['version']}"
52
+
53
+ source = deprecate_build_system(pyproject, "source", ".")
54
+ run_tests = (
55
+ os.environ.get("CMEEL_RUN_TESTS", "ON").upper()
56
+ not in ("0", "NO", "OFF", "FALSE")
57
+ if "CMEEL_RUN_TESTS" in os.environ
58
+ else deprecate_build_system(pyproject, "run-tests", True)
59
+ )
60
+ run_tests_after_install = deprecate_build_system(
61
+ pyproject,
62
+ "run-tests-after-install",
63
+ False,
64
+ )
65
+ build_number = deprecate_build_system(pyproject, "build-number", 0)
66
+ configure_args = deprecate_build_system(pyproject, "configure-args", [])
67
+
68
+ check_relocatable = deprecate_build_system(pyproject, "check-relocatable", True)
69
+ fix_pkg_config = deprecate_build_system(pyproject, "fix-pkg-config", True)
70
+
71
+ LOG.info("build wheel")
72
+
73
+ # Patch
74
+
75
+ patch()
76
+
77
+ # Set env
78
+
79
+ if run_tests_after_install:
80
+ path = f"{install / SITELIB}"
81
+ old = os.environ.get("PYTHONPATH", "")
82
+ if old:
83
+ path += f"{os.pathsep}{old}"
84
+ os.environ.update(PYTHONPATH=path)
85
+
86
+ # Configure
87
+
88
+ LOG.info("configure")
89
+ configure_env = cmeel_config.get_configure_env()
90
+ configure_args = cmeel_config.get_configure_args(
91
+ conf,
92
+ install,
93
+ configure_args,
94
+ configure_env,
95
+ run_tests,
96
+ )
97
+ configure_cmd = ["cmake", "-S", source, "-B", str(build), *configure_args]
98
+ LOG.debug("configure environment: %s", configure_env)
99
+ LOG.debug("configure command: %s", configure_cmd)
100
+ check_call(configure_cmd, env=configure_env)
101
+
102
+ LOG.info("build")
103
+ build_cmd = ["cmake", "--build", str(build), f"-j{cmeel_config.jobs}"]
104
+ LOG.debug("build command: %s", build_cmd)
105
+ check_call(build_cmd)
106
+
107
+ launch_tests(True, run_tests and not run_tests_after_install, pyproject, build)
108
+
109
+ LOG.info("install")
110
+ install_cmd = ["cmake", "--build", str(build), "-t", "install"]
111
+ LOG.debug("install command: %s", install_cmd)
112
+ check_call(install_cmd)
113
+
114
+ launch_tests(False, run_tests and run_tests_after_install, pyproject, build)
115
+
116
+ LOG.info("fix relocatablization")
117
+ # Replace absolute install path in generated .cmake files, if any.
118
+ for cmake_file in install.rglob("*.cmake"):
119
+ ff = install / f"{cmake_file.stem}.fix"
120
+ with cmake_file.open("r") as fr, ff.open("w") as fw:
121
+ fw.write(fr.read().replace(str(install), "${PACKAGE_PREFIX_DIR}"))
122
+ cmake_file.unlink()
123
+ ff.rename(cmake_file)
124
+
125
+ LOG.info("create dist-info")
126
+
127
+ dist_info = wheel_dir / f"{distribution}.dist-info"
128
+ dist_info.mkdir(parents=True)
129
+
130
+ LOG.info("create dist-info / METADATA")
131
+
132
+ with (dist_info / "METADATA").open("w") as f:
133
+ requires = pyproject["build-system"]["requires"]
134
+ f.write("\n".join(metadata(conf, dist_info, requires)))
135
+
136
+ LOG.info("create dist-info / top level")
137
+ with (dist_info / "top_level.txt").open("w") as f:
138
+ f.write("")
139
+
140
+ LOG.info("create dist-info / WHEEL")
141
+ with (dist_info / "WHEEL").open("w") as f:
142
+ f.write(
143
+ "\n".join(
144
+ [
145
+ "Wheel-Version: 1.0",
146
+ f"Generator: cmeel {__version__}",
147
+ "Root-Is-Purelib: false",
148
+ f"Tag: {get_tag(pyproject)}",
149
+ "",
150
+ ],
151
+ ),
152
+ )
153
+
154
+ expose_bin(install, wheel_dir, distribution)
155
+
156
+ ensure_relocatable(check_relocatable, install, prefix)
157
+
158
+ if editable:
159
+ LOG.info("Add .pth in wheel")
160
+ with (wheel_dir / f"{distribution}.pth").open("w") as f:
161
+ f.write(str((install / SITELIB).absolute()))
162
+ elif fix_pkg_config:
163
+ LOG.info("fix pkg-config files")
164
+ for fc in install.glob("**/*.pc"):
165
+ with fc.open() as f:
166
+ pc_file = f.read()
167
+ if str(install) in pc_file:
168
+ rel = str(fc.parent.relative_to(install))
169
+ fix = "/".join(["${pcfiledir}"] + [".." for _ in rel.split("/")])
170
+ LOG.warning("fix pkg-config %s: replace %s by %s", fc, install, fix)
171
+ with fc.open("w") as f:
172
+ f.write(pc_file.replace(str(install), fix))
173
+
174
+ LOG.info("wheel pack")
175
+ pack = check_output(
176
+ [
177
+ sys.executable,
178
+ "-m",
179
+ "wheel",
180
+ "pack",
181
+ "--build-number",
182
+ str(build_number),
183
+ "-d",
184
+ wheel_directory,
185
+ str(wheel_dir),
186
+ ],
187
+ ).decode()
188
+ LOG.debug("wheel pack output: %s", pack)
189
+ parse_pack = re.search("Repacking wheel as (.*\\.whl)\\.\\.\\.", pack)
190
+ if parse_pack is None:
191
+ err = (
192
+ "'wheel pack' command did not provide the .whl name, "
193
+ "or the parser must be updated. Please report the following output: \n"
194
+ )
195
+ raise FileNotFoundError(err + pack)
196
+ name = Path(parse_pack.group(1)).name
197
+ LOG.debug("returning '%s'", name)
198
+
199
+ LOG.info("done")
200
+ return name
@@ -5,7 +5,6 @@ https://packaging.python.org/en/latest/specifications/declaring-project-metadata
5
5
  """
6
6
 
7
7
  import glob
8
- import re
9
8
  import warnings
10
9
  from pathlib import Path
11
10
  from typing import Any, Dict, List, Tuple, Union
@@ -13,14 +12,6 @@ from typing import Any, Dict, List, Tuple, Union
13
12
  LICENSE_GLOBS = ["LICEN[CS]E*", "COPYING*", "NOTICE*", "AUTHORS*"]
14
13
 
15
14
 
16
- def normalize(name: str) -> str:
17
- """Normalize name.
18
-
19
- ref. https://packaging.python.org/en/latest/specifications/name-normalization
20
- """
21
- return re.sub(r"[-_.]+", "-", name).lower()
22
-
23
-
24
15
  def get_license(conf: Dict[str, Any], dist_info: Path) -> List[str]:
25
16
  """Parse 'license' and 'license-files' keys."""
26
17
  metadata = []
@@ -237,3 +228,22 @@ def get_keywords(conf: Dict[str, Any]) -> List[str]:
237
228
  keywords = ",".join(conf["keywords"])
238
229
  metadata.append(f"Keywords: {keywords}")
239
230
  return metadata
231
+
232
+
233
+ def metadata(conf, dist_info, requires) -> List[str]:
234
+ """Return the lines which should go in the METADATA / PKG-INFO file."""
235
+ return [
236
+ "Metadata-Version: 2.1",
237
+ f"Name: {conf['name']}",
238
+ f"Version: {conf['version']}",
239
+ f"Summary: {conf['description']}",
240
+ f"Requires-Python: {conf.get('requires-python', '>=3.8')}",
241
+ *get_license(conf, dist_info),
242
+ *get_people(conf, "author"),
243
+ *get_people(conf, "maintainer"),
244
+ *get_keywords(conf),
245
+ *get_urls(conf),
246
+ *get_deps(conf, requires),
247
+ *[f"Classifier: {classifier}" for classifier in conf.get("classifiers", [])],
248
+ *get_readme(conf),
249
+ ]
@@ -0,0 +1,36 @@
1
+ """Generate .tar.gz source distribution."""
2
+
3
+ import logging
4
+ from pathlib import Path
5
+
6
+ try:
7
+ import tomllib # type: ignore
8
+ except ModuleNotFoundError:
9
+ import tomli as tomllib # type: ignore
10
+
11
+ try:
12
+ import git_archive_all
13
+ except ImportError as e:
14
+ err = "You need the 'build' extra option to use this build module.\n"
15
+ err += "For this you can install the 'cmeel[build]' package."
16
+ raise ImportError(err) from e
17
+
18
+ from .utils import normalize
19
+
20
+ LOG = logging.getLogger("cmeel.sdist")
21
+
22
+
23
+ def sdist_impl(sdist_directory) -> str:
24
+ """Implement the build_sdist entry point."""
25
+ LOG.info("load conf from pyproject.toml")
26
+ with Path("pyproject.toml").open("rb") as f:
27
+ pyproject = tomllib.load(f)
28
+
29
+ conf = pyproject["project"]
30
+ conf["name"] = normalize(conf["name"])
31
+ distribution = f"{conf['name'].replace('-', '_')}-{conf['version']}"
32
+
33
+ git_archive_all.main(
34
+ ["git_archive_all.py", str(Path(sdist_directory) / f"{distribution}.tar.gz")],
35
+ )
36
+ return distribution
@@ -0,0 +1,193 @@
1
+ """Utilities."""
2
+
3
+ import logging
4
+ import os
5
+ import re
6
+ import sys
7
+ import warnings
8
+ from importlib.util import find_spec
9
+ from pathlib import Path
10
+ from subprocess import CalledProcessError, check_call, check_output, run
11
+
12
+ from .config import cmeel_config
13
+
14
+ try:
15
+ from packaging.tags import sys_tags
16
+ except ImportError as e:
17
+ err = "You need the 'build' extra option to use this build module.\n"
18
+ err += "For this you can install the 'cmeel[build]' package."
19
+ raise ImportError(err) from e
20
+
21
+ LOG = logging.getLogger("cmeel.utils")
22
+
23
+ PATCH_IGNORE = [
24
+ "hunk ignored",
25
+ "hunks ignored",
26
+ "Skipping patch.",
27
+ "The next patch would delete",
28
+ ]
29
+
30
+ EXECUTABLE = """#!python
31
+ from cmeel.run import cmeel_run
32
+ cmeel_run()
33
+ """
34
+
35
+
36
+ class PatchError(CalledProcessError):
37
+ """Exception raised when patch operation failed."""
38
+
39
+ def __str__(self):
40
+ """Render this error as a string."""
41
+ if self.returncode and self.returncode < 0:
42
+ return super().__str__()
43
+ return (
44
+ f"Command '{self.cmd}' exit status {self.returncode}\n"
45
+ f"with output:\n{self.output}\n"
46
+ f"and stderr:\n{self.stderr}\n"
47
+ )
48
+
49
+
50
+ class NonRelocatableError(Exception):
51
+ """Exception raised when absolute paths are in the final package."""
52
+
53
+ pass
54
+
55
+
56
+ def deprecate_build_system(pyproject, key, default):
57
+ """Cmeel up to v0.22 was using the "build-system" section of pyproject.toml.
58
+
59
+ This function helps to deprecate that and move to "tool.cmeel".
60
+ """
61
+ if key in pyproject["build-system"]:
62
+ default = pyproject["build-system"][key]
63
+ warnings.warn(
64
+ 'Using the "build-system" section of pyproject.toml for cmeel '
65
+ "configuration is deprecated since cmeel v0.23 and will be removed in v1.\n"
66
+ f'Please move your "{key} = {default}" to the "tool.cmeel" section.',
67
+ DeprecationWarning,
68
+ stacklevel=2,
69
+ )
70
+ if "tool" in pyproject and "cmeel" in pyproject["tool"]:
71
+ return pyproject["tool"]["cmeel"].get(key, default)
72
+ return default
73
+
74
+
75
+ def normalize(name: str) -> str:
76
+ """Normalize name.
77
+
78
+ ref. https://packaging.python.org/en/latest/specifications/name-normalization
79
+ """
80
+ return re.sub(r"[-_.]+", "-", name).lower()
81
+
82
+
83
+ def log_pip():
84
+ """Log output of pip freeze."""
85
+ if LOG.getEffectiveLevel() <= logging.DEBUG:
86
+ if find_spec("pip") is not None:
87
+ LOG.debug("pip freeze:")
88
+ deps = check_output([sys.executable, "-m", "pip", "freeze"], text=True)
89
+ for dep in deps.strip().split("\n"):
90
+ LOG.debug(" %s", dep)
91
+
92
+
93
+ def get_tag(pyproject) -> str:
94
+ """Find the correct tag for the wheel."""
95
+ tag = str(next(sys_tags()))
96
+ # handle cross compilation on macOS with cibuildwheel
97
+ # ref. https://github.com/pypa/cibuildwheel/blob/6549a9/cibuildwheel/macos.py#L221
98
+ if "_PYTHON_HOST_PLATFORM" in os.environ:
99
+ plat = os.environ["_PYTHON_HOST_PLATFORM"].replace("-", "_").replace(".", "_")
100
+ tag = "-".join(tag.split("-")[:-1] + [plat])
101
+
102
+ if deprecate_build_system(pyproject, "py3-none", False):
103
+ tag = "-".join(["py3", "none", tag.split("-")[-1]])
104
+ elif deprecate_build_system(pyproject, "any", False):
105
+ tag = "py3-none-any"
106
+ elif deprecate_build_system(pyproject, "pyver-any", False):
107
+ tag = f"py3{sys.version_info.minor}-none-any"
108
+ return tag
109
+
110
+
111
+ def patch():
112
+ """Apply cmeel.patch if it exists and was not already applied."""
113
+ if Path("cmeel.patch").exists():
114
+ LOG.info("patching")
115
+ cmd = ["patch", "-p0", "-s", "-N", "-i", "cmeel.patch"]
116
+ ret = run(cmd, capture_output=True, text=True)
117
+ if ret.returncode != 0:
118
+ # If this patch was already applied, it's okay.
119
+ for line in ret.stdout.split("\n"):
120
+ if not line or any(val in line for val in PATCH_IGNORE):
121
+ continue
122
+ raise PatchError(
123
+ returncode=ret.returncode,
124
+ cmd=cmd,
125
+ output=ret.stdout,
126
+ stderr=ret.stderr + f"\nwrong line: {line}\n",
127
+ )
128
+ LOG.info("this patch was already applied")
129
+
130
+
131
+ def expose_bin(install: Path, wheel_dir: Path, distribution: str):
132
+ """Add scripts wrapping calls to CMEEL_PREFIX/bin/ executables."""
133
+ bin_dir = install / "bin"
134
+ if bin_dir.is_dir():
135
+ LOG.info("adding executables")
136
+ scripts = wheel_dir / f"{distribution}.data" / "scripts"
137
+ scripts.mkdir(parents=True)
138
+ for fn in bin_dir.glob("*"):
139
+ executable = scripts / fn.name
140
+ with executable.open("w") as fe:
141
+ fe.write(EXECUTABLE)
142
+ executable.chmod(0o755)
143
+
144
+
145
+ def ensure_relocatable(check_relocatable: bool, install: Path, prefix: Path):
146
+ """Ensure no cmake file contains wrong absolute paths."""
147
+ if not check_relocatable:
148
+ return
149
+ LOG.info("check generated cmake files")
150
+ wrong_dirs = [
151
+ "/tmp/pip-build-env",
152
+ "/tmp/pip-req-build",
153
+ "/opt/_internal",
154
+ str(prefix),
155
+ ]
156
+ for fc in install.glob("**/*.cmake"):
157
+ with fc.open() as f:
158
+ cmake_file = f.read()
159
+ if any(wrong_dir in cmake_file for wrong_dir in wrong_dirs):
160
+ lines = cmake_file.split("\n")
161
+ # Get indexes of of problematic lines
162
+ indexes = [
163
+ idx
164
+ for idx, line in enumerate(lines)
165
+ if any(wrong_dir in line for wrong_dir in wrong_dirs)
166
+ ]
167
+ # Get lines at those indexes and around them to display
168
+ display = [
169
+ f"{i}: {line}"
170
+ for i, line in enumerate(lines)
171
+ if any(idx in indexes for idx in (i - 2, i - 1, i, i + 1, i + 2))
172
+ ]
173
+ raise NonRelocatableError(
174
+ f"{fc} references temporary paths:\n" + "\n".join(display),
175
+ )
176
+
177
+
178
+ def launch_tests(before: bool, now: bool, pyproject, build: Path):
179
+ """Launch tests, before or after the install."""
180
+ if not now:
181
+ return
182
+
183
+ test_cmd = deprecate_build_system(
184
+ pyproject,
185
+ "test-cmd",
186
+ ["cmake", "--build", "BUILD_DIR", "-t", "test"],
187
+ )
188
+ LOG.info("test {} install".format("before") if before else "after")
189
+ test_env = cmeel_config.get_test_env()
190
+ cmd = [i.replace("BUILD_DIR", str(build)) for i in test_cmd]
191
+ LOG.debug("test environment: %s", test_env)
192
+ LOG.debug("test command: %s", cmd)
193
+ check_call(cmd, env=test_env)
@@ -23,32 +23,32 @@ include = ['cmeel.pth']
23
23
  license = "BSD-2-Clause"
24
24
  name = "cmeel"
25
25
  readme = "README.md"
26
- version = "0.46.0"
26
+ version = "0.47.1"
27
27
 
28
28
  [tool.poetry.dependencies]
29
- cmake = {optional = true, version = "^3.22.3"}
30
- importlib-metadata = {python = "<3.8", version = "^6.0.0"}
31
- packaging = {optional = true, version = "^23.0"}
32
- python = "^3.7"
29
+ cmake = {optional = true, version = "^3.27.0"}
30
+ git-archive-all = {optional = true, version = "^1.23.1"}
31
+ packaging = {optional = true, version = "^23.1"}
32
+ python = "^3.8"
33
33
  tomli = {python = "< 3.11", version = "^2.0.1"}
34
- wheel = {optional = true, version = ">=0.38.4,<0.41.0"}
34
+ wheel = {optional = true, version = "^0.41.0"}
35
35
 
36
36
  [tool.poetry.extras]
37
- build = ["cmake", "packaging", "wheel"]
37
+ build = ["cmake", "git-archive-all", "packaging", "wheel"]
38
38
 
39
39
  [tool.poetry.group.dev]
40
40
  optional = true
41
41
 
42
42
  [tool.poetry.group.dev.dependencies]
43
- black = "^23.1.0"
44
- furo = "^2023.3.27"
45
- isort = {python = "^3.8", version = "^5.12.0"}
46
- mypy = "^1.1.1"
47
- myst-parser = ">=0.18.1,<1.1.0"
48
- requests = "^2.29.0"
49
- ruff = ">=0.0.264,<0.0.271"
50
- safety = {allow-prereleases = true, version = "^2.4.0b1"}
51
- sphinx = "^5.3.0"
43
+ black = "^23.7.0"
44
+ furo = "^2023.7.26"
45
+ isort = "^5.12.0"
46
+ mypy = "^1.4.1"
47
+ myst-parser = "^2.0.0"
48
+ requests = "^2.31.0"
49
+ ruff = "^0.0.282"
50
+ # safety = {allow-prereleases = true, version = "^2.4.0b1"} TODO: bump when they fix packaging support
51
+ sphinx = "^7.1.2"
52
52
 
53
53
  [tool.poetry.scripts]
54
54
  cmeel = "cmeel.__main__:main"
@@ -1,357 +0,0 @@
1
- """Cmeel build.
2
-
3
- Functions to generate package archives.
4
- """
5
- import logging
6
- import os
7
- import re
8
- import sys
9
- import warnings
10
- from importlib.util import find_spec
11
- from pathlib import Path
12
- from subprocess import CalledProcessError, check_call, check_output, run
13
-
14
- try:
15
- from packaging.tags import sys_tags
16
- except ImportError as e:
17
- err = "You need the 'build' extra option to use this build module.\n"
18
- err += "For this you can install the 'cmeel[build]' package."
19
- raise ImportError(err) from e
20
- try:
21
- import tomllib # type: ignore
22
- except ModuleNotFoundError:
23
- import tomli as tomllib # type: ignore
24
-
25
- from . import __version__
26
- from .config import cmeel_config
27
- from .consts import CMEEL_PREFIX, SITELIB
28
- from .metadata import (
29
- get_deps,
30
- get_keywords,
31
- get_license,
32
- get_people,
33
- get_readme,
34
- get_urls,
35
- normalize,
36
- )
37
-
38
- LOG = logging.getLogger("cmeel")
39
- EXECUTABLE = """#!python
40
- from cmeel.run import cmeel_run
41
- cmeel_run()
42
- """
43
- PATCH_IGNORE = [
44
- "hunk ignored",
45
- "hunks ignored",
46
- "Skipping patch.",
47
- "The next patch would delete",
48
- ]
49
-
50
-
51
- class NonRelocatableError(Exception):
52
- """Exception raised when absolute paths are in the final package."""
53
-
54
- pass
55
-
56
-
57
- class PatchError(CalledProcessError):
58
- """Exception raised when patch operation failed."""
59
-
60
- def __str__(self):
61
- """Render this error as a string."""
62
- if self.returncode and self.returncode < 0:
63
- return super().__str__()
64
- return (
65
- f"Command '{self.cmd}' exit status {self.returncode}\n"
66
- f"with output:\n{self.output}\n"
67
- f"and stderr:\n{self.stderr}\n"
68
- )
69
-
70
-
71
- def deprecate_build_system(pyproject, key, default):
72
- """Cmeel up to v0.22 was using the "build-system" section of pyproject.toml.
73
-
74
- This function helps to deprecate that and move to "tool.cmeel".
75
- """
76
- if key in pyproject["build-system"]:
77
- default = pyproject["build-system"][key]
78
- warnings.warn(
79
- 'Using the "build-system" section of pyproject.toml for cmeel '
80
- "configuration is deprecated since cmeel v0.23 and will be removed in v1.\n"
81
- f'Please move your "{key} = {default}" to the "tool.cmeel" section.',
82
- DeprecationWarning,
83
- stacklevel=2,
84
- )
85
- if "tool" in pyproject and "cmeel" in pyproject["tool"]:
86
- return pyproject["tool"]["cmeel"].get(key, default)
87
- return default
88
-
89
-
90
- def build_editable(wheel_directory, config_settings=None, metadata_directory=None):
91
- """Build an editable wheel: main entry point for PEP 660."""
92
- os.environ["CMAKE_INSTALL_MODE"] = "ABS_SYMLINK"
93
- return build(wheel_directory, editable=True)
94
-
95
-
96
- def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
97
- """Build a binary wheel: main entry point for PEP 517."""
98
- return build(wheel_directory, editable=False)
99
-
100
-
101
- def build(wheel_directory, editable=False): # noqa: C901 TODO
102
- """Run CMake configure / build / test / install steps, and pack the wheel."""
103
- logging.basicConfig(level=cmeel_config.log_level.upper())
104
- LOG.info("CMake Wheel in editable mode" if editable else "CMake Wheel")
105
- LOG.info("cmeel version %s" % __version__)
106
- if LOG.getEffectiveLevel() <= logging.DEBUG:
107
- if find_spec("pip") is not None:
108
- LOG.debug("pip freeze:")
109
- deps = check_output([sys.executable, "-m", "pip", "freeze"], text=True)
110
- for dep in deps.strip().split("\n"):
111
- LOG.debug(" %s", dep)
112
-
113
- prefix = Path(".") / "build-editable" if editable else cmeel_config.temp_dir
114
- build = prefix / "bld"
115
- wheel_dir = prefix / "whl"
116
- install = (prefix if editable else wheel_dir) / CMEEL_PREFIX
117
- tag = str(next(sys_tags()))
118
- # handle cross compilation on macOS with cibuildwheel
119
- # ref. https://github.com/pypa/cibuildwheel/blob/6549a9/cibuildwheel/macos.py#L221
120
- if "_PYTHON_HOST_PLATFORM" in os.environ:
121
- plat = os.environ["_PYTHON_HOST_PLATFORM"].replace("-", "_").replace(".", "_")
122
- tag = "-".join(tag.split("-")[:-1] + [plat])
123
-
124
- LOG.info("load conf from pyproject.toml")
125
- with Path("pyproject.toml").open("rb") as f:
126
- pyproject = tomllib.load(f)
127
- conf = pyproject["project"]
128
- conf["name"] = normalize(conf["name"])
129
- source = deprecate_build_system(pyproject, "source", ".")
130
- run_tests = (
131
- os.environ.get("CMEEL_RUN_TESTS", "ON").upper()
132
- not in ("0", "NO", "OFF", "FALSE")
133
- if "CMEEL_RUN_TESTS" in os.environ
134
- else deprecate_build_system(pyproject, "run-tests", True)
135
- )
136
- run_tests_after_install = deprecate_build_system(
137
- pyproject,
138
- "run-tests-after-install",
139
- False,
140
- )
141
- build_number = deprecate_build_system(pyproject, "build-number", 0)
142
- configure_args = deprecate_build_system(pyproject, "configure-args", [])
143
- test_cmd = deprecate_build_system(
144
- pyproject,
145
- "test-cmd",
146
- ["cmake", "--build", "BUILD_DIR", "-t", "test"],
147
- )
148
- check_relocatable = deprecate_build_system(pyproject, "check-relocatable", True)
149
- fix_pkg_config = deprecate_build_system(pyproject, "fix-pkg-config", True)
150
- if deprecate_build_system(pyproject, "py3-none", False):
151
- tag = "-".join(["py3", "none", tag.split("-")[-1]])
152
- elif deprecate_build_system(pyproject, "any", False):
153
- tag = "py3-none-any"
154
- elif deprecate_build_system(pyproject, "pyver-any", False):
155
- tag = f"py3{sys.version_info.minor}-none-any"
156
- distribution = f"{conf['name'].replace('-', '_')}-{conf['version']}"
157
-
158
- LOG.info("build wheel")
159
-
160
- # Patch
161
-
162
- if Path("cmeel.patch").exists():
163
- LOG.info("patching")
164
- cmd = ["patch", "-p0", "-s", "-N", "-i", "cmeel.patch"]
165
- ret = run(cmd, capture_output=True, text=True)
166
- if ret.returncode != 0:
167
- # If this patch was already applied, it's okay.
168
- for line in ret.stdout.split("\n"):
169
- if not line or any(val in line for val in PATCH_IGNORE):
170
- continue
171
- raise PatchError(
172
- returncode=ret.returncode,
173
- cmd=cmd,
174
- output=ret.stdout,
175
- stderr=ret.stderr + f"\nwrong line: {line}\n",
176
- )
177
- LOG.info("this patch was already applied")
178
-
179
- # Set env
180
-
181
- if run_tests_after_install:
182
- path = f"{install / SITELIB}"
183
- old = os.environ.get("PYTHONPATH", "")
184
- if old:
185
- path += f"{os.pathsep}{old}"
186
- os.environ.update(PYTHONPATH=path)
187
-
188
- # Configure
189
-
190
- LOG.info("configure")
191
- configure_env = cmeel_config.get_configure_env()
192
- configure_args = cmeel_config.get_configure_args(
193
- conf,
194
- install,
195
- configure_args,
196
- configure_env,
197
- run_tests,
198
- )
199
- configure_cmd = ["cmake", "-S", source, "-B", str(build), *configure_args]
200
- LOG.debug("configure environment: %s", configure_env)
201
- LOG.debug("configure command: %s", configure_cmd)
202
- check_call(configure_cmd, env=configure_env)
203
-
204
- LOG.info("build")
205
- build_cmd = ["cmake", "--build", str(build), f"-j{cmeel_config.jobs}"]
206
- LOG.debug("build command: %s", build_cmd)
207
- check_call(build_cmd)
208
-
209
- def launch_tests():
210
- LOG.info("test")
211
- test_env = cmeel_config.get_test_env()
212
- cmd = [i.replace("BUILD_DIR", str(build)) for i in test_cmd]
213
- LOG.debug("test environment: %s", test_env)
214
- LOG.debug("test command: %s", cmd)
215
- check_call(cmd, env=test_env)
216
-
217
- if run_tests and not run_tests_after_install:
218
- launch_tests()
219
-
220
- LOG.info("install")
221
- install_cmd = ["cmake", "--build", str(build), "-t", "install"]
222
- LOG.debug("install command: %s", install_cmd)
223
- check_call(install_cmd)
224
-
225
- if run_tests and run_tests_after_install:
226
- launch_tests()
227
-
228
- LOG.info("fix relocatablization")
229
- # Replace absolute install path in generated .cmake files, if any.
230
- for f in install.rglob("*.cmake"):
231
- ff = install / f"{f.stem}.fix"
232
- with f.open("r") as fr, ff.open("w") as fw:
233
- fw.write(fr.read().replace(str(install), "${PACKAGE_PREFIX_DIR}"))
234
- f.unlink()
235
- ff.rename(f)
236
-
237
- LOG.info("create dist-info")
238
-
239
- dist_info = wheel_dir / f"{distribution}.dist-info"
240
- dist_info.mkdir(parents=True)
241
-
242
- LOG.info("create dist-info / METADATA")
243
-
244
- metadata = [
245
- "Metadata-Version: 2.1",
246
- f"Name: {conf['name']}",
247
- f"Version: {conf['version']}",
248
- f"Summary: {conf['description']}",
249
- f"Requires-Python: {conf.get('requires-python', '>=3.7')}",
250
- *get_license(conf, dist_info),
251
- *get_people(conf, "author"),
252
- *get_people(conf, "maintainer"),
253
- *get_keywords(conf),
254
- *get_urls(conf),
255
- *get_deps(conf, pyproject["build-system"]["requires"]),
256
- *[f"Classifier: {classifier}" for classifier in conf.get("classifiers", [])],
257
- *get_readme(conf),
258
- ]
259
-
260
- with (dist_info / "METADATA").open("w") as f:
261
- f.write("\n".join(metadata))
262
-
263
- LOG.info("create dist-info / top level")
264
- with (dist_info / "top_level.txt").open("w") as f:
265
- f.write("")
266
-
267
- LOG.info("create dist-info / WHEEL")
268
- with (dist_info / "WHEEL").open("w") as f:
269
- f.write(
270
- "\n".join(
271
- [
272
- "Wheel-Version: 1.0",
273
- f"Generator: cmeel {__version__}",
274
- "Root-Is-Purelib: false",
275
- f"Tag: {tag}",
276
- "",
277
- ],
278
- ),
279
- )
280
-
281
- bin_dir = install / "bin"
282
- if bin_dir.is_dir():
283
- LOG.info("adding executables")
284
- scripts = wheel_dir / f"{distribution}.data" / "scripts"
285
- scripts.mkdir(parents=True)
286
- for fn in bin_dir.glob("*"):
287
- executable = scripts / fn.name
288
- with executable.open("w") as fe:
289
- fe.write(EXECUTABLE)
290
- executable.chmod(0o755)
291
-
292
- if check_relocatable:
293
- LOG.info("check generated cmake files")
294
- wrong_dirs = [
295
- "/tmp/pip-build-env",
296
- "/tmp/pip-req-build",
297
- "/opt/_internal",
298
- str(prefix),
299
- ]
300
- for fc in install.glob("**/*.cmake"):
301
- with fc.open() as f:
302
- cmake_file = f.read()
303
- if any(wrong_dir in cmake_file for wrong_dir in wrong_dirs):
304
- lines = cmake_file.split("\n")
305
- # Get indexes of of problematic lines
306
- indexes = [
307
- idx
308
- for idx, line in enumerate(lines)
309
- if any(wrong_dir in line for wrong_dir in wrong_dirs)
310
- ]
311
- # Get lines at those indexes and around them to display
312
- display = [
313
- f"{i}: {line}"
314
- for i, line in enumerate(lines)
315
- if any(
316
- idx in indexes for idx in (i - 2, i - 1, i, i + 1, i + 2)
317
- )
318
- ]
319
- raise NonRelocatableError(
320
- f"{fc} references temporary paths:\n" + "\n".join(display),
321
- )
322
- if fix_pkg_config and not editable:
323
- LOG.info("fix pkg-config files")
324
- for fc in install.glob("**/*.pc"):
325
- with fc.open() as f:
326
- pc_file = f.read()
327
- if str(install) in pc_file:
328
- rel = str(fc.parent.relative_to(install))
329
- fix = "/".join(["${pcfiledir}"] + [".." for _ in rel.split("/")])
330
- LOG.warning("fix pkg-config %s: replace %s by %s", fc, install, fix)
331
- with fc.open("w") as f:
332
- f.write(pc_file.replace(str(install), fix))
333
- if editable:
334
- LOG.info("Add .pth in wheel")
335
- with (wheel_dir / f"{distribution}.pth").open("w") as f:
336
- f.write(str((install / SITELIB).absolute()))
337
-
338
- LOG.info("wheel pack")
339
- pack = check_output(
340
- [
341
- sys.executable,
342
- "-m",
343
- "wheel",
344
- "pack",
345
- "--build-number",
346
- str(build_number),
347
- "-d",
348
- wheel_directory,
349
- str(wheel_dir),
350
- ],
351
- ).decode()
352
- LOG.debug("wheel pack output: %s", pack)
353
- name = Path(re.search("Repacking wheel as (.*\\.whl)\\.\\.\\.", pack).group(1)).name
354
- LOG.debug("returning '%s'", name)
355
-
356
- LOG.info("done")
357
- return name
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes