Skip to content

Commit

Permalink
Revert "Migrate dxtbx build backend to hatchling (cctbx#766)"
Browse files Browse the repository at this point in the history
This reverts commit 2727313.

This is causing failures in libtbx builds where the entry_points are not
being picked up from the specific-installation location in the build/dxtbx/lib
folder. Revert to fix main, so this can be investigated separately.
  • Loading branch information
ndevenish committed Oct 29, 2024
1 parent cb8d706 commit f30e353
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 140 deletions.
113 changes: 113 additions & 0 deletions build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""
Handle dynamic aspects of setup.py and building.
This is separate because the non-dynamic stuff can generally be moved
out of a setup.py, but mainly because at the moment it's how poetry
offloads the unresolved build phases.
"""

from __future__ import annotations

import ast
import itertools
import re
import sys
from pathlib import Path
from typing import Any, Dict, List


def get_entry_point(filename: Path, prefix: str, import_path: str) -> List[str]:
"""Returns the entry point string for a given path.
This looks for LIBTBX_SET_DISPATCHER_NAME, and a root function
named 'run'. It can return multiple results for each file, if more
than one dispatcher name is bound.
Args:
filename:
The python file to parse. Will look for a run() function
and any number of LIBTBX_SET_DISPATCHER_NAME.
prefix: The prefix to output the entry point console script with
import_path: The import path to get to the package the file is in
Returns:
A list of entry_point specifications
"""
contents = filename.read_text()
tree = ast.parse(contents)
# Find root functions named "run"
has_run = any(
x
for x in tree.body
if (isinstance(x, ast.FunctionDef) and x.name == "run")
or (isinstance(x, ast.ImportFrom) and "run" in [a.name for a in x.names])
)
if not has_run:
return []
# Find if we need an alternate name via LIBTBX_SET_DISPATCHER_NAME
alternate_names = re.findall(
r"^#\s*LIBTBX_SET_DISPATCHER_NAME\s+(.*)$", contents, re.M
)
if alternate_names:
return [f"{name}={import_path}.{filename.stem}:run" for name in alternate_names]

return [f"{prefix}.{filename.stem}={import_path}.{filename.stem}:run"]


def enumerate_format_classes(path: Path) -> List[str]:
"""Find all Format*.py files and contained Format classes in a path"""
format_classes = []
for filename in path.glob("Format*.py"):
content = filename.read_bytes()
try:
parsetree = ast.parse(content)
except SyntaxError:
print(f" *** Could not parse {filename.name}")
continue
for top_level_def in parsetree.body:
if not isinstance(top_level_def, ast.ClassDef):
continue
base_names = [
baseclass.id
for baseclass in top_level_def.bases
if isinstance(baseclass, ast.Name) and baseclass.id.startswith("Format")
]
if base_names:
classname = top_level_def.name
format_classes.append(
f"{classname}:{','.join(base_names)} = dxtbx.format.{filename.stem}:{classname}"
)
# print(" found", classname, " based on ", str(base_names))
return format_classes


def build(setup_kwargs: Dict[str, Any]) -> None:
"""Called by setup.py to inject any dynamic configuration"""
package_path = Path(__file__).parent / "src" / "dxtbx"
entry_points = setup_kwargs.setdefault("entry_points", {})
console_scripts = entry_points.setdefault("console_scripts", [])
# Work out what dispatchers to add
all_dispatchers = sorted(
itertools.chain(
*[
get_entry_point(f, "dxtbx", "dxtbx.command_line")
for f in (package_path / "command_line").glob("*.py")
]
)
)
console_scripts.extend(x for x in all_dispatchers if x not in console_scripts)
libtbx_dispatchers = entry_points.setdefault("libtbx.dispatcher.script", [])
libtbx_dispatchers.extend(
"{name}={name}".format(name=x.split("=")[0]) for x in console_scripts
)

dxtbx_format = entry_points.setdefault("dxtbx.format", [])
format_classes = sorted(enumerate_format_classes(package_path / "format"))
dxtbx_format.extend([x for x in format_classes if x not in dxtbx_format])

print(f"Found {len(entry_points['console_scripts'])} dxtbx dispatchers")
print(f"Found {len(entry_points['dxtbx.format'])} Format classes")


if __name__ == "__main__":
sys.exit("Cannot call build.py directly, please use setup.py instead")
2 changes: 1 addition & 1 deletion dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ run:
test:
- dials-data
- pip
- pytest >6
- pytest
- pytest-mock
- pytest-nunit # [win]
- pytest-xdist
98 changes: 0 additions & 98 deletions hatch_build.py

This file was deleted.

1 change: 0 additions & 1 deletion newsfragments/766.misc

This file was deleted.

42 changes: 2 additions & 40 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,34 +1,5 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "dxtbx"
version = "3.23.dev"
description = "Diffraction Experiment Toolkit"
authors = [
{ name = "Diamond Light Source", email = "dials-support@lists.sourceforge.net" },
]
license = { file = "LICENSE.txt" }
readme = "README.md"
requires-python = ">=3.9, <3.13"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: BSD License",
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3",
]
dynamic = ["entry-points", "scripts"]

[project.urls]
Homepage = "https://dials.github.io"
Repository = "https://github.com/cctbx/dxtbx"

[tool.hatch.metadata.hooks.custom.entry-points]
[tool.black]
include = '\.pyi?$|/SConscript$|/libtbx_config$'

[tool.towncrier]
package = "dxtbx"
Expand Down Expand Up @@ -96,12 +67,3 @@ section-order = [

[tool.mypy]
no_implicit_optional = true

[tool.pytest.ini_options]
addopts = "-rsxX"
filterwarnings = [
"ignore:the matrix subclass is not the recommended way:PendingDeprecationWarning",
"ignore:numpy.dtype size changed:RuntimeWarning",
"ignore:Deprecated call to `pkg_resources.declare_namespace:DeprecationWarning",
"ignore:`product` is deprecated as of NumPy:DeprecationWarning:h5py|numpy",
]
10 changes: 10 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[pytest]
addopts = -rsxX
filterwarnings =
ignore:the matrix subclass is not the recommended way:PendingDeprecationWarning
ignore:numpy.dtype size changed:RuntimeWarning
ignore:Deprecated call to `pkg_resources.declare_namespace:DeprecationWarning
ignore:`product` is deprecated as of NumPy:DeprecationWarning:h5py|numpy
junit_family = legacy
markers =
regression: dxtbx regression test
13 changes: 13 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[metadata]
classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Science/Research
License :: OSI Approved :: BSD License
Operating System :: MacOS
Operating System :: Microsoft :: Windows
Operating System :: POSIX :: Linux
Programming Language :: Python :: 3
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
41 changes: 41 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from __future__ import annotations

from pathlib import Path

import setuptools

from build import build

# Static version number which is updated by bump2version
# Do not change this manually - use 'bump2version <major/minor/patch/release>'
__version_tag__ = "3.23.dev"

setup_kwargs = {
"name": "dxtbx",
"version": __version_tag__,
"long_description": Path(__file__).parent.joinpath("README.md").read_text(),
"description": "Diffraction Experiment Toolbox",
"author": "Diamond Light Source",
"license": "BSD-3-Clause",
"author_email": "dials-support@lists.sourceforge.net",
"project_urls": {
"homepage": "https://dials.github.io",
"repository": "https://github.com/cctbx/dxtbx",
},
"packages": setuptools.find_packages(where="src"),
"package_dir": {"": "src"},
"package_data": {
"": ["*"],
"dxtbx": ["array_family/*", "boost_python/*", "example/*", "py.typed"],
"dxtbx.format": ["boost_python/*"],
"dxtbx.masking": ["boost_python/*"],
"dxtbx.model": ["boost_python/*"],
},
"entry_points": {
"libtbx.precommit": ["dxtbx=dxtbx"],
"libtbx.dispatcher.script": ["pytest=pytest"],
},
}

build(setup_kwargs)
setuptools.setup(**setup_kwargs)

0 comments on commit f30e353

Please sign in to comment.