diff --git a/python/.gitignore b/python/.gitignore index 5621902..23c6e30 100644 --- a/python/.gitignore +++ b/python/.gitignore @@ -1,7 +1,3 @@ -# Build artifacts dirs. -/*.egg-info/ -/build/ - # Python bytecode. __pycache__/ diff --git a/python/CHANGES.md b/python/CHANGES.md index dad2572..0675738 100644 --- a/python/CHANGES.md +++ b/python/CHANGES.md @@ -1,5 +1,9 @@ # insta-science +## 0.4.4 + +Use a 'User-Agent' header of `insta-science/` when fetching URLs. + ## 0.4.3 Implement proper HTTP error handling and add retry support in for failed `science` fetches. diff --git a/python/RELEASE.md b/python/RELEASE.md index 3d55b36..c8233f7 100644 --- a/python/RELEASE.md +++ b/python/RELEASE.md @@ -4,7 +4,7 @@ ### Version Bump and Changelog -1. Bump the version in [`insta_science/version.py`](insta_science/version.py). +1. Bump the version in [`insta_science/_internal/version.py`](insta_science/_internal/version.py). 2. Run `uv run dev-cmd` as a sanity check on the state of the project. 3. Update [`CHANGES.md`](CHANGES.md) with any changes that are likely to be useful to consumers. 4. Run `uv run dev-cmd -q release -- --dry-run` as a sanity check the release will work once the diff --git a/python/insta_science/__init__.py b/python/insta_science/__init__.py index 97d5c32..89a336e 100644 --- a/python/insta_science/__init__.py +++ b/python/insta_science/__init__.py @@ -11,9 +11,9 @@ ScienceExe, ScienceNotFound, Url, + __version__, ensure_installed, ) -from .version import __version__ __all__ = ( "CURRENT_PLATFORM", diff --git a/python/insta_science/_internal/__init__.py b/python/insta_science/_internal/__init__.py index 3ea836a..763e39b 100644 --- a/python/insta_science/_internal/__init__.py +++ b/python/insta_science/_internal/__init__.py @@ -6,6 +6,7 @@ from .model import Digest, Science, ScienceExe, Url from .platform import CURRENT_PLATFORM, Platform from .science import ensure_installed +from .version import __version__ __all__ = ( "CURRENT_PLATFORM", @@ -17,5 +18,6 @@ "ScienceExe", "ScienceNotFound", "Url", + "__version__", "ensure_installed", ) diff --git a/python/insta_science/_internal/fetcher.py b/python/insta_science/_internal/fetcher.py index 321fdfa..9ad03b3 100644 --- a/python/insta_science/_internal/fetcher.py +++ b/python/insta_science/_internal/fetcher.py @@ -29,6 +29,7 @@ from .errors import InputError from .hashing import Digest, ExpectedDigest, Fingerprint from .model import Url +from .version import __version__ logger = logging.getLogger(__name__) @@ -95,6 +96,7 @@ def require_password(auth_type: str) -> str: def _configured_client(url: Url, headers: Mapping[str, str] | None = None) -> httpx.Client: headers = dict(headers) if headers else {} + headers.setdefault("User-Agent", f"insta-science/{__version__}") auth = _configure_auth(url) if "Authorization" not in headers else None return httpx.Client(follow_redirects=True, headers=headers, auth=auth) diff --git a/python/insta_science/version.py b/python/insta_science/_internal/version.py similarity index 83% rename from python/insta_science/version.py rename to python/insta_science/_internal/version.py index 74f04b1..1e01519 100644 --- a/python/insta_science/version.py +++ b/python/insta_science/_internal/version.py @@ -1,4 +1,4 @@ # Copyright 2024 Science project contributors. # Licensed under the Apache License, Version 2.0 (see LICENSE). -__version__ = "0.4.3" +__version__ = "0.4.4" diff --git a/python/insta_science/util.py b/python/insta_science/util.py index 3a63662..453bc6b 100644 --- a/python/insta_science/util.py +++ b/python/insta_science/util.py @@ -16,14 +16,13 @@ from packaging.version import Version -from . import CURRENT_PLATFORM, InputError, Platform, Science +from . import CURRENT_PLATFORM, InputError, Platform, Science, __version__ from ._internal import a_scie, parser, project, science from ._internal.bytes import ByteAmount from ._internal.cache import DownloadCache, download_cache from ._internal.colors import Colors, color_support from ._internal.du import DiskUsage from ._internal.model import Configuration -from .version import __version__ def download( diff --git a/python/pyproject.toml b/python/pyproject.toml index 5bfa0c2..f172780 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -57,7 +57,7 @@ insta-science = "insta_science.shim:main" insta-science-util = "insta_science.util:main" [tool.setuptools.dynamic] -version = {attr = "insta_science.version.__version__"} +version = {attr = "insta_science._internal.version.__version__"} [tool.setuptools.packages.find] where = ["."] @@ -71,6 +71,7 @@ dev = [ "pytest", "pytest-xdist", "ruff", + "setuptools", "types-appdirs", "types-colorama", "types-tqdm", diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 0000000..f47fbcc --- /dev/null +++ b/python/setup.py @@ -0,0 +1,39 @@ +# Copyright 2025 Science project contributors. +# Licensed under the Apache License, Version 2.0 (see LICENSE). + +import atexit +import shutil +import tempfile +from pathlib import Path + +from setuptools import setup + +_BUILD_DIR: Path | None = None + + +def ensure_unique_build_dir() -> Path: + global _BUILD_DIR + if _BUILD_DIR is None: + _build_dir = Path(tempfile.mkdtemp(prefix="insta-science-dist-build.")) + atexit.register(shutil.rmtree, _build_dir, ignore_errors=True) + _BUILD_DIR = _build_dir + return _BUILD_DIR + + +def unique_build_dir(name) -> str: + path = ensure_unique_build_dir() / name + path.mkdir() + return str(path) + + +if __name__ == "__main__": + setup( + # The `egg_info --egg-base`, `build --build-base` and `bdist_wheel --bdist-dir` setup.py + # sub-command options we pass below work around the otherwise default `/build/` + # directory for all three which defeats concurrency in tests. + options={ + "egg_info": {"egg_base": unique_build_dir("egg_base")}, + "build": {"build_base": unique_build_dir("build_base")}, + "bdist_wheel": {"bdist_dir": unique_build_dir("bdist_dir")}, + } + ) diff --git a/python/uv.lock b/python/uv.lock index ef1a496..20b48c7 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -88,7 +88,7 @@ wheels = [ [[package]] name = "dev-cmd" -version = "0.10.4" +version = "0.11.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aioconsole" }, @@ -97,9 +97,9 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f9/0a/1b8fddadf62feae0ac705926cf3350d2998ee273966e594d28d955d8e95f/dev_cmd-0.10.4.tar.gz", hash = "sha256:4806e5c14b2da723b07c3e1e072b0113c0945ec1673469f0a6db6ff7228b73ba", size = 39987 } +sdist = { url = "https://files.pythonhosted.org/packages/71/05/9fd907b1ad956cd8979faa2e5bd00c4866c03e97b42172702c8f29dc0bc4/dev_cmd-0.11.1.tar.gz", hash = "sha256:4a9d30bb399b7cb6e1948c882ad883d54a6e8b77cb65f0c377220ccf7927ace3", size = 41158 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/84/8252735984970a9b34decd7f339a88ba48b7b6910a1c57cffd2c6415d97f/dev_cmd-0.10.4-py3-none-any.whl", hash = "sha256:f30c33808767f8d172685e2a30c81eddca654d315e493d86a9f2cf7f78b83bae", size = 26881 }, + { url = "https://files.pythonhosted.org/packages/70/0f/c4c66db5807a9a1527982eebd4ba62a2f76efcc6fb8b7e9d2c63bc3b4cc2/dev_cmd-0.11.1-py3-none-any.whl", hash = "sha256:395f0ac099e8ec40736b3865602c809082b84bb28c9bd062fd06ba35e7b9954e", size = 27068 }, ] [[package]] @@ -187,7 +187,7 @@ wheels = [ [[package]] name = "insta-science" -version = "0.4.3" +version = "0.4.4" source = { editable = "." } dependencies = [ { name = "ansicolors" }, @@ -210,6 +210,8 @@ dev = [ { name = "pytest" }, { name = "pytest-xdist" }, { name = "ruff" }, + { name = "setuptools", version = "75.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "setuptools", version = "75.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "types-appdirs" }, { name = "types-colorama" }, { name = "types-tqdm" }, @@ -237,6 +239,7 @@ dev = [ { name = "pytest" }, { name = "pytest-xdist" }, { name = "ruff" }, + { name = "setuptools" }, { name = "types-appdirs" }, { name = "types-colorama" }, { name = "types-tqdm" }, @@ -377,6 +380,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/13/9f/026e18ca7d7766783d779dae5e9c656746c6ede36ef73c6d934aaf4a6dec/ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08", size = 9074500 }, ] +[[package]] +name = "setuptools" +version = "75.3.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/22/a438e0caa4576f8c383fa4d35f1cc01655a46c75be358960d815bfbb12bd/setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686", size = 1351577 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/12/282ee9bce8b58130cb762fbc9beabd531549952cac11fc56add11dcb7ea0/setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd", size = 1251070 }, +] + +[[package]] +name = "setuptools" +version = "75.8.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/92/ec/089608b791d210aec4e7f97488e67ab0d33add3efccb83a056cbafe3a2a6/setuptools-75.8.0.tar.gz", hash = "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6", size = 1343222 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/8a/b9dc7678803429e4a3bc9ba462fa3dd9066824d3c607490235c6a796be5a/setuptools-75.8.0-py3-none-any.whl", hash = "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3", size = 1228782 }, +] + [[package]] name = "sniffio" version = "1.3.1"