Compare commits
15
Commits
a8b7b59484
...
v2.0.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f7b67203a | ||
|
|
a27e9e5763 | ||
|
|
fd0045d3e0 | ||
|
|
515f4bbeae | ||
|
|
ef31fb4b4e | ||
|
|
707f11f578 | ||
|
|
b1d34f8f0f | ||
|
|
565879dd52 | ||
|
|
0d0f430f6f | ||
|
|
5ac40b1ba5 | ||
|
|
fa4ff1f03c | ||
|
|
0a39151ba0 | ||
|
|
82a702db0c | ||
|
|
b886a7c147 | ||
|
|
4518a93a3a |
@@ -14,12 +14,38 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.CI_RUNNER_TOKEN }}
|
||||
|
||||
- name: Sync dependencies
|
||||
env:
|
||||
UV_LINK_MODE: copy
|
||||
UV_INDEX_GITEA_USERNAME: ci-bot
|
||||
UV_INDEX_GITEA_PASSWORD: ${{ secrets.CI_RUNNER_TOKEN }}
|
||||
run: uv sync --all-extras
|
||||
|
||||
- name: Upgrade dependencies
|
||||
env:
|
||||
UV_INDEX_GITEA_USERNAME: ci-bot
|
||||
UV_INDEX_GITEA_PASSWORD: ${{ secrets.CI_RUNNER_TOKEN }}
|
||||
run: uv lock --upgrade
|
||||
|
||||
- name: Update pre-commit hook revs
|
||||
env:
|
||||
UV_INDEX_GITEA_USERNAME: ci-bot
|
||||
UV_INDEX_GITEA_PASSWORD: ${{ secrets.CI_RUNNER_TOKEN }}
|
||||
run: uv run pre-commit autoupdate
|
||||
|
||||
- name: Sync upgraded dependencies
|
||||
env:
|
||||
UV_LINK_MODE: copy
|
||||
UV_INDEX_GITEA_USERNAME: ci-bot
|
||||
UV_INDEX_GITEA_PASSWORD: ${{ secrets.CI_RUNNER_TOKEN }}
|
||||
run: uv sync --all-extras
|
||||
|
||||
- name: Smoke check
|
||||
run: |
|
||||
uv run ruff check .
|
||||
uv run ruff format --check .
|
||||
uv run mypy .
|
||||
|
||||
- name: Commit and push changes
|
||||
env:
|
||||
API_URL: ${{ vars.API_URL }}
|
||||
|
||||
@@ -74,3 +74,23 @@ jobs:
|
||||
-H "Authorization: token ${CI_RUNNER_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD"
|
||||
|
||||
# Publish here instead of relying on publish.yml tag trigger: release commits use
|
||||
# [skip ci], which suppresses tag-push workflows, and Gitea does not emit release
|
||||
# events for releases created by the CI bot account.
|
||||
- name: Build package
|
||||
if: steps.meta.outputs.bump != 'skip'
|
||||
env:
|
||||
UV_LINK_MODE: copy
|
||||
UV_INDEX_GITEA_USERNAME: ci-bot
|
||||
UV_INDEX_GITEA_PASSWORD: ${{ secrets.CI_RUNNER_TOKEN }}
|
||||
run: |
|
||||
uv sync --no-dev --frozen
|
||||
uv build
|
||||
|
||||
- name: Publish to Gitea Package Registry
|
||||
if: steps.meta.outputs.bump != 'skip'
|
||||
env:
|
||||
UV_PUBLISH_TOKEN: ${{ secrets.CI_RUNNER_TOKEN }}
|
||||
UV_PUBLISH_URL: ${{ vars.REPOSITORY_URL }}
|
||||
run: uv publish
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
UV_LINK_MODE: copy
|
||||
UV_INDEX_GITEA_USERNAME: ci-bot
|
||||
UV_INDEX_GITEA_PASSWORD: ${{ secrets.CI_RUNNER_TOKEN }}
|
||||
run: uv sync --frozen
|
||||
run: uv sync --all-extras --frozen
|
||||
|
||||
- name: Run safety check
|
||||
run: uv run safety check
|
||||
|
||||
+19
-17
@@ -11,28 +11,30 @@ repos:
|
||||
- id: name-tests-test
|
||||
- id: check-merge-conflict
|
||||
|
||||
# Python linting and formatting with Ruff
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.12.8
|
||||
# Python tooling via uv (versions pinned in uv.lock)
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: ruff-check
|
||||
args: [--fix]
|
||||
name: ruff check
|
||||
entry: uv run ruff check --fix
|
||||
language: system
|
||||
types: [python]
|
||||
- id: ruff-format
|
||||
|
||||
# Static type checking with mypy
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.8.0
|
||||
hooks:
|
||||
name: ruff format
|
||||
entry: uv run ruff format
|
||||
language: system
|
||||
types: [python]
|
||||
- id: mypy
|
||||
additional_dependencies:
|
||||
- types-redis
|
||||
|
||||
# Python syntax modernization with pyupgrade
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.20.0
|
||||
hooks:
|
||||
name: mypy
|
||||
entry: uv run mypy .
|
||||
language: system
|
||||
types: [python]
|
||||
pass_filenames: false
|
||||
- id: pyupgrade
|
||||
args: ["--py312-plus"]
|
||||
name: pyupgrade
|
||||
entry: uv run pyupgrade --py312-plus
|
||||
language: system
|
||||
types: [python]
|
||||
|
||||
# Formatting for Markdown, JSON, and YAML with Prettier
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
|
||||
@@ -198,8 +198,8 @@ Releases are automated when a pull request is merged to `main`. CI reads the **m
|
||||
|
||||
1. Open a PR targeting `main` (see [`.gitea/PULL_REQUEST_TEMPLATE.md`](.gitea/PULL_REQUEST_TEMPLATE.md)).
|
||||
2. If the PR changes files under `python_repositories/`, the title **must** start with a version bump prefix (enforced by CI).
|
||||
3. On merge, [`release.yml`](.gitea/workflows/release.yml) bumps [`pyproject.toml`](pyproject.toml) and syncs [`uv.lock`](uv.lock), commits, tags `vX.Y.Z`, creates a Gitea release with auto-generated notes, and pushes the tag.
|
||||
4. [`publish.yml`](.gitea/workflows/publish.yml) builds and publishes the package to the Gitea Package Registry.
|
||||
3. On merge, [`release.yml`](.gitea/workflows/release.yml) bumps [`pyproject.toml`](pyproject.toml) and syncs [`uv.lock`](uv.lock), commits, tags `vX.Y.Z`, creates a Gitea release with auto-generated notes, pushes the tag, and publishes the package to the Gitea Package Registry.
|
||||
4. [`publish.yml`](.gitea/workflows/publish.yml) handles manual `v*.*.*` tag pushes only (automated releases publish from `release.yml` because release commits use `[skip ci]`, which suppresses tag-push workflows).
|
||||
|
||||
Docs-, CI-, and test-only PRs do not need a prefix and will not trigger a release.
|
||||
|
||||
|
||||
+17
-5
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "python-repositories"
|
||||
version = "2.0.2"
|
||||
version = "2.0.4"
|
||||
description = "Various python repository interfaces exposed as a python package."
|
||||
authors = [
|
||||
{ name = "Brian Bjarke Jensen", email = "[email protected]" }
|
||||
@@ -60,6 +60,18 @@ name = "gitea"
|
||||
url = "https://gitea.lille-vemmelund.dk/api/packages/brian/pypi/simple/"
|
||||
explicit = true
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 88
|
||||
target-version = "py312"
|
||||
|
||||
[tool.ruff.lint]
|
||||
extend-select = ["I"]
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
known-first-party = ["python_repositories", "tests"]
|
||||
combine-as-imports = true
|
||||
force-sort-within-sections = true
|
||||
|
||||
[tool.mypy]
|
||||
python_version = "3.12"
|
||||
warn_return_any = true # nudge to use stricter types
|
||||
@@ -87,12 +99,12 @@ ignore_missing_imports = true
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"mypy>=1.17.1",
|
||||
"pre-commit>=4.3.0",
|
||||
"mypy>=2.1.0",
|
||||
"pre-commit>=4.6.0",
|
||||
"pytest>=8.4.1",
|
||||
"pytest-cov>=7.0.0",
|
||||
"pyupgrade>=3.20.0",
|
||||
"ruff>=0.12.11",
|
||||
"pyupgrade>=3.21.2",
|
||||
"ruff>=0.15.20",
|
||||
"safety>=3.6.0",
|
||||
"testcontainers>=4.13.0",
|
||||
"types-redis>=4.6.0.20241004",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from abc import abstractmethod
|
||||
import time
|
||||
from typing import Self
|
||||
|
||||
import structlog
|
||||
@@ -73,7 +73,7 @@ class ConnectionAwareAdapter(ConnectionAwareInterface, ContextAwareInterface):
|
||||
self._invalidate_health_cache()
|
||||
return
|
||||
if self._is_client_ready() and self.is_connected():
|
||||
self.logger.info(f"Already connected to {self.connection_name}")
|
||||
self.logger.info("Already connected", connection_name=self.connection_name)
|
||||
return
|
||||
self.disconnect()
|
||||
self._establish_connection()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Definition of MinioAdapter class."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
from python_repositories.adapters.connection_aware_adapter import (
|
||||
@@ -88,7 +89,7 @@ class MinioAdapter(ObjectRepositoryInterface, ConnectionAwareAdapter):
|
||||
raise ConnectionError(
|
||||
f"Bucket '{bucket}' does not exist on Minio at {endpoint}"
|
||||
)
|
||||
self.logger.info(f"Creating bucket '{bucket}'")
|
||||
self.logger.info("Creating bucket", bucket=bucket)
|
||||
client.make_bucket(bucket)
|
||||
self._client = client
|
||||
self._bucket_name = bucket
|
||||
@@ -138,7 +139,7 @@ class MinioAdapter(ObjectRepositoryInterface, ConnectionAwareAdapter):
|
||||
content_type=content_type,
|
||||
)
|
||||
self.logger.debug(
|
||||
f"Put object '{object_name}' into bucket '{self._bucket_name}'"
|
||||
"Put object", object_name=object_name, bucket=self._bucket_name
|
||||
)
|
||||
|
||||
def get(self, object_name: str) -> BytesIO | None:
|
||||
@@ -163,13 +164,15 @@ class MinioAdapter(ObjectRepositoryInterface, ConnectionAwareAdapter):
|
||||
buffer.write(chunk)
|
||||
buffer.seek(0)
|
||||
self.logger.debug(
|
||||
f"Got object '{object_name}' from bucket '{self._bucket_name}'"
|
||||
"Got object", object_name=object_name, bucket=self._bucket_name
|
||||
)
|
||||
return buffer
|
||||
except minio.S3Error as exc:
|
||||
if exc.code == "NoSuchKey":
|
||||
self.logger.warning(
|
||||
f"Object '{object_name}' not found in bucket '{self._bucket_name}'"
|
||||
"Object not found",
|
||||
object_name=object_name,
|
||||
bucket=self._bucket_name,
|
||||
)
|
||||
return None
|
||||
raise
|
||||
@@ -193,7 +196,7 @@ class MinioAdapter(ObjectRepositoryInterface, ConnectionAwareAdapter):
|
||||
object_name=object_name,
|
||||
)
|
||||
self.logger.debug(
|
||||
f"Deleted object '{object_name}' from bucket '{self._bucket_name}'"
|
||||
"Deleted object", object_name=object_name, bucket=self._bucket_name
|
||||
)
|
||||
|
||||
def list_objects(self, prefix: str = "") -> list[str]:
|
||||
@@ -215,6 +218,9 @@ class MinioAdapter(ObjectRepositoryInterface, ConnectionAwareAdapter):
|
||||
obj.object_name for obj in objects if obj.object_name is not None
|
||||
]
|
||||
self.logger.debug(
|
||||
f"Listed {len(object_names)} object(s) in bucket '{self._bucket_name}' with prefix '{prefix}'"
|
||||
"Listed objects",
|
||||
count=len(object_names),
|
||||
bucket=self._bucket_name,
|
||||
prefix=prefix,
|
||||
)
|
||||
return object_names
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Definition of RedisAdapter class."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterator
|
||||
from typing import Any, cast
|
||||
|
||||
@@ -101,7 +102,7 @@ class RedisAdapter(JsonRepositoryInterface, ConnectionAwareAdapter):
|
||||
assert self._client is not None
|
||||
# Set data
|
||||
self._client.json().set(key, self.path, data)
|
||||
self.logger.debug(f"Set {key} to {data}")
|
||||
self.logger.debug("Set key", key=key, data_keys=list(data.keys()))
|
||||
|
||||
def get(self, key: str) -> dict[str, Any] | None:
|
||||
"""Get a JSON object from Redis."""
|
||||
@@ -116,7 +117,7 @@ class RedisAdapter(JsonRepositoryInterface, ConnectionAwareAdapter):
|
||||
dict[str, Any] | None,
|
||||
self._client.json().get(key),
|
||||
)
|
||||
self.logger.debug(f"Got {data} from {key}")
|
||||
self.logger.debug("Got value", key=key, found=data is not None)
|
||||
return data
|
||||
|
||||
def delete(self, key: str) -> None:
|
||||
@@ -129,7 +130,7 @@ class RedisAdapter(JsonRepositoryInterface, ConnectionAwareAdapter):
|
||||
assert self._client is not None
|
||||
# Delete data
|
||||
self._client.json().delete(key)
|
||||
self.logger.debug(f"Deleted {key}")
|
||||
self.logger.debug("Deleted key", key=key)
|
||||
|
||||
def _validate_pattern(self, pattern: str) -> None:
|
||||
if not isinstance(pattern, str) or len(pattern) == 0:
|
||||
@@ -147,7 +148,7 @@ class RedisAdapter(JsonRepositoryInterface, ConnectionAwareAdapter):
|
||||
self._client.keys(pattern),
|
||||
)
|
||||
keys: list[str] = [key.decode(self.encoding) for key in keys_raw]
|
||||
self.logger.debug(f"Got {keys} matching {pattern}")
|
||||
self.logger.debug("Listed keys", pattern=pattern, count=len(keys))
|
||||
return keys
|
||||
|
||||
def scan_keys(
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
import os
|
||||
|
||||
from python_utils import check_env
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
import os
|
||||
|
||||
from python_utils import check_env
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Definition of JsonRepositoryInterface abstract base class."""
|
||||
|
||||
from collections.abc import Iterator
|
||||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Iterator
|
||||
from typing import Any
|
||||
|
||||
|
||||
|
||||
@@ -11,15 +11,16 @@ set -euo pipefail
|
||||
BRANCH="${BRANCH:-renovate/auto-deps-update}"
|
||||
BASE_BRANCH="${BASE_BRANCH:-main}"
|
||||
LOCKFILE="${LOCKFILE:-uv.lock}"
|
||||
PRE_COMMIT_CONFIG="${PRE_COMMIT_CONFIG:-.pre-commit-config.yaml}"
|
||||
|
||||
if git diff --quiet "$LOCKFILE"; then
|
||||
if git diff --quiet "$LOCKFILE" && git diff --quiet "$PRE_COMMIT_CONFIG"; then
|
||||
echo "No dependency updates available."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git config user.name "CI Bot"
|
||||
git config user.email "[email protected]"
|
||||
git add "$LOCKFILE"
|
||||
git add "$LOCKFILE" "$PRE_COMMIT_CONFIG"
|
||||
git commit -m "chore(deps): update dependencies [automated]"
|
||||
|
||||
git remote set-url origin "https://x-access-token:${CI_RUNNER_TOKEN}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git"
|
||||
@@ -48,7 +49,12 @@ print(
|
||||
json.dumps(
|
||||
{
|
||||
"title": "chore(deps): update dependencies",
|
||||
"body": "This PR was created automatically to update dependencies.",
|
||||
"body": (
|
||||
"This PR was created automatically to update dependencies.\n\n"
|
||||
"- `uv.lock`: upgraded Python dependencies\n"
|
||||
"- `.pre-commit-config.yaml`: updated remote hook revs via "
|
||||
"`pre-commit autoupdate`"
|
||||
),
|
||||
"head": os.environ["BRANCH"],
|
||||
"base": os.environ["BASE_BRANCH"],
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"""Integration tests configuration."""
|
||||
|
||||
import logging
|
||||
from collections.abc import Generator
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
|
||||
from minio import Minio
|
||||
import pytest
|
||||
import redis
|
||||
import structlog
|
||||
from minio import Minio
|
||||
from testcontainers.core.container import DockerContainer
|
||||
from testcontainers.core.waiting_utils import WaitStrategy, WaitStrategyTarget
|
||||
from testcontainers.minio import MinioContainer
|
||||
|
||||
@@ -5,8 +5,8 @@ from io import BytesIO
|
||||
import os
|
||||
import random
|
||||
|
||||
import pytest
|
||||
from minio import Minio
|
||||
import pytest
|
||||
|
||||
from python_repositories.examples.artifact_object_repository import (
|
||||
ArtifactObjectRepository,
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
from collections.abc import Generator
|
||||
from dataclasses import replace
|
||||
from io import BytesIO
|
||||
import logging
|
||||
import random
|
||||
from io import BytesIO
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from minio import Minio, S3Error
|
||||
import pytest
|
||||
from urllib3.response import BaseHTTPResponse
|
||||
|
||||
from python_repositories.adapters.minio_adapter import MinioAdapter
|
||||
@@ -102,7 +102,8 @@ def test_should_log_info_when_already_connected(
|
||||
"""Test that the MinioAdapter logs info when connect is called while already connected."""
|
||||
with caplog.at_level(logging.INFO):
|
||||
minio_adapter.connect()
|
||||
assert "Already connected to Minio" in caplog.text
|
||||
assert "Already connected" in caplog.text
|
||||
assert "Minio" in caplog.text
|
||||
|
||||
|
||||
def test_should_raise_connection_error_when_unable_to_connect() -> None:
|
||||
@@ -150,7 +151,8 @@ def test_connect_creates_bucket_when_create_bucket_if_missing_enabled(
|
||||
with caplog.at_level(logging.INFO):
|
||||
adapter.connect()
|
||||
|
||||
assert f"Creating bucket '{bucket_name}'" in caplog.text
|
||||
assert "Creating bucket" in caplog.text
|
||||
assert bucket_name in caplog.text
|
||||
|
||||
|
||||
def test_should_log_error_on_exception_during_exit(
|
||||
@@ -233,10 +235,11 @@ def test_should_log_warning_when_getting_nonexistent_object(
|
||||
with caplog.at_level("WARNING"):
|
||||
result = adapter.get(object_name)
|
||||
assert result is None
|
||||
assert (
|
||||
f"Object '{object_name}' not found in bucket '{adapter._bucket_name}'"
|
||||
in caplog.text
|
||||
)
|
||||
assert "Object not found" in caplog.text
|
||||
assert object_name in caplog.text
|
||||
bucket_name = adapter._bucket_name
|
||||
assert bucket_name is not None
|
||||
assert bucket_name in caplog.text
|
||||
|
||||
|
||||
def test_should_reraise_s3error_other_than_no_such_key() -> None:
|
||||
|
||||
@@ -56,7 +56,8 @@ def test_should_log_info_when_already_connected(
|
||||
"""Test that the RedisAdapter logs info when connect is called while already connected."""
|
||||
with caplog.at_level(logging.INFO):
|
||||
redis_adapter.connect()
|
||||
assert "Already connected to Redis" in caplog.text
|
||||
assert "Already connected" in caplog.text
|
||||
assert "Redis" in caplog.text
|
||||
|
||||
|
||||
def test_should_raise_connection_error_when_unable_to_connect() -> None:
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import builtins
|
||||
from collections.abc import Callable, Mapping, Sequence
|
||||
import importlib
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
from collections.abc import Callable, Mapping, Sequence
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ from __future__ import annotations
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from minio import Minio
|
||||
import pytest
|
||||
import redis
|
||||
from minio import Minio
|
||||
|
||||
from python_repositories.adapters.minio_adapter import MinioAdapter
|
||||
from python_repositories.adapters.redis_adapter import RedisAdapter
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Unit tests for ConnectionAwareInterface."""
|
||||
|
||||
import pytest
|
||||
|
||||
from python_repositories.interfaces.connection_aware_interface import (
|
||||
ConnectionAwareInterface,
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from python_repositories.interfaces.context_aware_interface import ContextAwareInterface
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from python_repositories.interfaces.json_repository_interface import (
|
||||
JsonRepositoryInterface,
|
||||
)
|
||||
|
||||
@@ -5,8 +5,8 @@ from __future__ import annotations
|
||||
from dataclasses import replace
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from minio import Minio, S3Error
|
||||
import pytest
|
||||
from urllib3.response import BaseHTTPResponse
|
||||
|
||||
from python_repositories.adapters.minio_adapter import MinioAdapter
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
||||
from python_repositories.interfaces.object_repository_interface import (
|
||||
ObjectRepositoryInterface,
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
revision = 2
|
||||
requires-python = ">=3.12"
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.15'",
|
||||
@@ -1056,7 +1056,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "python-repositories"
|
||||
version = "2.0.2"
|
||||
version = "2.0.4"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "python-dotenv" },
|
||||
@@ -1097,12 +1097,12 @@ provides-extras = ["redis", "minio"]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "mypy", specifier = ">=1.17.1" },
|
||||
{ name = "pre-commit", specifier = ">=4.3.0" },
|
||||
{ name = "mypy", specifier = ">=2.1.0" },
|
||||
{ name = "pre-commit", specifier = ">=4.6.0" },
|
||||
{ name = "pytest", specifier = ">=8.4.1" },
|
||||
{ name = "pytest-cov", specifier = ">=7.0.0" },
|
||||
{ name = "pyupgrade", specifier = ">=3.20.0" },
|
||||
{ name = "ruff", specifier = ">=0.12.11" },
|
||||
{ name = "pyupgrade", specifier = ">=3.21.2" },
|
||||
{ name = "ruff", specifier = ">=0.15.20" },
|
||||
{ name = "safety", specifier = ">=3.6.0" },
|
||||
{ name = "testcontainers", specifier = ">=4.13.0" },
|
||||
{ name = "types-redis", specifier = ">=4.6.0.20241004" },
|
||||
|
||||
Reference in New Issue
Block a user