fix: secure Python package baseline
This commit is contained in:
1 parent
3dce6c0b8d
commit
3e7786bb73
4 files changed
+92
-12
No files matched your search
@@ -8,7 +8,7 @@ Official Python SDK for the [Elydora](https://elydora.com) tamper-evident audit
|
||||
pip install elydora
|
||||
```
|
||||
|
||||
Requires Python 3.9+.
|
||||
Requires Python 3.10+.
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
"""Type definitions matching the Elydora backend API contract.
|
||||
|
||||
All types use TypedDict for structural typing, compatible with Python 3.9+.
|
||||
All types use TypedDict for structural typing, compatible with Python 3.10+.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
+10
-10
@@ -1,5 +1,5 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=68.0", "wheel"]
|
||||
requires = ["setuptools>=77.0.3", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
@@ -7,24 +7,24 @@ name = "elydora"
|
||||
dynamic = ["version"]
|
||||
description = "Python SDK for the Elydora tamper-evident audit platform"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
requires-python = ">=3.9"
|
||||
license = "MIT"
|
||||
requires-python = ">=3.10"
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3.14",
|
||||
"Typing :: Typed",
|
||||
]
|
||||
dependencies = [
|
||||
"requests>=2.28.0",
|
||||
"aiohttp>=3.8.0",
|
||||
"cryptography>=41.0.0",
|
||||
"requests>=2.33.0",
|
||||
"aiohttp>=3.14.1",
|
||||
"urllib3>=2.7.0",
|
||||
"cryptography>=48.0.1",
|
||||
"tomlkit>=0.15.1,<1.0.0",
|
||||
"typing_extensions>=4.0.0;python_version<'3.11'",
|
||||
]
|
||||
@@ -34,8 +34,8 @@ elydora = "elydora.cli:main"
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pytest>=7.0",
|
||||
"pytest-asyncio>=0.21",
|
||||
"pytest>=9.0.3",
|
||||
"pytest-asyncio>=1.4.0",
|
||||
"mypy>=1.0",
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
from pathlib import Path
|
||||
|
||||
from packaging.requirements import Requirement
|
||||
from packaging.version import Version
|
||||
import tomlkit
|
||||
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def _pyproject() -> dict[str, object]:
|
||||
return tomlkit.parse((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def _project_metadata() -> dict[str, object]:
|
||||
return _pyproject()["project"]
|
||||
|
||||
|
||||
def _requirements(entries: object) -> dict[str, Requirement]:
|
||||
assert isinstance(entries, list)
|
||||
requirements = (Requirement(str(entry)) for entry in entries)
|
||||
return {requirement.name: requirement for requirement in requirements}
|
||||
|
||||
|
||||
def _assert_safe_floor(
|
||||
requirement: Requirement,
|
||||
vulnerable: str,
|
||||
fixed: str,
|
||||
) -> None:
|
||||
assert Version(vulnerable) not in requirement.specifier
|
||||
assert Version(fixed) in requirement.specifier
|
||||
|
||||
|
||||
def test_python_support_matches_maintained_runtime_line() -> None:
|
||||
project = _project_metadata()
|
||||
|
||||
assert project["requires-python"] == ">=3.10"
|
||||
assert "Programming Language :: Python :: 3.9" not in project["classifiers"]
|
||||
assert "Programming Language :: Python :: 3.14" in project["classifiers"]
|
||||
|
||||
|
||||
def test_license_uses_current_packaging_metadata() -> None:
|
||||
document = _pyproject()
|
||||
project = document["project"]
|
||||
assert isinstance(project, dict)
|
||||
build_system = document["build-system"]
|
||||
assert isinstance(build_system, dict)
|
||||
build_requirements = _requirements(build_system["requires"])
|
||||
|
||||
assert project["license"] == "MIT"
|
||||
assert all(
|
||||
not str(classifier).startswith("License ::")
|
||||
for classifier in project["classifiers"]
|
||||
)
|
||||
assert Version("77.0.3") in build_requirements["setuptools"].specifier
|
||||
|
||||
|
||||
def test_dependency_floors_exclude_known_vulnerable_releases() -> None:
|
||||
project = _project_metadata()
|
||||
runtime = _requirements(project["dependencies"])
|
||||
optional = project["optional-dependencies"]
|
||||
assert isinstance(optional, dict)
|
||||
development = _requirements(optional["dev"])
|
||||
|
||||
_assert_safe_floor(runtime["requests"], "2.32.5", "2.33.0")
|
||||
_assert_safe_floor(runtime["aiohttp"], "3.13.5", "3.14.1")
|
||||
_assert_safe_floor(runtime["urllib3"], "2.6.3", "2.7.0")
|
||||
_assert_safe_floor(runtime["cryptography"], "41.0.0", "48.0.1")
|
||||
_assert_safe_floor(development["pytest"], "8.4.2", "9.0.3")
|
||||
|
||||
|
||||
def test_async_test_runner_supports_pytest_nine() -> None:
|
||||
project = _project_metadata()
|
||||
optional = project["optional-dependencies"]
|
||||
assert isinstance(optional, dict)
|
||||
development = _requirements(optional["dev"])
|
||||
|
||||
requirement = development["pytest-asyncio"]
|
||||
assert Version("1.3.0") not in requirement.specifier
|
||||
assert Version("1.4.0") in requirement.specifier
|
||||
Reference in new issue
Block a user