-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is pretty complete support with decent tests. The `insta=science-util` command family is still un-done.
- Loading branch information
Showing
19 changed files
with
1,057 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,8 @@ | ||
# Sdist build artifacts dirs. | ||
# Build artifacts dirs. | ||
/*.egg-info/ | ||
/build/ | ||
|
||
# Python bytecode. | ||
__pycache__/ | ||
|
||
# UV outputs artifacts here. | ||
/dist/ | ||
/dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,23 @@ | ||
# inst-science | ||
# insta-science | ||
|
||
The `inst-science` Python project distribution provides two convenience console scripts to make | ||
The `insta-science` Python project distribution provides two convenience console scripts to make | ||
bootstrapping `science` for use in Python project easier: | ||
+ `inst-science`: This is a shim script that ensures `science` is installed and forwards all | ||
supplied arguments to it. Instead of `science`, just use `inst-science`. You can configure the | ||
+ `insta-science`: This is a shim script that ensures `science` is installed and forwards all | ||
supplied arguments to it. Instead of `science`, just use `insta-science`. You can configure the | ||
`science` version to use, where to find `science` binaries and where to install them via the | ||
`[tool.inst-science]` table in your `pyproject.toml` file. | ||
+ `inst-science-util`: This script provides utilities for managing `science` binaries. In | ||
`[tool.insta-science]` table in your `pyproject.toml` file. | ||
+ `insta-science-util`: This script provides utilities for managing `science` binaries. In | ||
particular, it supports downloading families of `science` binaries for various platforms for | ||
use in internal serving systems for offline or isolated installation. | ||
|
||
This project is under active early development and APIs and configuration are likely to change | ||
rapidly in breaking ways until the 1.0 release. | ||
|
||
## Development | ||
|
||
Development uses [`uv`](https://docs.astral.sh/uv/getting-started/installation/). Install as you | ||
best see fit. | ||
|
||
With `uv` installed, running `uv run dev-cmd` is enough to get the tools inst-science uses installed | ||
With `uv` installed, running `uv run dev-cmd` is enough to get the tools insta-science uses installed | ||
and run against the codebase. This includes formatting code, linting code, performing type checks | ||
and then running tests. |
This file was deleted.
Oops, something went wrong.
File renamed without changes.
2 changes: 1 addition & 1 deletion
2
python/inst_science/__main__.py → python/insta_science/__main__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
# Copyright 2024 Science project contributors. | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
from inst_science import shim | ||
from insta_science import shim | ||
|
||
if __name__ == "__main__": | ||
shim.science() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Copyright 2024 Science project contributors. | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
from __future__ import annotations | ||
|
||
from dataclasses import dataclass | ||
from datetime import timedelta | ||
from pathlib import PurePath | ||
|
||
from packaging.version import Version | ||
|
||
from insta_science.fetcher import fetch_and_verify | ||
from insta_science.hashing import Digest, Fingerprint | ||
from insta_science.model import Science, Url | ||
from insta_science.platform import Platform | ||
|
||
|
||
@dataclass(frozen=True) | ||
class _LoadResult: | ||
path: PurePath | ||
binary_name: str | ||
|
||
|
||
def _load_project_release( | ||
project_name: str, | ||
binary_name: str, | ||
version: Version | None = None, | ||
fingerprint: Digest | Fingerprint | None = None, | ||
platform: Platform = Platform.current(), | ||
) -> _LoadResult: | ||
qualified_binary_name = platform.qualified_binary_name(binary_name) | ||
base_url = f"https://github.com/a-scie/{project_name}/releases" | ||
if version: | ||
version_path = f"download/v{version}" | ||
ttl = None | ||
else: | ||
version_path = "latest/download" | ||
ttl = timedelta(days=5) | ||
path = fetch_and_verify( | ||
url=Url(f"{base_url}/{version_path}/{qualified_binary_name}"), | ||
fingerprint=fingerprint, | ||
executable=True, | ||
ttl=ttl, | ||
) | ||
return _LoadResult(path=path, binary_name=qualified_binary_name) | ||
|
||
|
||
def science( | ||
specification: Science | None = None, platform: Platform = Platform.current() | ||
) -> PurePath: | ||
version = specification.version if specification else None | ||
fingerprint = specification.digest if specification and specification.digest else None | ||
return _load_project_release( | ||
project_name="lift", | ||
binary_name="science-fat", | ||
version=version, | ||
fingerprint=fingerprint, | ||
platform=platform, | ||
).path |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# Copyright 2024 Science project contributors. | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
from __future__ import annotations | ||
|
||
import atexit | ||
import hashlib | ||
import os | ||
from contextlib import contextmanager | ||
from dataclasses import dataclass | ||
from datetime import datetime, timedelta | ||
from functools import cache | ||
from pathlib import Path | ||
from typing import Iterator, Union | ||
|
||
import appdirs | ||
from filelock import FileLock | ||
from typing_extensions import TypeAlias | ||
|
||
|
||
@dataclass(frozen=True) | ||
class Complete: | ||
path: Path | ||
|
||
|
||
@dataclass(frozen=True) | ||
class Missing: | ||
path: Path | ||
work: Path | ||
|
||
|
||
CacheResult: TypeAlias = Union[Complete, Missing] | ||
|
||
|
||
_TTL_EXPIRY_FORMAT = "%m/%d/%y %H:%M:%S" | ||
|
||
|
||
@dataclass(frozen=True) | ||
class DownloadCache: | ||
base_dir: Path | ||
|
||
@contextmanager | ||
def get_or_create(self, url: str, ttl: timedelta | None = None) -> Iterator[CacheResult]: | ||
"""A context manager that yields a `cache result. | ||
If the cache result is `Missing`, the block yielded to should materialize the given url | ||
to the `Missing.work` path. Upon successful exit from this context manager, the given url's | ||
content will exist at the cache result path. | ||
""" | ||
cached_file = self.base_dir / hashlib.sha256(url.encode()).hexdigest() | ||
|
||
ttl_file = cached_file.with_suffix(".ttl") if ttl else None | ||
if ttl_file and not ttl_file.exists(): | ||
cached_file.unlink(missing_ok=True) | ||
elif ttl_file: | ||
try: | ||
datetime_object = datetime.strptime( | ||
ttl_file.read_text().strip(), _TTL_EXPIRY_FORMAT | ||
) | ||
if datetime.now() > datetime_object: | ||
cached_file.unlink(missing_ok=True) | ||
except ValueError: | ||
cached_file.unlink(missing_ok=True) | ||
|
||
if cached_file.exists(): | ||
yield Complete(path=cached_file) | ||
return | ||
|
||
cached_file.parent.mkdir(parents=True, exist_ok=True) | ||
with FileLock(str(cached_file.with_name(f"{cached_file.name}.lck"))): | ||
if cached_file.exists(): | ||
yield Complete(path=cached_file) | ||
return | ||
|
||
work = cached_file.with_name(f"{cached_file.name}.work") | ||
work.unlink(missing_ok=True) | ||
atexit.register(work.unlink, missing_ok=True) | ||
yield Missing(path=cached_file, work=work) | ||
if not work.exists(): | ||
return | ||
work.rename(cached_file) | ||
if ttl_file and ttl: | ||
ttl_file.write_text((datetime.now() + ttl).strftime(_TTL_EXPIRY_FORMAT)) | ||
|
||
|
||
@cache | ||
def download_cache() -> DownloadCache: | ||
return DownloadCache( | ||
base_dir=Path( | ||
os.environ.get("INSTA_SCIENCE_CACHE", appdirs.user_cache_dir(appname="insta-science")) | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Copyright 2024 Science project contributors. | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
|
||
class InputError(ValueError): | ||
"""An error caused by bad input. | ||
These errors are discriminated by the main application as containing error information bound | ||
for a user who may have supplied bad input that they can correct or may be running the | ||
application in a bad environmental setup that they can correct. | ||
By default, backtraces will not be displayed for these exceptions since they are not | ||
exceptional cases; they're anticipated errors. | ||
""" | ||
|
||
|
||
class InvalidProjectError(InputError): | ||
"""Indicates bad pyproject.toml configuration for `[tool.insta-science]`.""" |
Oops, something went wrong.