Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-hishel for openSUSE:Leap:16.0 checked in at 2025-07-24 08:30:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Leap:16.0/python-hishel (Old) and /work/SRC/openSUSE:Leap:16.0/.python-hishel.new.8875 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-hishel" Thu Jul 24 08:30:52 2025 rev:2 rq:1293697 version:0.1.2 Changes: -------- --- /work/SRC/openSUSE:Leap:16.0/python-hishel/python-hishel.changes 2025-04-25 15:21:40.208176735 +0200 +++ /work/SRC/openSUSE:Leap:16.0/.python-hishel.new.8875/python-hishel.changes 2025-07-24 08:30:56.277649219 +0200 @@ -1,0 +2,11 @@ +Wed Jun 11 10:07:20 UTC 2025 - John Paul Adrian Glaubitz <adrian.glaub...@suse.com> + +- Update to 0.1.2 + * Add check for fips compliant python. (#325) + * Fix compatibility with httpx. (#291) + * Use SyncByteStream instead of ByteStream. (#298) + * Don't raise exceptions if date-containing headers are invalid. (#318) + * Fix for S3 Storage missing metadata in API request. (#320) +- Update BuildRequires and Requires from pyproject.toml + +------------------------------------------------------------------- Old: ---- hishel-0.1.1.tar.gz New: ---- hishel-0.1.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-hishel.spec ++++++ --- /var/tmp/diff_new_pack.B4w25f/_old 2025-07-24 08:30:56.549660529 +0200 +++ /var/tmp/diff_new_pack.B4w25f/_new 2025-07-24 08:30:56.553660694 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-hishel # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2025 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-hishel -Version: 0.1.1 +Version: 0.1.2 Release: 0 Summary: Persistent cache implementation for httpx and httpcore License: BSD-3-Clause @@ -29,7 +29,7 @@ BuildRequires: %{python_module pip} BuildRequires: python-rpm-macros # SECTION test requirements -BuildRequires: %{python_module httpx >= 0.22.0} +BuildRequires: %{python_module httpx >= 0.28.0} BuildRequires: %{python_module PyYAML} BuildRequires: %{python_module pytest} BuildRequires: %{python_module redis} @@ -38,7 +38,7 @@ BuildRequires: %{pythons} # /SECTION BuildRequires: fdupes -Requires: python-httpx >= 0.22.0 +Requires: python-httpx >= 0.28.0 Requires: python-typing_extensions >= 4.8.0 Suggests: python-pyyaml == 6.0.1 Suggests: python-redis == 5.0.1 ++++++ hishel-0.1.1.tar.gz -> hishel-0.1.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/.github/dependabot.yml new/hishel-0.1.2/.github/dependabot.yml --- old/hishel-0.1.1/.github/dependabot.yml 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/.github/dependabot.yml 2025-04-04 23:15:26.000000000 +0200 @@ -4,7 +4,11 @@ directory: "/" schedule: interval: "monthly" + groups: + python-packages: + patterns: + - "*" - package-ecosystem: "github-actions" directory: "/" schedule: - interval: monthly \ No newline at end of file + interval: monthly diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/.github/workflows/main.yml new/hishel-0.1.2/.github/workflows/main.yml --- old/hishel-0.1.1/.github/workflows/main.yml 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/.github/workflows/main.yml 2025-04-04 23:15:26.000000000 +0200 @@ -24,12 +24,14 @@ with: python-version: "${{ matrix.python-version }}" allow-prereleases: true - - name: "Install dependencies" - run: scripts/install - name: Start Redis - uses: supercharge/redis-github-action@1.7.0 + uses: supercharge/redis-github-action@1.8.0 with: redis-version: ${{ matrix.redis-version }} + - name: "Setup uv" + uses: astral-sh/setup-uv@v5 + with: + version: "0.6.12" - name: "Run tests" run: scripts/test - name: Upload coverage reports to Codecov diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/.github/workflows/publish.yml new/hishel-0.1.2/.github/workflows/publish.yml --- old/hishel-0.1.1/.github/workflows/publish.yml 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/.github/workflows/publish.yml 2025-04-04 23:15:26.000000000 +0200 @@ -13,14 +13,18 @@ HISHEL_PYPI: ${{ secrets.HISHEL_PYPI }} steps: - - uses: "actions/checkout@v4" - - uses: "actions/setup-python@v5" + - name: "Checkout code" + uses: "actions/checkout@v4" + - name: "Set up Python (use latest version for publishing)" + uses: "actions/setup-python@v5" with: python-version: 3.13 - - name: "Install dependencies" - run: "pip install -r requirements.txt" + - name: "Setup uv" + uses: astral-sh/setup-uv@v5 + with: + version: "0.6.12" - name: "Build" - run: "hatch build" + run: "uv build" - name: "Publish docs" run: ./scripts/publish-docs - name: "Publish" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/.gitignore new/hishel-0.1.2/.gitignore --- old/hishel-0.1.1/.gitignore 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/.gitignore 2025-04-04 23:15:26.000000000 +0200 @@ -1,4 +1,5 @@ venv/ __pycache__/ .coverage -.cache/ \ No newline at end of file +.cache/ +.idea/ \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/CHANGELOG.md new/hishel-0.1.2/CHANGELOG.md --- old/hishel-0.1.1/CHANGELOG.md 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/CHANGELOG.md 2025-04-04 23:15:26.000000000 +0200 @@ -1,8 +1,16 @@ # Changelog +## 0.1.2 (5th April, 2025) + +- Add check for fips compliant python. (#325) +- Fix compatibility with httpx. (#291) +- Use `SyncByteStream` instead of `ByteStream`. (#298) +- Don't raise exceptions if date-containing headers are invalid. (#318) +- Fix for S3 Storage missing metadata in API request. (#320) + ## 0.1.1 (2nd Nov, 2024) -- FIx typig extensions nor found. (#290) +- Fix typing extensions not found. (#290) ## 0.1.0 (2nd Nov, 2024) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/hishel/__init__.py new/hishel-0.1.2/hishel/__init__.py --- old/hishel-0.1.1/hishel/__init__.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/hishel/__init__.py 2025-04-04 23:15:26.000000000 +0200 @@ -14,4 +14,4 @@ httpx.Client = CacheClient # type: ignore -__version__ = "0.1.1" +__version__ = "0.1.2" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/hishel/_async/_pool.py new/hishel-0.1.2/hishel/_async/_pool.py --- old/hishel-0.1.1/hishel/_async/_pool.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/hishel/_async/_pool.py 2025-04-04 23:15:26.000000000 +0200 @@ -47,7 +47,7 @@ self._storage = storage if storage is not None else AsyncFileStorage(serializer=JSONSerializer()) - if not isinstance(self._storage, AsyncBaseStorage): + if not isinstance(self._storage, AsyncBaseStorage): # pragma: no cover raise TypeError(f"Expected subclass of `AsyncBaseStorage` but got `{storage.__class__.__name__}`") self._controller = controller if controller is not None else Controller() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/hishel/_async/_transports.py new/hishel-0.1.2/hishel/_async/_transports.py --- old/hishel-0.1.1/hishel/_async/_transports.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/hishel/_async/_transports.py 2025-04-04 23:15:26.000000000 +0200 @@ -64,7 +64,7 @@ self._storage = storage if storage is not None else AsyncFileStorage(serializer=JSONSerializer()) - if not isinstance(self._storage, AsyncBaseStorage): + if not isinstance(self._storage, AsyncBaseStorage): # pragma: no cover raise TypeError(f"Expected subclass of `AsyncBaseStorage` but got `{storage.__class__.__name__}`") self._controller = controller if controller is not None else Controller() @@ -152,7 +152,7 @@ # Controller has determined that the response needs to be re-validated. assert isinstance(res.stream, tp.AsyncIterable) revalidation_request = Request( - method=res.method, + method=res.method.decode(), url=normalized_url(res.url), headers=res.headers, stream=AsyncCacheStream(res.stream), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/hishel/_controller.py new/hishel-0.1.2/hishel/_controller.py --- old/hishel-0.1.1/hishel/_controller.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/hishel/_controller.py 2025-04-04 23:15:26.000000000 +0200 @@ -60,8 +60,12 @@ if header_presents(response.headers, b"expires"): expires = extract_header_values_decoded(response.headers, b"expires", single=True)[0] expires_timestamp = parse_date(expires) + if expires_timestamp is None: + return None date = extract_header_values_decoded(response.headers, b"date", single=True)[0] date_timestamp = parse_date(date) + if date_timestamp is None: + return None return expires_timestamp - date_timestamp return None @@ -72,11 +76,12 @@ if last_modified: last_modified_timestamp = parse_date(last_modified[0]) - now = clock.now() + if last_modified_timestamp is not None: + now = clock.now() - ONE_WEEK = 604_800 + ONE_WEEK = 604_800 - return min(ONE_WEEK, int((now - last_modified_timestamp) * 0.1)) + return min(ONE_WEEK, int((now - last_modified_timestamp) * 0.1)) ONE_DAY = 86_400 return ONE_DAY @@ -89,6 +94,8 @@ return float("inf") # type: ignore date = parse_date(extract_header_values_decoded(response.headers, b"date")[0]) + if date is None: + return float("inf") # type: ignore now = clock.now() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/hishel/_headers.py new/hishel-0.1.2/hishel/_headers.py --- old/hishel-0.1.1/hishel/_headers.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/hishel/_headers.py 2025-04-04 23:15:26.000000000 +0200 @@ -94,13 +94,13 @@ for value_char in value: if value_char not in tchar: raise ParseError( - f"The character '{value_char!r}' " "is not permitted for the unquoted values." + f"The character '{value_char!r}' is not permitted for the unquoted values." ) else: for value_char in value[1:-1]: if value_char not in qdtext: raise ParseError( - f"The character '{value_char!r}' " "is not permitted for the quoted values." + f"The character '{value_char!r}' is not permitted for the quoted values." ) break diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/hishel/_s3.py new/hishel-0.1.2/hishel/_s3.py --- old/hishel-0.1.1/hishel/_s3.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/hishel/_s3.py 2025-04-04 23:15:26.000000000 +0200 @@ -75,7 +75,16 @@ if not obj["Key"].startswith("hishel-"): # pragma: no cover continue - if get_timestamp_in_ms() - float(obj["Metadata"]["created_at"]) > ttl: + try: + metadata_obj = self._client.head_object(Bucket=self._bucket_name, Key=obj["Key"]).get("Metadata", {}) + except ClientError as e: + if e.response["Error"]["Code"] == "404": + continue + + if not metadata_obj or "created_at" not in metadata_obj: + continue + + if get_timestamp_in_ms() - float(metadata_obj["created_at"]) > ttl: self._client.delete_object(Bucket=self._bucket_name, Key=obj["Key"]) def remove_entry(self, key: str) -> None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/hishel/_sync/_pool.py new/hishel-0.1.2/hishel/_sync/_pool.py --- old/hishel-0.1.1/hishel/_sync/_pool.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/hishel/_sync/_pool.py 2025-04-04 23:15:26.000000000 +0200 @@ -47,7 +47,7 @@ self._storage = storage if storage is not None else FileStorage(serializer=JSONSerializer()) - if not isinstance(self._storage, BaseStorage): + if not isinstance(self._storage, BaseStorage): # pragma: no cover raise TypeError(f"Expected subclass of `BaseStorage` but got `{storage.__class__.__name__}`") self._controller = controller if controller is not None else Controller() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/hishel/_sync/_transports.py new/hishel-0.1.2/hishel/_sync/_transports.py --- old/hishel-0.1.1/hishel/_sync/_transports.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/hishel/_sync/_transports.py 2025-04-04 23:15:26.000000000 +0200 @@ -5,7 +5,7 @@ import httpcore import httpx -from httpx import ByteStream, Request, Response +from httpx import SyncByteStream, Request, Response from httpx._exceptions import ConnectError from hishel._utils import extract_header_values_decoded, normalized_url @@ -29,7 +29,7 @@ return Response(status_code=504) -class CacheStream(ByteStream): +class CacheStream(SyncByteStream): def __init__(self, httpcore_stream: tp.Iterable[bytes]): self._httpcore_stream = httpcore_stream @@ -64,7 +64,7 @@ self._storage = storage if storage is not None else FileStorage(serializer=JSONSerializer()) - if not isinstance(self._storage, BaseStorage): + if not isinstance(self._storage, BaseStorage): # pragma: no cover raise TypeError(f"Expected subclass of `BaseStorage` but got `{storage.__class__.__name__}`") self._controller = controller if controller is not None else Controller() @@ -152,7 +152,7 @@ # Controller has determined that the response needs to be re-validated. assert isinstance(res.stream, tp.Iterable) revalidation_request = Request( - method=res.method, + method=res.method.decode(), url=normalized_url(res.url), headers=res.headers, stream=CacheStream(res.stream), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/hishel/_utils.py new/hishel-0.1.2/hishel/_utils.py --- old/hishel-0.1.1/hishel/_utils.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/hishel/_utils.py 2025-04-04 23:15:26.000000000 +0200 @@ -1,8 +1,8 @@ import calendar +import hashlib import time import typing as tp from email.utils import parsedate_tz -from hashlib import blake2b import anyio import httpcore @@ -30,7 +30,7 @@ if isinstance(url, httpcore.URL): port = f":{url.port}" if url.port is not None else "" - return f'{url.scheme.decode("ascii")}://{url.host.decode("ascii")}{port}{url.target.decode("ascii")}' + return f"{url.scheme.decode('ascii')}://{url.host.decode('ascii')}{port}{url.target.decode('ascii')}" assert False, "Invalid type for `normalized_url`" # pragma: no cover @@ -49,10 +49,26 @@ key_parts = [request.method, encoded_url, body] - key = blake2b(digest_size=16, usedforsecurity=False) - for part in key_parts: - key.update(part) - return key.hexdigest() + # FIPs mode disables blake2 algorithm, use sha256 instead when not found. + blake2b_hasher = None + sha256_hasher = hashlib.sha256(usedforsecurity=False) + try: + blake2b_hasher = hashlib.blake2b(digest_size=16, usedforsecurity=False) + except (ValueError, TypeError, AttributeError): + pass + + hexdigest: str + if blake2b_hasher: + for part in key_parts: + blake2b_hasher.update(part) + + hexdigest = blake2b_hasher.hexdigest() + else: + for part in key_parts: + sha256_hasher.update(part) + + hexdigest = sha256_hasher.hexdigest() + return hexdigest def extract_header_values( @@ -82,9 +98,11 @@ return bool(extract_header_values(headers, header_key, single=True)) -def parse_date(date: str) -> int: +def parse_date(date: str) -> tp.Optional[int]: expires = parsedate_tz(date) - timestamp = calendar.timegm(expires[:6]) # type: ignore + if expires is None: + return None + timestamp = calendar.timegm(expires[:6]) return timestamp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/pyproject.toml new/hishel-0.1.2/pyproject.toml --- old/hishel-0.1.1/pyproject.toml 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/pyproject.toml 2025-04-04 23:15:26.000000000 +0200 @@ -29,7 +29,7 @@ "Topic :: Internet :: WWW/HTTP", ] dependencies = [ - "httpx>=0.22.0", + "httpx>=0.28.0", ] [project.optional-dependencies] @@ -39,7 +39,7 @@ ] redis = [ - "redis==5.0.1" + "redis==5.0.4" ] sqlite = [ @@ -122,3 +122,20 @@ [tool.ruff.lint.isort] combine-as-imports = true + +[dependency-groups] +dev = [ + "anyio==4.7.0", + "coverage==7.6.10", + "hatch==1.9.3", + "mkdocs==1.6.1", + "mkdocs-material==9.5.1", + "mypy==1.14.1", + "pytest==8.3.4", + "ruff==0.11.0", + "trio==0.28.0", + "types-boto3==1.0.2", + "types-pyyaml==6.0.12.20240311", + "types-redis==4.6.0.20240425", + "zipp>=3.19.1", +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/requirements.txt new/hishel-0.1.2/requirements.txt --- old/hishel-0.1.1/requirements.txt 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/requirements.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,22 +0,0 @@ --e .[yaml,redis,sqlite,s3] - -# linting -ruff==0.3.0 -mypy==1.10.0 - -# docs -mkdocs==1.5.3 -mkdocs-material==9.5.1 - -# tests -pytest==8.0.2 -types-boto3==1.0.2 -types-redis==4.6.0.20240425 -anyio==4.4.0 -trio==0.25.0 -coverage==7.6.0 -types-PyYAML==6.0.12.20240311 - -# build -hatch==1.7.0 -zipp>=3.19.1 # not directly required, pinned by Snyk to avoid a vulnerability diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/scripts/check new/hishel-0.1.2/scripts/check --- old/hishel-0.1.1/scripts/check 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/scripts/check 2025-04-04 23:15:26.000000000 +0200 @@ -1,12 +1,8 @@ #! /bin/bash -ex -export PREFIX="" -if [ -d '.venv' ] ; then - export PREFIX=".venv/bin/" -fi export SOURCE_FILES="hishel tests" -${PREFIX}ruff format $SOURCE_FILES --diff -${PREFIX}ruff check $SOURCE_FILES -${PREFIX}mypy $SOURCE_FILES -${PREFIX}python unasync.py --check +uv run ruff format $SOURCE_FILES --diff +uv run ruff check $SOURCE_FILES +uv run --all-extras mypy $SOURCE_FILES +uv run python unasync.py --check diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/scripts/install new/hishel-0.1.2/scripts/install --- old/hishel-0.1.1/scripts/install 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/scripts/install 1970-01-01 01:00:00.000000000 +0100 @@ -1,9 +0,0 @@ -#! /bin/bash -x - -rm -rf .venv -pip install uv -uv venv - -source .venv/bin/activate - -uv pip install -r requirements.txt \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/scripts/lint new/hishel-0.1.2/scripts/lint --- old/hishel-0.1.1/scripts/lint 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/scripts/lint 2025-04-04 23:15:26.000000000 +0200 @@ -1,11 +1,5 @@ #! /bin/bash -ex -export PREFIX="" -if [ -d '.venv' ]; then - export PREFIX=".venv/bin/" -fi -export SOURCE_FILES="hishel tests" - -${PREFIX}ruff check --fix $SOURCE_FILES -${PREFIX}ruff format $SOURCE_FILES -${PREFIX}python unasync.py +uv run ruff check --fix $SOURCE_FILES +uv run ruff format $SOURCE_FILES +uv run python unasync.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/scripts/publish new/hishel-0.1.2/scripts/publish --- old/hishel-0.1.1/scripts/publish 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/scripts/publish 2025-04-04 23:15:26.000000000 +0200 @@ -1,3 +1,3 @@ #! /bin/bash -ex -hatch publish -u __token__ -a $HISHEL_PYPI +uv publish -t $HISHEL_PYPI diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/scripts/publish-docs new/hishel-0.1.2/scripts/publish-docs --- old/hishel-0.1.1/scripts/publish-docs 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/scripts/publish-docs 2025-04-04 23:15:26.000000000 +0200 @@ -1,3 +1,3 @@ #! /bin/bash -ex -mkdocs gh-deploy --force +uv run mkdocs gh-deploy --force diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/scripts/test new/hishel-0.1.2/scripts/test --- old/hishel-0.1.1/scripts/test 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/scripts/test 2025-04-04 23:15:26.000000000 +0200 @@ -1,11 +1,6 @@ #! /bin/bash -ex -export PREFIX="" -if [ -d '.venv' ] ; then - export PREFIX=".venv/bin/" -fi - ./scripts/check -${PREFIX}coverage run -m pytest tests +uv run coverage run -m pytest tests -${PREFIX}coverage report --show-missing --skip-covered --fail-under=100 \ No newline at end of file +uv run coverage report --show-missing --skip-covered --fail-under=100 \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/tests/_async/test_pool.py new/hishel-0.1.2/tests/_async/test_pool.py --- old/hishel-0.1.1/tests/_async/test_pool.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/tests/_async/test_pool.py 2025-04-04 23:15:26.000000000 +0200 @@ -1,8 +1,5 @@ -import typing as tp - import httpcore import pytest -import sniffio from httpcore._models import Request, Response import hishel @@ -214,26 +211,6 @@ @pytest.mark.anyio -async def test_pool_with_wrong_type_of_storage(): - storage: tp.Union[hishel.FileStorage, hishel.AsyncFileStorage] - - try: # pragma: no cover - sniffio.current_async_library() - error = "Expected subclass of `Async" "BaseStorage` but got `FileStorage`" - storage = hishel.FileStorage() - except sniffio.AsyncLibraryNotFoundError: # pragma: no cover - error = "Expected subclass of `BaseStorage` but got `Async" "FileStorage`" - storage = getattr(hishel, "Async" + "FileStorage")() - - with pytest.raises(TypeError, match=error): - hishel.AsyncCacheConnectionPool( - pool=hishel.MockAsyncConnectionPool(), - controller=hishel.Controller(), - storage=storage, # type: ignore - ) - - -@pytest.mark.anyio async def test_pool_caching_post_method(): controller = hishel.Controller(cacheable_methods=["POST"]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/tests/_async/test_transport.py new/hishel-0.1.2/tests/_async/test_transport.py --- old/hishel-0.1.1/tests/_async/test_transport.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/tests/_async/test_transport.py 2025-04-04 23:15:26.000000000 +0200 @@ -1,8 +1,5 @@ -import typing as tp - import httpx import pytest -import sniffio import hishel from hishel._utils import BaseClock, extract_header_values_decoded @@ -237,26 +234,6 @@ @pytest.mark.anyio -async def test_transport_with_wrong_type_of_storage(): - storage: tp.Union[hishel.AsyncFileStorage, hishel.FileStorage] - - try: # pragma: no cover - sniffio.current_async_library() - error = "Expected subclass of `Async" "BaseStorage` but got `FileStorage`" - storage = hishel.FileStorage() - except sniffio.AsyncLibraryNotFoundError: # pragma: no cover - error = "Expected subclass of `BaseStorage` but got `Async" "FileStorage`" - storage = getattr(hishel, "Async" + "FileStorage")() - - with pytest.raises(TypeError, match=error): - hishel.AsyncCacheTransport( - transport=hishel.MockAsyncTransport(), - controller=hishel.Controller(), - storage=storage, # type: ignore - ) - - -@pytest.mark.anyio async def test_transport_caching_post_method(): controller = hishel.Controller(cacheable_methods=["POST"]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/tests/_sync/test_pool.py new/hishel-0.1.2/tests/_sync/test_pool.py --- old/hishel-0.1.1/tests/_sync/test_pool.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/tests/_sync/test_pool.py 2025-04-04 23:15:26.000000000 +0200 @@ -1,8 +1,5 @@ -import typing as tp - import httpcore import pytest -import sniffio from httpcore._models import Request, Response import hishel @@ -214,26 +211,6 @@ -def test_pool_with_wrong_type_of_storage(): - storage: tp.Union[hishel.FileStorage, hishel.FileStorage] - - try: # pragma: no cover - sniffio.current_async_library() - error = "Expected subclass of `Async" "BaseStorage` but got `FileStorage`" - storage = hishel.FileStorage() - except sniffio.AsyncLibraryNotFoundError: # pragma: no cover - error = "Expected subclass of `BaseStorage` but got `Async" "FileStorage`" - storage = getattr(hishel, "Async" + "FileStorage")() - - with pytest.raises(TypeError, match=error): - hishel.CacheConnectionPool( - pool=hishel.MockConnectionPool(), - controller=hishel.Controller(), - storage=storage, # type: ignore - ) - - - def test_pool_caching_post_method(): controller = hishel.Controller(cacheable_methods=["POST"]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/tests/_sync/test_transport.py new/hishel-0.1.2/tests/_sync/test_transport.py --- old/hishel-0.1.1/tests/_sync/test_transport.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/tests/_sync/test_transport.py 2025-04-04 23:15:26.000000000 +0200 @@ -1,8 +1,5 @@ -import typing as tp - import httpx import pytest -import sniffio import hishel from hishel._utils import BaseClock, extract_header_values_decoded @@ -237,26 +234,6 @@ -def test_transport_with_wrong_type_of_storage(): - storage: tp.Union[hishel.FileStorage, hishel.FileStorage] - - try: # pragma: no cover - sniffio.current_async_library() - error = "Expected subclass of `Async" "BaseStorage` but got `FileStorage`" - storage = hishel.FileStorage() - except sniffio.AsyncLibraryNotFoundError: # pragma: no cover - error = "Expected subclass of `BaseStorage` but got `Async" "FileStorage`" - storage = getattr(hishel, "Async" + "FileStorage")() - - with pytest.raises(TypeError, match=error): - hishel.CacheTransport( - transport=hishel.MockTransport(), - controller=hishel.Controller(), - storage=storage, # type: ignore - ) - - - def test_transport_caching_post_method(): controller = hishel.Controller(cacheable_methods=["POST"]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/tests/test_controller.py new/hishel-0.1.2/tests/test_controller.py --- old/hishel-0.1.1/tests/test_controller.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/tests/test_controller.py 2025-04-04 23:15:26.000000000 +0200 @@ -262,6 +262,32 @@ assert freshness_lifetime == 86400 # one day +def test_get_freshness_lifetime_with_invalid_expires(): + response = Response( + status=200, + headers=[ + (b"Expires", b"0"), + (b"Date", b"Mon, 24 Aug 2015 12:00:00 GMT"), + ], + ) + + freshness_lifetime = get_freshness_lifetime(response=response) + assert freshness_lifetime is None + + +def test_get_freshness_lifetime_with_invalid_date(): + response = Response( + status=200, + headers=[ + (b"Expires", b"Mon, 25 Aug 2015 12:00:00 GMT"), + (b"Date", b"0"), + ], + ) + + freshness_lifetime = get_freshness_lifetime(response=response) + assert freshness_lifetime is None + + def test_get_heuristic_freshness(): ONE_WEEK = 604_800 @@ -280,6 +306,13 @@ assert get_heuristic_freshness(response=response, clock=Clock()) == ONE_DAY +def test_get_heuristic_invalid_last_modified(): + ONE_DAY = 86400 + + response = Response(status=200, headers=[(b"Last-Modified", "0")]) + assert get_heuristic_freshness(response=response, clock=Clock()) == ONE_DAY + + def test_get_age(): class MockedClock(BaseClock): def now(self) -> int: @@ -291,6 +324,13 @@ def test_get_age_return_inf_for_invalid_date(): + response = Response(status=200, headers=[(b"Date", b"0")]) + age = get_age(response=response, clock=Clock()) + + assert age == float("inf") + + +def test_get_age_return_inf_for_no_date(): age = get_age(response=Response(status=200), clock=Clock()) assert age == float("inf") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/tests/test_headers.py new/hishel-0.1.2/tests/test_headers.py --- old/hishel-0.1.1/tests/test_headers.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/tests/test_headers.py 2025-04-04 23:15:26.000000000 +0200 @@ -65,7 +65,7 @@ header = ['max-age="123"'] with pytest.raises( ValidationError, - match="The argument 'max_age' should be an " "integer, but a quote was found.", + match="The argument 'max_age' should be an integer, but a quote was found.", ): parse_cache_control(header) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/tests/test_utils.py new/hishel-0.1.2/tests/test_utils.py --- old/hishel-0.1.1/tests/test_utils.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/tests/test_utils.py 2025-04-04 23:15:26.000000000 +0200 @@ -1,3 +1,5 @@ +from unittest import mock + import httpcore import pytest from httpcore import Request @@ -22,6 +24,16 @@ assert key == "bd152069787aaad359c85af6f2edbb25" +def test_fips_generate_key(): + request = Request(b"GET", "https://example.com", headers=[]) + + # Simulate FIPS mode by using sha256 instead of blake2b + with mock.patch("hashlib.blake2b", side_effect=AttributeError("ERROR")): + key = generate_key(request) + + assert key == "ea96dc6995764a0e6cf26bd2550deb01c18f69c0e586aa1fe201683129b8c15a" + + def test_extract_header_values(): headers = [ (b"Content-Type", b"application/json"), @@ -89,6 +101,12 @@ assert timestamp == 1440504000 +def test_parse_invalid_date(): + date = "0" + timestamp = parse_date(date) + assert timestamp is None + + def test_float_seconds_to_milliseconds(): seconds = 1.234 milliseconds = float_seconds_to_int_milliseconds(seconds) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hishel-0.1.1/unasync.py new/hishel-0.1.2/unasync.py --- old/hishel-0.1.1/unasync.py 2024-11-02 10:03:17.000000000 +0100 +++ new/hishel-0.1.2/unasync.py 2025-04-04 23:15:26.000000000 +0200 @@ -27,7 +27,7 @@ ("AsyncClient", "Client"), ("AsyncIterable", "Iterable"), ("AsyncCacheStream", "CacheStream"), - ("AsyncByteStream", "ByteStream"), + ("AsyncByteStream", "SyncByteStream"), ("AsyncCacheConnectionPool", "CacheConnectionPool"), ("handle_async_request", "handle_request"), ("aread", "read"),