From 2ece9d5c71bcb55b97c29beba3455cab44757b72 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Sun, 12 Jul 2026 10:40:04 +0200 Subject: [PATCH 1/4] feat: rate-limit the API, and the scheduling and forecasting triggers in particular Scheduling is our most expensive operation, and nothing stopped a client from triggering it in a tight loop. A generous default limit now applies to every endpoint under /api/, and a stricter limit to the endpoints which trigger schedules and forecasts. Both limits are configurable, and can be overridden per account through the "rate_limits" account attribute. What the trigger limit is counted against is a business decision, so hosts choose: per asset, per account, or per user. Counts live in the Redis we already connect to. If Redis is unreachable, we let requests through rather than take the API down with it. This picks up the tech spike in #587, which worked around flask-classful not supporting per-method decorators. It does support them now, so the cost-function workaround is gone. Closes #306. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01C2JTqYVFPmJgX7kN2DSvbE --- documentation/api/change_log.rst | 1 + documentation/changelog.rst | 1 + documentation/configuration.rst | 66 + flexmeasures/api/__init__.py | 3 + flexmeasures/api/common/rate_limiting.py | 139 ++ flexmeasures/api/common/responses.py | 4 + flexmeasures/api/v3_0/assets.py | 2 + flexmeasures/api/v3_0/sensors.py | 3 + .../api/v3_0/tests/test_rate_limiting.py | 195 +++ flexmeasures/utils/config_defaults.py | 15 + pyproject.toml | 2 + uv.lock | 1500 +++++++++-------- 12 files changed, 1233 insertions(+), 698 deletions(-) create mode 100644 flexmeasures/api/common/rate_limiting.py create mode 100644 flexmeasures/api/v3_0/tests/test_rate_limiting.py diff --git a/documentation/api/change_log.rst b/documentation/api/change_log.rst index c75a260f70..7900ec8585 100644 --- a/documentation/api/change_log.rst +++ b/documentation/api/change_log.rst @@ -8,6 +8,7 @@ API change log v3.0-32 | July XX, 2026 """""""""""""""""""""""" +- API endpoints are now rate-limited. A request which exceeds a limit is answered with a ``429 (Too Many Requests)`` status code and a ``Retry-After`` header stating how many seconds to wait. Responses also carry ``X-RateLimit-*`` headers, describing the limit that applied, how much of it is left, and when it resets. A stricter limit applies to ``POST /assets//schedules/trigger``, ``POST /sensors//schedules/trigger`` and ``POST /sensors//forecasts/trigger`` than to other endpoints; the health endpoints are exempt. - Extended ``GET /api/v3_0/jobs/`` with a ``result`` field containing ``unresolved`` and ``resolved`` arrays, each keyed by asset ID. For scheduling jobs, this surfaces soft state-of-charge constraint analysis: ``soc-minima`` and ``soc-maxima`` violations (with a ``violation`` magnitude) or satisfied constraints (with a ``margin`` headroom). Both arrays are empty when no SoC constraints were defined. v3.0-31 | 2026-06-01 diff --git a/documentation/changelog.rst b/documentation/changelog.rst index f59adfd1b4..c280fd2488 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -13,6 +13,7 @@ v1.0.0 | July XX, 2026 New features ------------- +* The API is now rate-limited, with a generous default limit on all endpoints and a stricter limit on triggering schedules and forecasts. Limits are configurable, and can be set per account through the ``rate_limits`` account attribute [see `PR #2302 `_] * Breaking behaviour change: the top-level flex-context's ``relax-constraints`` field now defaults to ``True`` (matching the default already used within each ``commodities`` entry), so constraint violations are softly penalized by default instead of being hard constraints, unless explicitly set to ``False`` [see `PR #2172 `_] * Support for creating new assets by using another asset as a template from the UI. [see `PR #2195 `_ and `PR #2268 `_ * In the UI, asset and sensor lists can be filtered by ID prefix through API-backed search fields [see `PR #2231 `_] diff --git a/documentation/configuration.rst b/documentation/configuration.rst index fd6ee7c4f4..de994ee330 100644 --- a/documentation/configuration.rst +++ b/documentation/configuration.rst @@ -769,6 +769,72 @@ Password of the redis server. Default: ``None`` +.. _rate-limiting-config: + +API rate limiting +----------------- + +FlexMeasures rate-limits its API, to protect the server against clients which ask for more than their fair share ― +in particular against clients which re-trigger expensive computations like scheduling in a tight loop. + +Two limits apply. A default limit applies to every API endpoint, and a stricter limit applies to the endpoints +which trigger scheduling and forecasting. Requests which exceed a limit are answered with a ``429`` status code, +and a ``Retry-After`` header telling the client how long to wait. + +Counts are kept in Redis (see :ref:`redis-config`), so that all your workers share them. If Redis cannot be +reached, FlexMeasures lets requests through rather than refusing them. + +.. note:: The limiter runs before authentication, so requests without valid credentials are counted per IP address. + +Individual accounts can be given their own limits, which take precedence over the settings below, by setting the +``rate_limits`` account attribute (with ``flexmeasures edit attribute``). Use the value ``"unlimited"`` to exempt +an account from a limit altogether: + +.. code-block:: json + + { + "rate_limits": { + "default": "1000 per minute", + "trigger": "unlimited" + } + } + +RATELIMIT_ENABLED +^^^^^^^^^^^^^^^^^ + +Whether to rate-limit the API at all. Set this to ``False`` to turn rate limiting off. + +Default: ``True`` + +FLEXMEASURES_API_DEFAULT_RATE_LIMIT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +How often a client may call any API endpoint. Counted per user (or per IP address, if unauthenticated). +The health endpoints are exempt, so that monitoring cannot lock itself out. + +Default: ``"500 per minute"`` + +FLEXMEASURES_API_TRIGGER_RATE_LIMIT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +How often a client may trigger a schedule or a forecast. This is the expensive work, so this limit is stricter +than the default one. + +Default: ``"10 per 5 minutes"`` + +FLEXMEASURES_API_RATE_LIMIT_KEY +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +What ``FLEXMEASURES_API_TRIGGER_RATE_LIMIT`` is counted against. How often it is reasonable to re-compute a +schedule is a business decision, so you decide what shares a budget: + +- ``"account+asset"``: each asset gets its own budget, so scheduling one asset never blocks another. +- ``"account"``: the account has a single budget, shared by all of its assets and users. +- ``"user"``: each user gets their own budget. + +Default: ``"account+asset"`` + + Demonstrations -------------- diff --git a/flexmeasures/api/__init__.py b/flexmeasures/api/__init__.py index c4c8a445a9..779f43ffee 100644 --- a/flexmeasures/api/__init__.py +++ b/flexmeasures/api/__init__.py @@ -13,6 +13,7 @@ from flexmeasures.data import db from flexmeasures import __version__ as flexmeasures_version +from flexmeasures.api.common import rate_limiting from flexmeasures.api.common.utils.api_utils import catch_timed_belief_replacements from flexmeasures.data.models.user import User from flexmeasures.api.common.utils.args_parsing import ( @@ -156,6 +157,8 @@ def register_at(app: Flask): app.register_error_handler(IntegrityError, catch_timed_belief_replacements) app.unauthorized_handler_api = invalid_sender + rate_limiting.register_at(app) + app.register_blueprint( flexmeasures_api, url_prefix="/api" ) # now registering the blueprint will affect all endpoints diff --git a/flexmeasures/api/common/rate_limiting.py b/flexmeasures/api/common/rate_limiting.py new file mode 100644 index 0000000000..f0f71b84bf --- /dev/null +++ b/flexmeasures/api/common/rate_limiting.py @@ -0,0 +1,139 @@ +""" +Rate limiting for the FlexMeasures API. + +Two limits apply: + +- a generous default limit on every endpoint under ``/api/``, and +- a stricter limit on the endpoints that trigger expensive computation (scheduling and forecasting). + +Both are configurable (see ``FLEXMEASURES_API_DEFAULT_RATE_LIMIT`` and ``FLEXMEASURES_API_TRIGGER_RATE_LIMIT``), +and both can be overridden per account, by setting e.g. +``account.attributes["rate_limits"]["trigger"] = "50 per hour"``. +The special value "unlimited" exempts an account from a limit. + +Note that the limiter runs before authentication, so unauthenticated callers are counted by IP address. +""" + +from __future__ import annotations + +from flask import Flask, current_app, jsonify, request +from flask_limiter import Limiter, RequestLimit +from flask_limiter.util import get_remote_address +from flask_login import current_user + +from flexmeasures.api.common.responses import too_many_requests + +# Endpoints under /api/ which the default limit should not apply to +EXEMPT_PATH_PREFIXES = ("/api/v3_0/health",) + + +def _account_rate_limit(limit_name: str) -> str | None: + """Look up an account's override for the given limit, if any.""" + if not current_user.is_authenticated or current_user.account is None: + return None + rate_limits = (current_user.account.attributes or {}).get("rate_limits", {}) + return rate_limits.get(limit_name) + + +def _is_unlimited(limit_name: str) -> bool: + """Whether the account is exempt from the given limit.""" + return _account_rate_limit(limit_name) == "unlimited" + + +def default_key_func() -> str: + """Count requests against the user, or against the IP address if unauthenticated.""" + if current_user.is_authenticated: + return f"user:{current_user.id}" + return get_remote_address() + + +def trigger_key_func() -> str: + """Count triggers against whatever the host configured. + + The request path contains both the resource type and its ID, + so it distinguishes assets from sensors without us having to parse view args. + """ + if not current_user.is_authenticated: + return get_remote_address() + key = current_app.config["FLEXMEASURES_API_RATE_LIMIT_KEY"] + if key == "user": + return f"user:{current_user.id}" + if key == "account": + return f"account:{current_user.account_id}" + if key == "account+asset": + return f"account:{current_user.account_id}|{request.path}" + raise ValueError( + f"Unknown FLEXMEASURES_API_RATE_LIMIT_KEY '{key}'. Use 'account+asset', 'account' or 'user'." + ) + + +def default_limit() -> str: + return ( + _account_rate_limit("default") + or current_app.config["FLEXMEASURES_API_DEFAULT_RATE_LIMIT"] + ) + + +def trigger_limit() -> str: + return ( + _account_rate_limit("trigger") + or current_app.config["FLEXMEASURES_API_TRIGGER_RATE_LIMIT"] + ) + + +def _exempt_from_default_limit() -> bool: + """The default limit only applies to the API, and not to endpoints we exempt explicitly.""" + if not request.path.startswith("/api/"): + return True + if request.path.startswith(EXEMPT_PATH_PREFIXES): + return True + return _is_unlimited("default") + + +limiter = Limiter( + key_func=default_key_func, + default_limits=[default_limit], + default_limits_exempt_when=_exempt_from_default_limit, + headers_enabled=True, # sets Retry-After and X-RateLimit-* headers +) + + +def limit_triggers(): + """Decorator for endpoints which trigger expensive computation, like scheduling.""" + return limiter.limit( + trigger_limit, + key_func=trigger_key_func, + exempt_when=lambda: _is_unlimited("trigger"), + ) + + +def rate_limit_exceeded_handler(error): + """Respond to a hit rate limit like we respond to other API errors. + + The Retry-After and X-RateLimit-* headers are added by the limiter itself, after this request. + """ + limit: RequestLimit | None = limiter.current_limit + message = "You hit a rate limit." + if limit is not None: + message += f" This endpoint allows {limit.limit}." + response_data, status_code = too_many_requests(message) + response = jsonify(response_data) + response.status_code = status_code + return response + + +def register_at(app: Flask): + """Set up rate limiting, storing counts in the Redis we already connected to.""" + app.config.setdefault("RATELIMIT_STORAGE_URI", "redis://") + if app.config["RATELIMIT_STORAGE_URI"].startswith("redis://"): + # Reuse the connection we already made, rather than opening a second one + app.config.setdefault( + "RATELIMIT_STORAGE_OPTIONS", + {"connection_pool": app.redis_connection.connection_pool}, + ) + # If Redis is unreachable, let requests through rather than take the API down with it. + app.config.setdefault("RATELIMIT_SWALLOW_ERRORS", True) + app.config.setdefault("RATELIMIT_IN_MEMORY_FALLBACK_ENABLED", True) + + limiter.init_app(app) + app.register_error_handler(429, rate_limit_exceeded_handler) diff --git a/flexmeasures/api/common/responses.py b/flexmeasures/api/common/responses.py index 5b161ffa27..2a86a7a877 100644 --- a/flexmeasures/api/common/responses.py +++ b/flexmeasures/api/common/responses.py @@ -399,6 +399,10 @@ def request_too_large(message: str) -> ResponseTuple: return dict(result="Rejected", status="PAYLOAD_TOO_LARGE", message=message), 413 +def too_many_requests(message: str) -> ResponseTuple: + return dict(result="Rejected", status="TOO_MANY_REQUESTS", message=message), 429 + + def pluralize(usef_role_name: str) -> str: """Adding a trailing 's' works well for USEF roles.""" return "%ss" % usef_role_name diff --git a/flexmeasures/api/v3_0/assets.py b/flexmeasures/api/v3_0/assets.py index 10b988d648..f4185dc8bc 100644 --- a/flexmeasures/api/v3_0/assets.py +++ b/flexmeasures/api/v3_0/assets.py @@ -69,6 +69,7 @@ unprocessable_entity, request_processed, ) +from flexmeasures.api.common.rate_limiting import limit_triggers from flexmeasures.api.common.schemas.users import AccountIdField from flexmeasures.api.common.schemas.assets import default_response_fields from flexmeasures.ui.utils.view_utils import clear_session, set_session_variables @@ -1332,6 +1333,7 @@ def update_keep_legends_below_graphs(self, **kwargs): }, 200 @route("//schedules/trigger", methods=["POST"]) + @limit_triggers() @use_args(AssetTriggerSchema(), location="args_and_json", as_kwargs=True) # Simplification of checking for create-children access on each of the flexible sensors, # which assumes each of the flexible sensors belongs to the given asset. diff --git a/flexmeasures/api/v3_0/sensors.py b/flexmeasures/api/v3_0/sensors.py index e28a7f0c4a..a55e5b73ab 100644 --- a/flexmeasures/api/v3_0/sensors.py +++ b/flexmeasures/api/v3_0/sensors.py @@ -36,6 +36,7 @@ ) from flexmeasures.api.common.schemas.sensors import SensorId # noqa F401 from flexmeasures.api.common.schemas.users import AccountIdField +from flexmeasures.api.common.rate_limiting import limit_triggers from flexmeasures.api.common.utils.api_utils import process_sensor_data_ingestion from flexmeasures.data.services.utils import job_status_description from flexmeasures.api.common.utils.deprecation_utils import ( @@ -795,6 +796,7 @@ def get_data(self, id: int, **sensor_data_description: dict): return dict(**response, **d), s @route("//schedules/trigger", methods=["POST"]) + @limit_triggers() @use_kwargs( {"sensor": SensorIdField(data_key="id")}, location="path", @@ -1842,6 +1844,7 @@ def get_status(self, id, sensor): return {"sensors_data": status_data}, 200 @route("//forecasts/trigger", methods=["POST"]) + @limit_triggers() @use_args( ForecastingTriggerSchema( # partial=True, diff --git a/flexmeasures/api/v3_0/tests/test_rate_limiting.py b/flexmeasures/api/v3_0/tests/test_rate_limiting.py new file mode 100644 index 0000000000..6cc96e4873 --- /dev/null +++ b/flexmeasures/api/v3_0/tests/test_rate_limiting.py @@ -0,0 +1,195 @@ +from flask import url_for +import pytest + +from flexmeasures.api.common.rate_limiting import limiter +from flexmeasures.api.v3_0.tests.utils import message_for_trigger_schedule + + +@pytest.fixture +def rate_limiting(app, monkeypatch): + """Start each test with a clean count. + + Note that the limits are set very high during tests (see TestingConfig), + so each test here lowers the limit it wants to hit. + """ + limiter.reset() + yield monkeypatch + limiter.reset() + + +def trigger(client, sensor_id: int, message: dict | None = None): + """Post to the schedule trigger endpoint. + + Note that the limiter counts a request before its payload is validated, + so tests which only care about counting may pass an empty message. + """ + return client.post( + url_for("SensorAPI:trigger_schedule", id=sensor_id), + json=message if message is not None else {}, + ) + + +@pytest.mark.parametrize( + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_no_rate_limiting_when_disabled( + app, add_battery_assets, rate_limiting, requesting_user +): + """Hosts can turn rate limiting off altogether.""" + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per day" + ) + rate_limiting.setattr(limiter, "enabled", False) + sensor = add_battery_assets["Test battery"].sensors[0] + with app.test_client() as client: + for _ in range(3): + assert trigger(client, sensor.id).status_code != 429 + + +@pytest.mark.parametrize( + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_default_rate_limit(app, rate_limiting, requesting_user): + """The default limit applies to any API endpoint, and says how long to wait.""" + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_DEFAULT_RATE_LIMIT", "2 per minute" + ) + with app.test_client() as client: + for _ in range(2): + assert client.get(url_for("SensorAPI:index")).status_code == 200 + response = client.get(url_for("SensorAPI:index")) + + assert response.status_code == 429 + assert response.json["status"] == "TOO_MANY_REQUESTS" + assert "2 per 1 minute" in response.json["message"] + assert "Retry-After" in response.headers + + +@pytest.mark.parametrize( + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_health_endpoint_is_exempt_from_default_rate_limit( + app, rate_limiting, requesting_user +): + """Monitoring should not be able to rate-limit itself out of checking on us.""" + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_DEFAULT_RATE_LIMIT", "1 per minute" + ) + with app.test_client() as client: + for _ in range(3): + assert client.get(url_for("HealthAPI:is_ready")).status_code == 200 + + +@pytest.mark.parametrize( + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_trigger_rate_limit( + app, + add_market_prices, + add_battery_assets, + add_charging_station_assets, + keep_scheduling_queue_empty, + rate_limiting, + requesting_user, +): + """A schedule can be triggered successfully, but not again right away.""" + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" + ) + sensor = add_battery_assets["Test battery"].sensors[0] + # Ask for a new job, so that an identical job cached by an earlier test cannot be reused, + # which would leave the queue length unchanged and tell us nothing. + message = message_for_trigger_schedule() | {"force-new-job-creation": True} + scheduling_queue = app.queues["scheduling"] + queue_length_before = len(scheduling_queue) + + with app.test_client() as client: + assert trigger(client, sensor.id, message).status_code == 200 + + # The accepted trigger queued a scheduling job + assert len(scheduling_queue) == queue_length_before + 1 + queue_length_after_first_trigger = len(scheduling_queue) + + response = trigger(client, sensor.id, message) + + assert response.status_code == 429 + assert response.json["status"] == "TOO_MANY_REQUESTS" + + # The rate-limited trigger did no work + assert len(scheduling_queue) == queue_length_after_first_trigger + + +@pytest.mark.parametrize( + "rate_limit_key, expected_status_code_for_other_sensor", + [ + # Each asset gets its own budget ... + ("account+asset", 422), + # ... unless the whole account or user shares one budget + ("account", 429), + ("user", 429), + ], +) +@pytest.mark.parametrize( + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_trigger_rate_limit_key( + app, + add_battery_assets, + rate_limiting, + requesting_user, + rate_limit_key, + expected_status_code_for_other_sensor, +): + """The host decides whether the trigger limit is counted per asset, per account or per user.""" + rate_limiting.setitem(app.config, "FLEXMEASURES_API_RATE_LIMIT_KEY", rate_limit_key) + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" + ) + sensor = add_battery_assets["Test battery"].sensors[0] + other_sensor = add_battery_assets["Test small battery"].sensors[0] + + with app.test_client() as client: + assert trigger(client, sensor.id).status_code == 422 # spends the budget + assert trigger(client, sensor.id).status_code == 429 + response = trigger(client, other_sensor.id) + + assert response.status_code == expected_status_code_for_other_sensor + + +@pytest.mark.parametrize( + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_account_can_override_trigger_rate_limit( + db, app, add_battery_assets, rate_limiting, requesting_user +): + """An account's own limit takes precedence over the configured default.""" + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" + ) + requesting_user.account.attributes["rate_limits"] = {"trigger": "2 per 5 minutes"} + db.session.commit() + sensor = add_battery_assets["Test battery"].sensors[0] + + with app.test_client() as client: + for _ in range(2): + assert trigger(client, sensor.id).status_code == 422 + assert trigger(client, sensor.id).status_code == 429 + + +@pytest.mark.parametrize( + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_account_can_be_exempt_from_trigger_rate_limit( + db, app, add_battery_assets, rate_limiting, requesting_user +): + """An account can be exempted from a limit altogether.""" + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" + ) + requesting_user.account.attributes["rate_limits"] = {"trigger": "unlimited"} + db.session.commit() + sensor = add_battery_assets["Test battery"].sensors[0] + + with app.test_client() as client: + for _ in range(3): + assert trigger(client, sensor.id).status_code == 422 diff --git a/flexmeasures/utils/config_defaults.py b/flexmeasures/utils/config_defaults.py index d19492142e..4202ef80fe 100644 --- a/flexmeasures/utils/config_defaults.py +++ b/flexmeasures/utils/config_defaults.py @@ -176,6 +176,15 @@ class Config(object): FLEXMEASURES_REDIS_PORT: int = 6379 FLEXMEASURES_REDIS_DB_NR: int = 0 # Redis per default has 16 databases, [0-15] FLEXMEASURES_REDIS_PASSWORD: str | None = None + # API rate limiting (see flexmeasures.api.common.rate_limiting) + RATELIMIT_ENABLED: bool = ( + True # Flask-Limiter's own switch, to turn off rate limiting altogether + ) + FLEXMEASURES_API_DEFAULT_RATE_LIMIT: str = "500 per minute" + FLEXMEASURES_API_TRIGGER_RATE_LIMIT: str = "10 per 5 minutes" + FLEXMEASURES_API_RATE_LIMIT_KEY: str = ( + "account+asset" # what to count triggers against: "account+asset", "account" or "user" + ) FLEXMEASURES_JS_VERSIONS: dict = dict( vega="5.22.1", vegaembed="6.21.0", @@ -279,6 +288,12 @@ class TestingConfig(Config): hours=2 * 24 ) # if more than 2 days, consider setting up more days of price data for tests + # The rate limiter stays initialized during tests (turning it on later is not possible), + # but its limits are set so high that only the rate limiting tests, which lower them, will hit them. + RATELIMIT_STORAGE_URI: str = "memory://" + FLEXMEASURES_API_DEFAULT_RATE_LIMIT: str = "1000000 per hour" + FLEXMEASURES_API_TRIGGER_RATE_LIMIT: str = "1000000 per hour" + SECURITY_TWO_FACTOR = False # disable 2FA SECURITY_TOTP_SECRETS = {"1": "00000000000000000000000000000000"} SECURITY_PASSWORD_CHECK_BREACHED = None # disable breached password checking diff --git a/pyproject.toml b/pyproject.toml index 391143a324..477ced9942 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,6 +78,8 @@ dependencies = [ "flask-marshmallow>=1.4.0", "flask-cors>=6.0.2", "flask-swagger-ui>=5.21.0", + # Note: the redis extra (used for rate-limit storage) currently pins redis<8 + "Flask-Limiter[redis]>=4.0", "sentry-sdk[flask]>=2.52.0", "marshmallow>=3", # See GH#1450 (failing tests on older Python versions) diff --git a/uv.lock b/uv.lock index 9e234afa4d..5e14854a9e 100644 --- a/uv.lock +++ b/uv.lock @@ -2,21 +2,21 @@ version = 1 revision = 3 requires-python = ">=3.10, <3.13" resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'win32')", "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'win32')", @@ -45,10 +45,10 @@ name = "alembic" version = "1.18.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "mako", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "mako", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "tomli", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/94/13/8b084e0f2efb0275a1d534838844926f798bd766566b1375174e2448cd31/alembic-1.18.4.tar.gz", hash = "sha256:cb6e1fd84b6174ab8dbb2329f86d631ba9559dd78df550b57804d607672cedbc", size = 2056725, upload-time = "2026-02-10T16:00:47.195Z" } wheels = [ @@ -60,11 +60,11 @@ name = "altair" version = "6.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "jinja2", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "jsonschema", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "narwhals", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "jinja2", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "jsonschema", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "narwhals", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "packaging", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/86/97/9a0dc61efd4f2dee29cb6d8edbbacdb789ce48cbffd98efa2b3ab145b297/altair-6.2.1.tar.gz", hash = "sha256:ca0298fa20b1a4fae22eff8847b95f74912bd90544013ad36af192119883ea64", size = 766468, upload-time = "2026-06-05T16:23:36.57Z" } wheels = [ @@ -85,7 +85,7 @@ name = "apispec" version = "6.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "packaging", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/4a/f1/1f5a9332df3ecd90cc5ab69bc58a4174b8ba2ac1720c4c26b01d20751bf5/apispec-6.10.0.tar.gz", hash = "sha256:0a888555cd4aa5fb7176041be15684154fd8961055e1672e703abf737e8761bf", size = 80631, upload-time = "2026-03-06T21:48:40.916Z" } wheels = [ @@ -94,7 +94,7 @@ wheels = [ [package.optional-dependencies] yaml = [ - { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "pyyaml", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] [[package]] @@ -102,10 +102,10 @@ name = "apispec-oneofschema" version = "3.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "apispec", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "marshmallow-oneofschema", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "apispec", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow-oneofschema", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c5/79/9bc6993ade0a3b841812cd46523ecf244bbb9deacb14d29d04eff541a2c7/apispec_oneofschema-3.0.2.tar.gz", hash = "sha256:03fad9b6d88f0e61669700d2e544e1410064d3cc267dc5d1d174b26f69bd05b7", size = 3677, upload-time = "2025-07-28T06:11:24.009Z" } wheels = [ @@ -117,7 +117,7 @@ name = "apispec-webframeworks" version = "1.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "apispec", extra = ["yaml"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "apispec", extra = ["yaml"], marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f9/1f/8d98328269a2507b6cfe37e8a70725d168626615865dc7aec30e8720c495/apispec_webframeworks-1.2.0.tar.gz", hash = "sha256:5689288c266a2713c2f516eacc14ea2fec9b21f193edc8f659c770342b97fd81", size = 10837, upload-time = "2024-09-16T19:01:18.051Z" } wheels = [ @@ -129,7 +129,7 @@ name = "argon2-cffi" version = "25.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "argon2-cffi-bindings", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "argon2-cffi-bindings", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } wheels = [ @@ -141,7 +141,7 @@ name = "argon2-cffi-bindings" version = "25.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cffi", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "cffi", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } wheels = [ @@ -167,8 +167,8 @@ name = "arrow" version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tzdata", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "python-dateutil", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "tzdata", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/33/032cdc44182491aa708d06a68b62434140d8c50820a087fac7af37703357/arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7", size = 152931, upload-time = "2025-10-18T17:46:46.761Z" } wheels = [ @@ -275,13 +275,13 @@ name = "black" version = "24.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "mypy-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pathspec", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "platformdirs", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "click", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "mypy-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "packaging", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pathspec", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "platformdirs", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "tomli", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/04/b0/46fb0d4e00372f4a86a6f8efa3cb193c9f64863615e39010b1477e010578/black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f", size = 644810, upload-time = "2024-08-02T17:43:18.405Z" } wheels = [ @@ -353,7 +353,7 @@ name = "cffi" version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pycparser", marker = "(implementation_name != 'PyPy' and sys_platform == 'darwin') or (implementation_name != 'PyPy' and sys_platform == 'linux') or (implementation_name != 'PyPy' and sys_platform == 'win32')" }, + { name = "pycparser", marker = "(implementation_name != 'PyPy' and os_name != 'nt' and sys_platform == 'darwin') or (implementation_name != 'PyPy' and os_name != 'nt' and sys_platform == 'linux') or (implementation_name != 'PyPy' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } wheels = [ @@ -470,7 +470,7 @@ name = "click-default-group" version = "1.2.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "click", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1d/ce/edb087fb53de63dad3b36408ca30368f438738098e668b78c87f93cd41df/click_default_group-1.2.4.tar.gz", hash = "sha256:eb3f3c99ec0d456ca6cd2a7f08f7d4e91771bef51b01bdd9580cc6450fe1251e", size = 3505, upload-time = "2023-08-04T07:54:58.425Z" } wheels = [ @@ -500,15 +500,15 @@ name = "contourpy" version = "1.3.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" } wheels = [ @@ -555,14 +555,14 @@ name = "contourpy" version = "1.3.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", @@ -573,7 +573,7 @@ resolution-markers = [ "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } wheels = [ @@ -611,7 +611,7 @@ name = "convertdate" version = "2.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pymeeus", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "pymeeus", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3a/8d/540bf9cdbcd59352ecf7a1925197881465a6c24fd6171765dc11bbeed19e/convertdate-2.4.1.tar.gz", hash = "sha256:ace904a9d0230742732471748160b99d6ae881c2d0dc9a2463c7a37340c56c91", size = 52505, upload-time = "2026-02-08T00:37:53.812Z" } wheels = [ @@ -673,7 +673,7 @@ wheels = [ [package.optional-dependencies] toml = [ - { name = "tomli", marker = "(python_full_version <= '3.11' and sys_platform == 'darwin') or (python_full_version <= '3.11' and sys_platform == 'linux') or (python_full_version <= '3.11' and sys_platform == 'win32')" }, + { name = "tomli", marker = "(python_full_version <= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version <= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version <= '3.11' and sys_platform == 'win32')" }, ] [[package]] @@ -681,7 +681,7 @@ name = "croniter" version = "6.2.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "python-dateutil", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/df/de/5832661ed55107b8a09af3f0a2e71e0957226a59eb1dcf0a445cce6daf20/croniter-6.2.2.tar.gz", hash = "sha256:ba60832a5ec8e12e51b8691c3309a113d1cf6526bdf1a48150ce8ec7a532d0ab", size = 113762, upload-time = "2026-03-15T08:43:48.112Z" } wheels = [ @@ -693,8 +693,8 @@ name = "cryptography" version = "49.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cffi", marker = "(platform_python_implementation != 'PyPy' and sys_platform == 'darwin') or (platform_python_implementation != 'PyPy' and sys_platform == 'linux') or (platform_python_implementation != 'PyPy' and sys_platform == 'win32')" }, - { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "cffi", marker = "(os_name != 'nt' and platform_python_implementation != 'PyPy' and sys_platform == 'darwin') or (os_name != 'nt' and platform_python_implementation != 'PyPy' and sys_platform == 'linux') or (platform_python_implementation != 'PyPy' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" } wheels = [ @@ -746,29 +746,29 @@ name = "darts" version = "0.45.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "holidays", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "joblib", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "matplotlib", version = "3.10.9", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "matplotlib", version = "3.11.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "narwhals", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "nfoursid", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyod", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "scikit-learn", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "shap", version = "0.49.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'darwin')" }, - { name = "shap", version = "0.51.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "shap", version = "0.52.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "statsmodels", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "xarray", version = "2025.6.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "xarray", version = "2026.4.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "holidays", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "joblib", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "matplotlib", version = "3.10.9", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "matplotlib", version = "3.11.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "narwhals", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "nfoursid", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "pandas", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyod", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "requests", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "scikit-learn", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "shap", version = "0.49.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin')" }, + { name = "shap", version = "0.51.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "shap", version = "0.52.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "statsmodels", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "tqdm", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "xarray", version = "2025.6.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "xarray", version = "2026.4.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3a/b1/cae38a86011799c23ee6baa35c0345a34e3002e4ef0e0685e9a1947e41ff/darts-0.45.0.tar.gz", hash = "sha256:ae59113e56a9798a6f05cfb4c306c6d0d6f356d17dc215cb3956887d54539831", size = 690353, upload-time = "2026-06-19T14:50:34.46Z" } wheels = [ @@ -784,6 +784,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/25/2a75b47cb057b1e164c604fb81ab690a6cdb5e2260ce651194eae90f64a3/deepmerge-2.1.0-py3-none-any.whl", hash = "sha256:8f148339a91d680a75ecb74ade235d9e759a93df373a0b04e9d31c8666cfeb75", size = 14345, upload-time = "2026-06-22T05:46:06.742Z" }, ] +[[package]] +name = "deprecated" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wrapt", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/85/12f0a49a7c4ffb70572b6c2ef13c90c88fd190debda93b23f026b25f9634/deprecated-1.3.1.tar.gz", hash = "sha256:b1b50e0ff0c1fddaa5708a2c6b0a6588bb09b892825ab2b214ac9ea9d92a5223", size = 2932523, upload-time = "2025-10-30T08:19:02.757Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/d0/205d54408c08b13550c733c4b85429e7ead111c7f0014309637425520a9a/deprecated-1.3.1-py2.py3-none-any.whl", hash = "sha256:597bfef186b6f60181535a29fbe44865ce137a5079f295b479886c82729d5f3f", size = 11298, upload-time = "2025-10-30T08:19:00.758Z" }, +] + [[package]] name = "dill" version = "0.4.1" @@ -807,9 +819,9 @@ name = "docutils" version = "0.21.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", @@ -824,14 +836,14 @@ name = "docutils" version = "0.22.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", @@ -851,8 +863,8 @@ name = "email-validator" version = "2.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "dnspython", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "idna", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "dnspython", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "idna", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } wheels = [ @@ -873,7 +885,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -885,9 +897,9 @@ name = "fakeredis" version = "2.36.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "redis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sortedcontainers", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "redis", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sortedcontainers", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0a/ed/86ed74d8829c3bc565025c1c9efaf8518c9165fbf8c9cc2c026c8ed21bd9/fakeredis-2.36.2.tar.gz", hash = "sha256:c37a0b307fae3f27ec7c19e59519e57b8c52782e00303df9075361b5ba441be6", size = 213336, upload-time = "2026-06-17T13:25:38.934Z" } wheels = [ @@ -908,9 +920,9 @@ name = "flake8" version = "7.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "mccabe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pycodestyle", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyflakes", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "mccabe", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pycodestyle", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyflakes", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/37/72/e8d66150c4fcace3c0a450466aa3480506ba2cae7b61e100a2613afc3907/flake8-7.1.1.tar.gz", hash = "sha256:049d058491e228e03e67b390f311bbf88fce2dbaa8fa673e7aea87b7198b8d38", size = 48054, upload-time = "2024-08-04T20:32:44.311Z" } wheels = [ @@ -928,12 +940,12 @@ name = "flask" version = "3.1.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "blinker", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "itsdangerous", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "jinja2", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "werkzeug", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "blinker", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "click", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "itsdangerous", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "jinja2", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "markupsafe", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "werkzeug", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/26/00/35d85dcce6c57fdc871f3867d465d780f302a175ea360f62533f12b27e2b/flask-3.1.3.tar.gz", hash = "sha256:0ef0e52b8a9cd932855379197dd8f94047b359ca0a78695144304cb45f87c9eb", size = 759004, upload-time = "2026-02-19T05:00:57.678Z" } wheels = [ @@ -945,7 +957,7 @@ name = "flask-classful" version = "0.16.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/54/9f/0a2e2144e3e32d1d8e5bd66acb3cb54f76b7072ab832a6be9b7d707d2015/flask_classful-0.16.0.tar.gz", hash = "sha256:9073dc705f59e301da84d981f48bdff1901a5170700b685f42548d6f754156d5", size = 8806, upload-time = "2023-09-07T21:44:49.908Z" } wheels = [ @@ -957,9 +969,9 @@ name = "flask-cors" version = "6.0.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "werkzeug", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "werkzeug", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/47/03/4e464a50860f9adf08b5c1d3479cb8ea1f12af2aa69535c7042c6e628135/flask_cors-6.0.5.tar.gz", hash = "sha256:30c5031552cd59f620ac0c8211dac45b345d3b2df310e7721879e4f46ef9c601", size = 101386, upload-time = "2026-06-08T20:20:17.765Z" } wheels = [ @@ -971,20 +983,40 @@ name = "flask-json" version = "0.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ba/4a/6046e195241772f4b6add3adcd4e820004c6151afc587d8c7d0d4ffeb473/Flask-JSON-0.4.0.tar.gz", hash = "sha256:07945d66024f3b77694ce1db5d1fe83940f2aa3bcad8a608535686be67e4bc48", size = 15899, upload-time = "2023-05-06T07:45:52.873Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/ae/87/3b3ae3ca23dd90b15faa1128c473c1cf16d42e9f95efc5e4a1b77bf22260/Flask_JSON-0.4.0-py3-none-any.whl", hash = "sha256:1c1b87a657daa2179fc19f1ffc78204a716c7c5139673dc5038772db4d9f1988", size = 8714, upload-time = "2023-05-06T07:45:50.883Z" }, ] +[[package]] +name = "flask-limiter" +version = "4.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "limits", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "ordered-set", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4e/98/71780be5d1afb941219c4b48d241d4e246e3062b017caa4e79c4dc71314c/flask_limiter-4.1.1.tar.gz", hash = "sha256:ca11608fc7eec43dcea606964ca07c3bd4ec1ae89043a0f67f717899a4f48106", size = 403198, upload-time = "2025-12-06T17:39:00.575Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/7c/9fe9ffc83be199011bb0c6deb82cdcbc5a355601e380581de9dbc30490dd/flask_limiter-4.1.1-py3-none-any.whl", hash = "sha256:e1ae13e06e6b3e39a4902e7d240b901586b25932c2add7bd5f5eeb4bdc11111b", size = 30554, upload-time = "2025-12-06T17:38:59.162Z" }, +] + +[package.optional-dependencies] +redis = [ + { name = "limits", extra = ["redis"], marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, +] + [[package]] name = "flask-login" version = "0.6.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "werkzeug", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "werkzeug", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c3/6e/2f4e13e373bb49e68c02c51ceadd22d172715a06716f9299d9df01b6ddb2/Flask-Login-0.6.3.tar.gz", hash = "sha256:5e23d14a607ef12806c699590b89d0f0e0d67baeec599d75947bf9c147330333", size = 48834, upload-time = "2023-10-30T14:53:21.151Z" } wheels = [ @@ -996,8 +1028,8 @@ name = "flask-mail" version = "0.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "blinker", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "blinker", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ba/29/e92dc84c675d1e8d260d5768eb3fb65c70cbd33addecf424187587bee862/flask_mail-0.10.0.tar.gz", hash = "sha256:44083e7b02bbcce792209c06252f8569dd5a325a7aaa76afe7330422bd97881d", size = 8152, upload-time = "2024-05-23T22:30:12.612Z" } wheels = [ @@ -1009,16 +1041,16 @@ name = "flask-marshmallow" version = "1.4.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "flask", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "flask", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/09/43/6e5c19e8abc01f5daf1d3c8ad169c495335390572b8bead3f7e7302131c6/flask_marshmallow-1.4.0.tar.gz", hash = "sha256:98c90a253052c72d2ddddc925539ac33bbd780c6fba86478ffe18e3b89d8b471", size = 40970, upload-time = "2026-02-04T16:07:59.916Z" } wheels = [ @@ -1030,14 +1062,14 @@ name = "flask-marshmallow" version = "1.5.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", @@ -1048,8 +1080,8 @@ resolution-markers = [ "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "flask", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "flask", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/65/ca/22f00dffdd6709332247960e0c1223995bc22ff7537834bffc44ab9ab90b/flask_marshmallow-1.5.0.tar.gz", hash = "sha256:7c06b56e41647eccdb3cd57c25b109f19191b4c62509362bd64920cdf601a066", size = 41188, upload-time = "2026-04-16T02:58:30.853Z" } wheels = [ @@ -1061,9 +1093,9 @@ name = "flask-migrate" version = "4.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "alembic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "alembic", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5a/8e/47c7b3c93855ceffc2eabfa271782332942443321a07de193e4198f920cf/flask_migrate-4.1.0.tar.gz", hash = "sha256:1a336b06eb2c3ace005f5f2ded8641d534c18798d64061f6ff11f79e1434126d", size = 21965, upload-time = "2025-01-10T18:51:11.848Z" } wheels = [ @@ -1075,8 +1107,8 @@ name = "flask-principal" version = "0.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "blinker", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "blinker", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/14/c7/2531aca6ab7baa3774fde2dfc9c9dd6d5a42576a1013a93701bfdc402fdd/Flask-Principal-0.4.0.tar.gz", hash = "sha256:f5d6134b5caebfdbb86f32d56d18ee44b080876a27269560a96ea35f75c99453", size = 5452, upload-time = "2013-06-14T18:56:14.264Z" } @@ -1085,14 +1117,14 @@ name = "flask-security-too" version = "5.8.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "email-validator", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-login", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-principal", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-wtf", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "libpass", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "wtforms", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "email-validator", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-login", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-principal", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-wtf", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "libpass", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "markupsafe", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "wtforms", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/16/8b/9b6af966ce15689ad22e9bd51aceffca0b7ab9c47a258bbb9fe69d7bec01/flask_security_too-5.8.1.tar.gz", hash = "sha256:19450675a19055a3229b9ba5447491fa1233b41c0edf4917ea970222a15fc09e", size = 751524, upload-time = "2026-05-21T18:57:36.674Z" } wheels = [ @@ -1101,14 +1133,14 @@ wheels = [ [package.optional-dependencies] fsqla = [ - { name = "flask-sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "flask-sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] mfa = [ - { name = "cryptography", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "phonenumberslite", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "qrcode", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "webauthn", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "cryptography", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "phonenumberslite", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "qrcode", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "webauthn", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] [[package]] @@ -1116,8 +1148,8 @@ name = "flask-sqlalchemy" version = "3.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/91/53/b0a9fcc1b1297f51e68b69ed3b7c3c40d8c45be1391d77ae198712914392/flask_sqlalchemy-3.1.1.tar.gz", hash = "sha256:e4b68bb881802dda1a7d878b2fc84c06d1ee57fb40b874d3dc97dabfa36b8312", size = 81899, upload-time = "2023-09-11T21:42:36.147Z" } wheels = [ @@ -1129,7 +1161,7 @@ name = "flask-sslify" version = "0.1.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/6e/98/54f2ffaf886d25eb1591cfb534c04cbf983236d657d58d180fd9ccbb5e7f/Flask-SSLify-0.1.5.tar.gz", hash = "sha256:d33e1d3c09cd95154176aa8a7319418e52129fc482dd56d8a8ad7c24500d543e", size = 3034, upload-time = "2015-04-02T20:25:24.407Z" } @@ -1138,7 +1170,7 @@ name = "flask-swagger-ui" version = "5.32.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c8/db/06cd2b77fff6c115c37dc8ec4db04ee6e5119799a27c7e19410f0f303c0e/flask_swagger_ui-5.32.6.tar.gz", hash = "sha256:38730cb566e5f1d70deb8bb1035ef1565b35dc50cdfd2a9e507779a751d46930", size = 613730, upload-time = "2026-05-18T10:31:09.328Z" } wheels = [ @@ -1150,9 +1182,9 @@ name = "flask-wtf" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "itsdangerous", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "wtforms", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "itsdangerous", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "wtforms", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/91/f1/605a56d4ea217b307f3e6f4d663e0351253d85d841edc93ba559f0648e19/flask_wtf-1.3.0.tar.gz", hash = "sha256:61d5dabc50c3df885c297dcbd80810443a5d632106c8a69cab8ce740f0cdd7cc", size = 50414, upload-time = "2026-04-23T07:41:55.096Z" } wheels = [ @@ -1164,7 +1196,7 @@ name = "flexcache" version = "0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/55/b0/8a21e330561c65653d010ef112bf38f60890051d244ede197ddaa08e50c1/flexcache-0.3.tar.gz", hash = "sha256:18743bd5a0621bfe2cf8d519e4c3bfdf57a269c15d1ced3fb4b64e0ff4600656", size = 15816, upload-time = "2024-03-09T03:21:07.555Z" } wheels = [ @@ -1175,123 +1207,124 @@ wheels = [ name = "flexmeasures" source = { editable = "." } dependencies = [ - { name = "altair", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "apispec", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "apispec-oneofschema", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "apispec-webframeworks", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "argon2-cffi", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "bcrypt", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "click-default-group", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "cryptography", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "darts", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "email-validator", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-classful", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-cors", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-json", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-login", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-mail", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-marshmallow", version = "1.4.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "flask-marshmallow", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "flask-migrate", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-security-too", extra = ["fsqla", "mfa"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-sslify", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-swagger-ui", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask-wtf", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "highspy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "humanize", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "inflect", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "inflection", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "iso8601", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "isodate", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "lightgbm", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "marshmallow-oneofschema", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "marshmallow-polyfield", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "marshmallow-sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pillow", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pint", version = "0.24.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "pint", version = "0.25.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "psycopg2-binary", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "py-moneyed", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyomo", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyopenssl", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "python-dotenv", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytz", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "redis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "rq", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "rq-dashboard", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "rq-win", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sentry-sdk", extra = ["flask"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tabulate", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "timely-beliefs", extra = ["forecast"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tldextract", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "uniplot", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "urllib3", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "vl-convert-python", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "webargs", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "werkzeug", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "workalendar", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "xlrd", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "altair", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "apispec", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "apispec-oneofschema", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "apispec-webframeworks", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "argon2-cffi", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "bcrypt", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "click", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "click-default-group", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "cryptography", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "darts", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "email-validator", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-classful", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-cors", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-json", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-limiter", extra = ["redis"], marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-login", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-mail", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-marshmallow", version = "1.4.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "flask-marshmallow", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "flask-migrate", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-security-too", extra = ["fsqla", "mfa"], marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-sslify", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-swagger-ui", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask-wtf", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "highspy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "humanize", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "inflect", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "inflection", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "iso8601", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "isodate", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "lightgbm", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow-oneofschema", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "marshmallow-polyfield", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "marshmallow-sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pandas", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pillow", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pint", version = "0.24.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "pint", version = "0.25.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "psycopg2-binary", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "py-moneyed", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pydantic", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyomo", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyopenssl", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "python-dotenv", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytz", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyyaml", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "redis", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "rq", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "rq-dashboard", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "rq-win", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sentry-sdk", extra = ["flask"], marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "tabulate", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "timely-beliefs", extra = ["forecast"], marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "tldextract", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "uniplot", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "urllib3", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "vl-convert-python", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "webargs", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "werkzeug", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "workalendar", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "xlrd", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] [package.dev-dependencies] dev = [ - { name = "black", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flake8", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flake8-blind-except", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "mypy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "poethepoet", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyinstrument", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-runner", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-click", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-pytz", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-redis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-setuptools", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-tabulate", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-tzlocal", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "watchdog", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "black", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flake8", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flake8-blind-except", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "mypy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "poethepoet", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyinstrument", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytest-runner", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-click", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-python-dateutil", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-pytz", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-pyyaml", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-redis", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-requests", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-setuptools", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-tabulate", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-tzlocal", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "watchdog", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] docs = [ - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "sphinx-copybutton", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx-fontawesome", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx-rtd-theme", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx-tabs", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinxcontrib-httpdomain", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinxcontrib-mermaid", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinxcontrib-openapi", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinx-copybutton", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinx-fontawesome", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinx-rtd-theme", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinx-tabs", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinxcontrib-httpdomain", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinxcontrib-mermaid", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinxcontrib-openapi", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] test = [ - { name = "fakeredis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "lupa", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "openpyxl", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-cov", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-mock", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-runner", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-sugar", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "requests-mock", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "fakeredis", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "lupa", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "openpyxl", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytest", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytest-cov", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytest-flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytest-mock", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytest-runner", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytest-sugar", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "requests", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "requests-mock", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] visualize-data-model = [ - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pillow", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sqlalchemy-schemadisplay", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "packaging", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pillow", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sqlalchemy-schemadisplay", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] [package.metadata] @@ -1311,6 +1344,7 @@ requires-dist = [ { name = "flask-classful", specifier = ">=0.16" }, { name = "flask-cors", specifier = ">=6.0.2" }, { name = "flask-json", specifier = ">=0.4.0" }, + { name = "flask-limiter", extras = ["redis"], specifier = ">=4.0" }, { name = "flask-login", specifier = ">=0.6.3" }, { name = "flask-mail", specifier = ">=0.10.0" }, { name = "flask-marshmallow", specifier = ">=1.4.0" }, @@ -1417,7 +1451,7 @@ name = "flexparser" version = "0.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/82/99/b4de7e39e8eaf8207ba1a8fa2241dd98b2ba72ae6e16960d8351736d8702/flexparser-0.4.tar.gz", hash = "sha256:266d98905595be2ccc5da964fe0a2c3526fbbffdc45b65b3146d75db992ef6b2", size = 31799, upload-time = "2024-11-07T02:00:56.249Z" } wheels = [ @@ -1493,8 +1527,8 @@ name = "highspy" version = "1.14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7a/66/e74b1a805f65c52666e3b54cfc1ba783e745c2c8a7abaae9e7ef2d9e7270/highspy-1.14.0.tar.gz", hash = "sha256:b09cb5e3179a25fc615b8b0941130b0f71e19372c119f3dd620d63b54cd3ca4c", size = 1654913, upload-time = "2026-04-06T15:53:31.738Z" } wheels = [ @@ -1535,7 +1569,7 @@ name = "holidays" version = "0.99" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "python-dateutil", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/37/69/7626f743128513c919ed058530d62a86902099532a86222260b0cfc70d7c/holidays-0.99.tar.gz", hash = "sha256:9ef8278cdfb67dbd93309ec9b30c30609ab35fd57cb207ce4593f80dc91196f5", size = 931630, upload-time = "2026-06-15T20:39:42.38Z" } wheels = [ @@ -1574,7 +1608,7 @@ name = "importlib-metadata" version = "9.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "zipp", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a9/01/15bb152d77b21318514a96f43af312635eb2500c96b55398d020c93d86ea/importlib_metadata-9.0.0.tar.gz", hash = "sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc", size = 56405, upload-time = "2026-03-20T06:42:56.999Z" } wheels = [ @@ -1586,8 +1620,8 @@ name = "inflect" version = "7.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "more-itertools", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typeguard", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "more-itertools", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typeguard", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/78/c6/943357d44a21fd995723d07ccaddd78023eace03c1846049a2645d4324a3/inflect-7.5.0.tar.gz", hash = "sha256:faf19801c3742ed5a05a8ce388e0d8fe1a07f8d095c82201eb904f5d27ad571f", size = 73751, upload-time = "2024-12-28T17:11:18.897Z" } wheels = [ @@ -1644,7 +1678,7 @@ name = "jinja2" version = "3.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "markupsafe", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } wheels = [ @@ -1665,11 +1699,11 @@ name = "jsonschema" version = "4.26.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "jsonschema-specifications", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "referencing", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "rpds-py", version = "2026.5.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "attrs", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "jsonschema-specifications", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "referencing", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "rpds-py", version = "2026.5.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } wheels = [ @@ -1681,7 +1715,7 @@ name = "jsonschema-specifications" version = "2025.9.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "referencing", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "referencing", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } wheels = [ @@ -1813,11 +1847,11 @@ name = "lightgbm" version = "4.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/68/0b/a2e9f5c5da7ef047cc60cef37f86185088845e8433e54d2e7ed439cce8a3/lightgbm-4.6.0.tar.gz", hash = "sha256:cb1c59720eb569389c0ba74d14f52351b573af489f230032a1c9f314f8bab7fe", size = 1703705, upload-time = "2025-02-15T04:03:03.111Z" } wheels = [ @@ -1828,6 +1862,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5e/23/f8b28ca248bb629b9e08f877dd2965d1994e1674a03d67cd10c5246da248/lightgbm-4.6.0-py3-none-win_amd64.whl", hash = "sha256:37089ee95664b6550a7189d887dbf098e3eadab03537e411f52c63c121e3ba4b", size = 1451509, upload-time = "2025-02-15T04:03:01.515Z" }, ] +[[package]] +name = "limits" +version = "5.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "deprecated", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "packaging", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/69/826a5d1f45426c68d8f6539f8d275c0e4fcaa57f0c017ec3100986558a41/limits-5.8.0.tar.gz", hash = "sha256:c9e0d74aed837e8f6f50d1fcebcf5fd8130957287206bc3799adaee5092655da", size = 226104, upload-time = "2026-02-05T07:17:35.859Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/98/cb5ca20618d205a09d5bec7591fbc4130369c7e6308d9a676a28ff3ab22c/limits-5.8.0-py3-none-any.whl", hash = "sha256:ae1b008a43eb43073c3c579398bd4eb4c795de60952532dc24720ab45e1ac6b8", size = 60954, upload-time = "2026-02-05T07:17:34.425Z" }, +] + +[package.optional-dependencies] +redis = [ + { name = "redis", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, +] + [[package]] name = "llvmlite" version = "0.47.0" @@ -1911,7 +1964,7 @@ name = "mako" version = "1.3.12" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "markupsafe", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/00/62/791b31e69ae182791ec67f04850f2f062716bbd205483d63a215f3e062d3/mako-1.3.12.tar.gz", hash = "sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a", size = 400219, upload-time = "2026-04-28T19:01:08.512Z" } wheels = [ @@ -1964,15 +2017,15 @@ name = "marshmallow" version = "3.26.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "packaging", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/55/79/de6c16cc902f4fc372236926b0ce2ab7845268dcc30fb2fbb7f71b418631/marshmallow-3.26.2.tar.gz", hash = "sha256:bbe2adb5a03e6e3571b573f42527c6fe926e17467833660bebd11593ab8dfd57", size = 222095, upload-time = "2025-12-22T06:53:53.309Z" } wheels = [ @@ -1984,14 +2037,14 @@ name = "marshmallow" version = "4.3.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", @@ -2011,8 +2064,8 @@ name = "marshmallow-oneofschema" version = "3.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/bb/42/a0e00dea6a831acfe9d3fe664d695b7cefc02c27dd69d9ccb4bdc3c3d1a7/marshmallow_oneofschema-3.2.0.tar.gz", hash = "sha256:c06c8d9f14d51ffff152d66d85bd5f27d55cff10752a3b1f8c1f948bf5f597a0", size = 9096, upload-time = "2025-05-08T13:49:34.798Z" } wheels = [ @@ -2024,8 +2077,8 @@ name = "marshmallow-polyfield" version = "5.11" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0e/55/b752d034a09afe34d680c65cf8634c0c55f9b57e7a673774bc13ca44b53e/marshmallow-polyfield-5.11.tar.gz", hash = "sha256:8075a9cc490da4af58b902b4a40a99882dd031adb7aaa96abd147a4fcd53415f", size = 8596, upload-time = "2022-10-26T03:10:40.661Z" } @@ -2034,9 +2087,9 @@ name = "marshmallow-sqlalchemy" version = "1.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ee/fe/247c297809e64116f766716632adbc3f4cd06f376f56dc15bb92f170d247/marshmallow_sqlalchemy-1.5.0.tar.gz", hash = "sha256:e51192c204770645a2fab0d72f44f8789272eef75951f84b1608d6b4b0bfe0e6", size = 51349, upload-time = "2026-04-01T23:21:03.833Z" } wheels = [ @@ -2048,23 +2101,23 @@ name = "matplotlib" version = "3.10.9" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "contourpy", version = "1.3.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "cycler", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "fonttools", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "kiwisolver", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "packaging", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "pillow", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "pyparsing", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "python-dateutil", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "contourpy", version = "1.3.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "cycler", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "fonttools", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "kiwisolver", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "pillow", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "pyparsing", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "python-dateutil", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/63/1b/4be5be87d43d327a0cf4de1a56e86f7f84c89312452406cf122efe2839e6/matplotlib-3.10.9.tar.gz", hash = "sha256:fd66508e8c6877d98e586654b608a0456db8d7e8a546eb1e2600efd957302358", size = 34811233, upload-time = "2026-04-24T00:14:13.539Z" } wheels = [ @@ -2101,14 +2154,14 @@ name = "matplotlib" version = "3.11.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", @@ -2119,15 +2172,15 @@ resolution-markers = [ "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "contourpy", version = "1.3.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "cycler", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "fonttools", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "kiwisolver", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "packaging", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "pillow", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "pyparsing", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "python-dateutil", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "contourpy", version = "1.3.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "cycler", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "fonttools", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "kiwisolver", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "pillow", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "pyparsing", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "python-dateutil", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1f/24/080c99d223d158d3a8902769269ab6da5b50f7a0e6e072513907e02b7a6c/matplotlib-3.11.0.tar.gz", hash = "sha256:68c0c7be01b30dcca3638934f7f591df73401235cbdbf0d1ab1c71e7db7f8b57", size = 33251176, upload-time = "2026-06-12T02:29:15.508Z" } wheels = [ @@ -2164,7 +2217,7 @@ name = "mistune" version = "3.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/10/55/ede164a9ff68694455bf42217e9e75b174e4048436688cfff7b382ae486c/mistune-3.3.1.tar.gz", hash = "sha256:7d2108b532850ab81d3e92a5566abe1168f4f27c0c9dbe914e02d1d06e2a0288", size = 111268, upload-time = "2026-06-22T01:32:05.843Z" } wheels = [ @@ -2185,12 +2238,12 @@ name = "mypy" version = "2.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ast-serialize", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "librt", marker = "(platform_python_implementation != 'PyPy' and sys_platform == 'darwin') or (platform_python_implementation != 'PyPy' and sys_platform == 'linux') or (platform_python_implementation != 'PyPy' and sys_platform == 'win32')" }, - { name = "mypy-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pathspec", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "ast-serialize", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "librt", marker = "(os_name != 'nt' and platform_python_implementation != 'PyPy' and sys_platform == 'darwin') or (os_name != 'nt' and platform_python_implementation != 'PyPy' and sys_platform == 'linux') or (platform_python_implementation != 'PyPy' and sys_platform == 'win32')" }, + { name = "mypy-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pathspec", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "tomli", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/82/15/cca9d88503549ed6fedeaa1d448cdddd542ee8a490232d732e278036fbf2/mypy-2.1.0.tar.gz", hash = "sha256:81e76ad12c2d804512e9b13240d1588316531bfba07558286078bfbce9613633", size = 3898359, upload-time = "2026-05-11T18:37:36.237Z" } wheels = [ @@ -2241,11 +2294,11 @@ name = "nfoursid" version = "1.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "matplotlib", version = "3.10.9", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "matplotlib", version = "3.11.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "matplotlib", version = "3.10.9", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "matplotlib", version = "3.11.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "pandas", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ab/36/1c0543d9c5ca3a692ea5244de68a74776e38e49b77b6ddb1ec3e8e28beca/nfoursid-1.0.2.tar.gz", hash = "sha256:d65ba1bb98715f6310d0136aecdc997313caa239c08cc95f7e48378f77d06a24", size = 15475, upload-time = "2025-07-24T13:01:40.167Z" } wheels = [ @@ -2257,9 +2310,9 @@ name = "numba" version = "0.65.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "llvmlite", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "llvmlite", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f6/c5/db2ac3685833d626c0dcae6bd2330cd68433e1fd248d15f70998160d3ad7/numba-0.65.1.tar.gz", hash = "sha256:19357146c32fe9ed25059ab915e8465fb13951cf6b0aace3826b76886373ab23", size = 2765600, upload-time = "2026-04-24T02:02:56.551Z" } wheels = [ @@ -2282,9 +2335,9 @@ name = "numpy" version = "2.2.6" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", @@ -2332,14 +2385,14 @@ name = "numpy" version = "2.4.6" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", @@ -2387,7 +2440,7 @@ name = "openpyxl" version = "3.1.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "et-xmlfile", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "et-xmlfile", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3d/f9/88d94a75de065ea32619465d2f77b29a0469500e99012523b91cc4141cd1/openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050", size = 186464, upload-time = "2024-06-28T14:03:44.161Z" } wheels = [ @@ -2399,8 +2452,8 @@ name = "openturns" version = "1.27.post1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "dill", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "psutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "dill", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "psutil", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/18/cc/659945cbc51ccfebf4b341dbd441190d192ff0bd895fa9768df389e4c6f4/openturns-1.27.post1-cp39-abi3-macosx_14_0_arm64.whl", hash = "sha256:e547db66d27550a93f01bbf863a97b85fde7c31e7daa99e555f3bb40c259c57e", size = 46865937, upload-time = "2026-06-19T07:39:15.578Z" }, @@ -2409,6 +2462,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/65/94/f0eca064d559317e48cab6f6dacbcc6c9416ba724ad79ac7a06e5a494d75/openturns-1.27.post1-cp39-abi3-win_amd64.whl", hash = "sha256:e8ae8667c611c06d5b8540d922cb7c0441428896244e7c0ca9b4ea8807697c2a", size = 65433628, upload-time = "2026-06-18T06:45:24.817Z" }, ] +[[package]] +name = "ordered-set" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/ca/bfac8bc689799bcca4157e0e0ced07e70ce125193fc2e166d2e685b7e2fe/ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8", size = 12826, upload-time = "2022-01-26T14:38:56.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/55/af02708f230eb77084a299d7b08175cff006dea4f2721074b92cdb0296c0/ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562", size = 7634, upload-time = "2022-01-26T14:38:48.677Z" }, +] + [[package]] name = "packaging" version = "26.2" @@ -2423,11 +2485,11 @@ name = "pandas" version = "2.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytz", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tzdata", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "python-dateutil", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytz", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "tzdata", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } wheels = [ @@ -2477,8 +2539,8 @@ name = "patsy" version = "1.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/be/44/ed13eccdd0519eff265f44b670d46fbb0ec813e2274932dc1c0e48520f7d/patsy-1.0.2.tar.gz", hash = "sha256:cdc995455f6233e90e22de72c37fcadb344e7586fb83f06696f54d92f8ce74c0", size = 399942, upload-time = "2025-10-20T16:17:37.535Z" } wheels = [ @@ -2556,18 +2618,18 @@ name = "pint" version = "0.24.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "flexcache", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "flexparser", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "platformdirs", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "flexcache", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "flexparser", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "platformdirs", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/20/bb/52b15ddf7b7706ed591134a895dbf6e41c8348171fb635e655e0a4bbb0ea/pint-0.24.4.tar.gz", hash = "sha256:35275439b574837a6cd3020a5a4a73645eb125ce4152a73a2f126bf164b91b80", size = 342225, upload-time = "2024-11-07T16:29:46.061Z" } wheels = [ @@ -2579,14 +2641,14 @@ name = "pint" version = "0.25.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", @@ -2597,10 +2659,10 @@ resolution-markers = [ "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "flexcache", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "flexparser", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "platformdirs", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "typing-extensions", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "flexcache", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "flexparser", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "platformdirs", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/52/9d/b1379cdbd33a49d17d627bc24e2b63cca06a1c5343b38072d2889499e82e/pint-0.25.3.tar.gz", hash = "sha256:f8f5df6cf65314d74da1ade1bf96f8e3e4d0c41b51577ac53c49e7d44ca5acee", size = 255106, upload-time = "2026-03-19T21:57:08.72Z" } wheels = [ @@ -2639,9 +2701,9 @@ name = "poethepoet" version = "0.46.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pastel", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "pastel", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyyaml", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "tomli", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3b/f5/d501fcb67e450fd3fae9db06050420c0c6043758cfa8c30ba40278211265/poethepoet-0.46.0.tar.gz", hash = "sha256:daf8469031879ef59ef0b34fdba83574d65e41eb9186e20cd0f7c89ce479b030", size = 117276, upload-time = "2026-05-15T15:52:02.548Z" } wheels = [ @@ -2653,11 +2715,11 @@ name = "properscoring" version = "0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/38/ac/513d2c8653ab6bc66c4502372e6e4e20ce6a136cde4c1ba9908ec36e34c1/properscoring-0.1.tar.gz", hash = "sha256:b0cc4963cc218b728d6c5f77b3259c8f835ae00e32e82678cdf6936049b93961", size = 17848, upload-time = "2015-11-12T19:54:29.615Z" } wheels = [ @@ -2726,8 +2788,8 @@ name = "py-moneyed" version = "3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "babel", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "babel", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/2c/d9/cb6f113d2b7cf930bb3963d2b84ee245c20f93f9afc2e41adece58d324ae/py-moneyed-3.0.tar.gz", hash = "sha256:4906f0f02cf2b91edba2e156f2d4e9a78f224059ab8c8fa2ff26230c75d894e8", size = 20385, upload-time = "2022-11-27T21:29:38.564Z" } wheels = [ @@ -2748,7 +2810,7 @@ name = "pyasn1-modules" version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pyasn1", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "pyasn1", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } wheels = [ @@ -2778,10 +2840,10 @@ name = "pydantic" version = "2.13.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "annotated-types", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pydantic-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typing-inspection", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "annotated-types", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pydantic-core", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typing-inspection", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } wheels = [ @@ -2793,7 +2855,7 @@ name = "pydantic-core" version = "2.46.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } wheels = [ @@ -2864,7 +2926,7 @@ name = "pydot" version = "4.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pyparsing", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "pyparsing", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/35/b17cb89ff865484c6a20ef46bf9d95a5f07328292578de0b295f4a6beec2/pydot-4.0.1.tar.gz", hash = "sha256:c2148f681c4a33e08bf0e26a9e5f8e4099a82e0e2a068098f32ce86577364ad5", size = 162594, upload-time = "2025-06-17T20:09:56.454Z" } wheels = [ @@ -2941,16 +3003,16 @@ name = "pyod" version = "3.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "joblib", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "matplotlib", version = "3.10.9", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "matplotlib", version = "3.11.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "numba", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "scikit-learn", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "joblib", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "matplotlib", version = "3.10.9", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "matplotlib", version = "3.11.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "numba", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "scikit-learn", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/98/e6/462a2947437ff5acfc8de698630693d73f58355b4b5b69cda00d98c0ab59/pyod-3.6.1.tar.gz", hash = "sha256:a3081ec589d0d99d33b84efe8da1b82ae22022fd83f3721f30b19ac950f427c3", size = 351105, upload-time = "2026-06-17T02:46:35.823Z" } wheels = [ @@ -2962,7 +3024,7 @@ name = "pyomo" version = "6.8.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ply", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "ply", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c8/bf/29450fb25c87e7f37815190805e8f7af57ef259f6721bfed51ee547b5b44/Pyomo-6.8.2.tar.gz", hash = "sha256:40d8f7b216ad1602bb254f4296591608dd94fe2c961dc1e63ca6b84fb397bed6", size = 2877062, upload-time = "2024-11-18T22:55:21.872Z" } wheels = [ @@ -2988,8 +3050,8 @@ name = "pyopenssl" version = "26.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "cryptography", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/74/b7/da07bae88f5a9506b4def6f2f4903cf4c3b8831e560dba8fa18ca08f758f/pyopenssl-26.3.0.tar.gz", hash = "sha256:589de7fae1c9ea670d18422ed00fc04da787bbde8e1454aea872aa57b49ad341", size = 182024, upload-time = "2026-06-12T20:28:07.458Z" } wheels = [ @@ -3011,12 +3073,12 @@ version = "9.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "iniconfig", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pluggy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pygments", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "exceptiongroup", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "iniconfig", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "packaging", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pluggy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pygments", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "tomli", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ @@ -3028,9 +3090,9 @@ name = "pytest-cov" version = "7.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "coverage", extra = ["toml"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pluggy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "coverage", extra = ["toml"], marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pluggy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytest", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" } wheels = [ @@ -3042,9 +3104,9 @@ name = "pytest-flask" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "werkzeug", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytest", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "werkzeug", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/fb/23/32b36d2f769805c0f3069ca8d9eeee77b27fcf86d41d40c6061ddce51c7d/pytest-flask-1.3.0.tar.gz", hash = "sha256:58be1c97b21ba3c4d47e0a7691eb41007748506c36bf51004f78df10691fa95e", size = 35816, upload-time = "2023-10-23T14:53:20.696Z" } wheels = [ @@ -3056,7 +3118,7 @@ name = "pytest-mock" version = "3.15.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "pytest", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" } wheels = [ @@ -3077,8 +3139,8 @@ name = "pytest-sugar" version = "1.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "termcolor", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "pytest", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "termcolor", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/4e/60fed105549297ba1a700e1ea7b828044842ea27d72c898990510b79b0e2/pytest-sugar-1.1.1.tar.gz", hash = "sha256:73b8b65163ebf10f9f671efab9eed3d56f20d2ca68bda83fa64740a92c08f65d", size = 16533, upload-time = "2025-08-23T12:19:35.737Z" } wheels = [ @@ -3090,7 +3152,7 @@ name = "python-dateutil" version = "2.9.0.post0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "six", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "six", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } wheels = [ @@ -3174,14 +3236,14 @@ wheels = [ [[package]] name = "redis" -version = "8.0.0" +version = "7.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "async-timeout", marker = "(python_full_version < '3.11.3' and sys_platform == 'darwin') or (python_full_version < '3.11.3' and sys_platform == 'linux') or (python_full_version < '3.11.3' and sys_platform == 'win32')" }, + { name = "async-timeout", marker = "(python_full_version < '3.11.3' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11.3' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11.3' and sys_platform == 'win32')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/53/ae/ed461cca5780b5fc8b9fe8ca0ed98d89508645fb9d880c24cc42c087678f/redis-8.0.0.tar.gz", hash = "sha256:a00c5355432051ac14e593b8b197fc76c887ee12d55a0984f69328a1115fdc49", size = 5101591, upload-time = "2026-05-28T12:45:13.5Z" } +sdist = { url = "https://files.pythonhosted.org/packages/51/93/05e7d4a65285066a74f48697f9b9cde5cfce71398033d69ed83c3d98f5c9/redis-7.4.1.tar.gz", hash = "sha256:1a1df5067062cf7cbe677994e391f8ee0840f499d370f1a71266e0dd3aa9308e", size = 4945742, upload-time = "2026-06-05T09:10:06.703Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/27/e3/b519734372d305bd547534a9f32e4ce9f98552af753dce72cf3483a0ff0b/redis-8.0.0-py3-none-any.whl", hash = "sha256:c938c18338585009f0bc310f4c7e4e4b4d37639356c4ac072cedf3af570c8dc7", size = 499870, upload-time = "2026-05-28T12:45:11.697Z" }, + { url = "https://files.pythonhosted.org/packages/4a/2e/2677f3f93dae0497e7e33b6637302e7f3744efc553f34231183e32584885/redis-7.4.1-py3-none-any.whl", hash = "sha256:1fa4647af1c5e93a2c685aa248ee44cce092691146d41390518dabe9a99839b0", size = 410171, upload-time = "2026-06-05T09:10:05.128Z" }, ] [[package]] @@ -3189,7 +3251,7 @@ name = "redis-sentinel-url" version = "1.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "redis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "redis", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cc/e3/68de4c8aacbd9952667d7d0f5af55b873553a09a6227ac5b7f7c622610c9/Redis-Sentinel-Url-1.0.1.tar.gz", hash = "sha256:ec1854ab9379a28789423c3cd4082739fb69c7b4b11bb50ae7858697c131b13e", size = 7599, upload-time = "2017-04-05T07:47:55.456Z" } wheels = [ @@ -3201,10 +3263,10 @@ name = "referencing" version = "0.37.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "rpds-py", version = "2026.5.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "attrs", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "rpds-py", version = "2026.5.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } wheels = [ @@ -3216,10 +3278,10 @@ name = "requests" version = "2.34.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "certifi", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "charset-normalizer", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "idna", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "urllib3", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "certifi", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "charset-normalizer", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "idna", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "urllib3", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } wheels = [ @@ -3231,7 +3293,7 @@ name = "requests-file" version = "3.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "requests", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3c/f8/5dc70102e4d337063452c82e1f0d95e39abfe67aa222ed8a5ddeb9df8de8/requests_file-3.0.1.tar.gz", hash = "sha256:f14243d7796c588f3521bd423c5dea2ee4cc730e54a3cac9574d78aca1272576", size = 6967, upload-time = "2025-10-20T18:56:42.279Z" } wheels = [ @@ -3243,7 +3305,7 @@ name = "requests-mock" version = "1.12.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "requests", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/92/32/587625f91f9a0a3d84688bf9cfc4b2480a7e8ec327cefd0ff2ac891fd2cf/requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401", size = 60901, upload-time = "2024-03-29T03:54:29.446Z" } wheels = [ @@ -3264,9 +3326,9 @@ name = "rpds-py" version = "0.30.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", @@ -3336,14 +3398,14 @@ name = "rpds-py" version = "2026.5.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", @@ -3404,9 +3466,9 @@ name = "rq" version = "2.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "croniter", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "redis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "click", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "croniter", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "redis", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cc/a8/7bf65cda593feb5888214a4d1e64aae6fc5eb0bbbb74df922c916099a3e5/rq-2.10.0.tar.gz", hash = "sha256:2d8c533dd27500fedabec06295f18db595966e4f22744e6988fe31155b8f7a21", size = 754610, upload-time = "2026-06-20T03:11:45.919Z" } wheels = [ @@ -3418,11 +3480,11 @@ name = "rq-dashboard" version = "0.8.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "arrow", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "redis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "redis-sentinel-url", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "rq", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "arrow", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "redis", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "redis-sentinel-url", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "rq", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/51/73/2e4347593d50bed8dcf0ba89ac180133f04de056fc9f7c701cfd56988f9a/rq_dashboard-0.8.7.tar.gz", hash = "sha256:068964cd677787586724ae71d051c4c963fdd5ea86515f1b42357bf983253951", size = 210994, upload-time = "2026-05-26T05:06:08.925Z" } wheels = [ @@ -3434,8 +3496,8 @@ name = "rq-win" version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "rq", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "times", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "rq", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "times", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/6f/fe/92187f1ebb14760299e401e29ed6c1f4f3d415ed130fbc1575f148689242/rq_win-0.4.2.tar.gz", hash = "sha256:f7c4a573a225ffc48044050d6b2b188e8423ffaec318d80af94462b6751f9478", size = 4550, upload-time = "2025-06-09T07:47:34.642Z" } wheels = [ @@ -3456,13 +3518,13 @@ name = "scikit-learn" version = "1.7.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "joblib", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "threadpoolctl", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "joblib", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "threadpoolctl", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/98/c2/a7855e41c9d285dfe86dc50b250978105dce513d6e459ea66a6aeb0e1e0c/scikit_learn-1.7.2.tar.gz", hash = "sha256:20e9e49ecd130598f1ca38a1d85090e1a600147b9c02fa6f15d69cb53d968fda", size = 7193136, upload-time = "2025-09-09T08:21:29.075Z" } wheels = [ @@ -3488,15 +3550,15 @@ name = "scipy" version = "1.15.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" } wheels = [ @@ -3534,17 +3596,17 @@ name = "scipy" version = "1.17.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'win32')", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0", size = 30573822, upload-time = "2026-02-23T00:26:24.851Z" } wheels = [ @@ -3575,17 +3637,17 @@ name = "scipy" version = "1.18.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'win32')", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a7/25/c2700dfaf6442b4effaa91af24ebce5dc9d31bb4a69706313aae70d72cd0/scipy-1.18.0.tar.gz", hash = "sha256:67b2ad2ad54c72ca6d04975a9b2df8c3638c34ddd5b28738e94fc2b57929d378", size = 30774447, upload-time = "2026-06-19T15:01:43.456Z" } wheels = [ @@ -3606,8 +3668,8 @@ name = "sentry-sdk" version = "2.63.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "certifi", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "urllib3", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "certifi", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "urllib3", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ba/c8/b3c970a5b186722d276cd40a05b3254e03bccc0208560aff20f612e018e8/sentry_sdk-2.63.0.tar.gz", hash = "sha256:2a1502bf864769275dbc8c2c9fc7a0f7f5e18358180b615d262d13a31ffba216", size = 912449, upload-time = "2026-06-16T12:45:57.553Z" } wheels = [ @@ -3616,9 +3678,9 @@ wheels = [ [package.optional-dependencies] flask = [ - { name = "blinker", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "blinker", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "flask", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "markupsafe", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] [[package]] @@ -3635,31 +3697,31 @@ name = "shap" version = "0.49.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "cloudpickle", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'darwin')" }, - { name = "numba", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'darwin')" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and platform_machine == 'x86_64' and sys_platform == 'darwin'" }, - { name = "packaging", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'darwin')" }, - { name = "pandas", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'darwin')" }, - { name = "scikit-learn", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'darwin')" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*' and platform_machine == 'x86_64' and sys_platform == 'darwin'" }, - { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' and platform_machine == 'x86_64' and sys_platform == 'darwin'" }, - { name = "slicer", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'darwin')" }, - { name = "tqdm", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'darwin')" }, - { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'darwin')" }, + { name = "cloudpickle", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin')" }, + { name = "numba", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin'" }, + { name = "packaging", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin')" }, + { name = "pandas", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin')" }, + { name = "scikit-learn", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin')" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*' and os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin'" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' and os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin'" }, + { name = "slicer", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin')" }, + { name = "tqdm", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin')" }, + { name = "typing-extensions", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/dc/c6/9823a7f483aa9f3179fc359c10d22da9e418b1a7a3fc99a42b705d05e82a/shap-0.49.1.tar.gz", hash = "sha256:1114ecd804fff29f50d522ce6031082fcf42fe4a32fb1b5da233b2415d784c8c", size = 4084725, upload-time = "2025-10-14T10:04:49.75Z" } wheels = [ @@ -3688,25 +3750,25 @@ name = "shap" version = "0.51.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'win32')", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "cloudpickle", marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "llvmlite", marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "numba", marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "packaging", marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "pandas", marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "scikit-learn", marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "slicer", marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "tqdm", marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "typing-extensions", marker = "(python_full_version == '3.11.*' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "cloudpickle", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "llvmlite", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "numba", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "pandas", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "scikit-learn", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "slicer", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "tqdm", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a4/0a/4a3ee4b1a3654f2a9ae038a64bb3e91a42af3da07577d69b65241f010970/shap-0.51.0.tar.gz", hash = "sha256:cfa17ff213657c9d50285aa923d79b0037a62e2ee1a31bc3eec7e196b00bdb59", size = 4108336, upload-time = "2026-03-04T09:18:19.985Z" } wheels = [ @@ -3731,24 +3793,24 @@ name = "shap" version = "0.52.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'win32')", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "cloudpickle", marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "llvmlite", marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "numba", marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "packaging", marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "pandas", marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "scikit-learn", marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "slicer", marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "tqdm", marker = "(python_full_version >= '3.12' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "cloudpickle", marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "llvmlite", marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "numba", marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "pandas", marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "scikit-learn", marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "slicer", marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "tqdm", marker = "(python_full_version >= '3.12' and os_name != 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/fc/0a/aa278f42c08cb47f2bb503085be0c521da2886929c6605b6105748a7590f/shap-0.52.0.tar.gz", hash = "sha256:81d4ae478f67f8122de1bb411dc4e3ddff0604cbc27dc9cb8ea66d5c73462fd2", size = 4192842, upload-time = "2026-05-28T14:17:49.011Z" } wheels = [ @@ -3775,16 +3837,16 @@ name = "sktime" version = "1.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "joblib", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "scikit-base", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "scikit-learn", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "joblib", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pandas", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "scikit-base", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "scikit-learn", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e6/7f/7eb6441625dc3c5d66f71d3b40b6f5c24de3c758f71aa57792656b3ae166/sktime-1.0.1.tar.gz", hash = "sha256:3cc20576a03d46447e935c3d3512450ffd5b65ee0320af65db5ff71f4373d453", size = 36261136, upload-time = "2026-06-11T20:53:15.797Z" } wheels = [ @@ -3823,31 +3885,31 @@ name = "sphinx" version = "8.1.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "alabaster", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "babel", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "alabaster", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "babel", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, { name = "colorama", marker = "python_full_version < '3.11' and sys_platform == 'win32'" }, - { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "imagesize", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "jinja2", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "packaging", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "pygments", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "requests", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "snowballstemmer", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-applehelp", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-devhelp", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-htmlhelp", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-jsmath", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-qthelp", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-serializinghtml", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "tomli", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "imagesize", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "jinja2", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "pygments", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "requests", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "snowballstemmer", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-applehelp", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-devhelp", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-htmlhelp", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-jsmath", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-qthelp", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-serializinghtml", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "tomli", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611, upload-time = "2024-10-13T20:27:13.93Z" } wheels = [ @@ -3859,33 +3921,33 @@ name = "sphinx" version = "9.0.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'win32')", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "alabaster", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "babel", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "alabaster", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "babel", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, { name = "colorama", marker = "python_full_version == '3.11.*' and sys_platform == 'win32'" }, - { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "imagesize", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "jinja2", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "packaging", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "pygments", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "requests", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "roman-numerals", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "snowballstemmer", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-applehelp", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-devhelp", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-htmlhelp", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-jsmath", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-qthelp", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-serializinghtml", marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "imagesize", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "jinja2", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "pygments", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "requests", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "roman-numerals", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "snowballstemmer", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-applehelp", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-devhelp", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-htmlhelp", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-jsmath", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-qthelp", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-serializinghtml", marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/50/a8c6ccc36d5eacdfd7913ddccd15a9cee03ecafc5ee2bc40e1f168d85022/sphinx-9.0.4.tar.gz", hash = "sha256:594ef59d042972abbc581d8baa577404abe4e6c3b04ef61bd7fc2acbd51f3fa3", size = 8710502, upload-time = "2025-12-04T07:45:27.343Z" } wheels = [ @@ -3897,33 +3959,33 @@ name = "sphinx" version = "9.1.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'win32')", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "alabaster", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "babel", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "alabaster", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "babel", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, { name = "colorama", marker = "python_full_version >= '3.12' and sys_platform == 'win32'" }, - { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "imagesize", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "jinja2", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "packaging", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "pygments", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "requests", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "roman-numerals", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "snowballstemmer", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-applehelp", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-devhelp", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-htmlhelp", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-jsmath", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-qthelp", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-serializinghtml", marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "imagesize", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "jinja2", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "pygments", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "requests", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "roman-numerals", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "snowballstemmer", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-applehelp", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-devhelp", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-htmlhelp", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-jsmath", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-qthelp", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-serializinghtml", marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cd/bd/f08eb0f4eed5c83f1ba2a3bd18f7745a2b1525fad70660a1c00224ec468a/sphinx-9.1.0.tar.gz", hash = "sha256:7741722357dd75f8190766926071fed3bdc211c74dd2d7d4df5404da95930ddb", size = 8718324, upload-time = "2025-12-31T15:09:27.646Z" } wheels = [ @@ -3935,9 +3997,9 @@ name = "sphinx-copybutton" version = "0.5.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/fc/2b/a964715e7f5295f77509e59309959f4125122d648f86b4fe7d70ca1d882c/sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd", size = 23039, upload-time = "2023-04-14T08:10:22.998Z" } wheels = [ @@ -3949,9 +4011,9 @@ name = "sphinx-fontawesome" version = "0.0.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e0/c5/9c14765c7f4721a7df3dc3710e3ce041b0042f91c8c75991434405657c30/sphinx_fontawesome-0.0.6.tar.gz", hash = "sha256:fa38d32f1654ad61f442096965f4069c074f37d7f2fadfa37f46b393938a5bdb", size = 22385, upload-time = "2017-09-24T10:41:17.113Z" } @@ -3960,13 +4022,13 @@ name = "sphinx-mdinclude" version = "0.6.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "mistune", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pygments", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "mistune", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pygments", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b6/a7/c9a7888bb2187fdb06955d71e75f6f266b7e179b356ac76138d160a5b7eb/sphinx_mdinclude-0.6.2.tar.gz", hash = "sha256:447462e82cb8be61404a2204227f920769eb923d2f57608e3325f3bb88286b4c", size = 65257, upload-time = "2024-08-03T19:07:37.643Z" } wheels = [ @@ -3978,12 +4040,12 @@ name = "sphinx-rtd-theme" version = "3.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "sphinxcontrib-jquery", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinxcontrib-jquery", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/84/68/a1bfbf38c0f7bccc9b10bbf76b94606f64acb1552ae394f0b8285bfaea25/sphinx_rtd_theme-3.1.0.tar.gz", hash = "sha256:b44276f2c276e909239a4f6c955aa667aaafeb78597923b1c60babc76db78e4c", size = 7620915, upload-time = "2026-01-12T16:03:31.17Z" } wheels = [ @@ -3995,12 +4057,12 @@ name = "sphinx-tabs" version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "pygments", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "docutils", version = "0.22.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "pygments", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ce/30/ca5b0de830f369968d8e3483dd45a8908fd10169c05cd9837f0bd075982e/sphinx_tabs-3.5.0.tar.gz", hash = "sha256:91dba1187e4c35fd37380a56ac228bbd54c6c649b2351829f3bf033718277537", size = 17006, upload-time = "2026-03-03T23:00:30.404Z" } wheels = [ @@ -4039,9 +4101,9 @@ name = "sphinxcontrib-httpdomain" version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/76/a2/b9b96904f691a0b4ccb8277a72b4ec351590286b44a433d0cefe78703c2b/sphinxcontrib_httpdomain-2.0.0.tar.gz", hash = "sha256:9e4e8733bf41ee4d9d5f9eb4dbf3cc2c22a665221ba42c5c3ae181b98af8855d", size = 17155, upload-time = "2026-02-04T21:23:56.422Z" } wheels = [ @@ -4053,9 +4115,9 @@ name = "sphinxcontrib-jquery" version = "4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/de/f3/aa67467e051df70a6330fe7770894b3e4f09436dea6881ae0b4f3d87cad8/sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a", size = 122331, upload-time = "2023-03-14T15:01:01.944Z" } wheels = [ @@ -4076,11 +4138,11 @@ name = "sphinxcontrib-mermaid" version = "2.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "jinja2", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "jinja2", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyyaml", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/19/75/3a1cc926da8c563c58ddc124a7b3fe5ccadcae96c96e3a6f8ac3653a210a/sphinxcontrib_mermaid-2.0.2.tar.gz", hash = "sha256:f09576c78ca93fa0e3034fd9c45aaffa7c44ab449de9c43b8b8d262afe52bc66", size = 19265, upload-time = "2026-05-05T13:59:02.959Z" } wheels = [ @@ -4092,15 +4154,15 @@ name = "sphinxcontrib-openapi" version = "0.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "deepmerge", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "jsonschema", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "picobox", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "sphinx-mdinclude", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinxcontrib-httpdomain", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "deepmerge", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "jsonschema", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "picobox", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyyaml", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "sphinx", version = "9.1.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sphinx-mdinclude", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sphinxcontrib-httpdomain", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/bec7b89e981cc5ee18ccc5dd966257203bae8ceb893bfa7cc7e44f0df2e0/sphinxcontrib_openapi-0.9.0.tar.gz", hash = "sha256:c3c445a13c99706d8837b21b78e1caa8be5eb16b8f83a297a1fdf19f1c31d487", size = 95302, upload-time = "2026-02-10T18:41:24.543Z" } wheels = [ @@ -4130,8 +4192,8 @@ name = "sqlalchemy" version = "2.0.51" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "greenlet", marker = "(platform_machine == 'AMD64' and sys_platform == 'darwin') or (platform_machine == 'WIN32' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and sys_platform == 'darwin') or (platform_machine == 'amd64' and sys_platform == 'darwin') or (platform_machine == 'ppc64le' and sys_platform == 'darwin') or (platform_machine == 'win32' and sys_platform == 'darwin') or (platform_machine == 'x86_64' and sys_platform == 'darwin') or (platform_machine == 'AMD64' and sys_platform == 'linux') or (platform_machine == 'WIN32' and sys_platform == 'linux') or (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'amd64' and sys_platform == 'linux') or (platform_machine == 'ppc64le' and sys_platform == 'linux') or (platform_machine == 'win32' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'WIN32' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'win32') or (platform_machine == 'amd64' and sys_platform == 'win32') or (platform_machine == 'ppc64le' and sys_platform == 'win32') or (platform_machine == 'win32' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'win32')" }, - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "greenlet", marker = "(os_name != 'nt' and platform_machine == 'AMD64' and sys_platform == 'darwin') or (os_name != 'nt' and platform_machine == 'WIN32' and sys_platform == 'darwin') or (os_name != 'nt' and platform_machine == 'aarch64' and sys_platform == 'darwin') or (os_name != 'nt' and platform_machine == 'amd64' and sys_platform == 'darwin') or (os_name != 'nt' and platform_machine == 'ppc64le' and sys_platform == 'darwin') or (os_name != 'nt' and platform_machine == 'win32' and sys_platform == 'darwin') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (os_name != 'nt' and platform_machine == 'AMD64' and sys_platform == 'linux') or (os_name != 'nt' and platform_machine == 'WIN32' and sys_platform == 'linux') or (os_name != 'nt' and platform_machine == 'aarch64' and sys_platform == 'linux') or (os_name != 'nt' and platform_machine == 'amd64' and sys_platform == 'linux') or (os_name != 'nt' and platform_machine == 'ppc64le' and sys_platform == 'linux') or (os_name != 'nt' and platform_machine == 'win32' and sys_platform == 'linux') or (os_name != 'nt' and platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'WIN32' and sys_platform == 'win32') or (platform_machine == 'aarch64' and sys_platform == 'win32') or (platform_machine == 'amd64' and sys_platform == 'win32') or (platform_machine == 'ppc64le' and sys_platform == 'win32') or (platform_machine == 'win32' and sys_platform == 'win32') or (platform_machine == 'x86_64' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/02/f1/a7a892f18d4d224e6b26f706531eafccc41e37594d37d304786969ee13cb/sqlalchemy-2.0.51.tar.gz", hash = "sha256:804dccd8a4a6242c4e30ad961e540e18a588f6527202f2d6791b01845d59fdc9", size = 9912201, upload-time = "2026-06-15T15:41:20.012Z" } wheels = [ @@ -4164,10 +4226,10 @@ name = "sqlalchemy-schemadisplay" version = "2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pillow", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pydot", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "setuptools", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "pillow", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pydot", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "setuptools", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/4f/b0/d4587a6223dd563072ed5d0b94e0d062bb3d019bf16d0e65a85324c49efc/sqlalchemy_schemadisplay-2.0.tar.gz", hash = "sha256:e90b9c9868814975d674a889aadb7c4651658f0e119e1c9320279ea527744d5e", size = 11637, upload-time = "2024-02-15T11:52:53.355Z" } wheels = [ @@ -4179,14 +4241,14 @@ name = "statsmodels" version = "0.14.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "patsy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pandas", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "patsy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0d/81/e8d74b34f85285f7335d30c5e3c2d7c0346997af9f3debf9a0a9a63de184/statsmodels-0.14.6.tar.gz", hash = "sha256:4d17873d3e607d398b85126cd4ed7aad89e4e9d89fc744cdab1af3189a996c2a", size = 20689085, upload-time = "2025-12-05T23:08:39.522Z" } wheels = [ @@ -4242,19 +4304,19 @@ name = "timely-beliefs" version = "3.5.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "importlib-metadata", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "isodate", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "openturns", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pandas", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "properscoring", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "psycopg2-binary", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytz", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, - { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and sys_platform == 'darwin') or (python_full_version >= '3.12' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, - { name = "sqlalchemy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "importlib-metadata", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "isodate", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "openturns", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pandas", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "properscoring", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "psycopg2-binary", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pytz", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and sys_platform == 'win32')" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and sys_platform == 'win32')" }, + { name = "sqlalchemy", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c7/bb/9369de8f0af17b9063c70073cb63b4d6d32d2ac16105ad1967cce1e393e2/timely_beliefs-3.5.5.tar.gz", hash = "sha256:c165db5e92fb3557296b6dbfb9b526de27729f6bb5b23b1b4d65ea1b407216d5", size = 793855, upload-time = "2026-05-04T15:10:38.682Z" } wheels = [ @@ -4263,9 +4325,9 @@ wheels = [ [package.optional-dependencies] forecast = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "sktime", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "sktime", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] [[package]] @@ -4273,7 +4335,7 @@ name = "times" version = "0.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "arrow", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "arrow", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/41/be/ec94886bf2540dca5c120950b290f6b4aa42c35476d4a82aefb19de0ebe9/times-0.7.tar.gz", hash = "sha256:ed9da7bd0384ff4e1b3fc84114c27c2e3987072dbaf24425340bfedd405bc4b5", size = 4228, upload-time = "2014-08-24T06:13:25.293Z" } wheels = [ @@ -4285,10 +4347,10 @@ name = "tldextract" version = "5.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "filelock", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "idna", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "requests-file", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "filelock", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "idna", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "requests", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "requests-file", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/65/7b/644fbbb49564a6cb124a8582013315a41148dba2f72209bba14a84242bf0/tldextract-5.3.1.tar.gz", hash = "sha256:a72756ca170b2510315076383ea2993478f7da6f897eef1f4a5400735d5057fb", size = 126105, upload-time = "2025-12-28T23:58:05.532Z" } wheels = [ @@ -4339,7 +4401,7 @@ name = "typeguard" version = "4.5.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/67/1c/dfba5c4633cafc4c701f237d2ba63b416805047fd6d96aab4cfc40969f98/typeguard-4.5.2.tar.gz", hash = "sha256:5a16dcac23502039299c97c8941651bc33d7ea8cc4b2f7d6bbb1b528f6eea423", size = 80240, upload-time = "2026-05-14T12:59:40.857Z" } wheels = [ @@ -4351,7 +4413,7 @@ name = "types-cffi" version = "2.0.0.20260518" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "types-setuptools", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "types-setuptools", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/bd/0b/b352742758a6054d1053783887bf8cfb739deda1102fda8722294bdc01f7/types_cffi-2.0.0.20260518.tar.gz", hash = "sha256:f9707e66c13454789a58f8843d1ded4a66f1e9c8b10bd24d5eb5e0f25c0c5472", size = 17790, upload-time = "2026-05-18T06:06:50.672Z" } wheels = [ @@ -4372,9 +4434,9 @@ name = "types-flask" version = "1.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "types-click", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-jinja2", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-werkzeug", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "types-click", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-jinja2", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-werkzeug", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/79/65/728a104973133a45fba50f3d1e1ee832287666ac74cfd47004cea8402ea3/types-Flask-1.1.6.tar.gz", hash = "sha256:aac777b3abfff9436e6b01f6d08171cf23ea6e5be71cbf773aaabb1c5763e9cf", size = 9829, upload-time = "2021-11-26T06:21:31.199Z" } wheels = [ @@ -4386,7 +4448,7 @@ name = "types-jinja2" version = "2.11.9" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "types-markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "types-markupsafe", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/46/c4/b82309bfed8195de7997672deac301bd6f5bd5cbb6a3e392b7fe780d7852/types-Jinja2-2.11.9.tar.gz", hash = "sha256:dbdc74a40aba7aed520b7e4d89e8f0fe4286518494208b35123bcf084d4b8c81", size = 13302, upload-time = "2021-11-26T06:21:17.496Z" } wheels = [ @@ -4407,8 +4469,8 @@ name = "types-pyopenssl" version = "24.1.0.20240722" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-cffi", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "cryptography", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-cffi", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/93/29/47a346550fd2020dac9a7a6d033ea03fccb92fa47c726056618cc889745e/types-pyOpenSSL-24.1.0.20240722.tar.gz", hash = "sha256:47913b4678a01d879f503a12044468221ed8576263c1540dcb0484ca21b08c39", size = 8458, upload-time = "2024-07-22T02:32:22.558Z" } wheels = [ @@ -4447,8 +4509,8 @@ name = "types-redis" version = "4.6.0.20241004" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "types-pyopenssl", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "cryptography", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "types-pyopenssl", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3a/95/c054d3ac940e8bac4ca216470c80c26688a0e79e09f520a942bb27da3386/types-redis-4.6.0.20241004.tar.gz", hash = "sha256:5f17d2b3f9091ab75384153bfa276619ffa1cf6a38da60e10d5e6749cc5b902e", size = 49679, upload-time = "2024-10-04T02:43:59.224Z" } wheels = [ @@ -4460,7 +4522,7 @@ name = "types-requests" version = "2.33.0.20260518" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "urllib3", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "urllib3", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e0/01/c5a19253fe1ac159159ddf9a3a07cec8bb5e486ec4d9002ad2821da0e5d2/types_requests-2.33.0.20260518.tar.gz", hash = "sha256:df7bd3bfe0ca8402dfb841e7d9be714bb5578203283d66d7dc4ef69343449a5e", size = 24752, upload-time = "2026-05-18T06:07:37.966Z" } wheels = [ @@ -4490,7 +4552,7 @@ name = "types-tzlocal" version = "5.1.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "types-pytz", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "types-pytz", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e7/cf/e4d446e57c0b14ed1da4de180d2a4cac773b667f183e83bdad76ea6e2238/types-tzlocal-5.1.0.1.tar.gz", hash = "sha256:b84a115c0c68f0d0fa9af1c57f0645eeef0e539147806faf1f95ac3ac01ce47b", size = 3549, upload-time = "2023-10-24T02:15:07.127Z" } wheels = [ @@ -4520,7 +4582,7 @@ name = "typing-inspection" version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "typing-extensions", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } wheels = [ @@ -4541,9 +4603,9 @@ name = "uniplot" version = "0.23.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "readchar", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "readchar", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/24/bc/61055938caab2c3b8fc24ff515dfbd07bdd6583877b2ebdb003df6204f55/uniplot-0.23.0.tar.gz", hash = "sha256:ec7b78c85e7c7a130fda0570369f8f3a0bf8b9519f105e2469e0f449f798cbbc", size = 42942, upload-time = "2026-06-21T07:24:38.343Z" } wheels = [ @@ -4606,9 +4668,9 @@ name = "webargs" version = "8.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "marshmallow", version = "3.26.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "marshmallow", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/37/64/17afc4e6f47eef154a553c6e56adcc9f1ac3003305c7df978d11aa62937e/webargs-8.7.1.tar.gz", hash = "sha256:799bf9039c76c23fd8dc1951107a75a9e561203c15d6ae8f89c1e46e234636c1", size = 97351, upload-time = "2025-10-29T16:07:50.066Z" } wheels = [ @@ -4620,11 +4682,11 @@ name = "webauthn" version = "2.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cbor2", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "cryptography", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyasn1", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyasn1-modules", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyopenssl", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "cbor2", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "cryptography", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyasn1", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyasn1-modules", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyopenssl", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/aa/5c/8ad4e9c8e2eb97f434f74058ff7de955aa47e255ab549d7381c80262318e/webauthn-2.8.0.tar.gz", hash = "sha256:cb3a49abbddb3a757e60c58f8b2b10ca20ef451935b97dfd7e9beedaabff7b10", size = 134197, upload-time = "2026-06-13T03:05:02.148Z" } wheels = [ @@ -4636,7 +4698,7 @@ name = "werkzeug" version = "3.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "markupsafe", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/dd/b2/381be8cfdee792dd117872481b6e378f85c957dd7c5bca38897b08f765fd/werkzeug-3.1.8.tar.gz", hash = "sha256:9bad61a4268dac112f1c5cd4630a56ede601b6ed420300677a869083d70a4c44", size = 875852, upload-time = "2026-04-02T18:49:14.268Z" } wheels = [ @@ -4648,10 +4710,10 @@ name = "workalendar" version = "17.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "convertdate", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "lunardate", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyluach", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "convertdate", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "lunardate", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "pyluach", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, + { name = "python-dateutil", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, { name = "tzdata", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a7/16/e2d59c5a3b2d01519778dc1820daab70054022d88ff8291df602b2620481/workalendar-17.0.0.tar.gz", hash = "sha256:b82d6024aed452505b01baf06dbe8d6309a3135ff1d39dee07c31b21ece853b4", size = 153468, upload-time = "2023-01-01T22:33:06.471Z" } @@ -4659,12 +4721,54 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4a/23/2fd9e240ae95be5653d57cc39d5377278eb376b4b3f30e27526d831b1668/workalendar-17.0.0-py3-none-any.whl", hash = "sha256:8fe1d6758f9a1af05d59cb81480afb912246ec7fa46e246b909897127cdbb1b0", size = 210652, upload-time = "2023-01-01T22:33:03.869Z" }, ] +[[package]] +name = "wrapt" +version = "2.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/a4/282c8e64300a59fc834518a54bf0afabb4ff9218b5fa76958b450459a844/wrapt-2.2.2.tar.gz", hash = "sha256:0788e321027c999bf221b667bd4a54aaefd1a36283749a860ac3eb77daed0302", size = 129068, upload-time = "2026-06-20T23:49:44.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/8b/59781d0fe7b0adfbea37f600857de4be68921e454aeecf1a11bda35cdccc/wrapt-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:055e6fcfaa28e58c6a8c247d48b92be9d56f818b7068aa4f22b15b3343a09931", size = 80556, upload-time = "2026-06-20T23:47:28.473Z" }, + { url = "https://files.pythonhosted.org/packages/94/dc/66c61aca927230c9cf97a3cb005c803971a1076ff9f7d61085d035c20085/wrapt-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8374eb6b1a58809211e84ff835a182bb17ab2807a5bfef23204c8cff38178a00", size = 81648, upload-time = "2026-06-20T23:47:30.504Z" }, + { url = "https://files.pythonhosted.org/packages/23/1b/545eee1c18f3af4cf140bb5822b6ef81ebe569df0a63ac109973103a30a5/wrapt-2.2.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:656593bb3f5529f03d27af4136c4d7b11990e470bcbc6fefa5ef218695bece55", size = 152956, upload-time = "2026-06-20T23:47:31.867Z" }, + { url = "https://files.pythonhosted.org/packages/44/a7/6f42a3d03e44dc612a5dcff324e7366075a7857f0be2d49a8cb8a68279b8/wrapt-2.2.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dfb00cb7bb22099e2f64b7340fb96113639aa7260c0972af3797ace2297b936c", size = 154771, upload-time = "2026-06-20T23:47:33.352Z" }, + { url = "https://files.pythonhosted.org/packages/bf/55/4d76175aaa97523c38f1d28f79d18ab41a1b116814158a818bc0eba00571/wrapt-2.2.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e7f10ee0bd53673bfd52b67cbce83336fe6cad90d2377b03baf66491d2bbfb91", size = 149460, upload-time = "2026-06-20T23:47:34.712Z" }, + { url = "https://files.pythonhosted.org/packages/84/9b/12e23264d8f4735e8483262f95c5a6b03c3665fd2a84bdf99a45b6a2f4ec/wrapt-2.2.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4402f57c5f0d0579599858ffbdd9bf4e3f0972f51096f2bd6cc7dab6b76ee49e", size = 153648, upload-time = "2026-06-20T23:47:36.092Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a3/bcd5ec37289dcd85ecd4d15395a6a6063d60bc45ff94a9d77814e1e54d64/wrapt-2.2.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:3a4eb7964ff4643d333c84f880bcf554652b2a1050aebc54ae696327f61acfaf", size = 148502, upload-time = "2026-06-20T23:47:37.623Z" }, + { url = "https://files.pythonhosted.org/packages/f2/be/716d708f607fa70f8a6eb47dff8ee945d5278dfc89ffeeff33039d052e63/wrapt-2.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e542b7c5af91e2123a8aabf19894319d5ec4268d2a9ffd2f239386133fc47746", size = 152238, upload-time = "2026-06-20T23:47:39.118Z" }, + { url = "https://files.pythonhosted.org/packages/b5/c0/1a48e7e54501274f5d906f18372221b13183b0afbb5b8bb4c7ca0392c0b4/wrapt-2.2.2-cp310-cp310-win32.whl", hash = "sha256:6e7e45b43d3c774d244fe7264378f5a3f0f383bc55a54a9866434e524540110f", size = 77278, upload-time = "2026-06-20T23:47:40.476Z" }, + { url = "https://files.pythonhosted.org/packages/b0/82/9cd69a1af288fbdedf01a10e3c8a0b6890b08c7f3f96d36a213699dbcd94/wrapt-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:955f1d6e72a352e478de8d8b503abe301c5e139a141b62eb0923bd694995025f", size = 80131, upload-time = "2026-06-20T23:47:41.785Z" }, + { url = "https://files.pythonhosted.org/packages/7f/73/8db7e27daef37ae70a53ea62bef7fe80cc51a8b5e9e9181a8be6eb9a999c/wrapt-2.2.2-cp310-cp310-win_arm64.whl", hash = "sha256:b89d8d73c82db2bb7e6090b3afd7973f980d24e905cc34394eab60b884b3bf67", size = 79615, upload-time = "2026-06-20T23:47:43.109Z" }, + { url = "https://files.pythonhosted.org/packages/27/15/0c2d55168707465abfc41f33c0b23d792a5fa9b65c26983606940900a120/wrapt-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f1a2ff355ece6a111ca7a20dc86df6659c9205d3fcee674ca34f2a2854fd4e73", size = 80782, upload-time = "2026-06-20T23:47:44.367Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b5/5c0b093eb48f8a062ef6267d3cb36e9bb1b88440181f6545a383c60efdf8/wrapt-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55b9a899e6fff5444f229d30aa6e9ac92d2216d9d60f33c771b5d76a760d5f8e", size = 81678, upload-time = "2026-06-20T23:47:45.857Z" }, + { url = "https://files.pythonhosted.org/packages/34/f3/de70937472dd3e8a4e6811192f9c6075efdffd4a2cd9b4596bf160f89668/wrapt-2.2.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a2d78c363f97d8bd718ee40432c66395685e9e98528ccaa423c3355d1715a26d", size = 159671, upload-time = "2026-06-20T23:47:47.345Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ec/40aed2330e7f02ecf74386ffcfef9ccb7108c6a430f15b6a252b663b1bed/wrapt-2.2.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d619e1eed9bd4f6ed9f24cd61971aa086fa86505289628d464bcf8a2c2e3f328", size = 160785, upload-time = "2026-06-20T23:47:48.759Z" }, + { url = "https://files.pythonhosted.org/packages/45/04/aa5309beed5344b00220ae6b3b24055852192656194c27947bee1736306a/wrapt-2.2.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:518b0c5e323511ec56a38894802ddd5e1222626484e68efe63f201854ad788e5", size = 153699, upload-time = "2026-06-20T23:47:50.177Z" }, + { url = "https://files.pythonhosted.org/packages/01/df/2def7e99d1fe87eea413f95f671924cdddcb08823b1ffd212748dfa6d062/wrapt-2.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4bccea5cdecffa9dd70e343741f0e41e0a16619313d04b72f78bb525162ebcd0", size = 159695, upload-time = "2026-06-20T23:47:51.602Z" }, + { url = "https://files.pythonhosted.org/packages/c7/f6/a906d01a2ce12157bad2404957b3e2140da354b8a70b2fa48bbf282871c0/wrapt-2.2.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:209112cafd963710a05d199aae431d79a28bc76eb8e6d1bbbb8ad24340722cae", size = 152813, upload-time = "2026-06-20T23:47:53.03Z" }, + { url = "https://files.pythonhosted.org/packages/02/49/bc0086292d239575b4c08f4cf8a4079fa58abbad58ec23abf84833a283ed/wrapt-2.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5a5290e4bf2f332fc29ce72ffb9a2fff678aaac047e2e9f5f7165cd7792e099", size = 158809, upload-time = "2026-06-20T23:47:54.391Z" }, + { url = "https://files.pythonhosted.org/packages/55/83/8fbd034de1f3e907edaa18786d5dd8f6932874edee0826c7cecb5cab03a1/wrapt-2.2.2-cp311-cp311-win32.whl", hash = "sha256:5499236ad1dc116012e2a5dd943f3f31af12fce452128e2bbcbd55a7d3d4d14c", size = 77414, upload-time = "2026-06-20T23:47:55.882Z" }, + { url = "https://files.pythonhosted.org/packages/7e/9c/23695baa331c6de4e874c3d78b8e0bed92e1d2a274e665b29858f6841672/wrapt-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:8636809939152be6ae20a6cef0fed9fe60f411b47847d0426a826884b469e971", size = 80368, upload-time = "2026-06-20T23:47:57.237Z" }, + { url = "https://files.pythonhosted.org/packages/08/49/40cefc342bf89b234a4490d741290fce781774b831aefb39c25471da96c9/wrapt-2.2.2-cp311-cp311-win_arm64.whl", hash = "sha256:5d0a142f7af07caeb5e5da87493162a7b8efa19ba919e550a746f7446e13fb30", size = 79489, upload-time = "2026-06-20T23:47:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/2a/85/180b40628b23772692a0c76e8030114e1c0ae068470ed531919f0a5f2a4a/wrapt-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8417fd3c674d3c8023d080292d29301531a12daf8bd938dd419710dd2f464f2b", size = 81484, upload-time = "2026-06-20T23:47:59.924Z" }, + { url = "https://files.pythonhosted.org/packages/94/f2/21c90f2a16689702e2aaff45795b11018dff2c9b1242bac10d225483f676/wrapt-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e7070c7472582e31af3dfc2622b2381a0df7435110a9388ed8db5ffbce67efb", size = 82151, upload-time = "2026-06-20T23:48:01.303Z" }, + { url = "https://files.pythonhosted.org/packages/5f/b3/7e6e9fcf4fe7e1b69a49fe6cc5a44e8224bab6283c5233c97e132f14908e/wrapt-2.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2e096c9d39a59b35b63c9aacfbbbec2088ff51ff1fc31051acc60a07f42f273a", size = 169828, upload-time = "2026-06-20T23:48:02.719Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/894f132d857ed5a9904d937baf368badcbe5ea9e436e2f1930fe21c9f1f0/wrapt-2.2.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d1a6050405bf334be33bf66296f113563622972a34900ae6fa60fd283a1a900", size = 171544, upload-time = "2026-06-20T23:48:04.266Z" }, + { url = "https://files.pythonhosted.org/packages/29/de/3c833e03725b477e9ea34028224dd21a48781830101e4e036f77e8b6b102/wrapt-2.2.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10adb01371408c6de504a6658b9886480f1a4919a83752748a387a504a21df79", size = 160663, upload-time = "2026-06-20T23:48:05.708Z" }, + { url = "https://files.pythonhosted.org/packages/33/be/27edce350b24e3054d9d047f65f16d4c4d4c1f3f31c4278a1f8a95c723c8/wrapt-2.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3442eee2a5798f9b451f1b2cd7518ce8b7e28a2a364696c414460a0e295c012a", size = 169387, upload-time = "2026-06-20T23:48:07.243Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c4/9fd9679af8bf38e146652c7f47b6b352c3e5795b4ad1c0b7f94e15ac2aa7/wrapt-2.2.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6c99012a22f735a85eed7c4b86a3e99c30fdd57d9e115b2b45f796264b58d0bf", size = 158849, upload-time = "2026-06-20T23:48:08.91Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c2/aa6c0c2206803068c6859dabe01f8c84c43744da93d4c67b8946d21655ee/wrapt-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b686cfc008776a3952d6213cb296ed7f45d782a8453936406faa89eac0835ab", size = 168147, upload-time = "2026-06-20T23:48:10.374Z" }, + { url = "https://files.pythonhosted.org/packages/42/63/3eb25da41049d20ae18fcab2dd8b056e02387c4bfa626cbdfb7c3b872e4f/wrapt-2.2.2-cp312-cp312-win32.whl", hash = "sha256:ef2cce266b5b0b07e19fa82e59673b81142b7a3607c8ed1254113d048ed668da", size = 77734, upload-time = "2026-06-20T23:48:11.769Z" }, + { url = "https://files.pythonhosted.org/packages/da/09/0390e008a305360948fa9ce69507d041ac12cb2ee5d28e34467e2ee79391/wrapt-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:abf8c20a2d72ee69e16328b3c91342c446e723bfe48bfcc4dded3b9722ac027f", size = 80585, upload-time = "2026-06-20T23:48:13.117Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b3/84c445c66969f2d3457276b183a48c91097d59bbef9af6c075366b0f8c36/wrapt-2.2.2-cp312-cp312-win_arm64.whl", hash = "sha256:c6c64c5d02578bc4c4bca4f0aef1504de933c1d5b4ac2710b9131111459506c8", size = 79553, upload-time = "2026-06-20T23:48:14.5Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d2/6317eb6d4554855bbf12d61857774af34747bf88a42c19bf306de67e2fa3/wrapt-2.2.2-py3-none-any.whl", hash = "sha256:5bad217350f19ce99ca5b5e71d406765ea86fe541628426772b657375ee1c048", size = 61460, upload-time = "2026-06-20T23:49:42.966Z" }, +] + [[package]] name = "wtforms" version = "3.2.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "markupsafe", marker = "(os_name != 'nt' and sys_platform == 'darwin') or (os_name != 'nt' and sys_platform == 'linux') or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e9/91/ed9b517da898e3fb747566aa3c12a734bd64ea7449a0d25ec74ce8f8b8eb/wtforms-3.2.2.tar.gz", hash = "sha256:7b00c73f8670f35d4edb0293dcd81b980528bee72fd662b182aaba27ae570b93", size = 139583, upload-time = "2026-05-03T05:53:44.147Z" } wheels = [ @@ -4676,17 +4780,17 @@ name = "xarray" version = "2025.6.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'linux'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin')", + "python_full_version < '3.11' and os_name == 'win' and sys_platform == 'darwin'", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'darwin'", "(python_full_version < '3.11' and os_name == 'nt' and sys_platform == 'win32') or (python_full_version < '3.11' and os_name == 'win' and sys_platform == 'win32')", "python_full_version < '3.11' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "packaging", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "pandas", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "pandas", marker = "(python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version < '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/19/ec/e50d833518f10b0c24feb184b209bb6856f25b919ba8c1f89678b930b1cd/xarray-2025.6.1.tar.gz", hash = "sha256:a84f3f07544634a130d7dc615ae44175419f4c77957a7255161ed99c69c7c8b0", size = 3003185, upload-time = "2025-06-12T03:04:09.099Z" } wheels = [ @@ -4698,14 +4802,14 @@ name = "xarray" version = "2026.4.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux')", - "(python_full_version == '3.11.*' and os_name == 'nt' and sys_platform == 'linux') or (python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux')", + "python_full_version >= '3.12' and os_name == 'win' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and os_name == 'win' and sys_platform == 'linux'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'linux'", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version >= '3.12' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin')", - "(python_full_version == '3.11.*' and os_name == 'nt' and platform_machine != 'x86_64' and sys_platform == 'darwin') or (python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin')", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version >= '3.12' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and os_name == 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", "python_full_version >= '3.12' and os_name != 'nt' and os_name != 'win' and platform_machine != 'x86_64' and sys_platform == 'darwin'", "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and platform_machine == 'x86_64' and sys_platform == 'darwin'", @@ -4716,9 +4820,9 @@ resolution-markers = [ "python_full_version == '3.11.*' and os_name != 'nt' and os_name != 'win' and sys_platform == 'win32'", ] dependencies = [ - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "packaging", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "pandas", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "packaging", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "pandas", marker = "(python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'darwin') or (python_full_version >= '3.11' and os_name != 'nt' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/4b/a6/6fe936a798a3a38a79c7422d1a31afd2e9a14690fcb0ccff96bc01f04bf2/xarray-2026.4.0.tar.gz", hash = "sha256:c4ac9a01a945d90d5b1628e2af045099a9d4943536d4f2ee3ae963c3b222d15b", size = 3132311, upload-time = "2026-04-13T19:45:36.688Z" } wheels = [ From 95b937fa58d1c36e075764f9b188d026c1009054 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Mon, 13 Jul 2026 12:36:29 +0200 Subject: [PATCH 2/4] docs: point the rate-limiting changelog entry at PR #2306 Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01C2JTqYVFPmJgX7kN2DSvbE --- documentation/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/changelog.rst b/documentation/changelog.rst index c280fd2488..21ecef5385 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -13,7 +13,7 @@ v1.0.0 | July XX, 2026 New features ------------- -* The API is now rate-limited, with a generous default limit on all endpoints and a stricter limit on triggering schedules and forecasts. Limits are configurable, and can be set per account through the ``rate_limits`` account attribute [see `PR #2302 `_] +* The API is now rate-limited, with a generous default limit on all endpoints and a stricter limit on triggering schedules and forecasts. Limits are configurable, and can be set per account through the ``rate_limits`` account attribute [see `PR #2306 `_] * Breaking behaviour change: the top-level flex-context's ``relax-constraints`` field now defaults to ``True`` (matching the default already used within each ``commodities`` entry), so constraint violations are softly penalized by default instead of being hard constraints, unless explicitly set to ``False`` [see `PR #2172 `_] * Support for creating new assets by using another asset as a template from the UI. [see `PR #2195 `_ and `PR #2268 `_ * In the UI, asset and sensor lists can be filtered by ID prefix through API-backed search fields [see `PR #2231 `_] From d283a5ead742f959cc707b5c5a489ff71b7f5f0f Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Mon, 13 Jul 2026 16:47:49 +0200 Subject: [PATCH 3/4] feat: move per-account rate limit overrides to a Plan model Replace Account.attributes["rate_limits"] with a first-class Plan table (Account.plan_id FK), per Nicolas' review on PR #2306. A plan holds default_rate_limit, trigger_rate_limit and rate_limit_key (Enum), plus not-yet-enforced quota columns (max_users, max_assets, max_clients) as groundwork for a follow-up PR. The trigger key resolution now falls back to the server config (and ultimately to "account+asset") instead of raising, so a bad key value can never turn into a 500 on every request for an account. --- documentation/api/change_log.rst | 2 +- documentation/changelog.rst | 2 +- documentation/configuration.rst | 21 +++---- flexmeasures/api/common/rate_limiting.py | 55 ++++++++++++++----- .../api/v3_0/tests/test_rate_limiting.py | 54 +++++++++++++++++- ...151c_add_plan_table_and_account_plan_id.py | 52 ++++++++++++++++++ flexmeasures/data/models/user.py | 48 +++++++++++++++- 7 files changed, 204 insertions(+), 30 deletions(-) create mode 100644 flexmeasures/data/migrations/versions/6a767f36151c_add_plan_table_and_account_plan_id.py diff --git a/documentation/api/change_log.rst b/documentation/api/change_log.rst index 7900ec8585..0e226f9111 100644 --- a/documentation/api/change_log.rst +++ b/documentation/api/change_log.rst @@ -8,7 +8,7 @@ API change log v3.0-32 | July XX, 2026 """""""""""""""""""""""" -- API endpoints are now rate-limited. A request which exceeds a limit is answered with a ``429 (Too Many Requests)`` status code and a ``Retry-After`` header stating how many seconds to wait. Responses also carry ``X-RateLimit-*`` headers, describing the limit that applied, how much of it is left, and when it resets. A stricter limit applies to ``POST /assets//schedules/trigger``, ``POST /sensors//schedules/trigger`` and ``POST /sensors//forecasts/trigger`` than to other endpoints; the health endpoints are exempt. +- API endpoints are now rate-limited. A request which exceeds a limit is answered with a ``429 (Too Many Requests)`` status code and a ``Retry-After`` header stating how many seconds to wait. Responses also carry ``X-RateLimit-*`` headers, describing the limit that applied, how much of it is left, and when it resets. A stricter limit applies to ``POST /assets//schedules/trigger``, ``POST /sensors//schedules/trigger`` and ``POST /sensors//forecasts/trigger`` than to other endpoints; the health endpoints are exempt. Per-account overrides are set by assigning the account a plan (a ``Plan`` database row), rather than through an account attribute. - Extended ``GET /api/v3_0/jobs/`` with a ``result`` field containing ``unresolved`` and ``resolved`` arrays, each keyed by asset ID. For scheduling jobs, this surfaces soft state-of-charge constraint analysis: ``soc-minima`` and ``soc-maxima`` violations (with a ``violation`` magnitude) or satisfied constraints (with a ``margin`` headroom). Both arrays are empty when no SoC constraints were defined. v3.0-31 | 2026-06-01 diff --git a/documentation/changelog.rst b/documentation/changelog.rst index 21ecef5385..18a60d7e17 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -13,7 +13,7 @@ v1.0.0 | July XX, 2026 New features ------------- -* The API is now rate-limited, with a generous default limit on all endpoints and a stricter limit on triggering schedules and forecasts. Limits are configurable, and can be set per account through the ``rate_limits`` account attribute [see `PR #2306 `_] +* The API is now rate-limited, with a generous default limit on all endpoints and a stricter limit on triggering schedules and forecasts. Limits are configurable, and can be set per account by assigning the account a plan [see `PR #2306 `_] * Breaking behaviour change: the top-level flex-context's ``relax-constraints`` field now defaults to ``True`` (matching the default already used within each ``commodities`` entry), so constraint violations are softly penalized by default instead of being hard constraints, unless explicitly set to ``False`` [see `PR #2172 `_] * Support for creating new assets by using another asset as a template from the UI. [see `PR #2195 `_ and `PR #2268 `_ * In the UI, asset and sensor lists can be filtered by ID prefix through API-backed search fields [see `PR #2231 `_] diff --git a/documentation/configuration.rst b/documentation/configuration.rst index de994ee330..de07399ea9 100644 --- a/documentation/configuration.rst +++ b/documentation/configuration.rst @@ -786,18 +786,12 @@ reached, FlexMeasures lets requests through rather than refusing them. .. note:: The limiter runs before authentication, so requests without valid credentials are counted per IP address. -Individual accounts can be given their own limits, which take precedence over the settings below, by setting the -``rate_limits`` account attribute (with ``flexmeasures edit attribute``). Use the value ``"unlimited"`` to exempt -an account from a limit altogether: - -.. code-block:: json - - { - "rate_limits": { - "default": "1000 per minute", - "trigger": "unlimited" - } - } +Individual accounts can be given their own limits, which take precedence over the settings below, by assigning +the account a ``Plan`` (``flexmeasures.data.models.user.Plan``) with ``default_rate_limit`` and/or +``trigger_rate_limit`` set. Use the value ``"unlimited"`` to exempt an account from a limit altogether. A plan's +``rate_limit_key`` (see ``FLEXMEASURES_API_RATE_LIMIT_KEY`` below) similarly overrides the server-wide setting for +accounts on that plan. A plan with a field left unset (``None``) falls back to the server-wide config setting for +that field. RATELIMIT_ENABLED ^^^^^^^^^^^^^^^^^ @@ -832,6 +826,9 @@ schedule is a business decision, so you decide what shares a budget: - ``"account"``: the account has a single budget, shared by all of its assets and users. - ``"user"``: each user gets their own budget. +An account's plan can override this per account (see above). An unrecognized value falls back to +``"account+asset"`` rather than raising an error. + Default: ``"account+asset"`` diff --git a/flexmeasures/api/common/rate_limiting.py b/flexmeasures/api/common/rate_limiting.py index f0f71b84bf..c1678abe5f 100644 --- a/flexmeasures/api/common/rate_limiting.py +++ b/flexmeasures/api/common/rate_limiting.py @@ -7,8 +7,8 @@ - a stricter limit on the endpoints that trigger expensive computation (scheduling and forecasting). Both are configurable (see ``FLEXMEASURES_API_DEFAULT_RATE_LIMIT`` and ``FLEXMEASURES_API_TRIGGER_RATE_LIMIT``), -and both can be overridden per account, by setting e.g. -``account.attributes["rate_limits"]["trigger"] = "50 per hour"``. +and both can be overridden per account, by assigning the account a ``Plan`` with +``default_rate_limit`` and/or ``trigger_rate_limit`` set (see ``flexmeasures.data.models.user.Plan``). The special value "unlimited" exempts an account from a limit. Note that the limiter runs before authentication, so unauthenticated callers are counted by IP address. @@ -22,17 +22,31 @@ from flask_login import current_user from flexmeasures.api.common.responses import too_many_requests +from flexmeasures.data.models.user import RateLimitKey # Endpoints under /api/ which the default limit should not apply to EXEMPT_PATH_PREFIXES = ("/api/v3_0/health",) +_VALID_RATE_LIMIT_KEYS = {key.value for key in RateLimitKey} -def _account_rate_limit(limit_name: str) -> str | None: - """Look up an account's override for the given limit, if any.""" + +def _plan(): + """The plan of the current user's account, if any.""" if not current_user.is_authenticated or current_user.account is None: return None - rate_limits = (current_user.account.attributes or {}).get("rate_limits", {}) - return rate_limits.get(limit_name) + return current_user.account.plan + + +def _account_rate_limit(limit_name: str) -> str | None: + """Look up an account's plan-level override for the given limit, if any.""" + plan = _plan() + if plan is None: + return None + if limit_name == "default": + return plan.default_rate_limit + if limit_name == "trigger": + return plan.trigger_rate_limit + return None def _is_unlimited(limit_name: str) -> bool: @@ -47,24 +61,39 @@ def default_key_func() -> str: return get_remote_address() +def _rate_limit_key_value() -> str: + """Determine what to count triggers against: the account's plan, or the server config. + + Falls back to the server config (and ultimately to a hardcoded default) rather than raising, + so that a bad value never turns into a 500 on every request for an account. + """ + plan = _plan() + if plan is not None and plan.rate_limit_key is not None: + return plan.rate_limit_key.value + key = current_app.config["FLEXMEASURES_API_RATE_LIMIT_KEY"] + if key not in _VALID_RATE_LIMIT_KEYS: + current_app.logger.error( + f"Unknown FLEXMEASURES_API_RATE_LIMIT_KEY '{key}'. " + f"Use one of {sorted(_VALID_RATE_LIMIT_KEYS)}. Falling back to '{RateLimitKey.ACCOUNT_PLUS_ASSET.value}'." + ) + return RateLimitKey.ACCOUNT_PLUS_ASSET.value + return key + + def trigger_key_func() -> str: - """Count triggers against whatever the host configured. + """Count triggers against whatever the host (or the account's plan) configured. The request path contains both the resource type and its ID, so it distinguishes assets from sensors without us having to parse view args. """ if not current_user.is_authenticated: return get_remote_address() - key = current_app.config["FLEXMEASURES_API_RATE_LIMIT_KEY"] + key = _rate_limit_key_value() if key == "user": return f"user:{current_user.id}" if key == "account": return f"account:{current_user.account_id}" - if key == "account+asset": - return f"account:{current_user.account_id}|{request.path}" - raise ValueError( - f"Unknown FLEXMEASURES_API_RATE_LIMIT_KEY '{key}'. Use 'account+asset', 'account' or 'user'." - ) + return f"account:{current_user.account_id}|{request.path}" # "account+asset" def default_limit() -> str: diff --git a/flexmeasures/api/v3_0/tests/test_rate_limiting.py b/flexmeasures/api/v3_0/tests/test_rate_limiting.py index 6cc96e4873..608e948464 100644 --- a/flexmeasures/api/v3_0/tests/test_rate_limiting.py +++ b/flexmeasures/api/v3_0/tests/test_rate_limiting.py @@ -3,6 +3,7 @@ from flexmeasures.api.common.rate_limiting import limiter from flexmeasures.api.v3_0.tests.utils import message_for_trigger_schedule +from flexmeasures.data.models.user import Plan, RateLimitKey @pytest.fixture @@ -166,7 +167,9 @@ def test_account_can_override_trigger_rate_limit( rate_limiting.setitem( app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" ) - requesting_user.account.attributes["rate_limits"] = {"trigger": "2 per 5 minutes"} + requesting_user.account.plan = Plan( + name="test-plan-override", trigger_rate_limit="2 per 5 minutes" + ) db.session.commit() sensor = add_battery_assets["Test battery"].sensors[0] @@ -186,10 +189,57 @@ def test_account_can_be_exempt_from_trigger_rate_limit( rate_limiting.setitem( app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" ) - requesting_user.account.attributes["rate_limits"] = {"trigger": "unlimited"} + requesting_user.account.plan = Plan( + name="test-plan-unlimited", trigger_rate_limit="unlimited" + ) db.session.commit() sensor = add_battery_assets["Test battery"].sensors[0] with app.test_client() as client: for _ in range(3): assert trigger(client, sensor.id).status_code == 422 + + +@pytest.mark.parametrize( + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_plan_rate_limit_key_overrides_config( + db, app, add_battery_assets, rate_limiting, requesting_user +): + """A plan's rate_limit_key takes precedence over the server-wide config setting.""" + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_RATE_LIMIT_KEY", "account+asset" + ) + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" + ) + requesting_user.account.plan = Plan( + name="test-plan-key", rate_limit_key=RateLimitKey.ACCOUNT + ) + db.session.commit() + sensor = add_battery_assets["Test battery"].sensors[0] + other_sensor = add_battery_assets["Test small battery"].sensors[0] + + with app.test_client() as client: + assert trigger(client, sensor.id).status_code == 422 # spends the budget + # The account-level key means the other sensor shares the same budget + assert trigger(client, other_sensor.id).status_code == 429 + + +@pytest.mark.parametrize( + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_invalid_rate_limit_key_falls_back_instead_of_erroring( + app, add_battery_assets, rate_limiting, requesting_user +): + """A bad FLEXMEASURES_API_RATE_LIMIT_KEY must not turn every request into a 500.""" + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_RATE_LIMIT_KEY", "not-a-real-key" + ) + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" + ) + sensor = add_battery_assets["Test battery"].sensors[0] + + with app.test_client() as client: + assert trigger(client, sensor.id).status_code == 422 diff --git a/flexmeasures/data/migrations/versions/6a767f36151c_add_plan_table_and_account_plan_id.py b/flexmeasures/data/migrations/versions/6a767f36151c_add_plan_table_and_account_plan_id.py new file mode 100644 index 0000000000..a34e160378 --- /dev/null +++ b/flexmeasures/data/migrations/versions/6a767f36151c_add_plan_table_and_account_plan_id.py @@ -0,0 +1,52 @@ +"""add plan table and account.plan_id + +Revision ID: 6a767f36151c +Revises: 4b0f2e9c1a6d +Create Date: 2026-07-13 16:39:05.655364 + +""" + +from alembic import op +import sqlalchemy as sa + +# revision identifiers, used by Alembic. +revision = "6a767f36151c" +down_revision = "4b0f2e9c1a6d" +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table( + "plan", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(length=80), nullable=False), + sa.Column("default_rate_limit", sa.String(length=80), nullable=True), + sa.Column("trigger_rate_limit", sa.String(length=80), nullable=True), + sa.Column( + "rate_limit_key", + sa.Enum("ACCOUNT_PLUS_ASSET", "ACCOUNT", "USER", name="ratelimitkey"), + nullable=True, + ), + sa.Column("max_users", sa.Integer(), nullable=True), + sa.Column("max_assets", sa.Integer(), nullable=True), + sa.Column("max_clients", sa.Integer(), nullable=True), + sa.PrimaryKeyConstraint("id", name=op.f("plan_pkey")), + sa.UniqueConstraint("name", name=op.f("plan_name_key")), + ) + with op.batch_alter_table("account", schema=None) as batch_op: + batch_op.add_column(sa.Column("plan_id", sa.Integer(), nullable=True)) + batch_op.create_foreign_key( + batch_op.f("account_plan_id_plan_fkey"), "plan", ["plan_id"], ["id"] + ) + + +def downgrade(): + with op.batch_alter_table("account", schema=None) as batch_op: + batch_op.drop_constraint( + batch_op.f("account_plan_id_plan_fkey"), type_="foreignkey" + ) + batch_op.drop_column("plan_id") + + op.drop_table("plan") + sa.Enum(name="ratelimitkey").drop(op.get_bind(), checkfirst=True) diff --git a/flexmeasures/data/models/user.py b/flexmeasures/data/models/user.py index 826fa9a295..69098986b8 100644 --- a/flexmeasures/data/models/user.py +++ b/flexmeasures/data/models/user.py @@ -1,5 +1,6 @@ from __future__ import annotations +import enum from typing import TYPE_CHECKING from datetime import datetime, timezone @@ -7,7 +8,7 @@ import pandas as pd from sqlalchemy import select, func from sqlalchemy.orm import relationship, backref -from sqlalchemy import Boolean, DateTime, Column, Integer, String, ForeignKey +from sqlalchemy import Boolean, DateTime, Column, Integer, String, ForeignKey, Enum from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.ext.mutable import MutableDict from sqlalchemy.dialects.postgresql import JSONB @@ -51,6 +52,48 @@ def __repr__(self): return "" % (self.name, self.id) +class RateLimitKey(enum.Enum): + """What a trigger rate limit is counted against. + + See flexmeasures.api.common.rate_limiting for how this is used. + """ + + ACCOUNT_PLUS_ASSET = "account+asset" + ACCOUNT = "account" + USER = "user" + + +class Plan(db.Model): + """ + A plan bundles the rate limits and quotas that apply to the accounts assigned to it. + + Rate limits (how often an account may call the API) and quotas (how many users or assets + an account may create) are enforced through separate code paths, but share this table because + they are both first-class properties of a commercial plan rather than ad hoc account attributes. + + Quota fields are not enforced yet; enforcement is left to a follow-up. + """ + + __tablename__ = "plan" + id = Column(Integer, primary_key=True) + name = Column(String(80), unique=True, nullable=False) + + # Rate limits, as flask-limiter limit strings (e.g. "500 per minute"), or "unlimited". + # NULL falls back to the server-wide config setting. + default_rate_limit = Column(String(80), nullable=True) + trigger_rate_limit = Column(String(80), nullable=True) + rate_limit_key = Column(Enum(RateLimitKey), nullable=True) + + # Quotas, not enforced yet. NULL means no quota (falls back to server-wide behaviour). + max_users = Column(Integer, nullable=True) + max_assets = Column(Integer, nullable=True) + # For consultancy accounts, capping the number of client accounts they may manage. + max_clients = Column(Integer, nullable=True) + + def __repr__(self): + return "" % (self.name, self.id) + + class Account(db.Model, AuthModelMixin): """ Account of a tenant on the server. @@ -87,6 +130,9 @@ class Account(db.Model, AuthModelMixin): "Account", back_populates="consultancy_client_accounts", remote_side=[id] ) + plan_id = Column(Integer, db.ForeignKey("plan.id"), default=None, nullable=True) + plan = db.relationship("Plan", backref=backref("accounts", lazy="dynamic")) + def __repr__(self): return "" % (self.name, self.id) From 18ac5d5e8b8abb7303d9b88fe088d43a0099977d Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Tue, 14 Jul 2026 13:12:48 +0200 Subject: [PATCH 4/4] Address review: count only accepted triggers, default to per-account budgets, surface plans in UI and CLI Nils's review on #2306, plus two bugs it surfaced. Counting: - The trigger limit now only deducts when a trigger was accepted (deduct_when), so a client whose payload we rejected, or who asked for someone else's asset, keeps their scheduling budget. The default limit still counts every request, including failed auth, so abuse stays bounded without a second counter. Keying: - FLEXMEASURES_API_RATE_LIMIT_KEY now defaults to "account" (how billing works), and an unrecognized value falls back to that too. - "account+asset" now keys on the actual asset, resolving the sensor's asset for the deprecated sensor endpoints, rather than on the request path. - The trigger endpoints now share one budget (shared_limit). They each had their own before, so a client could double their budget by alternating endpoints. - The default limit is now an application limit, i.e. one budget for the whole API rather than one per endpoint, which is what its docs already claimed. Plans: - Plan.legacy: retire a plan rather than editing one accounts are on. - Admins can see and set an account's plan on the account page; plan_id is admin-only on PATCH /accounts/, and cannot be set to a legacy plan. - flexmeasures add plan / edit plan, so plans can be created and retired. Limit strings are validated on creation rather than at request time. Tests trigger through the AssetAPI rather than the deprecated sensor endpoint, and use the RateLimitKey constants throughout. Signed-off-by: F.N. Claessen --- documentation/changelog.rst | 2 +- documentation/cli/commands.rst | 2 + documentation/configuration.rst | 65 ++++-- flexmeasures/api/common/rate_limiting.py | 73 ++++-- flexmeasures/api/v3_0/accounts.py | 90 ++++--- .../api/v3_0/tests/test_accounts_api.py | 67 ++++++ .../api/v3_0/tests/test_rate_limiting.py | 221 ++++++++++++++---- flexmeasures/cli/data_add.py | 87 ++++++- flexmeasures/cli/data_edit.py | 85 ++++++- flexmeasures/cli/tests/test_data_add.py | 58 +++++ flexmeasures/cli/utils.py | 27 ++- ...151c_add_plan_table_and_account_plan_id.py | 3 + flexmeasures/data/models/user.py | 4 + flexmeasures/data/schemas/account.py | 1 + flexmeasures/ui/static/openapi-specs.json | 14 +- .../ui/templates/accounts/account.html | 31 ++- flexmeasures/ui/tests/test_account_crud.py | 37 +++ flexmeasures/ui/views/accounts.py | 16 +- flexmeasures/utils/config_defaults.py | 2 +- flexmeasures/utils/validation_utils.py | 23 ++ 20 files changed, 790 insertions(+), 118 deletions(-) diff --git a/documentation/changelog.rst b/documentation/changelog.rst index 18a60d7e17..2580af6f30 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -13,7 +13,7 @@ v1.0.0 | July XX, 2026 New features ------------- -* The API is now rate-limited, with a generous default limit on all endpoints and a stricter limit on triggering schedules and forecasts. Limits are configurable, and can be set per account by assigning the account a plan [see `PR #2306 `_] +* The API is now rate-limited, with a generous default limit on all endpoints and a stricter limit on triggering schedules and forecasts (which only counts triggers we accepted). Limits are configurable, and can be set per account by putting the account on a plan, which hosts create with ``flexmeasures add plan`` and admins assign from the account page [see `PR #2306 `_] * Breaking behaviour change: the top-level flex-context's ``relax-constraints`` field now defaults to ``True`` (matching the default already used within each ``commodities`` entry), so constraint violations are softly penalized by default instead of being hard constraints, unless explicitly set to ``False`` [see `PR #2172 `_] * Support for creating new assets by using another asset as a template from the UI. [see `PR #2195 `_ and `PR #2268 `_ * In the UI, asset and sensor lists can be filtered by ID prefix through API-backed search fields [see `PR #2231 `_] diff --git a/documentation/cli/commands.rst b/documentation/cli/commands.rst index 1cd143e1c0..6690fa958a 100644 --- a/documentation/cli/commands.rst +++ b/documentation/cli/commands.rst @@ -28,6 +28,7 @@ of which some are referred to in this documentation. ``flexmeasures add initial-structure`` Initialize structural data like users, roles and asset types. ``flexmeasures add account-role`` Create a FlexMeasures tenant account role. ``flexmeasures add account`` Create a FlexMeasures tenant account. +``flexmeasures add plan`` Create a plan, which sets rate limits and quotas for the accounts on it. ``flexmeasures add user`` Create a FlexMeasures user. ``flexmeasures add asset-type`` Create a new asset type. ``flexmeasures add asset`` Create a new asset. @@ -68,6 +69,7 @@ of which some are referred to in this documentation. ================================================= ======================================= ``flexmeasures edit attribute`` Edit (or add) an asset attribute or sensor attribute. +``flexmeasures edit plan`` Edit a plan's rate limits and quotas, or retire it. ``flexmeasures edit secret`` Edit (or add) an encrypted secret on an account or asset. ``flexmeasures edit resample-data`` Assign a new event resolution to an existing sensor and resample its data accordingly. ``flexmeasures edit transfer-parenthood`` (Re)assign parent assets. diff --git a/documentation/configuration.rst b/documentation/configuration.rst index de07399ea9..d52a077640 100644 --- a/documentation/configuration.rst +++ b/documentation/configuration.rst @@ -784,14 +784,46 @@ and a ``Retry-After`` header telling the client how long to wait. Counts are kept in Redis (see :ref:`redis-config`), so that all your workers share them. If Redis cannot be reached, FlexMeasures lets requests through rather than refusing them. -.. note:: The limiter runs before authentication, so requests without valid credentials are counted per IP address. +The two limits count differently: -Individual accounts can be given their own limits, which take precedence over the settings below, by assigning -the account a ``Plan`` (``flexmeasures.data.models.user.Plan``) with ``default_rate_limit`` and/or -``trigger_rate_limit`` set. Use the value ``"unlimited"`` to exempt an account from a limit altogether. A plan's -``rate_limit_key`` (see ``FLEXMEASURES_API_RATE_LIMIT_KEY`` below) similarly overrides the server-wide setting for -accounts on that plan. A plan with a field left unset (``None``) falls back to the server-wide config setting for -that field. +- The **default limit** counts *every* request, including the ones we refuse. The limiter runs before + authentication, so requests without valid credentials are counted, too (per IP address, as there is no user + to count them against). This is what bounds a client who keeps sending requests we refuse. +- The **trigger limit** only counts triggers we *accepted*. It exists to protect the expensive computation which + a trigger sets in motion, and a request we rejected ― because its payload did not validate, or because the + asset belongs to someone else ― cost us no computation. In other words, a client who made a mistake in their + flex-model does not pay for it out of their scheduling budget (they still pay for it out of the default one). + +.. _rate-limiting-plans: + +Plans +^^^^^ + +Individual accounts can be given their own limits, which take precedence over the settings below, by putting the +account on a plan. A plan (``flexmeasures.data.models.user.Plan``) bundles the rate limits and quotas which apply +to the accounts assigned to it, so that it can be shared as a tier (say, "Free" and "Pro"): + +.. code-block:: bash + + $ flexmeasures add plan --name Pro --trigger-rate-limit "60 per 5 minutes" --rate-limit-key account + +Admins assign an account to a plan from the account page in the UI, or through +``PATCH /api/v3_0/accounts/`` (``plan_id``). + +A plan's ``default_rate_limit``, ``trigger_rate_limit`` and ``rate_limit_key`` override the settings below for the +accounts on that plan. A field left unset (``None``) falls back to the server-wide setting, so an account on a plan +which only sets ``trigger_rate_limit`` is treated like everybody else for all other requests. Use the value +``"unlimited"`` to exempt an account from a limit altogether. + +A plan usually reflects a contractual agreement, so rather than editing a plan which accounts are on, retire it +(``flexmeasures edit plan --name Pro --legacy``) and create the plan you want to offer instead. A legacy plan keeps +applying to the accounts already on it, but is no longer offered when assigning a plan. + +Plans also carry quotas (``max_users``, ``max_assets`` and ``max_clients``). These are not enforced yet. + +.. note:: Changing an account's ``rate_limit_key`` orphans the counters it has in Redis (the old keys simply expire), + so the account may get a fresh budget for the remainder of the current window. Harmless, but worth knowing + when you wonder why a plan change handed someone a clean slate. RATELIMIT_ENABLED ^^^^^^^^^^^^^^^^^ @@ -803,8 +835,8 @@ Default: ``True`` FLEXMEASURES_API_DEFAULT_RATE_LIMIT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -How often a client may call any API endpoint. Counted per user (or per IP address, if unauthenticated). -The health endpoints are exempt, so that monitoring cannot lock itself out. +How often a client may call the API. This is one budget for the whole API, counted per user (or per IP address, +if unauthenticated). The health endpoints are exempt, so that monitoring cannot lock itself out. Default: ``"500 per minute"`` @@ -812,7 +844,8 @@ FLEXMEASURES_API_TRIGGER_RATE_LIMIT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ How often a client may trigger a schedule or a forecast. This is the expensive work, so this limit is stricter -than the default one. +than the default one. The trigger endpoints share this budget, so triggering a forecast and triggering a schedule +draw on the same one. Default: ``"10 per 5 minutes"`` @@ -822,14 +855,16 @@ FLEXMEASURES_API_RATE_LIMIT_KEY What ``FLEXMEASURES_API_TRIGGER_RATE_LIMIT`` is counted against. How often it is reasonable to re-compute a schedule is a business decision, so you decide what shares a budget: -- ``"account+asset"``: each asset gets its own budget, so scheduling one asset never blocks another. -- ``"account"``: the account has a single budget, shared by all of its assets and users. +- ``"account"``: the account has a single budget, shared by all of its assets and users. This is how billing + usually works, so it is the default. +- ``"account+asset"``: each asset gets its own budget, so triggering for one asset never blocks another. Note + that this multiplies the limit by the number of assets an account has. - ``"user"``: each user gets their own budget. -An account's plan can override this per account (see above). An unrecognized value falls back to -``"account+asset"`` rather than raising an error. +An account's plan can override this per account (see :ref:`rate-limiting-plans`). An unrecognized value falls back +to ``"account"`` rather than raising an error. -Default: ``"account+asset"`` +Default: ``"account"`` Demonstrations diff --git a/flexmeasures/api/common/rate_limiting.py b/flexmeasures/api/common/rate_limiting.py index c1678abe5f..873def7d02 100644 --- a/flexmeasures/api/common/rate_limiting.py +++ b/flexmeasures/api/common/rate_limiting.py @@ -11,18 +11,26 @@ ``default_rate_limit`` and/or ``trigger_rate_limit`` set (see ``flexmeasures.data.models.user.Plan``). The special value "unlimited" exempts an account from a limit. +The two limits count differently. The default limit counts every request, including those we refuse +(so that a client hammering us with bad credentials is bounded, too). The trigger limit only counts +triggers we accepted, because it exists to protect the expensive computation which those set in motion: +a client whose payload we rejected did not cost us a schedule, and should not pay for one. + Note that the limiter runs before authentication, so unauthenticated callers are counted by IP address. """ from __future__ import annotations -from flask import Flask, current_app, jsonify, request +from flask import Flask, Response, current_app, jsonify, request from flask_limiter import Limiter, RequestLimit from flask_limiter.util import get_remote_address from flask_login import current_user from flexmeasures.api.common.responses import too_many_requests +from flexmeasures.data import db +from flexmeasures.data.models.time_series import Sensor from flexmeasures.data.models.user import RateLimitKey +from flexmeasures.utils.validation_utils import UNLIMITED_RATE_LIMIT # Endpoints under /api/ which the default limit should not apply to EXEMPT_PATH_PREFIXES = ("/api/v3_0/health",) @@ -51,7 +59,7 @@ def _account_rate_limit(limit_name: str) -> str | None: def _is_unlimited(limit_name: str) -> bool: """Whether the account is exempt from the given limit.""" - return _account_rate_limit(limit_name) == "unlimited" + return _account_rate_limit(limit_name) == UNLIMITED_RATE_LIMIT def default_key_func() -> str: @@ -74,26 +82,44 @@ def _rate_limit_key_value() -> str: if key not in _VALID_RATE_LIMIT_KEYS: current_app.logger.error( f"Unknown FLEXMEASURES_API_RATE_LIMIT_KEY '{key}'. " - f"Use one of {sorted(_VALID_RATE_LIMIT_KEYS)}. Falling back to '{RateLimitKey.ACCOUNT_PLUS_ASSET.value}'." + f"Use one of {sorted(_VALID_RATE_LIMIT_KEYS)}. Falling back to '{RateLimitKey.ACCOUNT.value}'." ) - return RateLimitKey.ACCOUNT_PLUS_ASSET.value + return RateLimitKey.ACCOUNT.value return key -def trigger_key_func() -> str: - """Count triggers against whatever the host (or the account's plan) configured. +def _asset_id_of_trigger() -> int | None: + """Which asset a trigger request is about. - The request path contains both the resource type and its ID, - so it distinguishes assets from sensors without us having to parse view args. + The asset endpoint names the asset in its path, while the (deprecated) sensor endpoints name a sensor, + so we resolve that sensor's asset. That way, both ways of triggering the same asset share one budget. + Returns None if we cannot tell, which the caller reads as "count this against the account as a whole". """ + resource_id = (request.view_args or {}).get("id") + try: + resource_id = int(resource_id) + except (TypeError, ValueError): + return None # the view is about to reject this request anyway + if "/assets/" in request.path: + return resource_id + sensor = db.session.get(Sensor, resource_id) + return sensor.generic_asset_id if sensor is not None else None + + +def trigger_key_func() -> str: + """Count triggers against whatever the host (or the account's plan) configured.""" if not current_user.is_authenticated: return get_remote_address() key = _rate_limit_key_value() - if key == "user": + if key == RateLimitKey.USER.value: return f"user:{current_user.id}" - if key == "account": - return f"account:{current_user.account_id}" - return f"account:{current_user.account_id}|{request.path}" # "account+asset" + account_key = f"account:{current_user.account_id}" + if key == RateLimitKey.ACCOUNT.value: + return account_key + asset_id = _asset_id_of_trigger() # "account+asset" + if asset_id is None: + return account_key + return f"{account_key}|asset:{asset_id}" def default_limit() -> str: @@ -121,18 +147,35 @@ def _exempt_from_default_limit() -> bool: limiter = Limiter( key_func=default_key_func, - default_limits=[default_limit], - default_limits_exempt_when=_exempt_from_default_limit, + # An application limit is one budget for the whole API, rather than one budget per endpoint, + # which is what "how often a client may call the API" should mean. + application_limits=[default_limit], + application_limits_exempt_when=_exempt_from_default_limit, headers_enabled=True, # sets Retry-After and X-RateLimit-* headers ) +def _trigger_set_work_in_motion(response: Response) -> bool: + """Whether a trigger request got to the expensive part, and should therefore be counted. + + A request we refused (bad credentials, no permission, invalid payload) cost us no computation, + so it does not spend the account's trigger budget. Such requests are still counted by the default + limit, which applies to every API endpoint. + """ + return response.status_code < 400 + + def limit_triggers(): """Decorator for endpoints which trigger expensive computation, like scheduling.""" - return limiter.limit( + return limiter.shared_limit( trigger_limit, + # All trigger endpoints share one budget. Without this, each of them would get its own, + # so a client could ask for twice as many schedules by alternating between the asset + # endpoint and the (deprecated) sensor endpoint. + scope="triggers", key_func=trigger_key_func, exempt_when=lambda: _is_unlimited("trigger"), + deduct_when=_trigger_set_work_in_motion, ) diff --git a/flexmeasures/api/v3_0/accounts.py b/flexmeasures/api/v3_0/accounts.py index 2bed3cf33f..54397b1464 100644 --- a/flexmeasures/api/v3_0/accounts.py +++ b/flexmeasures/api/v3_0/accounts.py @@ -12,7 +12,7 @@ from flexmeasures.auth.decorators import permission_required_for_context from flexmeasures.data.models.annotations import Annotation, get_or_create_annotation from flexmeasures.data.models.audit_log import AuditLog -from flexmeasures.data.models.user import Account, User +from flexmeasures.data.models.user import Account, Plan, User from flexmeasures.data.models.generic_assets import GenericAsset from flexmeasures.data.services.accounts import get_accounts, get_audit_log_records from flexmeasures.api.common.schemas.users import AccountIdField @@ -35,6 +35,63 @@ annotation_schema = AnnotationSchema() +def _validate_consultancy_account_id( + new_consultancy_account_id: int | None, account: Account +) -> tuple[dict, int] | None: + if new_consultancy_account_id is None: + return None # Allow clearing the consultancy relationship + existing_consultancy_account_id = ( + account.consultancy_account.id if account.consultancy_account else None + ) + if new_consultancy_account_id == existing_consultancy_account_id: + return None + new_consultant_account = db.session.get(Account, new_consultancy_account_id) + if not new_consultant_account or new_consultant_account.id == account.id: + return {"errors": ["Invalid consultancy_account_id"]}, 422 + return None + + +def _validate_plan_id( + new_plan_id: int | None, account: Account +) -> tuple[dict, int] | None: + if new_plan_id is None: + return None # Allow clearing the plan, which falls the account back on the server config + if new_plan_id == account.plan_id: + return None + new_plan = db.session.get(Plan, new_plan_id) + if new_plan is None: + return {"errors": ["Invalid plan_id"]}, 422 + if new_plan.legacy: + # A legacy plan keeps applying to the accounts already on it, but is not handed out anymore + return {"errors": ["Plan is a legacy plan"]}, 422 + return None + + +# Fields only an admin may set, each with a check on the value they want to set it to +ADMIN_ONLY_ACCOUNT_FIELDS = { + "consultancy_account_id": _validate_consultancy_account_id, + "plan_id": _validate_plan_id, +} + + +def check_admin_only_fields( + account_data: dict, account: Account +) -> tuple[dict, int] | None: + """Check the fields which only an admin may set, like which plan an account is on. + + Returns an error response if the update should not go through, and None if it should. + """ + for field, validate_field in ADMIN_ONLY_ACCOUNT_FIELDS.items(): + if field not in account_data: + continue + if not user_has_admin_access(current_user, "update"): + return {"errors": [f"You are not allowed to update {field}"]}, 401 + error_response = validate_field(account_data[field], account) + if error_response is not None: + return error_response + return None + + class AccountAPI(FlaskView): route_base = "/accounts" trailing_slash = False @@ -244,6 +301,7 @@ def patch(self, account_data: dict, id: int, account: Account): **Restrictions on Fields:** - The **id** field is read-only and cannot be updated. - The **consultancy_account_id** field can only be edited if the current user has an **admin** role. + - The **plan_id** field can only be edited if the current user has an **admin** role, and cannot be set to a legacy plan. security: - ApiKeyAuth: [] @@ -291,32 +349,9 @@ def patch(self, account_data: dict, id: int, account: Account): - Accounts """ - # Get existing consultancy_account_id - existing_consultancy_account_id = ( - account.consultancy_account.id if account.consultancy_account else None - ) - - if not user_has_admin_access(current_user, "update"): - if "consultancy_account_id" in account_data: - return { - "errors": ["You are not allowed to update consultancy_account_id"] - }, 401 - else: - # Check if consultancy_account_id has changed - if "consultancy_account_id" in account_data: - new_consultancy_account_id = account_data.get("consultancy_account_id") - if new_consultancy_account_id is None: - pass # Allow clearing the consultancy relationship - elif existing_consultancy_account_id != new_consultancy_account_id: - new_consultant_account = db.session.query(Account).get( - new_consultancy_account_id - ) - # Validate new consultant account - if ( - not new_consultant_account - or new_consultant_account.id == account.id - ): - return {"errors": ["Invalid consultancy_account_id"]}, 422 + error_response = check_admin_only_fields(account_data, account) + if error_response is not None: + return error_response # Track modified fields fields_to_check = [ @@ -325,6 +360,7 @@ def patch(self, account_data: dict, id: int, account: Account): "secondary_color", "logo_url", "consultancy_account_id", + "plan_id", "attributes", ] modified_fields = { diff --git a/flexmeasures/api/v3_0/tests/test_accounts_api.py b/flexmeasures/api/v3_0/tests/test_accounts_api.py index 5906f2c2b4..8f66a39936 100644 --- a/flexmeasures/api/v3_0/tests/test_accounts_api.py +++ b/flexmeasures/api/v3_0/tests/test_accounts_api.py @@ -5,6 +5,7 @@ from flask import url_for import pytest +from flexmeasures.data.models.user import Plan from flexmeasures.data.services.users import find_user_by_email @@ -283,3 +284,69 @@ def test_patch_account_attributes_with_consultancy( response.json["consultancy_account_id"] == consultancy_client_account.consultancy_account_id ) + + +@pytest.mark.parametrize( + "requesting_user, expected_status_code", + [ + ("test_admin_user@seita.nl", 200), + ("test_prosumer_user@seita.nl", 401), # only admins hand out plans + ], + indirect=["requesting_user"], +) +def test_patch_account_plan( + db, client, setup_api_test_data, requesting_user, expected_status_code +): + """Only an admin may put an account on a plan.""" + account = find_user_by_email("test_prosumer_user@seita.nl").account + plan = Plan( + name=f"test-plan-patch-{expected_status_code}", + trigger_rate_limit="60 per 5 minutes", + ) + db.session.add(plan) + db.session.commit() + + response = client.patch( + url_for("AccountAPI:patch", id=account.id), + json={"plan_id": plan.id}, + ) + print(f"Response: {response.json}") + assert response.status_code == expected_status_code + if expected_status_code == 200: + assert response.json["plan_id"] == plan.id + assert account.plan == plan + else: + assert account.plan != plan + + +@pytest.mark.parametrize("requesting_user", ["test_admin_user@seita.nl"], indirect=True) +def test_patch_account_unknown_plan(db, client, setup_api_test_data, requesting_user): + """A plan which does not exist cannot be assigned.""" + account = find_user_by_email("test_prosumer_user@seita.nl").account + plan_before = account.plan + + response = client.patch( + url_for("AccountAPI:patch", id=account.id), + json={"plan_id": 999999}, + ) + print(f"Response: {response.json}") + assert response.status_code == 422 + assert account.plan == plan_before + + +@pytest.mark.parametrize("requesting_user", ["test_admin_user@seita.nl"], indirect=True) +def test_patch_account_legacy_plan(db, client, setup_api_test_data, requesting_user): + """A legacy plan is no longer handed out, not even by an admin.""" + account = find_user_by_email("test_prosumer_user@seita.nl").account + plan_before = account.plan + legacy_plan = Plan(name="test-plan-retired", legacy=True) + db.session.add(legacy_plan) + db.session.commit() + + response = client.patch( + url_for("AccountAPI:patch", id=account.id), + json={"plan_id": legacy_plan.id}, + ) + print(f"Response: {response.json}") + assert response.status_code == 422 + assert account.plan == plan_before diff --git a/flexmeasures/api/v3_0/tests/test_rate_limiting.py b/flexmeasures/api/v3_0/tests/test_rate_limiting.py index 608e948464..6ed0294848 100644 --- a/flexmeasures/api/v3_0/tests/test_rate_limiting.py +++ b/flexmeasures/api/v3_0/tests/test_rate_limiting.py @@ -3,6 +3,8 @@ from flexmeasures.api.common.rate_limiting import limiter from flexmeasures.api.v3_0.tests.utils import message_for_trigger_schedule +from flexmeasures.data.models.generic_assets import GenericAsset +from flexmeasures.data.models.time_series import Sensor from flexmeasures.data.models.user import Plan, RateLimitKey @@ -18,15 +20,35 @@ def rate_limiting(app, monkeypatch): limiter.reset() -def trigger(client, sensor_id: int, message: dict | None = None): - """Post to the schedule trigger endpoint. +def message_for_trigger_asset_schedule(sensor: Sensor) -> dict: + """A message the asset trigger endpoint accepts, scheduling the given power sensor. - Note that the limiter counts a request before its payload is validated, - so tests which only care about counting may pass an empty message. + The asset endpoint takes a flex-model per flexible device, so we point the flex-model at the sensor. + We also ask for a new job, so that an identical job cached by an earlier test cannot be reused, + which would leave the queue length unchanged and tell us nothing. """ + message = message_for_trigger_schedule() + message["flex-model"] = [message["flex-model"] | {"sensor": sensor.id}] + message["force-new-job-creation"] = True + return message + + +def trigger(client, asset: GenericAsset, message: dict | None = None): + """Ask for a schedule for the asset's (first) power sensor. + + Pass ``message={}`` to have the request rejected: a message which says neither when to schedule + nor what does not survive validation. + """ + if message is None: + message = message_for_trigger_asset_schedule(asset.sensors[0]) + return client.post(url_for("AssetAPI:trigger_schedule", id=asset.id), json=message) + + +def trigger_through_deprecated_sensor_endpoint(client, sensor: Sensor): + """Ask for a schedule through the deprecated endpoint, which names a sensor rather than an asset.""" return client.post( - url_for("SensorAPI:trigger_schedule", id=sensor_id), - json=message if message is not None else {}, + url_for("SensorAPI:trigger_schedule", id=sensor.id), + json=message_for_trigger_schedule() | {"force-new-job-creation": True}, ) @@ -34,17 +56,22 @@ def trigger(client, sensor_id: int, message: dict | None = None): "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True ) def test_no_rate_limiting_when_disabled( - app, add_battery_assets, rate_limiting, requesting_user + app, + add_market_prices, + add_battery_assets, + keep_scheduling_queue_empty, + rate_limiting, + requesting_user, ): """Hosts can turn rate limiting off altogether.""" rate_limiting.setitem( app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per day" ) rate_limiting.setattr(limiter, "enabled", False) - sensor = add_battery_assets["Test battery"].sensors[0] + battery = add_battery_assets["Test battery"] with app.test_client() as client: for _ in range(3): - assert trigger(client, sensor.id).status_code != 429 + assert trigger(client, battery).status_code != 429 @pytest.mark.parametrize( @@ -88,7 +115,6 @@ def test_trigger_rate_limit( app, add_market_prices, add_battery_assets, - add_charging_station_assets, keep_scheduling_queue_empty, rate_limiting, requesting_user, @@ -97,37 +123,68 @@ def test_trigger_rate_limit( rate_limiting.setitem( app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" ) - sensor = add_battery_assets["Test battery"].sensors[0] - # Ask for a new job, so that an identical job cached by an earlier test cannot be reused, - # which would leave the queue length unchanged and tell us nothing. - message = message_for_trigger_schedule() | {"force-new-job-creation": True} + battery = add_battery_assets["Test battery"] scheduling_queue = app.queues["scheduling"] - queue_length_before = len(scheduling_queue) with app.test_client() as client: - assert trigger(client, sensor.id, message).status_code == 200 + assert trigger(client, battery).status_code == 200 # The accepted trigger queued a scheduling job - assert len(scheduling_queue) == queue_length_before + 1 - queue_length_after_first_trigger = len(scheduling_queue) + assert len(scheduling_queue) == 1 - response = trigger(client, sensor.id, message) + response = trigger(client, battery) assert response.status_code == 429 assert response.json["status"] == "TOO_MANY_REQUESTS" # The rate-limited trigger did no work - assert len(scheduling_queue) == queue_length_after_first_trigger + assert len(scheduling_queue) == 1 @pytest.mark.parametrize( - "rate_limit_key, expected_status_code_for_other_sensor", + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_rejected_triggers_do_not_spend_the_trigger_budget( + app, + add_market_prices, + add_battery_assets, + keep_scheduling_queue_empty, + rate_limiting, + requesting_user, +): + """The trigger budget is only spent on triggers which set computation in motion. + + A request we refuse costs us no schedule, so the client keeps their budget. That goes for any + request we refuse, whatever the reason (this test uses an invalid payload, but a request without + permission is refused in the same way), because the deduction keys off the response status. + + Note that refused requests are still counted by the default limit, which is what bounds a client + who keeps sending us requests we refuse. + """ + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" + ) + battery = add_battery_assets["Test battery"] + + with app.test_client() as client: + # We reject these, because the message says neither when to schedule nor what + for _ in range(3): + assert trigger(client, battery, message={}).status_code == 422 + + # The budget is still there for a trigger we do accept ... + assert trigger(client, battery).status_code == 200 + # ... and now it is spent + assert trigger(client, battery).status_code == 429 + + +@pytest.mark.parametrize( + "rate_limit_key, expected_status_code_for_other_asset", [ # Each asset gets its own budget ... - ("account+asset", 422), + (RateLimitKey.ACCOUNT_PLUS_ASSET.value, 200), # ... unless the whole account or user shares one budget - ("account", 429), - ("user", 429), + (RateLimitKey.ACCOUNT.value, 429), + (RateLimitKey.USER.value, 429), ], ) @pytest.mark.parametrize( @@ -135,33 +192,75 @@ def test_trigger_rate_limit( ) def test_trigger_rate_limit_key( app, + add_market_prices, add_battery_assets, + keep_scheduling_queue_empty, rate_limiting, requesting_user, rate_limit_key, - expected_status_code_for_other_sensor, + expected_status_code_for_other_asset, ): """The host decides whether the trigger limit is counted per asset, per account or per user.""" rate_limiting.setitem(app.config, "FLEXMEASURES_API_RATE_LIMIT_KEY", rate_limit_key) rate_limiting.setitem( app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" ) - sensor = add_battery_assets["Test battery"].sensors[0] - other_sensor = add_battery_assets["Test small battery"].sensors[0] + battery = add_battery_assets["Test battery"] + other_battery = add_battery_assets["Test small battery"] with app.test_client() as client: - assert trigger(client, sensor.id).status_code == 422 # spends the budget - assert trigger(client, sensor.id).status_code == 429 - response = trigger(client, other_sensor.id) + assert trigger(client, battery).status_code == 200 # spends the budget + assert trigger(client, battery).status_code == 429 + response = trigger(client, other_battery) - assert response.status_code == expected_status_code_for_other_sensor + assert response.status_code == expected_status_code_for_other_asset + + +@pytest.mark.parametrize( + "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True +) +def test_deprecated_sensor_endpoint_shares_the_asset_budget( + app, + add_market_prices, + add_battery_assets, + keep_scheduling_queue_empty, + rate_limiting, + requesting_user, +): + """Triggering an asset's sensor through the deprecated endpoint spends that asset's budget. + + Otherwise, a client could double their budget by alternating between the two endpoints. + """ + rate_limiting.setitem( + app.config, + "FLEXMEASURES_API_RATE_LIMIT_KEY", + RateLimitKey.ACCOUNT_PLUS_ASSET.value, + ) + rate_limiting.setitem( + app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" + ) + battery = add_battery_assets["Test battery"] + + with app.test_client() as client: + assert trigger(client, battery).status_code == 200 # spends the asset's budget + response = trigger_through_deprecated_sensor_endpoint( + client, battery.sensors[0] + ) + + assert response.status_code == 429 @pytest.mark.parametrize( "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True ) def test_account_can_override_trigger_rate_limit( - db, app, add_battery_assets, rate_limiting, requesting_user + db, + app, + add_market_prices, + add_battery_assets, + keep_scheduling_queue_empty, + rate_limiting, + requesting_user, ): """An account's own limit takes precedence over the configured default.""" rate_limiting.setitem( @@ -171,19 +270,25 @@ def test_account_can_override_trigger_rate_limit( name="test-plan-override", trigger_rate_limit="2 per 5 minutes" ) db.session.commit() - sensor = add_battery_assets["Test battery"].sensors[0] + battery = add_battery_assets["Test battery"] with app.test_client() as client: for _ in range(2): - assert trigger(client, sensor.id).status_code == 422 - assert trigger(client, sensor.id).status_code == 429 + assert trigger(client, battery).status_code == 200 + assert trigger(client, battery).status_code == 429 @pytest.mark.parametrize( "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True ) def test_account_can_be_exempt_from_trigger_rate_limit( - db, app, add_battery_assets, rate_limiting, requesting_user + db, + app, + add_market_prices, + add_battery_assets, + keep_scheduling_queue_empty, + rate_limiting, + requesting_user, ): """An account can be exempted from a limit altogether.""" rate_limiting.setitem( @@ -193,22 +298,30 @@ def test_account_can_be_exempt_from_trigger_rate_limit( name="test-plan-unlimited", trigger_rate_limit="unlimited" ) db.session.commit() - sensor = add_battery_assets["Test battery"].sensors[0] + battery = add_battery_assets["Test battery"] with app.test_client() as client: for _ in range(3): - assert trigger(client, sensor.id).status_code == 422 + assert trigger(client, battery).status_code == 200 @pytest.mark.parametrize( "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True ) def test_plan_rate_limit_key_overrides_config( - db, app, add_battery_assets, rate_limiting, requesting_user + db, + app, + add_market_prices, + add_battery_assets, + keep_scheduling_queue_empty, + rate_limiting, + requesting_user, ): """A plan's rate_limit_key takes precedence over the server-wide config setting.""" rate_limiting.setitem( - app.config, "FLEXMEASURES_API_RATE_LIMIT_KEY", "account+asset" + app.config, + "FLEXMEASURES_API_RATE_LIMIT_KEY", + RateLimitKey.ACCOUNT_PLUS_ASSET.value, ) rate_limiting.setitem( app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" @@ -217,29 +330,39 @@ def test_plan_rate_limit_key_overrides_config( name="test-plan-key", rate_limit_key=RateLimitKey.ACCOUNT ) db.session.commit() - sensor = add_battery_assets["Test battery"].sensors[0] - other_sensor = add_battery_assets["Test small battery"].sensors[0] + battery = add_battery_assets["Test battery"] + other_battery = add_battery_assets["Test small battery"] with app.test_client() as client: - assert trigger(client, sensor.id).status_code == 422 # spends the budget - # The account-level key means the other sensor shares the same budget - assert trigger(client, other_sensor.id).status_code == 429 + assert trigger(client, battery).status_code == 200 # spends the budget + # The account-level key means the other asset shares the same budget + assert trigger(client, other_battery).status_code == 429 @pytest.mark.parametrize( "requesting_user", ["test_prosumer_user@seita.nl"], indirect=True ) def test_invalid_rate_limit_key_falls_back_instead_of_erroring( - app, add_battery_assets, rate_limiting, requesting_user + app, + add_market_prices, + add_battery_assets, + keep_scheduling_queue_empty, + rate_limiting, + requesting_user, ): - """A bad FLEXMEASURES_API_RATE_LIMIT_KEY must not turn every request into a 500.""" + """A bad FLEXMEASURES_API_RATE_LIMIT_KEY must not turn every request into a 500. + + We fall back to counting against the account, which is what we count against by default. + """ rate_limiting.setitem( app.config, "FLEXMEASURES_API_RATE_LIMIT_KEY", "not-a-real-key" ) rate_limiting.setitem( app.config, "FLEXMEASURES_API_TRIGGER_RATE_LIMIT", "1 per 5 minutes" ) - sensor = add_battery_assets["Test battery"].sensors[0] + battery = add_battery_assets["Test battery"] + other_battery = add_battery_assets["Test small battery"] with app.test_client() as client: - assert trigger(client, sensor.id).status_code == 422 + assert trigger(client, battery).status_code == 200 + assert trigger(client, other_battery).status_code == 429 diff --git a/flexmeasures/cli/data_add.py b/flexmeasures/cli/data_add.py index 1670be9b30..1c9a325d9e 100755 --- a/flexmeasures/cli/data_add.py +++ b/flexmeasures/cli/data_add.py @@ -52,7 +52,13 @@ ) from flexmeasures.data.services.scheduling import make_schedule, create_scheduling_job from flexmeasures.data.services.users import create_user -from flexmeasures.data.models.user import Account, AccountRole, RolesAccounts +from flexmeasures.data.models.user import ( + Account, + AccountRole, + Plan, + RateLimitKey, + RolesAccounts, +) from flexmeasures.data.models.time_series import ( Sensor, TimedBelief, @@ -89,7 +95,11 @@ from flexmeasures.utils import flexmeasures_inflection from flexmeasures.utils.time_utils import server_now, apply_offset_chain from flexmeasures.utils.unit_utils import convert_units, ur -from flexmeasures.cli.utils import validate_color_cli, validate_url_cli +from flexmeasures.cli.utils import ( + validate_color_cli, + validate_rate_limit_cli, + validate_url_cli, +) from flexmeasures.data.utils import save_to_db from flexmeasures.data.services.utils import get_asset_or_sensor_ref from flexmeasures.data.models.reporting.profit import ProfitOrLossReporter @@ -164,6 +174,79 @@ def new_account_role(name: str, description: str): ) +@fm_add_data.command("plan") +@with_appcontext +@click.option("--name", required=True, help="Name of the plan, e.g. 'Pro'.") +@click.option( + "--default-rate-limit", + callback=validate_rate_limit_cli, + help="How often accounts on this plan may call any API endpoint, e.g. '1000 per minute'." + " Defaults to the FLEXMEASURES_API_DEFAULT_RATE_LIMIT setting. Pass 'unlimited' to exempt them.", +) +@click.option( + "--trigger-rate-limit", + callback=validate_rate_limit_cli, + help="How often accounts on this plan may trigger a schedule or forecast, e.g. '60 per 5 minutes'." + " Defaults to the FLEXMEASURES_API_TRIGGER_RATE_LIMIT setting. Pass 'unlimited' to exempt them.", +) +@click.option( + "--rate-limit-key", + type=click.Choice([key.value for key in RateLimitKey]), + help="What the trigger rate limit is counted against." + " Defaults to the FLEXMEASURES_API_RATE_LIMIT_KEY setting.", +) +@click.option( + "--max-users", + type=int, + help="How many users an account on this plan may have (not enforced yet).", +) +@click.option( + "--max-assets", + type=int, + help="How many assets an account on this plan may have (not enforced yet).", +) +@click.option( + "--max-clients", + type=int, + help="How many client accounts a consultancy account on this plan may have (not enforced yet).", +) +def new_plan( + name: str, + default_rate_limit: str | None, + trigger_rate_limit: str | None, + rate_limit_key: str | None, + max_users: int | None, + max_assets: int | None, + max_clients: int | None, +): + """ + Create a plan, which bundles the rate limits and quotas for the accounts assigned to it. + + Assign accounts to a plan from the account page in the UI (as an admin). + Any limit left unset falls back to the server-wide config setting. + """ + plan = db.session.execute(select(Plan).filter_by(name=name)).scalar_one_or_none() + if plan is not None: + click.secho(f"Plan '{name}' already exists.", **MsgStyle.ERROR) + raise click.Abort() + + plan = Plan( + name=name, + default_rate_limit=default_rate_limit, + trigger_rate_limit=trigger_rate_limit, + rate_limit_key=RateLimitKey(rate_limit_key) if rate_limit_key else None, + max_users=max_users, + max_assets=max_assets, + max_clients=max_clients, + ) + db.session.add(plan) + db.session.commit() + click.secho( + f"Plan '{name}' (ID: {plan.id}) successfully created.", + **MsgStyle.SUCCESS, + ) + + @fm_add_data.command("account") @with_appcontext @click.option("--name", required=True) diff --git a/flexmeasures/cli/data_edit.py b/flexmeasures/cli/data_edit.py index 8505013cfa..9c35d9ce4a 100644 --- a/flexmeasures/cli/data_edit.py +++ b/flexmeasures/cli/data_edit.py @@ -9,9 +9,9 @@ from flask import current_app as app from flask.cli import with_appcontext import json -from flexmeasures.data.models.user import Account +from flexmeasures.data.models.user import Account, Plan, RateLimitKey from flexmeasures.data.schemas.account import AccountIdField -from sqlalchemy import delete +from sqlalchemy import delete, select from flexmeasures import Sensor, Asset from flexmeasures.data import db @@ -27,6 +27,7 @@ DeprecatedOption, DeprecatedOptionsCommand, abort, + validate_rate_limit_cli, ) from flexmeasures.utils.flexmeasures_inflection import pluralize from flexmeasures.utils.secrets_utils import store_account_secret, store_asset_secret @@ -53,6 +54,86 @@ def fm_edit_data(): """FlexMeasures: Edit data.""" +@fm_edit_data.command("plan") +@with_appcontext +@click.option("--name", required=True, help="Name of the plan to edit.") +@click.option( + "--default-rate-limit", + callback=validate_rate_limit_cli, + help="How often accounts on this plan may call any API endpoint, e.g. '1000 per minute'." + " Pass 'unlimited' to exempt them.", +) +@click.option( + "--trigger-rate-limit", + callback=validate_rate_limit_cli, + help="How often accounts on this plan may trigger a schedule or forecast, e.g. '60 per 5 minutes'." + " Pass 'unlimited' to exempt them.", +) +@click.option( + "--rate-limit-key", + type=click.Choice([key.value for key in RateLimitKey]), + help="What the trigger rate limit is counted against.", +) +@click.option( + "--max-users", type=int, help="How many users an account on this plan may have." +) +@click.option( + "--max-assets", type=int, help="How many assets an account on this plan may have." +) +@click.option( + "--max-clients", + type=int, + help="How many client accounts a consultancy account on this plan may have.", +) +@click.option( + "--legacy/--no-legacy", + default=None, + help="Retire this plan (or bring it back). A legacy plan keeps applying to the accounts already on it," + " but is no longer offered when assigning a plan.", +) +def edit_plan( + name: str, + default_rate_limit: str | None, + trigger_rate_limit: str | None, + rate_limit_key: str | None, + max_users: int | None, + max_assets: int | None, + max_clients: int | None, + legacy: bool | None, +): + """ + Edit a plan's rate limits and quotas, or retire it. + + Only the fields you pass are changed. A plan usually reflects a contractual agreement, + so consider retiring a plan (--legacy) and creating a new one, rather than editing one + which accounts are on. + """ + plan = db.session.execute(select(Plan).filter_by(name=name)).scalar_one_or_none() + if plan is None: + abort(f"Plan '{name}' does not exist.") + + updates = { + "default_rate_limit": default_rate_limit, + "trigger_rate_limit": trigger_rate_limit, + "rate_limit_key": RateLimitKey(rate_limit_key) if rate_limit_key else None, + "max_users": max_users, + "max_assets": max_assets, + "max_clients": max_clients, + "legacy": legacy, + } + updates = {field: value for field, value in updates.items() if value is not None} + if not updates: + abort("Nothing to edit. Pass at least one field to change.") + for field, value in updates.items(): + setattr(plan, field, value) + db.session.commit() + + click.secho( + f"Plan '{name}' (ID: {plan.id}) successfully edited: {', '.join(updates)}.", + **MsgStyle.SUCCESS, + ) + + @fm_edit_data.command("attribute") @with_appcontext @click.option( diff --git a/flexmeasures/cli/tests/test_data_add.py b/flexmeasures/cli/tests/test_data_add.py index 5386a774bf..7a52abc72e 100644 --- a/flexmeasures/cli/tests/test_data_add.py +++ b/flexmeasures/cli/tests/test_data_add.py @@ -6,6 +6,7 @@ AccountAnnotationRelationship, ) from flexmeasures.data.models.data_sources import DataSource +from flexmeasures.data.models.user import Plan, RateLimitKey from flexmeasures.cli.tests.utils import ( check_command_ran_without_error, @@ -49,6 +50,63 @@ def test_add_annotation(app, fresh_db, setup_roles_users_fresh_db): ).scalar_one_or_none() +def test_add_plan(app, fresh_db): + from flexmeasures.cli.data_add import new_plan + + db = fresh_db + cli_input = { + "name": "Pro", + "trigger-rate-limit": "60 per 5 minutes", + "rate-limit-key": "account", + "max-assets": 200, + } + runner = app.test_cli_runner() + result = runner.invoke(new_plan, to_flags(cli_input)) + + check_command_ran_without_error(result) + assert "successfully created" in result.output + + plan = db.session.execute(select(Plan).filter_by(name="Pro")).scalar_one() + assert plan.trigger_rate_limit == "60 per 5 minutes" + assert plan.rate_limit_key == RateLimitKey.ACCOUNT + assert plan.max_assets == 200 + # Fields we did not set fall back on the server-wide config settings + assert plan.default_rate_limit is None + assert plan.legacy is False + + +def test_add_plan_with_invalid_rate_limit(app, fresh_db): + """A limit string we cannot make sense of is caught when the plan is created, + rather than when a request comes in.""" + from flexmeasures.cli.data_add import new_plan + + db = fresh_db + runner = app.test_cli_runner() + result = runner.invoke( + new_plan, to_flags({"name": "Typo", "trigger-rate-limit": "10 per fortnight"}) + ) + + assert result.exit_code != 0 + assert "not a valid rate limit" in result.output + assert db.session.execute(select(Plan).filter_by(name="Typo")).scalar() is None + + +def test_edit_plan(app, fresh_db): + """A plan can be retired, so that it is no longer handed out.""" + from flexmeasures.cli.data_edit import edit_plan + + db = fresh_db + plan = Plan(name="Pro", trigger_rate_limit="60 per 5 minutes") + db.session.add(plan) + db.session.commit() + + runner = app.test_cli_runner() + result = runner.invoke(edit_plan, ["--name", "Pro", "--legacy"]) + + check_command_ran_without_error(result) + assert db.session.execute(select(Plan).filter_by(name="Pro")).scalar_one().legacy + + def test_add_holidays(app, fresh_db, setup_roles_users_fresh_db): from flexmeasures.cli.data_add import add_holidays diff --git a/flexmeasures/cli/utils.py b/flexmeasures/cli/utils.py index f2a2ba10bb..84090e2492 100644 --- a/flexmeasures/cli/utils.py +++ b/flexmeasures/cli/utils.py @@ -17,7 +17,11 @@ from flexmeasures.data.schemas.utils import MarshmallowClickMixin from flexmeasures.utils.time_utils import get_most_recent_hour, get_timezone -from flexmeasures.utils.validation_utils import validate_color_hex, validate_url +from flexmeasures.utils.validation_utils import ( + validate_color_hex, + validate_rate_limit, + validate_url, +) from flexmeasures import Sensor @@ -317,6 +321,27 @@ def get_sensor_aliases( return aliases +def validate_rate_limit_cli(ctx, param, value): + """ + Optional parameter validation + + Validates that a given value is a rate limit Flask-Limiter can make sense of, + like "10 per 5 minutes", or "unlimited". + + Parameters: + :param ctx: Click context. + :param param: Click parameter name. + :param value: The rate limit to validate. + """ + + try: + validate_rate_limit(value) + except ValueError as e: + click.secho(str(e), **MsgStyle.ERROR) + raise click.Abort() + return value + + def validate_color_cli(ctx, param, value): """ Optional parameter validation diff --git a/flexmeasures/data/migrations/versions/6a767f36151c_add_plan_table_and_account_plan_id.py b/flexmeasures/data/migrations/versions/6a767f36151c_add_plan_table_and_account_plan_id.py index a34e160378..4170b00a86 100644 --- a/flexmeasures/data/migrations/versions/6a767f36151c_add_plan_table_and_account_plan_id.py +++ b/flexmeasures/data/migrations/versions/6a767f36151c_add_plan_table_and_account_plan_id.py @@ -31,6 +31,9 @@ def upgrade(): sa.Column("max_users", sa.Integer(), nullable=True), sa.Column("max_assets", sa.Integer(), nullable=True), sa.Column("max_clients", sa.Integer(), nullable=True), + sa.Column( + "legacy", sa.Boolean(), nullable=False, server_default=sa.text("false") + ), sa.PrimaryKeyConstraint("id", name=op.f("plan_pkey")), sa.UniqueConstraint("name", name=op.f("plan_name_key")), ) diff --git a/flexmeasures/data/models/user.py b/flexmeasures/data/models/user.py index 69098986b8..75dd3f05e3 100644 --- a/flexmeasures/data/models/user.py +++ b/flexmeasures/data/models/user.py @@ -90,6 +90,10 @@ class Plan(db.Model): # For consultancy accounts, capping the number of client accounts they may manage. max_clients = Column(Integer, nullable=True) + # A plan usually reflects a contractual agreement, so rather than editing one that accounts are on, + # retire it: a legacy plan keeps applying to the accounts already on it, but is no longer handed out. + legacy = Column(Boolean, nullable=False, default=False, server_default="false") + def __repr__(self): return "" % (self.name, self.id) diff --git a/flexmeasures/data/schemas/account.py b/flexmeasures/data/schemas/account.py index d38a1093bd..4d4a9c17ae 100644 --- a/flexmeasures/data/schemas/account.py +++ b/flexmeasures/data/schemas/account.py @@ -39,6 +39,7 @@ class Meta: attributes = JSON(required=False, load_default={}) account_roles = fields.Nested("AccountRoleSchema", exclude=("accounts",), many=True) consultancy_account_id = ma.auto_field() + plan_id = ma.auto_field(allow_none=True) @validates("primary_color") def validate_primary_color(self, value, **kwargs): diff --git a/flexmeasures/ui/static/openapi-specs.json b/flexmeasures/ui/static/openapi-specs.json index 8daa70bebd..ba6b5d977e 100644 --- a/flexmeasures/ui/static/openapi-specs.json +++ b/flexmeasures/ui/static/openapi-specs.json @@ -1805,7 +1805,7 @@ }, "patch": { "summary": "Update an existing account.", - "description": "This endpoint updates the details for an existing account.\n\nIn the JSON body, sent in only the fields you want to update.\n\nRestrictions on Fields:\n- The id field is read-only and cannot be updated.\n- The consultancy_account_id field can only be edited if the current user has an admin role.\n", + "description": "This endpoint updates the details for an existing account.\n\nIn the JSON body, sent in only the fields you want to update.\n\nRestrictions on Fields:\n- The id field is read-only and cannot be updated.\n- The consultancy_account_id field can only be edited if the current user has an admin role.\n- The plan_id field can only be edited if the current user has an admin role, and cannot be set to a legacy plan.\n", "security": [ { "ApiKeyAuth": [] @@ -5334,6 +5334,12 @@ "integer", "null" ] + }, + "plan_id": { + "type": [ + "integer", + "null" + ] } }, "additionalProperties": false @@ -6088,6 +6094,12 @@ "integer", "null" ] + }, + "plan_id": { + "type": [ + "integer", + "null" + ] } }, "required": [ diff --git a/flexmeasures/ui/templates/accounts/account.html b/flexmeasures/ui/templates/accounts/account.html index 82a2f99731..51811f9bb4 100644 --- a/flexmeasures/ui/templates/accounts/account.html +++ b/flexmeasures/ui/templates/accounts/account.html @@ -143,6 +143,25 @@

