diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05caaec..985761d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.11' - name: Install minimum dependencies run: | python -m pip install --upgrade pip @@ -35,7 +35,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] + python-version: ['3.11', '3.12', '3.13', '3.14'] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 diff --git a/INSTALL.rst b/INSTALL.rst index 032d881..2d57f11 100644 --- a/INSTALL.rst +++ b/INSTALL.rst @@ -27,11 +27,11 @@ For development, install in editable mode with the ``dev`` extra, which adds Requirements -------------------------------------------------------------------------------- -+ `Python 3.10 `__ ++ `Python 3.11 `__ + `requests 2.28 `__ + `beautifulsoup4 4.11 `__ + `PyYAML 6.0 `__ -+ `pandas 1.5 `__ ++ `pandas 2.2.3 `__ + `airr 2.0 `__ + `tqdm 4.64 `__ diff --git a/docs/conf.py b/docs/conf.py index 5763978..164aac9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # # sourcerer documentation build configuration file # diff --git a/pyproject.toml b/pyproject.toml index 1af3452..13eb6e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "sourcerer" dynamic = ["version"] description = "Download data from online immune repertoire databases and format it for Immcantation" readme = "README.rst" -requires-python = ">=3.10" +requires-python = ">=3.11" license = {file = "LICENSE"} authors = [{name = "Susanna Marquez"}] keywords = ["AIRR", "antibody", "repertoire", "immcantation", "OAS"] @@ -21,11 +21,17 @@ classifiers = [ # NB: the airr floor is 2.0 because the streaming validation report depends on # RearrangementSchema.validate_header/validate_row. This still satisfies changeo's # airr>=1.3.1, so the two coexist in the Immcantation container. +# +# NB: the pandas floor is 2.2.3 (not the older 1.5 that satisfies our own code) +# because pandas wheels built before numpy 2.0 existed are ABI-incompatible with +# a numpy>=2 runtime: pip resolves the newest numpy that satisfies pandas's own +# (unbounded) requirement, so an older pandas floor gets paired with a numpy it +# was never built against. 2.2.3 is the first pandas release built for numpy 2.x. dependencies = [ "requests>=2.28", "beautifulsoup4>=4.11", "PyYAML>=6.0", - "pandas>=1.5", + "pandas>=2.2.3", "airr>=2.0", "tqdm>=4.64", ] @@ -50,7 +56,7 @@ packages = ["src/sourcerer"] [tool.ruff] line-length = 90 -target-version = "py310" +target-version = "py311" [tool.ruff.lint] select = ["I", "E1", "E4", "E7", "E9", "F", "UP", "N"] diff --git a/requirements.txt b/requirements.txt index 4e0e649..4b841b6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ requests>=2.28 beautifulsoup4>=4.11 PyYAML>=6.0 -pandas>=1.5 +pandas>=2.2.3 airr>=2.0 tqdm>=4.64 diff --git a/src/sourcerer/Provenance.py b/src/sourcerer/Provenance.py index 1d0a776..ec35ce7 100644 --- a/src/sourcerer/Provenance.py +++ b/src/sourcerer/Provenance.py @@ -18,7 +18,7 @@ # Imports import logging import sys -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path import yaml @@ -43,7 +43,7 @@ def timestamp(): Returns: str: the current time as an ISO 8601 UTC string. """ - return datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ') + return datetime.now(UTC).strftime('%Y-%m-%dT%H:%M:%SZ') def relativize(path, root): diff --git a/src/sourcerer/Sources/Oas.py b/src/sourcerer/Sources/Oas.py index d843c41..6c98f99 100644 --- a/src/sourcerer/Sources/Oas.py +++ b/src/sourcerer/Sources/Oas.py @@ -25,6 +25,7 @@ import json import logging import re +from datetime import UTC from pathlib import Path from urllib.parse import urlparse @@ -964,7 +965,7 @@ def harvestSchema(self): Returns: SourceSchema: the harvested snapshot. """ - from datetime import datetime, timezone + from datetime import datetime from sourcerer.Schema import Collection, Field, SourceSchema from sourcerer.Version import __version__ @@ -980,7 +981,7 @@ def harvestSchema(self): return SourceSchema( source=self.name, - harvested=datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'), + harvested=datetime.now(UTC).strftime('%Y-%m-%dT%H:%M:%SZ'), harvested_by='sourcerer %s' % __version__, source_urls={'paired_form': PAIRED_FORM_URL, 'unpaired_form': UNPAIRED_FORM_URL, @@ -1106,13 +1107,13 @@ def enrichCatalog(self, rows, limit=None, force=False): Returns: int: how many units were successfully enriched. """ - from datetime import datetime, timezone + from datetime import datetime pending = list(rows) if force else [x for x in rows if needsDetail(x)] if limit is not None: pending = pending[:limit] - stamp = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ') + stamp = datetime.now(UTC).strftime('%Y-%m-%dT%H:%M:%SZ') enriched = 0 for row in pending: url = '%s?unit=%s' % (DETAIL_URL % row['collection'], row['unit_id']) diff --git a/tests/test_Packaging.py b/tests/test_Packaging.py index c028a25..da0f2b6 100644 --- a/tests/test_Packaging.py +++ b/tests/test_Packaging.py @@ -8,9 +8,8 @@ # Imports import os import re -import unittest - import tomllib +import unittest # Sourcerer imports import sourcerer