diff --git a/.dockerignore b/.dockerignore index 63d042f15..a0c82d379 100644 --- a/.dockerignore +++ b/.dockerignore @@ -17,3 +17,7 @@ geoportal/geomapfish_geoportal/locale/*.pot !package-lock.json !tsconfig.json !vite.config.ts +!ui +ui/dist/ +ui/node_modules/ +ui/static/fa-* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 900e981a9..9cf148621 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,13 +28,17 @@ repos: |geoportal/webpack.apps.js )$ - repo: https://github.com/sbrunner/integrity-updater - rev: 0.1.0 + rev: 0.2.0 hooks: - id: integrity-updater include: |- (?x)^( geoportal/geomapfish_geoportal/static/.* + |ui/.* )$ + args: + - --pre-commit + - --blacklist=https://maps\.googleapis\.com/ - repo: https://github.com/PyCQA/autoflake rev: v2.3.1 hooks: @@ -71,6 +75,10 @@ repos: - id: check-toml - id: check-yaml - id: check-json + exclude: |- + (?x)^( + ui/tsconfig\.json + )$ - id: end-of-file-fixer - id: trailing-whitespace - id: mixed-line-ending @@ -92,6 +100,7 @@ repos: (?x)^( pyproject\.toml )$ + - id: npm-lock - repo: https://github.com/codespell-project/codespell rev: v2.3.0 hooks: @@ -99,12 +108,14 @@ repos: exclude: |- (?x)^( (.*/)?poetry\.lock + |(.*/)?package-lock\.json |ci/cleanup |geoportal/geomapfish_geoportal/locale/.* |qgisserver/.*\.qg[sz] |geoportal/geomapfish_geoportal/static/story-map\.html |tilegeneration/config\.yaml\.tmpl |webcomponents/feedback\.ts + |ui/src/webcomponents/feedback\.ts )$ args: - --ignore-words=.github/spell-ignore-words.txt diff --git a/.python-version b/.python-version index c8cfe3959..2c0733315 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.10 +3.11 diff --git a/.secretsignore b/.secretsignore index 702b13f7f..fde2b7ce4 100644 --- a/.secretsignore +++ b/.secretsignore @@ -1 +1,2 @@ -/geoportal/geomapfish_geoportal/static-ngeo/js/apps/desktop_alt.html.ejs +[secrets] +AIzaSyA3NVIy-HOYT0a0CkChA6nFwqEFqHYWBVk diff --git a/.whitesource b/.whitesource deleted file mode 100644 index 705c7540f..000000000 --- a/.whitesource +++ /dev/null @@ -1,14 +0,0 @@ -{ - "scanSettings": { - "baseBranches": [] - }, - "checkRunSettings": { - "vulnerableCheckRunConclusionLevel": "failure", - "displayMode": "diff", - "useMendCheckNames": true - }, - "issueSettings": { - "minSeverityLevel": "LOW", - "issueType": "DEPENDENCY" - } -} diff --git a/Dockerfile b/Dockerfile index b39d2dc47..45aac0490 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ ENV CONFIG_VARS sqlalchemy.url sqlalchemy.pool_recycle sqlalchemy.pool_size sqla dbsessions urllogin host_forward_host headers_whitelist headers_blacklist \ smtp c2c.base_path welcome_email \ lingva_extractor interfaces_config interfaces devserver_url api authentication intranet metrics pdfreport \ - vector_tiles i18next main_ogc_server + vector_tiles i18next main_ogc_server static_files COPY . /tmp/config/ @@ -77,7 +77,7 @@ VOLUME /etc/geomapfish \ ############################################################################### -FROM node:21.2-slim AS custom-build +FROM node:20.18.0-slim AS webcomponent-build WORKDIR /app COPY package.json package-lock.json ./ @@ -86,9 +86,26 @@ RUN npm install --ignore-scripts COPY tsconfig.json vite.config.ts ./ COPY webcomponents/ ./webcomponents/ -RUN npm run build +RUN NODE_ENV=production npm run build + +############################################################################### + +FROM node:20.18.0-slim AS ui-build + +WORKDIR /app +COPY ui/package.json ui/package-lock.json ./ + +RUN npm install --ignore-scripts + +COPY ui/ ./ +RUN NODE_ENV=production npm run build ############################################################################### FROM gmf_config AS config -COPY --from=custom-build /app/dist/ /etc/geomapfish/static/custom/ + +COPY --from=webcomponent-build /app/dist/ /etc/geomapfish/static/custom/ + +COPY --from=ui-build /app/dist/* /etc/static-frontend/ +COPY --from=ui-build /app/node_modules/ngeo/dist/fa-* /etc/static-frontend/ +VOLUME /etc/static-frontend/ diff --git a/Makefile b/Makefile index 64cc1adf1..01528b407 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PROJECT_PUBLIC_URL=https://geomapfish-demo-2-8.camptocamp.com/ +PROJECT_PUBLIC_URL=https://geomapfish-demo-2-9.camptocamp.com/ DUMP_FILE=data/prod-2-7.dump PACKAGE=geomapfish LANGUAGES=en fr de it @@ -29,6 +29,8 @@ checks: prospector eslint ## Runs the checks prospector: ## Runs the Prospector checks docker compose run --entrypoint= --rm --volume=$(CURDIR)/geoportal:/app geoportal \ prospector --output-format=pylint --die-on-tool-error + docker build --tag=custom-checks --target=checks custom + docker run --rm custom-checks prospector --output-format=pylint --die-on-tool-error .PHONY: eslint eslint: ## Runs the eslint checks diff --git a/ci/cleanup b/ci/cleanup index 353622b8d..5248b3108 100755 --- a/ci/cleanup +++ b/ci/cleanup @@ -42,4 +42,3 @@ rm "$1/package-lock.json" rm "$1/custom/requirements.txt" rm "$1/custom/pyproject.toml" rm "$1/custom/poetry.lock" -rm "$1/.secretsignore" diff --git a/custom/.prospector.yaml b/custom/.prospector.yaml index 3d658b50a..2e066f823 100644 --- a/custom/.prospector.yaml +++ b/custom/.prospector.yaml @@ -1,8 +1,13 @@ +inherits: + - utils:base + - utils:fix + - utils:no-design-checks + - duplicated + pylint: disable: - missing-timeout # Default timeout set by c2cwsgiutils bandit: - run: true options: config: .bandit.yaml diff --git a/custom/Dockerfile b/custom/Dockerfile index f053ad10c..656b8593b 100644 --- a/custom/Dockerfile +++ b/custom/Dockerfile @@ -1,21 +1,23 @@ -FROM ghcr.io/osgeo/gdal:ubuntu-small-3.6.4 AS base-all +FROM ghcr.io/osgeo/gdal:ubuntu-small-3.9.2 AS base-all # Fail on error on pipe, see: https://github.com/hadolint/hadolint/wiki/DL4006. # Treat unset variables as an error when substituting. # Print commands and their arguments as they are executed. SHELL ["/bin/bash", "-o", "pipefail", "-cux"] -ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \ - SETUPTOOLS_USE_DISTUTILS=stdlib +ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt RUN --mount=type=cache,target=/var/lib/apt/lists \ apt-get update RUN --mount=type=cache,target=/var/lib/apt/lists \ --mount=type=cache,target=/var/cache,sharing=locked \ - apt-get install --assume-yes --no-install-recommends python3-pip python3-dev + apt-get install --assume-yes --no-install-recommends python3-pip python3-dev python3-venv \ + && python3 -m venv /venv -FROM base-all as poetry +ENV PATH=/venv/bin:$PATH + +FROM base-all AS poetry WORKDIR /tmp COPY requirements.txt ./ @@ -40,13 +42,13 @@ RUN --mount=type=cache,target=/var/cache,sharing=locked \ RUN --mount=type=cache,target=/root/.cache \ --mount=type=bind,from=poetry,source=/tmp,target=/tmp \ python3 -m pip install --disable-pip-version-check --no-deps --requirement=/tmp/requirements.txt \ - && strip /usr/local/lib/python3.*/dist-packages/*/*.so \ + && strip /usr/lib/python3/dist-packages/*/*.so \ && python3 -m compileall -q /usr/local/lib/python3.* -x '/(ptvsd|.*pydev.*|networkx)/' # hadolint ignore=DL3059 RUN apt-get remove --autoremove --assume-yes gcc -FROM base AS lint +FROM base AS checks RUN --mount=type=cache,target=/root/.cache \ --mount=type=bind,from=poetry,source=/tmp,target=/tmp \ @@ -56,22 +58,17 @@ WORKDIR /app COPY . ./ RUN --mount=type=cache,target=/root/.cache \ python3 -m pip install --disable-pip-version-check --no-deps --editable=. \ - && python3 -m compileall -q /app/custom \ - && prospector --output=pylint -X . \ - && touch /tmp/lint.ok + && python3 -m compileall -q /app/custom FROM base AS runtime -# Force to urn the lint with BUILD KIT -COPY --from=lint /tmp/lint.ok /tmp/ - WORKDIR /app COPY . ./ RUN --mount=type=cache,target=/root/.cache \ python3 -m pip install --disable-pip-version-check --no-deps --editable=. \ && python3 -m compileall -q /app/custom -CMD [ "/usr/local/bin/gunicorn", "--paste=production.ini" ] +CMD [ "/venv/bin/gunicorn", "--paste=production.ini" ] ARG GIT_HASH ENV GIT_HASH=${GIT_HASH} diff --git a/custom/custom/__init__.py b/custom/custom/__init__.py index e824b4c53..af76f4a12 100644 --- a/custom/custom/__init__.py +++ b/custom/custom/__init__.py @@ -1,6 +1,7 @@ import c2cwsgiutils.db import c2cwsgiutils.health_check -from pyramid.config import Configurator +from papyrus.renderers import GeoJSON # type: ignore[import-untyped] +from pyramid.config import Configurator # type: ignore[import-untyped] def main(global_config, **settings): @@ -12,6 +13,7 @@ def main(global_config, **settings): config.include(".routes") config.include("c2cwsgiutils.pyramid") dbsession = c2cwsgiutils.db.init(config, "sqlalchemy", "sqlalchemy_slave") + config.add_renderer("geojson", GeoJSON()) config.scan() # Initialize the health checks health_check = c2cwsgiutils.health_check.HealthCheck(config) diff --git a/custom/custom/alembic/env.py b/custom/custom/alembic/env.py index 72c8c7993..98277cfc8 100644 --- a/custom/custom/alembic/env.py +++ b/custom/custom/alembic/env.py @@ -1,7 +1,7 @@ """Pyramid bootstrap environment. """ from alembic import context -from pyramid.paster import get_appsettings, setup_logging +from pyramid.paster import get_appsettings, setup_logging # type: ignore[import-untyped] from sqlalchemy import engine_from_config from custom.models.meta import Base diff --git a/custom/custom/py.typed b/custom/custom/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/custom/custom/scripts/initialize_db.py b/custom/custom/scripts/initialize_db.py index f7a818abf..3de37d181 100644 --- a/custom/custom/scripts/initialize_db.py +++ b/custom/custom/scripts/initialize_db.py @@ -1,7 +1,7 @@ import argparse import sys -from pyramid.paster import bootstrap, setup_logging +from pyramid.paster import bootstrap, setup_logging # type: ignore[import-untyped] from sqlalchemy.exc import OperationalError from custom.models.meta import Base diff --git a/custom/custom/views/__init__.py b/custom/custom/views/__init__.py index 48aedcba7..781365470 100644 --- a/custom/custom/views/__init__.py +++ b/custom/custom/views/__init__.py @@ -1,8 +1,8 @@ import os -import pyramid.request -import pyramid.response -from cornice import Service +import pyramid.request # type: ignore[import-untyped] +import pyramid.response # type: ignore[import-untyped] +from cornice import Service # type: ignore[import-untyped] index = Service( name="index", diff --git a/custom/custom/views/cog.py b/custom/custom/views/cog.py index 31ace5190..37b59dd2c 100644 --- a/custom/custom/views/cog.py +++ b/custom/custom/views/cog.py @@ -1,12 +1,12 @@ import logging import os -import pyramid.request -import pyramid.response +import pyramid.request # type: ignore[import-untyped] +import pyramid.response # type: ignore[import-untyped] from azure.identity import DefaultAzureCredential from azure.storage.blob import BlobServiceClient, ContainerClient -from cornice import Service -from pyramid.httpexceptions import HTTPBadRequest +from cornice import Service # type: ignore[import-untyped] +from pyramid.httpexceptions import HTTPBadRequest # type: ignore[import-untyped] _LOGGING = logging.getLogger(__name__) _CLIENT = None @@ -38,7 +38,7 @@ def _get_azure_container_client(container: str) -> ContainerClient: @feedback.get() def swissalti3d(request: pyramid.request.Request) -> pyramid.response.Response: # Just to demonstrate that we can fet the user information - global _CLIENT + global _CLIENT # pylint: disable=global-statement if _CLIENT is None: _CLIENT = _get_azure_container_client(os.environ["AZURE_CONTAINER_NAME"]) blob = _CLIENT.get_blob_client(blob="swissalti3d_2m_archeo.tif") diff --git a/custom/custom/views/feedback.py b/custom/custom/views/feedback.py index 0da4e22d0..161a3aaae 100644 --- a/custom/custom/views/feedback.py +++ b/custom/custom/views/feedback.py @@ -2,10 +2,10 @@ import os from typing import Any -import pyramid.request +import pyramid.request # type: ignore[import-untyped] import requests -from cornice import Service -from pyramid.httpexceptions import HTTPBadRequest +from cornice import Service # type: ignore[import-untyped] +from pyramid.httpexceptions import HTTPBadRequest # type: ignore[import-untyped] from custom.models.feedback import Feedback from custom.util.send_mail import send_mail @@ -18,6 +18,11 @@ path="/feedback", cors_origins=( (f'https://{os.environ["VISIBLE_WEB_HOST"]}' if "VISIBLE_WEB_HOST" in os.environ else "*"), + *( + ["https://localhost:3002"] + if os.environ.get("DEV", "false").lower() in ("1", "true", "yes") + else [] + ), ), ) @@ -32,7 +37,7 @@ def feedback_post(request: pyramid.request.Request) -> Any: headers={"Cookie": request.headers.get("Cookie"), "Referer": request.referrer}, ).json() ) - except Exception: + except Exception: # pylint: disable=broad-exception-caught LOG.exception("Error on get user information") if ( @@ -64,12 +69,12 @@ def feedback_post(request: pyramid.request.Request) -> Any: text = "\n\n".join( [ "Ceci est un email automatique. Un nouveau feedback a été inséré dans la BD.", - "Cela concerne l'instance : " + instance, - "Son identifiant est le : " + str(new_feedback.id_feedback), - "User agent : " + new_feedback.ua, - "Permalink : " + new_feedback.permalink, - "User email : " + new_feedback.email, - "User text : " + new_feedback.text, + "Cela concerne l'instance: " + instance, + "Son identifiant est le: " + str(new_feedback.id_feedback), + "User agent: " + new_feedback.ua, # type: ignore[list-item] + "Permalink: " + new_feedback.permalink, # type: ignore[list-item] + "User email: " + new_feedback.email, # type: ignore[list-item] + "User text: " + new_feedback.text, # type: ignore[list-item] ] ) subject = "Feedback - Guichet cartographique" diff --git a/custom/custom/views/notfound.py b/custom/custom/views/notfound.py index 8209f8df6..82d96b9ac 100644 --- a/custom/custom/views/notfound.py +++ b/custom/custom/views/notfound.py @@ -1,4 +1,4 @@ -from pyramid.view import notfound_view_config +from pyramid.view import notfound_view_config # type: ignore[import-untyped] @notfound_view_config(renderer="custom:templates/404.mako") diff --git a/custom/custom/views/swisscom_heatmap/entry.py b/custom/custom/views/swisscom_heatmap/entry.py new file mode 100644 index 000000000..b9d6ee7d2 --- /dev/null +++ b/custom/custom/views/swisscom_heatmap/entry.py @@ -0,0 +1,90 @@ +import logging +import os +from datetime import datetime + +import pyramid.httpexceptions # type: ignore[import-untyped] +import pyramid.request # type: ignore[import-untyped] +import pyramid.response # type: ignore[import-untyped] +from cornice import Service # type: ignore[import-untyped] +from geojson import FeatureCollection # type: ignore[import-untyped] + +from custom.views.swisscom_heatmap.query_swisscom_heatmap_api import SwisscomHeatmapApi + +LOG = logging.getLogger(__name__) + +api = SwisscomHeatmapApi() + + +swisscom_heatmap_get_config = Service( + name="swisscom-heatmap-get-config", + description="The swisscom-heatmap get config service", + path="/swisscom-heatmap/get-config.json", + cors_origins=( + (f'https://{os.environ["VISIBLE_WEB_HOST"]}' if "VISIBLE_WEB_HOST" in os.environ else "*"), + *( + ["https://localhost:3002"] + if os.environ.get("DEV", "false").lower() in ("1", "true", "yes") + else [] + ), + ), +) + + +swisscom_heatmap_dwell_density = Service( + name="swisscom-heatmap-dwell-density", + description="The swisscom-heatmap dwell density service", + path="/swisscom-heatmap/dwell-density.json", + cors_origins=( + (f'https://{os.environ["VISIBLE_WEB_HOST"]}' if "VISIBLE_WEB_HOST" in os.environ else "*"), + *( + ["https://localhost:3002"] + if os.environ.get("DEV", "false").lower() in ("1", "true", "yes") + else [] + ), + ), +) + + +swisscom_heatmap_dwell_demographics = Service( + name="swisscom-heatmap-dwell-demographics", + description="The swisscom-heatmap dwell demographics service", + path="/swisscom-heatmap/dwell-demographics.json", + cors_origins=( + (f'https://{os.environ["VISIBLE_WEB_HOST"]}' if "VISIBLE_WEB_HOST" in os.environ else "*"), + *( + ["https://localhost:3002"] + if os.environ.get("DEV", "false").lower() in ("1", "true", "yes") + else [] + ), + ), +) # type: ignore[import-untyped] + + +@swisscom_heatmap_get_config.get(renderer="json") +def entry_get_config(_request: pyramid.request.Request) -> pyramid.response.Response: + return api.get_config() + + +def get_params(request: pyramid.request.Request) -> tuple[int, datetime]: + try: + postal_code = int(request.params["postal_code"]) + date_time = api.parse_date_time(request.params["date_time"]) + except ValueError as exc: + raise pyramid.httpexceptions.HTTPBadRequest() from exc + return postal_code, date_time + + +@swisscom_heatmap_dwell_density.get(renderer="geojson") +def entry_get_dwell_density( + request: pyramid.request.Request, +) -> FeatureCollection | pyramid.response.Response: + postal_code, date_time = get_params(request) + return api.get_dwell_density(postal_code, date_time) + + +@swisscom_heatmap_dwell_demographics.get(renderer="geojson") +def entry_get_dwell_demographics( + request: pyramid.request.Request, +) -> FeatureCollection | pyramid.response.Response: + postal_code, date_time = get_params(request) + return api.get_dwell_demographics(postal_code, date_time) diff --git a/custom/custom/views/swisscom_heatmap/query_swisscom_heatmap_api.py b/custom/custom/views/swisscom_heatmap/query_swisscom_heatmap_api.py new file mode 100644 index 000000000..e166d6d8f --- /dev/null +++ b/custom/custom/views/swisscom_heatmap/query_swisscom_heatmap_api.py @@ -0,0 +1,128 @@ +import logging +import os +from datetime import datetime +from typing import Any + +from geojson import Feature, FeatureCollection, Point # type: ignore[import-untyped] +from oauthlib.oauth2 import BackendApplicationClient +from pyramid.response import Response # type: ignore[import-untyped] +from requests_oauthlib import OAuth2Session # type: ignore[import-untyped] + +from custom.views.swisscom_heatmap.tile_id_to_coordinates import tile_id_to_ll + +LOG = logging.getLogger(__name__) + +CLIENT_ID = os.getenv("SWISSCOM_CLIENT_ID", "") # customer key in the Swisscom digital marketplace +CLIENT_SECRET = os.getenv("SWISSCOM_CLIENT_SECRET", "") # customer secret in the Swisscom digital marketplace +MIN_DATE = os.getenv("MIN_DATE", "03.10.2022") +MAX_DATE = os.getenv("MAX_DATE", "16.10.2022") +MAX_NB_TILES_REQUEST = int(os.getenv("MAX_NB_TILES_REQUEST", "100")) + +BASE_URL = "https://api.swisscom.com/layer/heatmaps/demo" +TKN_URL = "https://consent.swisscom.com/o/oauth2/token" +HEADERS = {"scs-version": "2"} # API version + + +class ExternalAPIError(Exception): + pass + + +class APIUsageExceededError(Exception): + pass + + +class SwisscomHeatmapApi: + error: Response = None + request_date = datetime.now() + nb_requests = 0 + + @staticmethod + def parse_date_time(date_time: str) -> datetime: + return datetime.strptime(date_time, "%d.%m.%YT%H:%M") + + def get_config(self) -> dict[str, str]: + return {"minDate": f"{MIN_DATE}", "maxDate": f"{MAX_DATE}"} + + def auth(self) -> OAuth2Session: + # Fetch an access token + client = BackendApplicationClient(client_id=CLIENT_ID) + oauth = OAuth2Session(client=client) + oauth.fetch_token(token_url=TKN_URL, client_id=CLIENT_ID, client_secret=CLIENT_SECRET) + return oauth + + def get_tiles_ids(self, oauth: OAuth2Session, postal_code: int) -> list[int]: + # For muni/district id, see https://www.atlas.bfs.admin.ch/maps/13/fr/17804_229_228_227/27579.html + # Municipalities and Districts doesn't work well probably because of the free plan + # Get all the first MAX_NB_TILES_REQUEST tile ids associated with the postal code of interest + muni_tiles_json = oauth.get(BASE_URL + f"/grids/postal-code-areas/{postal_code}", headers=HEADERS) + self.check_api_error(muni_tiles_json) + tiles = muni_tiles_json.json()["tiles"] + LOG.info("Nb tiles received: %s", len(tiles)) + return [t["tileId"] for t in muni_tiles_json.json()["tiles"]][:MAX_NB_TILES_REQUEST] + + def query_api_generic( + self, oauth: OAuth2Session, path: str, postal_code: int, date_time: datetime + ) -> str: + LOG.info("Querying with %s, %s, %s", path, postal_code, date_time) + tile_ids = self.get_tiles_ids(oauth, postal_code) + return ( + BASE_URL + + f"/heatmaps/{path}/{date_time.isoformat()}" + + "?tiles=" + + "&tiles=".join(map(str, tile_ids)) + ) + + def response_to_geojson_result(self, data: dict[str, Any]) -> FeatureCollection: + features = [] + for element in data["tiles"]: + coordinate = tile_id_to_ll(element["tileId"]) + features.append(Feature(geometry=Point(coordinate), properties=element)) + return FeatureCollection(features) + + def get_dwell_density(self, postal_code: int, date_time: datetime) -> FeatureCollection | Response: + self.error = None + try: + self.limit_query() + oauth = self.auth() + api_request = self.query_api_generic(oauth, "/dwell-density/hourly", postal_code, date_time) + response = oauth.get(api_request, headers=HEADERS) + self.check_api_error(response) + except (ExternalAPIError, APIUsageExceededError): + return self.error + return self.response_to_geojson_result(response.json()) + + def get_dwell_demographics(self, postal_code: int, date_time: datetime) -> FeatureCollection | Response: + self.error = None + try: + self.limit_query() + oauth = self.auth() + api_request = self.query_api_generic(oauth, "/dwell-demographics/hourly", postal_code, date_time) + response = oauth.get(api_request, headers=HEADERS) + self.check_api_error(response) + except (ExternalAPIError, APIUsageExceededError): + return self.error + return self.response_to_geojson_result(response.json()) + + def check_api_error(self, response: Response): + if response.status_code != 200: + err_code = response.status_code + err_txt = response.text + LOG.warning("External API error (code %s): %s", err_code, err_txt) + self.error = Response(err_txt, status=err_code) + raise ExternalAPIError("External api error") + + def limit_query(self): + """ + Limit amount of allowed queries per day. + [bgerber] It's rude, but we are using my own key ! + """ + delta = datetime.now() - self.request_date + if delta.total_seconds() > 86400: + self.request_date = datetime.now() + self.nb_requests = 0 + self.nb_requests += 1 + LOG.info("Request today %s", self.nb_requests) + if self.nb_requests > 500: + error = "Too much query today, try again tomorrow" + self.error = Response(error, status=403) + raise APIUsageExceededError(error) diff --git a/custom/custom/views/swisscom_heatmap/tile_id_to_coordinates.py b/custom/custom/views/swisscom_heatmap/tile_id_to_coordinates.py new file mode 100644 index 000000000..acbdd4e4e --- /dev/null +++ b/custom/custom/views/swisscom_heatmap/tile_id_to_coordinates.py @@ -0,0 +1,36 @@ +import math + +TILE_W = 100 +TILE_H = 100 + + +def _cantor_pairing(n1: int, n2: int) -> int: + """Cantor pairing function.""" + return ((n1 + n2) * (n1 + n2 + 1)) // 2 + n2 + + +def _cantor_unpairing(n: int) -> tuple[int, int]: + """Inverse Cantor pairing function.""" + w = int((math.sqrt(8 * n + 1) - 1) // 2) + t = (w * w + w) // 2 + n2 = n - t + n1 = w - n2 + return n1, n2 + + +def tile_ll_at(x: float, y: float) -> tuple[int, int]: + """Given a point (LV03), returns the lower-left corner of the tile it belongs to.""" + tix, tiy = x // TILE_W, y // TILE_H + return int(tix * TILE_W), int(tiy * TILE_H) + + +def tile_ll_to_id(tx: int, ty: int) -> int: + """Given the lower-left corner (LV03) of a tile, returns the id of that tile.""" + tix, tiy = tx // TILE_W, ty // TILE_H + return _cantor_pairing(tix, tiy) + + +def tile_id_to_ll(tid: int) -> tuple[int, int]: + """Given the id of a tile, returns the lower-left corner (LV03) of that tile.""" + tix, tiy = _cantor_unpairing(tid) + return tix * TILE_W, tiy * TILE_H diff --git a/custom/gunicorn.conf.py b/custom/gunicorn.conf.py index e8557cb62..c53e07715 100644 --- a/custom/gunicorn.conf.py +++ b/custom/gunicorn.conf.py @@ -7,15 +7,15 @@ from c2cwsgiutils import get_config_defaults -bind = ":8080" +bind = ":8080" # pylint: disable=invalid-name -worker_class = "gthread" +worker_class = "gthread" # pylint: disable=invalid-name workers = os.environ.get("GUNICORN_WORKERS", 2) threads = os.environ.get("GUNICORN_THREADS", 10) -preload = "true" +preload = "true" # pylint: disable=invalid-name -accesslog = "-" +accesslog = "-" # pylint: disable=invalid-name access_log_format = os.environ.get( "GUNICORN_ACCESS_LOG_FORMAT", '%(H)s %({Host}i)s %(m)s %(U)s?%(q)s "%(f)s" "%(a)s" %(s)s %(B)s %(D)s %(p)s', diff --git a/custom/poetry.lock b/custom/poetry.lock index 5d4827993..1f881a5fe 100644 --- a/custom/poetry.lock +++ b/custom/poetry.lock @@ -21,20 +21,15 @@ tz = ["backports.zoneinfo"] [[package]] name = "astroid" -version = "2.15.8" +version = "3.3.5" description = "An abstract syntax tree for Python with inference support." optional = false -python-versions = ">=3.7.2" +python-versions = ">=3.9.0" files = [ - {file = "astroid-2.15.8-py3-none-any.whl", hash = "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c"}, - {file = "astroid-2.15.8.tar.gz", hash = "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a"}, + {file = "astroid-3.3.5-py3-none-any.whl", hash = "sha256:a9d1c946ada25098d790e079ba2a1b112157278f3fb7e718ae6a9252f5835dc8"}, + {file = "astroid-3.3.5.tar.gz", hash = "sha256:5cfc40ae9f68311075d27ef68a4841bdc5cc7f6cf86671b49f00607d30188e2d"}, ] -[package.dependencies] -lazy-object-proxy = ">=1.4.0" -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} -wrapt = {version = ">=1.11,<2", markers = "python_version < \"3.11\""} - [[package]] name = "async-timeout" version = "4.0.3" @@ -127,6 +122,29 @@ test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", toml = ["tomli (>=1.1.0)"] yaml = ["PyYAML"] +[[package]] +name = "build" +version = "1.2.2.post1" +description = "A simple, correct Python build frontend" +optional = false +python-versions = ">=3.8" +files = [ + {file = "build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5"}, + {file = "build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "os_name == \"nt\""} +packaging = ">=19.1" +pyproject_hooks = "*" + +[package.extras] +docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"] +test = ["build[uv,virtualenv]", "filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"] +typing = ["build[uv]", "importlib-metadata (>=5.1)", "mypy (>=1.9.0,<1.10.0)", "tomli", "typing-extensions (>=3.7.4.3)"] +uv = ["uv (>=0.1.18)"] +virtualenv = ["virtualenv (>=20.0.35)"] + [[package]] name = "c2cwsgiutils" version = "6.0.8" @@ -464,6 +482,17 @@ files = [ graph = ["objgraph (>=1.7.2)"] profile = ["gprof2dot (>=2022.7.29)"] +[[package]] +name = "docutils" +version = "0.21.2" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.9" +files = [ + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, +] + [[package]] name = "dodgy" version = "0.2.1" @@ -505,6 +534,35 @@ files = [ [package.dependencies] flake8 = "*" +[[package]] +name = "geoalchemy2" +version = "0.15.2" +description = "Using SQLAlchemy with Spatial Databases" +optional = false +python-versions = ">=3.7" +files = [ + {file = "GeoAlchemy2-0.15.2-py3-none-any.whl", hash = "sha256:546455dc39f5bcdfc5b871e57d3f7546c8a6f798eb364c474200f488ace6fd32"}, + {file = "geoalchemy2-0.15.2.tar.gz", hash = "sha256:3af0272db927373e74ee3b064cdc9464ba08defdb945c51745db1b841482f5dc"}, +] + +[package.dependencies] +packaging = "*" +SQLAlchemy = ">=1.4" + +[package.extras] +shapely = ["Shapely (>=1.7)"] + +[[package]] +name = "geojson" +version = "3.1.0" +description = "Python bindings and utilities for GeoJSON" +optional = false +python-versions = ">=3.7" +files = [ + {file = "geojson-3.1.0-py3-none-any.whl", hash = "sha256:68a9771827237adb8c0c71f8527509c8f5bef61733aa434cefc9c9d4f0ebe8f3"}, + {file = "geojson-3.1.0.tar.gz", hash = "sha256:58a7fa40727ea058efc28b0e9ff0099eadf6d0965e04690830208d3ef571adac"}, +] + [[package]] name = "gitdb" version = "4.0.11" @@ -701,52 +759,6 @@ files = [ [package.extras] colors = ["colorama (>=0.4.6)"] -[[package]] -name = "lazy-object-proxy" -version = "1.10.0" -description = "A fast and thorough lazy object proxy." -optional = false -python-versions = ">=3.8" -files = [ - {file = "lazy-object-proxy-1.10.0.tar.gz", hash = "sha256:78247b6d45f43a52ef35c25b5581459e85117225408a4128a3daf8bf9648ac69"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:855e068b0358ab916454464a884779c7ffa312b8925c6f7401e952dcf3b89977"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab7004cf2e59f7c2e4345604a3e6ea0d92ac44e1c2375527d56492014e690c3"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc0d2fc424e54c70c4bc06787e4072c4f3b1aa2f897dfdc34ce1013cf3ceef05"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e2adb09778797da09d2b5ebdbceebf7dd32e2c96f79da9052b2e87b6ea495895"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1f711e2c6dcd4edd372cf5dec5c5a30d23bba06ee012093267b3376c079ec83"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-win32.whl", hash = "sha256:76a095cfe6045c7d0ca77db9934e8f7b71b14645f0094ffcd842349ada5c5fb9"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:b4f87d4ed9064b2628da63830986c3d2dca7501e6018347798313fcf028e2fd4"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fec03caabbc6b59ea4a638bee5fce7117be8e99a4103d9d5ad77f15d6f81020c"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c83f957782cbbe8136bee26416686a6ae998c7b6191711a04da776dc9e47d4"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009e6bb1f1935a62889ddc8541514b6a9e1fcf302667dcb049a0be5c8f613e56"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75fc59fc450050b1b3c203c35020bc41bd2695ed692a392924c6ce180c6f1dc9"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:782e2c9b2aab1708ffb07d4bf377d12901d7a1d99e5e410d648d892f8967ab1f"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-win32.whl", hash = "sha256:edb45bb8278574710e68a6b021599a10ce730d156e5b254941754a9cc0b17d03"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:e271058822765ad5e3bca7f05f2ace0de58a3f4e62045a8c90a0dfd2f8ad8cc6"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e98c8af98d5707dcdecc9ab0863c0ea6e88545d42ca7c3feffb6b4d1e370c7ba"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:952c81d415b9b80ea261d2372d2a4a2332a3890c2b83e0535f263ddfe43f0d43"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80b39d3a151309efc8cc48675918891b865bdf742a8616a337cb0090791a0de9"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e221060b701e2aa2ea991542900dd13907a5c90fa80e199dbf5a03359019e7a3"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:92f09ff65ecff3108e56526f9e2481b8116c0b9e1425325e13245abfd79bdb1b"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-win32.whl", hash = "sha256:3ad54b9ddbe20ae9f7c1b29e52f123120772b06dbb18ec6be9101369d63a4074"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:127a789c75151db6af398b8972178afe6bda7d6f68730c057fbbc2e96b08d282"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4ed0518a14dd26092614412936920ad081a424bdcb54cc13349a8e2c6d106a"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ad9e6ed739285919aa9661a5bbed0aaf410aa60231373c5579c6b4801bd883c"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc0a92c02fa1ca1e84fc60fa258458e5bf89d90a1ddaeb8ed9cc3147f417255"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0aefc7591920bbd360d57ea03c995cebc204b424524a5bd78406f6e1b8b2a5d8"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5faf03a7d8942bb4476e3b62fd0f4cf94eaf4618e304a19865abf89a35c0bbee"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-win32.whl", hash = "sha256:e333e2324307a7b5d86adfa835bb500ee70bfcd1447384a822e96495796b0ca4"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:cb73507defd385b7705c599a94474b1d5222a508e502553ef94114a143ec6696"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:366c32fe5355ef5fc8a232c5436f4cc66e9d3e8967c01fb2e6302fd6627e3d94"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2297f08f08a2bb0d32a4265e98a006643cd7233fb7983032bd61ac7a02956b3b"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18dd842b49456aaa9a7cf535b04ca4571a302ff72ed8740d06b5adcd41fe0757"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:217138197c170a2a74ca0e05bddcd5f1796c735c37d0eee33e43259b192aa424"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a3a87cf1e133e5b1994144c12ca4aa3d9698517fe1e2ca82977781b16955658"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-win32.whl", hash = "sha256:30b339b2a743c5288405aa79a69e706a06e02958eab31859f7f3c04980853b70"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:a899b10e17743683b293a729d3a11f2f399e8a90c73b089e29f5d0fe3509f0dd"}, - {file = "lazy_object_proxy-1.10.0-pp310.pp311.pp312.pp38.pp39-none-any.whl", hash = "sha256:80fa48bd89c8f2f456fc0765c11c23bf5af827febacd2f523ca5bc1893fcc09d"}, -] - [[package]] name = "mako" version = "1.3.5" @@ -953,7 +965,6 @@ files = [ [package.dependencies] mypy-extensions = ">=1.0.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = ">=4.6.0" [package.extras] @@ -1054,6 +1065,23 @@ files = [ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] +[[package]] +name = "papyrus" +version = "2.6.2" +description = "Geospatial Extensions for Pyramid" +optional = false +python-versions = ">=3.9" +files = [ + {file = "papyrus-2.6.2-py3-none-any.whl", hash = "sha256:e56a0c50ee2fa75de8a0ba71ddfb583adf0a517fbea706c2f2f7ddfc8e364430"}, + {file = "papyrus-2.6.2.tar.gz", hash = "sha256:565d19e30dedcd0b0e7fbee3ba0f9cb5627a6adc135545141dfd2f383776544a"}, +] + +[package.dependencies] +geoalchemy2 = ">=0.0.0,<1.0.0" +geojson = ">=3.0.0,<4.0.0" +pyramid = ">=2.0.0,<3.0.0" +shapely = ">=2.0.0,<3.0.0" + [[package]] name = "pastedeploy" version = "3.1.0" @@ -1276,32 +1304,33 @@ twisted = ["twisted"] [[package]] name = "prospector" -version = "1.10.3" +version = "1.12.0" description = "Prospector is a tool to analyse Python code by aggregating the result of other tools." optional = false -python-versions = ">=3.7.2,<4.0" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "prospector-1.10.3-py3-none-any.whl", hash = "sha256:8567df2218cdc97d29f297ee3e3b54b96b3a2dab835931955c3a7bbd95aff6f7"}, - {file = "prospector-1.10.3.tar.gz", hash = "sha256:f29ab19fd430869eb34490761af77406d2cfedd9b50292cf4d8db0288c9d764a"}, + {file = "prospector-1.12.0-py3-none-any.whl", hash = "sha256:485d889543c8b47e495b2abbf22151e64b3494564874c6e554564f550a891e37"}, + {file = "prospector-1.12.0.tar.gz", hash = "sha256:e598dddc406cbfe8b31a20d4391c7551841ed6772897a290ecaf272ee1ffabf6"}, ] [package.dependencies] -bandit = {version = ">=1.5.1", optional = true, markers = "extra == \"with_bandit\" or extra == \"with_everything\""} +bandit = {version = ">=1.5.1", optional = true, markers = "extra == \"with-bandit\" or extra == \"with_everything\""} dodgy = ">=0.2.1,<0.3.0" -flake8 = "<6.0.0" +flake8 = "<7.0.0" GitPython = ">=3.1.27,<4.0.0" mccabe = ">=0.7.0,<0.8.0" -mypy = {version = ">=0.600", optional = true, markers = "extra == \"with_mypy\" or extra == \"with_everything\""} +mypy = {version = ">=0.600", optional = true, markers = "extra == \"with-mypy\" or extra == \"with_everything\""} packaging = "*" pep8-naming = ">=0.3.3,<=0.10.0" pycodestyle = ">=2.9.0" pydocstyle = ">=2.0.0" -pyflakes = ">=2.2.0,<3" -pylint = ">=2.8.3" +pyflakes = ">=2.2.0,<4" +pylint = ">=3.0" pylint-celery = "0.3" pylint-django = ">=2.5,<2.6" pylint-flask = "0.6" pylint-plugin-utils = ">=0.7,<0.8" +pyroma = {version = ">=2.4", optional = true, markers = "extra == \"with-pyroma\" or extra == \"with_everything\""} PyYAML = "*" requirements-detector = ">=1.2.0" setoptconf-tmp = ">=0.3.1,<0.4.0" @@ -1315,6 +1344,28 @@ with-pyright = ["pyright (>=1.1.3)"] with-pyroma = ["pyroma (>=2.4)"] with-vulture = ["vulture (>=1.5)"] +[[package]] +name = "prospector-profile-duplicated" +version = "1.6.0" +description = "Profile that can be used to disable the duplicated or conflict rules between Prospector and other tools" +optional = false +python-versions = "*" +files = [ + {file = "prospector_profile_duplicated-1.6.0-py2.py3-none-any.whl", hash = "sha256:bf6a6aae0c7de48043b95e4d42e23ccd090c6c7115b6ee8c8ca472ffb1a2022b"}, + {file = "prospector_profile_duplicated-1.6.0.tar.gz", hash = "sha256:9c2d541076537405e8b2484cb6222276a2df17492391b6af1b192695770aab83"}, +] + +[[package]] +name = "prospector-profile-utils" +version = "1.9.1" +description = "Some utility Prospector profiles." +optional = false +python-versions = "*" +files = [ + {file = "prospector_profile_utils-1.9.1-py2.py3-none-any.whl", hash = "sha256:b458d8c4d59bdb1547e4630a2c6de4971946c4f0999443db6a9eef6d216b26b8"}, + {file = "prospector_profile_utils-1.9.1.tar.gz", hash = "sha256:008efa6797a85233fd8093dcb9d86f5fa5d89673e431c15cb1496a91c9b2c601"}, +] + [[package]] name = "psycopg2" version = "2.9.9" @@ -1423,25 +1474,26 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pylint" -version = "2.17.7" +version = "3.3.1" description = "python code static checker" optional = false -python-versions = ">=3.7.2" +python-versions = ">=3.9.0" files = [ - {file = "pylint-2.17.7-py3-none-any.whl", hash = "sha256:27a8d4c7ddc8c2f8c18aa0050148f89ffc09838142193fdbe98f172781a3ff87"}, - {file = "pylint-2.17.7.tar.gz", hash = "sha256:f4fcac7ae74cfe36bc8451e931d8438e4a476c20314b1101c458ad0f05191fad"}, + {file = "pylint-3.3.1-py3-none-any.whl", hash = "sha256:2f846a466dd023513240bc140ad2dd73bfc080a5d85a710afdb728c420a5a2b9"}, + {file = "pylint-3.3.1.tar.gz", hash = "sha256:9f3dcc87b1203e612b78d91a896407787e708b3f189b5fa0b307712d49ff0c6e"}, ] [package.dependencies] -astroid = ">=2.15.8,<=2.17.0-dev0" +astroid = ">=3.3.4,<=3.4.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -dill = {version = ">=0.2", markers = "python_version < \"3.11\""} -isort = ">=4.2.5,<6" +dill = [ + {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, +] +isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} tomlkit = ">=0.10.1" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] spelling = ["pyenchant (>=3.2,<4.0)"] @@ -1464,21 +1516,21 @@ pylint-plugin-utils = ">=0.2.1" [[package]] name = "pylint-django" -version = "2.5.3" +version = "2.5.2" description = "A Pylint plugin to help Pylint understand the Django web framework" optional = false python-versions = "*" files = [ - {file = "pylint-django-2.5.3.tar.gz", hash = "sha256:0ac090d106c62fe33782a1d01bda1610b761bb1c9bf5035ced9d5f23a13d8591"}, - {file = "pylint_django-2.5.3-py3-none-any.whl", hash = "sha256:56b12b6adf56d548412445bd35483034394a1a94901c3f8571980a13882299d5"}, + {file = "pylint-django-2.5.2.tar.gz", hash = "sha256:1933d82b4a92538a3b12aef91adfd7d866befd051d7a02d6245b0f965587d97c"}, + {file = "pylint_django-2.5.2-py3-none-any.whl", hash = "sha256:286dce8a31bc8ed5a523e8d8742b5a0e083b87f5f140ea4cde9aad612c03bd2d"}, ] [package.dependencies] -pylint = ">=2.0,<3" +pylint = ">=2.0" pylint-plugin-utils = ">=0.7" [package.extras] -for-tests = ["coverage", "django-tables2", "django-tastypie", "factory-boy", "pylint (>=2.13)", "pytest", "wheel"] +for-tests = ["coverage", "django-tables2", "django-tastypie", "factory-boy", "pytest", "wheel"] with-django = ["Django"] [[package]] @@ -1508,6 +1560,17 @@ files = [ [package.dependencies] pylint = ">=1.7" +[[package]] +name = "pyproject-hooks" +version = "1.2.0" +description = "Wrappers to call pyproject.toml-based build backend hooks." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913"}, + {file = "pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8"}, +] + [[package]] name = "pyramid" version = "2.0.2" @@ -1611,6 +1674,29 @@ transaction = ">=2.0" docs = ["Sphinx (>=1.8.1)", "pylons-sphinx-themes (>=1.0.9)"] testing = ["WebTest", "coverage (>=5.0)", "pytest", "pytest-cov"] +[[package]] +name = "pyroma" +version = "4.2" +description = "Test your project's packaging friendliness" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyroma-4.2-py3-none-any.whl", hash = "sha256:a59854b6f8a72b55384cc1de42410e5c5ac59d0c40a92e84fd8364aa6cec3e37"}, + {file = "pyroma-4.2.tar.gz", hash = "sha256:6c727dc4a7a10e12274faed5fb47ebd499ca0821995befec98e3cfcaf1e7383c"}, +] + +[package.dependencies] +build = ">=0.7.0" +docutils = "*" +packaging = "*" +pygments = "*" +requests = "*" +setuptools = ">=42" +trove-classifiers = ">=2022.6.26" + +[package.extras] +test = ["setuptools (>=60)", "zest.releaser[recommended]"] + [[package]] name = "pywin32" version = "306" @@ -1755,17 +1841,17 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"] [[package]] name = "requirements-detector" -version = "1.2.2" +version = "1.3.1" description = "Python tool to find and list requirements of a Python project" optional = false -python-versions = ">=3.7,<4.0" +python-versions = "<4.0,>=3.8" files = [ - {file = "requirements_detector-1.2.2-py3-none-any.whl", hash = "sha256:d7c60493bf166da3dd59de0e6cb25765e0e32a1931aeae92614034e5786d0bd0"}, - {file = "requirements_detector-1.2.2.tar.gz", hash = "sha256:3642cd7a5b261d79536c36bb7ecacf2adabd902d2e0e42bfb2ba82515da10501"}, + {file = "requirements_detector-1.3.1-py3-none-any.whl", hash = "sha256:3ef72e1c5c3ad11100058e8f074a5762a4902985e698099d2e7f1283758d4045"}, + {file = "requirements_detector-1.3.1.tar.gz", hash = "sha256:b89e34faf0e4d17f5736923918bd5401949cbe723294ccfefd698b3cda28e676"}, ] [package.dependencies] -astroid = ">=2.0,<3.0" +astroid = ">=3.0,<4.0" packaging = ">=21.3" semver = ">=3.0.0,<4.0.0" toml = ">=0.10.2,<0.11.0" @@ -1784,7 +1870,6 @@ files = [ [package.dependencies] markdown-it-py = ">=2.2.0" pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] @@ -1927,6 +2012,64 @@ enabler = ["pytest-enabler (>=2.2)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] +[[package]] +name = "shapely" +version = "2.0.6" +description = "Manipulation and analysis of geometric objects" +optional = false +python-versions = ">=3.7" +files = [ + {file = "shapely-2.0.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29a34e068da2d321e926b5073539fd2a1d4429a2c656bd63f0bd4c8f5b236d0b"}, + {file = "shapely-2.0.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c84c3f53144febf6af909d6b581bc05e8785d57e27f35ebaa5c1ab9baba13b"}, + {file = "shapely-2.0.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ad2fae12dca8d2b727fa12b007e46fbc522148a584f5d6546c539f3464dccde"}, + {file = "shapely-2.0.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3304883bd82d44be1b27a9d17f1167fda8c7f5a02a897958d86c59ec69b705e"}, + {file = "shapely-2.0.6-cp310-cp310-win32.whl", hash = "sha256:3ec3a0eab496b5e04633a39fa3d5eb5454628228201fb24903d38174ee34565e"}, + {file = "shapely-2.0.6-cp310-cp310-win_amd64.whl", hash = "sha256:28f87cdf5308a514763a5c38de295544cb27429cfa655d50ed8431a4796090c4"}, + {file = "shapely-2.0.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5aeb0f51a9db176da9a30cb2f4329b6fbd1e26d359012bb0ac3d3c7781667a9e"}, + {file = "shapely-2.0.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a7a78b0d51257a367ee115f4d41ca4d46edbd0dd280f697a8092dd3989867b2"}, + {file = "shapely-2.0.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f32c23d2f43d54029f986479f7c1f6e09c6b3a19353a3833c2ffb226fb63a855"}, + {file = "shapely-2.0.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3dc9fb0eb56498912025f5eb352b5126f04801ed0e8bdbd867d21bdbfd7cbd0"}, + {file = "shapely-2.0.6-cp311-cp311-win32.whl", hash = "sha256:d93b7e0e71c9f095e09454bf18dad5ea716fb6ced5df3cb044564a00723f339d"}, + {file = "shapely-2.0.6-cp311-cp311-win_amd64.whl", hash = "sha256:c02eb6bf4cfb9fe6568502e85bb2647921ee49171bcd2d4116c7b3109724ef9b"}, + {file = "shapely-2.0.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cec9193519940e9d1b86a3b4f5af9eb6910197d24af02f247afbfb47bcb3fab0"}, + {file = "shapely-2.0.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83b94a44ab04a90e88be69e7ddcc6f332da7c0a0ebb1156e1c4f568bbec983c3"}, + {file = "shapely-2.0.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:537c4b2716d22c92036d00b34aac9d3775e3691f80c7aa517c2c290351f42cd8"}, + {file = "shapely-2.0.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98fea108334be345c283ce74bf064fa00cfdd718048a8af7343c59eb40f59726"}, + {file = "shapely-2.0.6-cp312-cp312-win32.whl", hash = "sha256:42fd4cd4834747e4990227e4cbafb02242c0cffe9ce7ef9971f53ac52d80d55f"}, + {file = "shapely-2.0.6-cp312-cp312-win_amd64.whl", hash = "sha256:665990c84aece05efb68a21b3523a6b2057e84a1afbef426ad287f0796ef8a48"}, + {file = "shapely-2.0.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:42805ef90783ce689a4dde2b6b2f261e2c52609226a0438d882e3ced40bb3013"}, + {file = "shapely-2.0.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6d2cb146191a47bd0cee8ff5f90b47547b82b6345c0d02dd8b25b88b68af62d7"}, + {file = "shapely-2.0.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3fdef0a1794a8fe70dc1f514440aa34426cc0ae98d9a1027fb299d45741c381"}, + {file = "shapely-2.0.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c665a0301c645615a107ff7f52adafa2153beab51daf34587170d85e8ba6805"}, + {file = "shapely-2.0.6-cp313-cp313-win32.whl", hash = "sha256:0334bd51828f68cd54b87d80b3e7cee93f249d82ae55a0faf3ea21c9be7b323a"}, + {file = "shapely-2.0.6-cp313-cp313-win_amd64.whl", hash = "sha256:d37d070da9e0e0f0a530a621e17c0b8c3c9d04105655132a87cfff8bd77cc4c2"}, + {file = "shapely-2.0.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fa7468e4f5b92049c0f36d63c3e309f85f2775752e076378e36c6387245c5462"}, + {file = "shapely-2.0.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed5867e598a9e8ac3291da6cc9baa62ca25706eea186117034e8ec0ea4355653"}, + {file = "shapely-2.0.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81d9dfe155f371f78c8d895a7b7f323bb241fb148d848a2bf2244f79213123fe"}, + {file = "shapely-2.0.6-cp37-cp37m-win32.whl", hash = "sha256:fbb7bf02a7542dba55129062570211cfb0defa05386409b3e306c39612e7fbcc"}, + {file = "shapely-2.0.6-cp37-cp37m-win_amd64.whl", hash = "sha256:837d395fac58aa01aa544495b97940995211e3e25f9aaf87bc3ba5b3a8cd1ac7"}, + {file = "shapely-2.0.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c6d88ade96bf02f6bfd667ddd3626913098e243e419a0325ebef2bbd481d1eb6"}, + {file = "shapely-2.0.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8b3b818c4407eaa0b4cb376fd2305e20ff6df757bf1356651589eadc14aab41b"}, + {file = "shapely-2.0.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbc783529a21f2bd50c79cef90761f72d41c45622b3e57acf78d984c50a5d13"}, + {file = "shapely-2.0.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2423f6c0903ebe5df6d32e0066b3d94029aab18425ad4b07bf98c3972a6e25a1"}, + {file = "shapely-2.0.6-cp38-cp38-win32.whl", hash = "sha256:2de00c3bfa80d6750832bde1d9487e302a6dd21d90cb2f210515cefdb616e5f5"}, + {file = "shapely-2.0.6-cp38-cp38-win_amd64.whl", hash = "sha256:3a82d58a1134d5e975f19268710e53bddd9c473743356c90d97ce04b73e101ee"}, + {file = "shapely-2.0.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:392f66f458a0a2c706254f473290418236e52aa4c9b476a072539d63a2460595"}, + {file = "shapely-2.0.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eba5bae271d523c938274c61658ebc34de6c4b33fdf43ef7e938b5776388c1be"}, + {file = "shapely-2.0.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7060566bc4888b0c8ed14b5d57df8a0ead5c28f9b69fb6bed4476df31c51b0af"}, + {file = "shapely-2.0.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b02154b3e9d076a29a8513dffcb80f047a5ea63c897c0cd3d3679f29363cf7e5"}, + {file = "shapely-2.0.6-cp39-cp39-win32.whl", hash = "sha256:44246d30124a4f1a638a7d5419149959532b99dfa25b54393512e6acc9c211ac"}, + {file = "shapely-2.0.6-cp39-cp39-win_amd64.whl", hash = "sha256:2b542d7f1dbb89192d3512c52b679c822ba916f93479fa5d4fc2fe4fa0b3c9e8"}, + {file = "shapely-2.0.6.tar.gz", hash = "sha256:997f6159b1484059ec239cacaa53467fd8b5564dabe186cd84ac2944663b0bf6"}, +] + +[package.dependencies] +numpy = ">=1.14,<3" + +[package.extras] +docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] +test = ["pytest", "pytest-cov"] + [[package]] name = "six" version = "1.16.0" @@ -2100,17 +2243,6 @@ files = [ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - [[package]] name = "tomlkit" version = "0.13.2" @@ -2154,6 +2286,42 @@ files = [ [package.extras] docs = ["Sphinx (>=1.3.1)", "docutils", "pylons-sphinx-themes"] +[[package]] +name = "trove-classifiers" +version = "2024.10.21.16" +description = "Canonical source for classifiers on PyPI (pypi.org)." +optional = false +python-versions = "*" +files = [ + {file = "trove_classifiers-2024.10.21.16-py3-none-any.whl", hash = "sha256:0fb11f1e995a757807a8ef1c03829fbd4998d817319abcef1f33165750f103be"}, + {file = "trove_classifiers-2024.10.21.16.tar.gz", hash = "sha256:17cbd055d67d5e9d9de63293a8732943fabc21574e4c7b74edf112b4928cf5f3"}, +] + +[[package]] +name = "types-oauthlib" +version = "3.2.0.20240806" +description = "Typing stubs for oauthlib" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-oauthlib-3.2.0.20240806.tar.gz", hash = "sha256:31a8d7f7bffc067a4143d30167694ccb304316aced04de50741014155f502043"}, + {file = "types_oauthlib-3.2.0.20240806-py3-none-any.whl", hash = "sha256:581bb8e194700d16ae1f0b62a6039261ed1afd0b88e78782e1c48f6507c52f34"}, +] + +[[package]] +name = "types-requests" +version = "2.32.0.20240914" +description = "Typing stubs for requests" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-requests-2.32.0.20240914.tar.gz", hash = "sha256:2850e178db3919d9bf809e434eef65ba49d0e7e33ac92d588f4a5e295fffd405"}, + {file = "types_requests-2.32.0.20240914-py3-none-any.whl", hash = "sha256:59c2f673eb55f32a99b2894faf6020e1a9f4a402ad0f192bfee0b64469054310"}, +] + +[package.dependencies] +urllib3 = ">=2" + [[package]] name = "typing-extensions" version = "4.12.2" @@ -2286,13 +2454,13 @@ testing = ["coverage", "pytest", "pytest-cov"] [[package]] name = "waitress" -version = "3.0.0" +version = "3.0.1" description = "Waitress WSGI server" optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" files = [ - {file = "waitress-3.0.0-py3-none-any.whl", hash = "sha256:2a06f242f4ba0cc563444ca3d1998959447477363a2d7e9b8b4d75d35cfd1669"}, - {file = "waitress-3.0.0.tar.gz", hash = "sha256:005da479b04134cdd9dd602d1ee7c49d79de0537610d653674cc6cbde222b8a1"}, + {file = "waitress-3.0.1-py3-none-any.whl", hash = "sha256:26cdbc593093a15119351690752c99adc13cbc6786d75f7b6341d1234a3730ac"}, + {file = "waitress-3.0.1.tar.gz", hash = "sha256:ef0c1f020d9f12a515c4ec65c07920a702613afcad1dbfdc3bcec256b6c072b3"}, ] [package.extras] @@ -2314,85 +2482,6 @@ files = [ docs = ["Sphinx (>=1.7.5)", "pylons-sphinx-themes"] testing = ["coverage", "pytest (>=3.1.0)", "pytest-cov", "pytest-xdist"] -[[package]] -name = "wrapt" -version = "1.16.0" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = ">=3.6" -files = [ - {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, - {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, - {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, - {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, - {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, - {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, - {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, - {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, - {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, - {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, - {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, - {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, - {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, - {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, - {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, - {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, - {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, - {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, -] - [[package]] name = "zope-deprecation" version = "5.0" @@ -2485,5 +2574,5 @@ test = ["zope.testing"] [metadata] lock-version = "2.0" -python-versions = ">=3.9,<3.11" -content-hash = "02f888e6b00f4d70de163b3e6f362faa4e6a061cb0925b65893bd33c8075e765" +python-versions = ">=3.11,<3.13" +content-hash = "f096e578a519ad9db7b34042194027c39d66762b104f4bf6074e71fb9bea2645" diff --git a/custom/pyproject.toml b/custom/pyproject.toml index fd3ca5cd6..e8a192d19 100644 --- a/custom/pyproject.toml +++ b/custom/pyproject.toml @@ -5,13 +5,13 @@ description = 'Not used' authors = [] [tool.poetry.dependencies] -python = ">=3.9,<3.11" +python = ">=3.11,<3.13" gunicorn = "23.0.0" plaster-pastedeploy = "1.0.1" pyramid = "2.0.2" pyramid-mako = "1.1.0" pyramid-debugtoolbar = "4.12.1" -waitress = "3.0.0" +waitress = "3.0.1" alembic = "1.13.3" pyramid-retry = "2.1.1" pyramid-tm = "2.5" @@ -31,10 +31,17 @@ requests-oauthlib = "2.0.0" ujson = "5.10.0" azure-storage-blob = "12.23.1" azure-identity = "1.18.0" +papyrus = "2.6.2" +geojson = "3.1.0" +# To fix CVE urllib3 = { version = "2.2.3", optional = true } certifi = { version = "2024.8.30", optional = true } webob = { version = "1.8.8", optional = true } -cryptography = "43.0.1" +cryptography = { version = "43.0.1", optional = true } [tool.poetry.group.dev.dependencies] -prospector = { version = "1.10.3", extras = ["with_bandit", "with_mypy"] } +prospector = { version = "1.12.0", extras = ["with_bandit", "with_mypy", "with_pyroma"] } +prospector-profile-utils = "1.9.1" +prospector-profile-duplicated = "1.6.0" +types-requests = "2.32.0.20240914" +types-oauthlib = "3.2.0.20240806" diff --git a/custom/setup.py b/custom/setup.py deleted file mode 100755 index 18ba533f1..000000000 --- a/custom/setup.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python3 - - -from setuptools import find_packages, setup - -setup( - name="custom", - packages=find_packages(exclude=["tests.*"]), - entry_points={ - "paste.app_factory": [ - "main = custom:main", - ], - "console_scripts": [ - "custom-initialize-db = custom.scripts.initialize_db:main", - ], - }, -) diff --git a/docker-compose.override.sample.yaml b/docker-compose.override.sample.yaml index 3a226e49c..6393e55d8 100644 --- a/docker-compose.override.sample.yaml +++ b/docker-compose.override.sample.yaml @@ -19,11 +19,11 @@ services: # - ./../c2cgeoportal/geoportal/c2cgeoportal_geoportal:/opt/c2cgeoportal/geoportal/c2cgeoportal_geoportal # - ./../c2cgeoportal/admin/c2cgeoportal_admin:/opt/c2cgeoportal/admin/c2cgeoportal_admin # - ./../c2cgeoportal/bin:/opt/bin - # - ./../c2cwsgiutils/c2cwsgiutils:/usr/local/lib/python3.8/dist-packages/c2cwsgiutils - # - ./../dogpile.cache/dogpile:/usr/local/lib/python3.8/dist-packages/dogpile - # - ./../c2c.template/c2c/template:/usr/local/lib/python3.8/dist-packages/c2c/template + # - ./../c2cwsgiutils/c2cwsgiutils:/venv/lib/python3.8/site-packages/c2cwsgiutils + # - ./../dogpile.cache/dogpile:/venv/lib/python3.8/site-packages/dogpile + # - ./../c2c.template/c2c/template:/venv/lib/python3.8/site-packages/c2c/template command: - - /usr/local/bin/pserve + - /venv/bin/pserve - --reload - c2c:///app/development.ini environment: diff --git a/env.project b/env.project index 577cc9832..6ceb9689f 100644 --- a/env.project +++ b/env.project @@ -82,3 +82,7 @@ BASICAUTH=True # SENTRY_URL=https://8dfa6c72fcad48c487c6a89b22ce581b@o330647.ingest.sentry.io/1851011 # SENTRY_CLIENT_ENVIRONMENT=dev + +# Custom Swisscom heatmap plugin +SWISSCOM_CLIENT_ID=setme +SWISSCOM_CLIENT_SECRET=setme diff --git a/geoportal/CONST_vars.yaml b/geoportal/CONST_vars.yaml index 18f879bc0..e9145897b 100644 --- a/geoportal/CONST_vars.yaml +++ b/geoportal/CONST_vars.yaml @@ -73,6 +73,14 @@ vars: escapeValue: false backend: {} + static_files: + favicon.ico: /etc/geomapfish/static/images/favicon.ico + robot.txt: /etc/geomapfish/static/robot.txt + api.js: /etc/static-ngeo/api.js + api.js.map: /etc/static-ngeo/api.js.map + api.css: /etc/static-ngeo/api.css + apihelp.html: /etc/geomapfish/static/apihelp/index.html + interfaces_config: default: constants: diff --git a/geoportal/geomapfish_geoportal/static/cog.html b/geoportal/geomapfish_geoportal/static/cog.html index 9db100b06..ae7667259 100644 --- a/geoportal/geomapfish_geoportal/static/cog.html +++ b/geoportal/geomapfish_geoportal/static/cog.html @@ -7,7 +7,7 @@
Output message:
+${this.messageText}
+Output message:
+${this.messageText}
+