Edit {{ account.name }}

+ +
+
+ + +
+
{% endif %} @@ -189,10 +208,18 @@

Account

}} - {% if account.consultancy_account_name %} + + Plan + + {% if account.plan %} {{ account.plan.name }}{% if + account.plan.legacy %} (legacy){% endif %} {% else %} No + plan (server defaults apply) {% endif %} + + + {% if account.consultancy_account %} Consultancy - {{ account.consultancy_account_name }} + {{ account.consultancy_account.name }} {% endif %} {% if account.primary_color %} diff --git a/flexmeasures/ui/tests/test_account_crud.py b/flexmeasures/ui/tests/test_account_crud.py index 73dfe4379a..2b5d51d2e2 100644 --- a/flexmeasures/ui/tests/test_account_crud.py +++ b/flexmeasures/ui/tests/test_account_crud.py @@ -3,6 +3,7 @@ from flask import url_for from flask_login import current_user +from flexmeasures.data.models.user import Plan from flexmeasures.ui.tests.utils import login, logout @@ -41,6 +42,42 @@ def test_account_page_breadcrumb(db, client, as_prosumer_user1): assert current_user.account.name.encode() in account_page.data +def test_account_page_shows_plan(db, client, setup_accounts, as_prosumer_user1): + """The account page says which plan the account is on.""" + prosumer_account = setup_accounts["Prosumer"] + prosumer_account.plan = Plan(name="Pro", trigger_rate_limit="60 per 5 minutes") + db.session.commit() + + account_page = client.get( + url_for("AccountCrudUI:get", account_id=prosumer_account.id), + follow_redirects=True, + ) + assert account_page.status_code == 200 + assert b"Pro" in account_page.data + # A regular user does not get to change the plan + assert b'name="plan_id"' not in account_page.data + + +def test_account_page_lets_admin_change_the_plan( + db, client, setup_accounts, setup_roles_users, as_admin +): + """Admins get a dropdown of the plans they can put the account on.""" + prosumer_account = setup_accounts["Prosumer"] + db.session.add(Plan(name="Enterprise")) + db.session.add(Plan(name="Retired plan", legacy=True)) + db.session.commit() + + account_page = client.get( + url_for("AccountCrudUI:get", account_id=prosumer_account.id), + follow_redirects=True, + ) + assert account_page.status_code == 200 + assert b'name="plan_id"' in account_page.data + assert b"Enterprise" in account_page.data + # A plan we no longer hand out is not on offer + assert b"Retired plan" not in account_page.data + + def test_account_page_forbidden_for_different_account_user( db, client, setup_accounts, as_dummy_user3 ): diff --git a/flexmeasures/ui/views/accounts.py b/flexmeasures/ui/views/accounts.py index 58fc5288b3..f2c2129f92 100644 --- a/flexmeasures/ui/views/accounts.py +++ b/flexmeasures/ui/views/accounts.py @@ -1,6 +1,6 @@ from __future__ import annotations -from sqlalchemy import select +from sqlalchemy import or_, select from werkzeug.exceptions import Forbidden, NotFound, Unauthorized from flask_classful import FlaskView from flask_security import login_required @@ -11,7 +11,7 @@ from flexmeasures.ui.utils.view_utils import render_flexmeasures_template, ICON_MAPPING from flexmeasures.ui.utils.breadcrumb_utils import get_breadcrumb_info from flexmeasures.data.models.audit_log import AuditLog -from flexmeasures.data.models.user import Account +from flexmeasures.data.models.user import Account, Plan from flexmeasures.data.services.accounts import get_accounts, get_audit_log_records from flexmeasures.data import db from flexmeasures.ui.views import ( @@ -50,6 +50,17 @@ def get(self, account_id: str): potential_consultant_accounts = ( get_accounts() if user_has_admin_access(current_user, "read") else [] ) + # Only admins get to assign a plan, and only a plan we still hand out + # (or the legacy plan the account happens to be on already) + assignable_plans = ( + db.session.scalars( + select(Plan) + .filter(or_(Plan.legacy.is_(False), Plan.id == account.plan_id)) + .order_by(Plan.name) + ).all() + if user_has_admin_access(current_user, "read") + else [] + ) user_can_view_account_auditlog = True try: @@ -73,6 +84,7 @@ def get(self, account_id: str): "accounts/account.html", account=account, accounts=potential_consultant_accounts, + plans=assignable_plans, user_can_update_account=user_can_update_account, user_can_create_children=user_can_create_children, can_view_account_auditlog=user_can_view_account_auditlog, diff --git a/flexmeasures/utils/config_defaults.py b/flexmeasures/utils/config_defaults.py index 4202ef80fe..327e7f707e 100644 --- a/flexmeasures/utils/config_defaults.py +++ b/flexmeasures/utils/config_defaults.py @@ -183,7 +183,7 @@ class Config(object): FLEXMEASURES_API_DEFAULT_RATE_LIMIT: str = "500 per minute" FLEXMEASURES_API_TRIGGER_RATE_LIMIT: str = "10 per 5 minutes" FLEXMEASURES_API_RATE_LIMIT_KEY: str = ( - "account+asset" # what to count triggers against: "account+asset", "account" or "user" + "account" # what to count triggers against: "account", "account+asset" or "user" ) FLEXMEASURES_JS_VERSIONS: dict = dict( vega="5.22.1", diff --git a/flexmeasures/utils/validation_utils.py b/flexmeasures/utils/validation_utils.py index 651dbcd683..9096f75ba2 100644 --- a/flexmeasures/utils/validation_utils.py +++ b/flexmeasures/utils/validation_utils.py @@ -3,10 +3,33 @@ from typing import Callable import re +import limits + from flexmeasures.data.models.time_series import Sensor from flexmeasures.utils.unit_utils import ur +UNLIMITED_RATE_LIMIT = "unlimited" + + +def validate_rate_limit(value: str | None): + """ + Validate that a value is a rate limit which Flask-Limiter can make sense of, + like "500 per minute", or the special value "unlimited". + + Raises a ValueError if it is not. + """ + if value is None or value == UNLIMITED_RATE_LIMIT: + return + try: + limits.parse(value) + except ValueError: + raise ValueError( + f"'{value}' is not a valid rate limit." + f" Use a limit like '10 per 5 minutes', or '{UNLIMITED_RATE_LIMIT}'." + ) + + def validate_color_hex(value): """ Validates that a given value is a valid hex color code.