From 3b975e19ffcf183a675c80a4251a2f0861fcd3da Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Thu, 12 Sep 2024 07:53:19 +0800 Subject: [PATCH 1/9] Tooling changes (linting/formatting). --- .flake8 | 2 +- Dockerfile | 6 +- README.md | 22 ++--- poetry.lock | 166 +++++++++++++++++----------------- pyproject.toml | 10 ++ resource_tracking/settings.py | 19 ++-- resource_tracking/urls.py | 17 ++-- tracking/harvest.py | 40 +++----- tracking/models.py | 66 ++++---------- 9 files changed, 153 insertions(+), 195 deletions(-) diff --git a/.flake8 b/.flake8 index 7fb075d..55c8a7b 100644 --- a/.flake8 +++ b/.flake8 @@ -1,2 +1,2 @@ [flake8] -ignore = E265,E501,E722,W503 +ignore = E265,E501,E722 diff --git a/Dockerfile b/Dockerfile index bad9564..7956b36 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ RUN apt-get update -y \ FROM builder_base_rt AS python_libs_rt WORKDIR /app ARG POETRY_VERSION=1.8.3 -RUN pip install --no-cache-dir --root-user-action=ignore poetry=="${POETRY_VERSION}" +RUN pip install --no-cache-dir --root-user-action=ignore poetry==${POETRY_VERSION} COPY poetry.lock pyproject.toml ./ RUN poetry config virtualenvs.create false \ && poetry install --no-interaction --no-ansi --only main @@ -22,8 +22,8 @@ RUN poetry config virtualenvs.create false \ # Create a non-root user. ARG UID=10001 ARG GID=10001 -RUN groupadd -g "${GID}" appuser \ - && useradd --no-create-home --no-log-init --uid "${UID}" --gid "${GID}" appuser +RUN groupadd -g ${GID} appuser \ + && useradd --no-create-home --no-log-init --uid ${UID} --gid ${GID} appuser # Install the project. FROM python_libs_rt diff --git a/README.md b/README.md index 6d30e55..339ba14 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,9 @@ # Resource Tracking application -Django and Leaflet application that collects tracking information using IMAP -from a mailbox and displays it on a collection of layers provided by -Geoserver. The application also downloads observation data from -automatic weather stations. +Django and Leaflet application that collects tracking device information from a +variety of sources and aggregates it into a single database. -# Installation +## Installation The recommended way to set up this project for development is using [Poetry](https://python-poetry.org/docs/) to install and manage a virtual Python @@ -21,7 +19,7 @@ Manage new or updating project dependencies with Poetry also, like so: poetry add newpackage==1.0 -# Environment variables +## Environment variables This project uses confy to set environment variables (in a `.env` file). The following variables are required for the project to run: @@ -32,7 +30,7 @@ The following variables are required for the project to run: Other environment variables will be required to run the project in production (these are context-dependent). -# Running +## Running Use `runserver` to run a local copy of the application: @@ -42,27 +40,27 @@ Run console commands manually: poetry run python manage.py shell_plus -# Unit tests +## Unit tests Run unit tests like so: poetry run python manage.py test --keepdb -v2 -# Docker image +## Docker image To build a new Docker image from the `Dockerfile`: docker image build -t ghcr.io/dbca-wa/resource_tracking . -# Pre-commit hooks +## Pre-commit hooks This project includes the following pre-commit hooks: -- TruffleHog: https://docs.trufflesecurity.com/docs/scanning-git/precommit-hooks/ +- TruffleHog: Pre-commit hooks may have additional system dependencies to run. Optionally install pre-commit hooks locally like so: poetry run pre-commit install -Reference: https://pre-commit.com/ +Reference: diff --git a/poetry.lock b/poetry.lock index 58a561e..dc1ec08 100644 --- a/poetry.lock +++ b/poetry.lock @@ -176,78 +176,78 @@ files = [ [[package]] name = "cffi" -version = "1.17.0" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, - {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, - {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, - {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, - {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, - {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, - {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, - {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, - {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, - {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, - {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, - {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, - {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, - {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, - {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, - {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] @@ -569,19 +569,19 @@ python-dateutil = ">=2.4" [[package]] name = "filelock" -version = "3.15.4" +version = "3.16.0" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, - {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, + {file = "filelock-3.16.0-py3-none-any.whl", hash = "sha256:f6ed4c963184f4c84dd5557ce8fece759a3724b37b80c6c4f20a2f63a4dc6609"}, + {file = "filelock-3.16.0.tar.gz", hash = "sha256:81de9eb8453c769b63369f87f11131a7ab04e367f8d97ad39dc230daa07e3bec"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] -typing = ["typing-extensions (>=4.8)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.1.1)", "pytest (>=8.3.2)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.3)"] +typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "gunicorn" @@ -797,19 +797,19 @@ ptyprocess = ">=0.5" [[package]] name = "platformdirs" -version = "4.2.2" +version = "4.3.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, + {file = "platformdirs-4.3.2-py3-none-any.whl", hash = "sha256:eb1c8582560b34ed4ba105009a4badf7f6f85768b30126f351328507b2beb617"}, + {file = "platformdirs-4.3.2.tar.gz", hash = "sha256:9e5e27a08aa095dd127b9f2e764d74254f482fef22b0970773bfba79d091ab8c"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] [[package]] name = "pre-commit" @@ -1282,13 +1282,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.26.3" +version = "20.26.4" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"}, - {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"}, + {file = "virtualenv-20.26.4-py3-none-any.whl", hash = "sha256:48f2695d9809277003f30776d155615ffc11328e6a0a8c1f0ec80188d7874a55"}, + {file = "virtualenv-20.26.4.tar.gz", hash = "sha256:c17f4e0f3e6036e9f26700446f85c76ab11df65ff6d8a9cbfad9f71aabfcf23c"}, ] [package.dependencies] diff --git a/pyproject.toml b/pyproject.toml index 35b809a..551ece2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,16 @@ ipdb = "^0.13.13" pre-commit = "^3.8.0" mixer = "^7.2.2" +[tool.ruff] +line-length = 120 +indent-width = 4 + +[tool.ruff.lint] +ignore = ["E265", "E501", "E722"] + +[tool.djlint] +profile = "django" + [build-system] requires = ["poetry-core"] build-backend = "poetry.masonry.api" diff --git a/resource_tracking/settings.py b/resource_tracking/settings.py index a4f8c35..0e983b8 100644 --- a/resource_tracking/settings.py +++ b/resource_tracking/settings.py @@ -1,13 +1,14 @@ -from dbca_utils.utils import env -from django.core.exceptions import DisallowedHost -from django.db.utils import OperationalError -import dj_database_url import os -from pathlib import Path import sys import tomllib +from pathlib import Path from zoneinfo import ZoneInfo +import dj_database_url +from dbca_utils.utils import env +from django.core.exceptions import DisallowedHost +from django.db.utils import OperationalError + # Project paths # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = str(Path(__file__).resolve().parents[1]) @@ -170,12 +171,8 @@ def sentry_excluded_exceptions(event, hint): # Sentry settings SENTRY_DSN = env("SENTRY_DSN", None) SENTRY_SAMPLE_RATE = env("SENTRY_SAMPLE_RATE", 1.0) # Error sampling rate -SENTRY_TRANSACTION_SAMPLE_RATE = env( - "SENTRY_TRANSACTION_SAMPLE_RATE", 0.0 -) # Transaction sampling -SENTRY_PROFILES_SAMPLE_RATE = env( - "SENTRY_PROFILES_SAMPLE_RATE", 0.0 -) # Proportion of sampled transactions to profile. +SENTRY_TRANSACTION_SAMPLE_RATE = env("SENTRY_TRANSACTION_SAMPLE_RATE", 0.0) # Transaction sampling +SENTRY_PROFILES_SAMPLE_RATE = env("SENTRY_PROFILES_SAMPLE_RATE", 0.0) # Proportion of sampled transactions to profile. SENTRY_ENVIRONMENT = env("SENTRY_ENVIRONMENT", None) if SENTRY_DSN and SENTRY_ENVIRONMENT: import sentry_sdk diff --git a/resource_tracking/urls.py b/resource_tracking/urls.py index ba7a4fc..5d551ae 100644 --- a/resource_tracking/urls.py +++ b/resource_tracking/urls.py @@ -6,16 +6,15 @@ from tracking import urls as tracking_urls from tracking.admin import tracking_admin_site - -admin.site.site_header = 'Resource Tracking System administration' -admin.site.index_title = 'Resource Tracking System' -admin.site.site_title = 'Resource Tracking' +admin.site.site_header = "Resource Tracking System administration" +admin.site.index_title = "Resource Tracking System" +admin.site.site_title = "Resource Tracking" urlpatterns = [ - path('admin/', admin.site.urls), - path('sss_admin/', tracking_admin_site.urls), - path('api/', include(v1_api.urls)), - path('', include(tracking_urls)), - path('', RedirectView.as_view(pattern_name='admin:index'), name='home'), + path("admin/", admin.site.urls), + path("sss_admin/", tracking_admin_site.urls), + path("api/", include(v1_api.urls)), + path("", include(tracking_urls)), + path("", RedirectView.as_view(pattern_name="admin:index"), name="home"), ] diff --git a/tracking/harvest.py b/tracking/harvest.py index d18d6ed..f0bcecc 100644 --- a/tracking/harvest.py +++ b/tracking/harvest.py @@ -59,9 +59,7 @@ def harvest_tracking_email(device_type, purge_email=False): # Fetch the email message. status, message = email_utils.email_fetch(imap, uid) if status != "OK": - LOGGER.error( - f"Server response failure on fetching email UID {uid}: {status}" - ) + LOGGER.error(f"Server response failure on fetching email UID {uid}: {status}") continue # `result` will be a LoggedPoint, or None @@ -137,9 +135,7 @@ def save_mp70(message): device.altitude = data["altitude"] device.save() - loggedpoint, created = LoggedPoint.objects.get_or_create( - device=device, seen=seen, point=point - ) + loggedpoint, created = LoggedPoint.objects.get_or_create(device=device, seen=seen, point=point) if created: loggedpoint.source_device_type = "mp70" loggedpoint.heading = data["heading"] @@ -187,9 +183,7 @@ def save_spot(message): device.altitude = data["altitude"] device.save() - loggedpoint, created = LoggedPoint.objects.get_or_create( - device=device, seen=seen, point=point - ) + loggedpoint, created = LoggedPoint.objects.get_or_create(device=device, seen=seen, point=point) if created: loggedpoint.source_device_type = "spot" loggedpoint.heading = data["heading"] @@ -237,9 +231,7 @@ def save_iriditrak(message): device.altitude = data["altitude"] device.save() - loggedpoint, created = LoggedPoint.objects.get_or_create( - device=device, seen=seen, point=point - ) + loggedpoint, created = LoggedPoint.objects.get_or_create(device=device, seen=seen, point=point) if created: loggedpoint.source_device_type = "iriditrak" loggedpoint.heading = data["heading"] @@ -289,9 +281,7 @@ def save_dplus(message): device.altitude = data["altitude"] device.save() - loggedpoint, created = LoggedPoint.objects.get_or_create( - device=device, seen=seen, point=point - ) + loggedpoint, created = LoggedPoint.objects.get_or_create(device=device, seen=seen, point=point) if created: loggedpoint.source_device_type = "dplus" loggedpoint.heading = data["heading"] @@ -343,9 +333,7 @@ def save_dplus(message): def save_dfes_feed(): """Download and process the DFES API endpoint (returns GeoJSON), create new devices, update existing.""" LOGGER.info("Querying DFES API") - resp = requests.get( - url=settings.DFES_URL, auth=(settings.DFES_USER, settings.DFES_PASS) - ) + resp = requests.get(url=settings.DFES_URL, auth=(settings.DFES_USER, settings.DFES_PASS)) resp.raise_for_status() features = resp.json()["features"] LOGGER.info(f"DFES API returned {len(features)} features, processing") @@ -405,9 +393,7 @@ def save_dfes_feed(): device.save() - loggedpoint, created = LoggedPoint.objects.get_or_create( - device=device, seen=seen, point=point - ) + loggedpoint, created = LoggedPoint.objects.get_or_create(device=device, seen=seen, point=point) if created: loggedpoint.source_device_type = "dfes" loggedpoint.heading = data["heading"] @@ -442,6 +428,8 @@ def save_tracplus_feed(): tracplus_symbol_map = { "Aircraft": "spotter aircraft", "Helicopter": "rotary aircraft", + "Person": "person", + "Car": "2 wheel drive", } for row in latest: @@ -469,11 +457,7 @@ def save_tracplus_feed(): continue rego = row["Asset Regn"][:32].strip() - symbol = ( - tracplus_symbol_map[row["Asset Type"]] - if row["Asset Type"] in tracplus_symbol_map - else None - ) + symbol = tracplus_symbol_map[row["Asset Type"]] if row["Asset Type"] in tracplus_symbol_map else None if created: created_device += 1 @@ -497,9 +481,7 @@ def save_tracplus_feed(): device.save() - loggedpoint, created = LoggedPoint.objects.get_or_create( - device=device, seen=seen, point=point - ) + loggedpoint, created = LoggedPoint.objects.get_or_create(device=device, seen=seen, point=point) if created: loggedpoint.source_device_type = "tracplus" loggedpoint.heading = data["heading"] diff --git a/tracking/models.py b/tracking/models.py index 2635481..bac1ea3 100644 --- a/tracking/models.py +++ b/tracking/models.py @@ -1,14 +1,14 @@ +import logging + from django.conf import settings from django.contrib.auth.models import Group, User -from django.db import NotSupportedError from django.contrib.gis.db import models -from django.utils import timezone from django.contrib.humanize.templatetags.humanize import naturaltime -from django.dispatch import receiver -from django.db.models.signals import pre_save, post_save from django.core.validators import MaxValueValidator +from django.db.models.signals import post_save, pre_save +from django.dispatch import receiver from django.forms import ValidationError -import logging +from django.utils import timezone LOGGER = logging.getLogger("tracking") @@ -134,9 +134,7 @@ class Device(models.Model): verbose_name="Device ID", help_text="Device unique identifier", ) - registration = models.CharField( - max_length=32, default="No Rego", help_text="e.g. 1QBB157" - ) + registration = models.CharField(max_length=32, default="No Rego", help_text="e.g. 1QBB157") rin_number = models.PositiveIntegerField( validators=[MaxValueValidator(999)], verbose_name="Resource Identification Number (RIN)", @@ -144,9 +142,7 @@ class Device(models.Model): blank=True, help_text="Heavy Duty, Gang Truck or Plant only (HD/GT/P automatically prefixed).", ) - rin_display = models.CharField( - max_length=5, null=True, blank=True, verbose_name="RIN" - ) + rin_display = models.CharField(max_length=5, null=True, blank=True, verbose_name="RIN") symbol = models.CharField(max_length=32, choices=SYMBOL_CHOICES, default="other") district = models.CharField( max_length=32, @@ -154,22 +150,12 @@ class Device(models.Model): default=DISTRICT_OTHER, verbose_name="Region/District", ) - district_display = models.CharField( - max_length=100, default="Other", verbose_name="District" - ) - usual_driver = models.CharField( - max_length=50, null=True, blank=True, help_text="e.g. John Jones" - ) - usual_location = models.CharField( - max_length=50, null=True, blank=True, help_text="e.g. Karijini National Park" - ) - current_driver = models.CharField( - max_length=50, null=True, blank=True, help_text="e.g. Jodie Jones" - ) + district_display = models.CharField(max_length=100, default="Other", verbose_name="District") + usual_driver = models.CharField(max_length=50, null=True, blank=True, help_text="e.g. John Jones") + usual_location = models.CharField(max_length=50, null=True, blank=True, help_text="e.g. Karijini National Park") + current_driver = models.CharField(max_length=50, null=True, blank=True, help_text="e.g. Jodie Jones") callsign = models.CharField(max_length=50, null=True, blank=True, help_text="") - callsign_display = models.CharField( - max_length=50, null=True, blank=True, verbose_name="Callsign" - ) + callsign_display = models.CharField(max_length=50, null=True, blank=True, verbose_name="Callsign") contractor_details = models.CharField( max_length=50, null=True, @@ -181,24 +167,16 @@ class Device(models.Model): default=False, help_text="Device will only be shown on internal DBCA resource tracking live view (not to DFES, etc.)", ) - hidden = models.BooleanField( - default=False, help_text="Device hidden from DBCA resource tracking live view" - ) + hidden = models.BooleanField(default=False, help_text="Device hidden from DBCA resource tracking live view") deleted = models.BooleanField(default=False, verbose_name="Deleted?") fire_use = models.BooleanField(default=None, null=True, verbose_name="Fire use") seen = models.DateTimeField(null=True, editable=False) point = models.PointField(null=True, editable=False) - heading = models.PositiveIntegerField( - default=0, help_text="Heading in degrees", editable=False - ) - velocity = models.PositiveIntegerField( - default=0, help_text="Speed in metres/hr", editable=False - ) - altitude = models.IntegerField( - default=0, help_text="Altitude above sea level in metres", editable=False - ) + heading = models.PositiveIntegerField(default=0, help_text="Heading in degrees", editable=False) + velocity = models.PositiveIntegerField(default=0, help_text="Speed in metres/hr", editable=False) + altitude = models.IntegerField(default=0, help_text="Altitude above sea level in metres", editable=False) message = models.PositiveIntegerField(default=3, choices=RAW_EQ_CHOICES) source_device_type = models.CharField( max_length=32, @@ -295,15 +273,9 @@ class LoggedPoint(models.Model): device = models.ForeignKey(Device, on_delete=models.PROTECT) seen = models.DateTimeField(editable=False, db_index=True) point = models.PointField(editable=False) - heading = models.PositiveIntegerField( - default=0, help_text="Heading in degrees", editable=False - ) - velocity = models.PositiveIntegerField( - default=0, help_text="Speed in metres/hr", editable=False - ) - altitude = models.IntegerField( - default=0, help_text="Altitude above sea level in metres", editable=False - ) + heading = models.PositiveIntegerField(default=0, help_text="Heading in degrees", editable=False) + velocity = models.PositiveIntegerField(default=0, help_text="Speed in metres/hr", editable=False) + altitude = models.IntegerField(default=0, help_text="Altitude above sea level in metres", editable=False) message = models.PositiveIntegerField(default=3, choices=RAW_EQ_CHOICES) source_device_type = models.CharField( max_length=32, From d7691a98cb67719602f79ad19193fa1e562f043a Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Thu, 12 Sep 2024 08:41:55 +0800 Subject: [PATCH 2/9] Migrate Flake8 config into pyproject.toml --- .flake8 | 2 -- pyproject.toml | 14 +++++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) delete mode 100644 .flake8 diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 55c8a7b..0000000 --- a/.flake8 +++ /dev/null @@ -1,2 +0,0 @@ -[flake8] -ignore = E265,E501,E722 diff --git a/pyproject.toml b/pyproject.toml index 551ece2..c1fd665 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ package-mode = false [tool.poetry.dependencies] python = "^3.12" django = "4.2.15" -psycopg = {version = "3.2.1", extras = ["binary", "pool"]} +psycopg = { version = "3.2.1", extras = ["binary", "pool"] } dbca-utils = "2.0.2" python-dotenv = "1.0.1" dj-database-url = "2.2.0" @@ -18,9 +18,9 @@ django-extensions = "3.2.3" django-tastypie = "0.14.7" django-geojson = "4.1.0" unicodecsv = "0.14.1" -whitenoise = {version = "6.7.0", extras = ["brotli"]} +whitenoise = { version = "6.7.0", extras = ["brotli"] } azure-storage-blob = "12.22.0" -sentry-sdk = {version = "2.14.0", extras = ["django"]} +sentry-sdk = { version = "2.14.0", extras = ["django"] } [tool.poetry.group.dev.dependencies] ipython = "^8.27.0" @@ -28,13 +28,17 @@ ipdb = "^0.13.13" pre-commit = "^3.8.0" mixer = "^7.2.2" +# Reference: https://docs.astral.sh/ruff/configuration/ [tool.ruff] line-length = 120 -indent-width = 4 [tool.ruff.lint] -ignore = ["E265", "E501", "E722"] +ignore = [ + "E501", # Line too long + "E722", # Bare except +] +# Reference: https://www.djlint.com/docs/configuration/ [tool.djlint] profile = "django" From 453c44b0aa6cd77eff2476961ad23412356c442a Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Thu, 12 Sep 2024 09:21:26 +0800 Subject: [PATCH 3/9] Formatter changes. --- tracking/static/js/resource_map.js | 101 +++++++-------- tracking/templates/tracking/resource_map.html | 122 ++++++++++++------ 2 files changed, 135 insertions(+), 88 deletions(-) diff --git a/tracking/static/js/resource_map.js b/tracking/static/js/resource_map.js index 4f1d2fe..71b8c71 100644 --- a/tracking/static/js/resource_map.js +++ b/tracking/static/js/resource_map.js @@ -1,5 +1,7 @@ "use strict"; -const geoserver_wmts_url = geoserver_url + "/gwc/service/wmts?service=WMTS&request=GetTile&version=1.0.0&tilematrixset=gda94&tilematrix=gda94:{z}&tilecol={x}&tilerow={y}"; +const geoserver_wmts_url = + geoserver_url + + "/gwc/service/wmts?service=WMTS&request=GetTile&version=1.0.0&tilematrixset=gda94&tilematrix=gda94:{z}&tilecol={x}&tilerow={y}"; const geoserver_wmts_url_base = geoserver_wmts_url + "&format=image/jpeg"; const geoserver_wmts_url_overlay = geoserver_wmts_url + "&format=image/png"; @@ -34,7 +36,7 @@ const dbcaBushfires = L.tileLayer( zoomOffset: -2, transparent: true, opacity: 0.75, - } + }, ); const dfesBushfires = L.tileLayer( geoserver_wmts_url_overlay + "&layer=landgate:authorised_fireshape_dfes-032", @@ -43,10 +45,11 @@ const dfesBushfires = L.tileLayer( zoomOffset: -2, transparent: true, opacity: 0.75, - } + }, ); const dbcaRegions = L.tileLayer( - geoserver_wmts_url_overlay + "&layer=cddp:kaartdijin-boodja-public_CPT_DBCA_REGIONS", + geoserver_wmts_url_overlay + + "&layer=cddp:kaartdijin-boodja-public_CPT_DBCA_REGIONS", { tileSize: 1024, zoomOffset: -2, @@ -127,13 +130,12 @@ const iconOther = L.icon({ iconAnchor: [16, 16], }); - function setDeviceStyle(feature, layer) { var callsign; if (feature.properties.callsign) { callsign = feature.properties.callsign; } else { - callsign = ''; + callsign = ""; } layer.bindTooltip( ` @@ -142,34 +144,34 @@ function setDeviceStyle(feature, layer) { Callsign: ${callsign}
Type: ${feature.properties.symbol}
Seen: ${feature.properties.age_text} - ` + `, ); // Set the feature icon. - if (feature.properties.icon == 'sss-2_wheel_drive') { + if (feature.properties.icon == "sss-2_wheel_drive") { layer.setIcon(iconCar); - } else if (feature.properties.icon == 'sss-4_wheel_drive_passenger') { + } else if (feature.properties.icon == "sss-4_wheel_drive_passenger") { layer.setIcon(iconCar); - } else if (feature.properties.icon == 'sss-4_wheel_drive_ute') { + } else if (feature.properties.icon == "sss-4_wheel_drive_ute") { layer.setIcon(iconUte); - } else if (feature.properties.icon == 'sss-light_unit') { + } else if (feature.properties.icon == "sss-light_unit") { layer.setIcon(iconLightUnit); - } else if (feature.properties.icon == 'sss-gang_truck') { + } else if (feature.properties.icon == "sss-gang_truck") { layer.setIcon(iconGangTruck); - } else if (feature.properties.icon == 'sss-comms_bus') { + } else if (feature.properties.icon == "sss-comms_bus") { layer.setIcon(iconCommsBus); - } else if (feature.properties.icon == 'sss-rotary_aircraft') { + } else if (feature.properties.icon == "sss-rotary_aircraft") { layer.setIcon(iconRotary); - } else if (feature.properties.icon == 'sss-spotter_aircraft') { + } else if (feature.properties.icon == "sss-spotter_aircraft") { layer.setIcon(iconPlane); - } else if (feature.properties.icon == 'sss-dozer') { + } else if (feature.properties.icon == "sss-dozer") { layer.setIcon(iconDozer); - } else if (feature.properties.icon == 'sss-float') { + } else if (feature.properties.icon == "sss-float") { layer.setIcon(iconFloat); - } else if (feature.properties.icon == 'sss-loader') { + } else if (feature.properties.icon == "sss-loader") { layer.setIcon(iconLoader); - } else if (feature.properties.icon == 'sss-aviation_fuel_truck') { + } else if (feature.properties.icon == "sss-aviation_fuel_truck") { layer.setIcon(iconFuelTruck); - } else if (feature.properties.icon == 'sss-person') { + } else if (feature.properties.icon == "sss-person") { layer.setIcon(iconPerson); } else { layer.setIcon(iconOther); @@ -178,7 +180,7 @@ function setDeviceStyle(feature, layer) { // Add the (initially) empty devices layer to the map. const trackedDevices = L.geoJSON(null, { - onEachFeature: setDeviceStyle + onEachFeature: setDeviceStyle, }); function refreshTrackedDevicesLayer(trackedDevicesLayer) { @@ -187,48 +189,45 @@ function refreshTrackedDevicesLayer(trackedDevicesLayer) { // Initial notification. Toastify({ text: "Refreshing tracked device data", - duration: 1500 + duration: 1500, }).showToast(); // Query the API endpoint for device data. - $.getJSON( - device_geojson_url, - function (data) { - // Add the device data to the GeoJSON layer. - trackedDevicesLayer.addData(data); - // Success notification. - Toastify({ - text: "Tracked device data refreshed", - duration: 1500 - }).showToast(); - }, - ); -}; + $.getJSON(device_geojson_url, function (data) { + // Add the device data to the GeoJSON layer. + trackedDevicesLayer.addData(data); + // Success notification. + Toastify({ + text: "Tracked device data refreshed", + duration: 1500, + }).showToast(); + }); +} // Immediately run the function, once. refreshTrackedDevicesLayer(trackedDevices); // Define map. -var map = L.map('map', { - crs: L.CRS.EPSG4326, // WGS 84 +var map = L.map("map", { + crs: L.CRS.EPSG4326, // WGS 84 center: [-31.96, 115.87], zoom: 12, minZoom: 4, maxZoom: 18, - layers: [mapboxStreets, trackedDevices], // Sets default selections. + layers: [mapboxStreets, trackedDevices], // Sets default selections. attributionControl: false, }); // Define layer groups. var baseMaps = { - 'Mapbox streets': mapboxStreets, - 'Landgate orthomosaic': landgateOrthomosaic, - 'State map base 250K': stateMapBase, + "Mapbox streets": mapboxStreets, + "Landgate orthomosaic": landgateOrthomosaic, + "State map base 250K": stateMapBase, }; var overlayMaps = { - 'Tracked devices': trackedDevices, - 'DBCA Going Bushfires': dbcaBushfires, - 'DFES Going Bushfires': dfesBushfires, - 'DBCA regions': dbcaRegions, - 'LGA boundaries': lgaBoundaries, + "Tracked devices": trackedDevices, + "DBCA Going Bushfires": dbcaBushfires, + "DFES Going Bushfires": dfesBushfires, + "DBCA regions": dbcaRegions, + "LGA boundaries": lgaBoundaries, }; // Define layer control. @@ -244,13 +243,13 @@ map.addControl(fullScreen); // Device registration search const searchControl = new L.Control.Search({ layer: trackedDevices, - propertyName: 'registration', - textPlaceholder: 'Search registration', + propertyName: "registration", + textPlaceholder: "Search registration", delayType: 1000, - textErr: 'Registration not found', + textErr: "Registration not found", zoom: 16, circleLocation: true, - autoCollapse: true + autoCollapse: true, }); map.addControl(searchControl); @@ -258,5 +257,5 @@ const refreshButton = L.easyButton( ``, function (btn, map) { refreshTrackedDevicesLayer(trackedDevices); - } + }, ).addTo(map); diff --git a/tracking/templates/tracking/resource_map.html b/tracking/templates/tracking/resource_map.html index 0d0f382..a379cff 100644 --- a/tracking/templates/tracking/resource_map.html +++ b/tracking/templates/tracking/resource_map.html @@ -1,22 +1,51 @@ {% load static %} - - + {{ page_title }} - - + + - - - - - - - + + + + + + + -
@@ -45,32 +73,52 @@
- - - - - - - - + + + + + + + From 82eafb175431433817f1a55f33ca105b113390e6 Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Tue, 17 Sep 2024 10:48:30 +0800 Subject: [PATCH 4/9] Tweak HealthCheckMiddleware.readiness to close DB cursor. --- manage.py | 5 +++-- resource_tracking/middleware.py | 9 ++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/manage.py b/manage.py index d3bbe1e..45f2a16 100755 --- a/manage.py +++ b/manage.py @@ -3,9 +3,10 @@ import sys # These lines are required for interoperability between local and container environments. -dot_env = os.path.join(os.getcwd(), '.env') +dot_env = os.path.join(os.getcwd(), ".env") if os.path.exists(dot_env): from dotenv import load_dotenv + load_dotenv() @@ -23,5 +24,5 @@ def main(): execute_from_command_line(sys.argv) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/resource_tracking/middleware.py b/resource_tracking/middleware.py index 9510401..c6911c3 100644 --- a/resource_tracking/middleware.py +++ b/resource_tracking/middleware.py @@ -1,13 +1,12 @@ -from django.db import connections -from django.http import HttpResponse, HttpResponseServerError import logging +from django.db import connections +from django.http import HttpResponse, HttpResponseServerError LOGGER = logging.getLogger("django") class HealthCheckMiddleware(object): - def __init__(self, get_response): self.get_response = get_response @@ -20,8 +19,7 @@ def __call__(self, request): return self.get_response(request) def liveness(self, request): - """Returns that the server is alive. - """ + """Returns that the server is alive.""" return HttpResponse("OK") def readiness(self, request): @@ -33,6 +31,7 @@ def readiness(self, request): cursor = connections["default"].cursor() cursor.execute("SELECT 1;") row = cursor.fetchone() + cursor.close() if row is None: return HttpResponseServerError("Database: invalid response") except Exception as e: From 98a20ee6436839fbee0555ee4247b1e61ba99724 Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Tue, 17 Sep 2024 14:11:13 +0800 Subject: [PATCH 5/9] LOGGER.error -> warning to avoid upsetting Sentry. --- tracking/email_utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tracking/email_utils.py b/tracking/email_utils.py index 71a7dd1..d4ebe43 100644 --- a/tracking/email_utils.py +++ b/tracking/email_utils.py @@ -1,7 +1,8 @@ -from django.conf import settings import email -from imaplib import IMAP4, IMAP4_SSL import logging +from imaplib import IMAP4, IMAP4_SSL + +from django.conf import settings LOGGER = logging.getLogger("tracking") @@ -14,7 +15,7 @@ def get_imap(mailbox="INBOX"): imap.select(mailbox) return imap except IMAP4.error: - LOGGER.error("Unable to log into mailbox") + LOGGER.warning("Unable to log into mailbox") return None From 858d262d7028d46983e5a0c236cce94e32cf95dd Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Fri, 20 Sep 2024 10:29:05 +0800 Subject: [PATCH 6/9] Bump psycopg, increment project minor version. --- kustomize/overlays/prod/kustomization.yaml | 2 +- poetry.lock | 139 +++++++++++---------- pyproject.toml | 4 +- 3 files changed, 78 insertions(+), 67 deletions(-) diff --git a/kustomize/overlays/prod/kustomization.yaml b/kustomize/overlays/prod/kustomization.yaml index d7d5169..b7ee3c8 100644 --- a/kustomize/overlays/prod/kustomization.yaml +++ b/kustomize/overlays/prod/kustomization.yaml @@ -26,4 +26,4 @@ patches: - path: service_patch.yaml images: - name: ghcr.io/dbca-wa/resource_tracking - newTag: 1.4.16 + newTag: 1.4.17 diff --git a/poetry.lock b/poetry.lock index dc1ec08..99ef63e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -845,89 +845,100 @@ wcwidth = "*" [[package]] name = "psycopg" -version = "3.2.1" +version = "3.2.2" description = "PostgreSQL database adapter for Python" optional = false python-versions = ">=3.8" files = [ - {file = "psycopg-3.2.1-py3-none-any.whl", hash = "sha256:ece385fb413a37db332f97c49208b36cf030ff02b199d7635ed2fbd378724175"}, - {file = "psycopg-3.2.1.tar.gz", hash = "sha256:dc8da6dc8729dacacda3cc2f17d2c9397a70a66cf0d2b69c91065d60d5f00cb7"}, + {file = "psycopg-3.2.2-py3-none-any.whl", hash = "sha256:babf565d459d8f72fb65da5e211dd0b58a52c51e4e1fa9cadecff42d6b7619b2"}, + {file = "psycopg-3.2.2.tar.gz", hash = "sha256:8bad2e497ce22d556dac1464738cb948f8d6bab450d965cf1d8a8effd52412e0"}, ] [package.dependencies] -psycopg-binary = {version = "3.2.1", optional = true, markers = "implementation_name != \"pypy\" and extra == \"binary\""} +psycopg-binary = {version = "3.2.2", optional = true, markers = "implementation_name != \"pypy\" and extra == \"binary\""} psycopg-pool = {version = "*", optional = true, markers = "extra == \"pool\""} -typing-extensions = ">=4.4" +typing-extensions = {version = ">=4.6", markers = "python_version < \"3.13\""} tzdata = {version = "*", markers = "sys_platform == \"win32\""} [package.extras] -binary = ["psycopg-binary (==3.2.1)"] -c = ["psycopg-c (==3.2.1)"] -dev = ["ast-comments (>=1.1.2)", "black (>=24.1.0)", "codespell (>=2.2)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.6)", "types-setuptools (>=57.4)", "wheel (>=0.37)"] +binary = ["psycopg-binary (==3.2.2)"] +c = ["psycopg-c (==3.2.2)"] +dev = ["ast-comments (>=1.1.2)", "black (>=24.1.0)", "codespell (>=2.2)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.11)", "types-setuptools (>=57.4)", "wheel (>=0.37)"] docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"] pool = ["psycopg-pool"] -test = ["anyio (>=4.0)", "mypy (>=1.6)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"] +test = ["anyio (>=4.0)", "mypy (>=1.11)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"] [[package]] name = "psycopg-binary" -version = "3.2.1" +version = "3.2.2" description = "PostgreSQL database adapter for Python -- C optimisation distribution" optional = false python-versions = ">=3.8" files = [ - {file = "psycopg_binary-3.2.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:cad2de17804c4cfee8640ae2b279d616bb9e4734ac3c17c13db5e40982bd710d"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:592b27d6c46a40f9eeaaeea7c1fef6f3c60b02c634365eb649b2d880669f149f"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a997efbaadb5e1a294fb5760e2f5643d7b8e4e3fe6cb6f09e6d605fd28e0291"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1d2b6438fb83376f43ebb798bf0ad5e57bc56c03c9c29c85bc15405c8c0ac5a"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b1f087bd84bdcac78bf9f024ebdbfacd07fc0a23ec8191448a50679e2ac4a19e"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:415c3b72ea32119163255c6504085f374e47ae7345f14bc3f0ef1f6e0976a879"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f092114f10f81fb6bae544a0ec027eb720e2d9c74a4fcdaa9dd3899873136935"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06a7aae34edfe179ddc04da005e083ff6c6b0020000399a2cbf0a7121a8a22ea"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0b018631e5c80ce9bc210b71ea885932f9cca6db131e4df505653d7e3873a938"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f8a509aeaac364fa965454e80cd110fe6d48ba2c80f56c9b8563423f0b5c3cfd"}, - {file = "psycopg_binary-3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:413977d18412ff83486eeb5875eb00b185a9391c57febac45b8993bf9c0ff489"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:62b1b7b07e00ee490afb39c0a47d8282a9c2822c7cfed9553a04b0058adf7e7f"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:f8afb07114ea9b924a4a0305ceb15354ccf0ef3c0e14d54b8dbeb03e50182dd7"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40bb515d042f6a345714ec0403df68ccf13f73b05e567837d80c886c7c9d3805"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6418712ba63cebb0c88c050b3997185b0ef54173b36568522d5634ac06153040"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:101472468d59c74bb8565fab603e032803fd533d16be4b2d13da1bab8deb32a3"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa3931f308ab4a479d0ee22dc04bea867a6365cac0172e5ddcba359da043854b"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dc314a47d44fe1a8069b075a64abffad347a3a1d8652fed1bab5d3baea37acb2"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:cc304a46be1e291031148d9d95c12451ffe783ff0cc72f18e2cc7ec43cdb8c68"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6f9e13600647087df5928875559f0eb8f496f53e6278b7da9511b4b3d0aff960"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b140182830c76c74d17eba27df3755a46442ce8d4fb299e7f1cf2f74a87c877b"}, - {file = "psycopg_binary-3.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:3c838806eeb99af39f934b7999e35f947a8e577997cc892c12b5053a97a9057f"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:7066d3dca196ed0dc6172f9777b2d62e4f138705886be656cccff2d555234d60"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:28ada5f610468c57d8a4a055a8ea915d0085a43d794266c4f3b9d02f4288f4db"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e8213bf50af073b1aa8dc3cff123bfeedac86332a16c1b7274910bc88a847c7"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74d623261655a169bc84a9669890975c229f2fa6e19a7f2d10a77675dcf1a707"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42781ba94e8842ee98bca5a7d0c44cc9d067500fedca2d6a90fa3609b6d16b42"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33e6669091d09f8ba36e10ce678a6d9916e110446236a9b92346464a3565635e"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b09e8a576a2ac69d695032ee76f31e03b30781828b5dd6d18c6a009e5a3d1c35"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8f28ff0cb9f1defdc4a6f8c958bf6787274247e7dfeca811f6e2f56602695fb1"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4c84fcac8a3a3479ac14673095cc4e1fdba2935499f72c436785ac679bec0d1a"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:950fd666ec9e9fe6a8eeb2b5a8f17301790e518953730ad44d715b59ffdbc67f"}, - {file = "psycopg_binary-3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:334046a937bb086c36e2c6889fe327f9f29bfc085d678f70fac0b0618949f674"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:1d6833f607f3fc7b22226a9e121235d3b84c0eda1d3caab174673ef698f63788"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d353e028b8f848b9784450fc2abf149d53a738d451eab3ee4c85703438128b9"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f34e369891f77d0738e5d25727c307d06d5344948771e5379ea29c76c6d84555"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ab58213cc976a1666f66bc1cb2e602315cd753b7981a8e17237ac2a185bd4a1"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0104a72a17aa84b3b7dcab6c84826c595355bf54bb6ea6d284dcb06d99c6801"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:059cbd4e6da2337e17707178fe49464ed01de867dc86c677b30751755ec1dc51"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:73f9c9b984be9c322b5ec1515b12df1ee5896029f5e72d46160eb6517438659c"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:af0469c00f24c4bec18c3d2ede124bf62688d88d1b8a5f3c3edc2f61046fe0d7"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:463d55345f73ff391df8177a185ad57b552915ad33f5cc2b31b930500c068b22"}, - {file = "psycopg_binary-3.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:302b86f92c0d76e99fe1b5c22c492ae519ce8b98b88d37ef74fda4c9e24c6b46"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:0879b5d76b7d48678d31278242aaf951bc2d69ca4e4d7cef117e4bbf7bfefda9"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f99e59f8a5f4dcd9cbdec445f3d8ac950a492fc0e211032384d6992ed3c17eb7"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84837e99353d16c6980603b362d0f03302d4b06c71672a6651f38df8a482923d"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ce965caf618061817f66c0906f0452aef966c293ae0933d4fa5a16ea6eaf5bb"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78c2007caf3c90f08685c5378e3ceb142bafd5636be7495f7d86ec8a977eaeef"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7a84b5eb194a258116154b2a4ff2962ea60ea52de089508db23a51d3d6b1c7d1"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4a42b8f9ab39affcd5249b45cac763ac3cf12df962b67e23fd15a2ee2932afe5"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:788ffc43d7517c13e624c83e0e553b7b8823c9655e18296566d36a829bfb373f"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:21927f41c4d722ae8eb30d62a6ce732c398eac230509af5ba1749a337f8a63e2"}, - {file = "psycopg_binary-3.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:921f0c7f39590763d64a619de84d1b142587acc70fd11cbb5ba8fa39786f3073"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:8eacbf58d4f8d7bc82e0a60476afa2622b5a58f639a3cc2710e3e37b72aff3cb"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:d07e62476ee8c54853b2b8cfdf3858a574218103b4cd213211f64326c7812437"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c22e615ee0ecfc6687bb8a39a4ed9d6bac030b5e72ac15e7324fd6e48979af71"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec29c7ec136263628e3f09a53e51d0a4b1ad765a6e45135707bfa848b39113f9"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:035753f80cbbf6aceca6386f53e139df70c7aca057b0592711047b5a8cfef8bb"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9ee99336151ff7c30682f2ef9cb1174d235bc1471322faabba97f9db1398167"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a60674dff4a4194e88312b463fb84ac80924c2b9e25d0e0460f3176bf1af4a6b"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3c701507a49340de422d77a6ce95918a0019990bbf27daec35aa40050c6eadb6"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1b3c5a04eaf8866e399315cff2e810260cce10b797437a9f49fd71b5f4b94d0a"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0ad9c09de4c262f516ae6891d042a4325649b18efa39dd82bbe0f7bc95c37bfb"}, + {file = "psycopg_binary-3.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:bf1d3582185cb43ecc27403bee2f5405b7a45ccaab46c8508d9a9327341574fc"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:554d208757129d34fa47b7c890f9ef922f754e99c6b089cb3a209aa0fe282682"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:71dc3cc10d1fd7d26a3079d0a5b4a8e8ad0d7b89a702ceb7605a52e4395be122"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86f578d63f2e1fdf87c9adaed4ff23d7919bda8791cf1380fa4cf3a857ccb8b"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a4eb737682c02a602a12aa85a492608066f77793dab681b1c4e885fedc160b1"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e120a576e74e4e612c48f4b021e322e320ca102534d78a0ca4db2ffd058ae8d"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:849d518e7d4c6186e1e48ea2ac2671912edf7e732fffe6f01dfed61cf0245de4"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8ee2b19152bcec8f356f989c31768702be5f139b4d51094273c4a9ddc8c55380"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:00273dd011892e8216fcef76b42f775ddaa6348664a7fffae2a27c9557f45bfa"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4bcb489615d7e56d1de42937e6a0fc13f766505729afdb54c2947a52db295220"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:06963f88916a177df95aaed27101af0989ba206654743b1a0e050b9d8e734686"}, + {file = "psycopg_binary-3.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:ed1ad836a0c21890c7f84e73c7ef1ed0950e0e4b0d8e49b609b6fd9c13f2ca21"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:0dd314229885a81f9497875295d8788e651b78945627540f1e78ed71595e614a"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:989acbe2f552769cdb780346cea32d86e7c117044238d5172ac10b025fe47194"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:566b1c530898590f0ac9d949cf94351c08d73c89f8800c74c0a63ffd89a383c8"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68d03efab7e2830a0df3aa4c29a708930e3f6b9fd98774ff9c4fd1f33deafecc"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e1f013bfb744023df23750fde51edcb606def8328473361db3c192c392c6060"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a06136aab55a2de7dd4e2555badae276846827cfb023e6ba1b22f7a7b88e3f1b"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:020c5154be144a1440cf87eae012b9004fb414ae4b9e7b1b9fb808fe39e96e83"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ef341c556aeaa43a2729b07b04e20bfffdcf3d96c4a96e728ca94fe4ce632d8c"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:66de2dd7d37bf66eb234ca9d907f5cd8caca43ff8d8a50dd5c15844d1cf0390c"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2eb6f8f410dbbb71b8c633f283b8588b63bee0a7321f00ab76e9c800c593f732"}, + {file = "psycopg_binary-3.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:b45553c6b614d02e1486585980afdfd18f0000aac668e2e87c6e32da1adb051a"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:1ee891287c2da57e7fee31fbe2fbcdf57125768133d811b02e9523d5a052eb28"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:5e95e4a8076ac7611e571623e1113fa84fd48c0459601969ffbf534d7aa236e7"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6269d79a3d7d76b6fcf0fafae8444da00e83777a6c68c43851351a571ad37155"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6dd5d21a298c3c53af20ced8da4ae4cd038c6fe88c80842a8888fa3660b2094"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cf64e41e238620f05aad862f06bc8424f8f320d8075f1499bd85a225d18bd57"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c482c3236ded54add31136a91d5223b233ec301f297fa2db79747404222dca6"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0718be095cefdad712542169d16fa58b3bd9200a3de1b0217ae761cdec1cf569"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fb303b03c243a9041e1873b596e246f7caaf01710b312fafa65b1db5cd77dd6f"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:705da5bc4364bd7529473225fca02b795653bc5bd824dbe43e1df0b1a40fe691"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:05406b96139912574571b1c56bb023839a9146cf4b57c4548f36251dd5909fa1"}, + {file = "psycopg_binary-3.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:7c357cf87e8d7612cfe781225be7669f35038a765d1b53ec9605f6c5aef9ee85"}, + {file = "psycopg_binary-3.2.2-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:059aa5e8fa119de328b4cb02ee80775443763b25682a02dd7d026b8d4f565834"}, + {file = "psycopg_binary-3.2.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05a50f94e1e4fa37a0074b09263b83b0aa038c3c72068a61f1ad61ea449ef9d5"}, + {file = "psycopg_binary-3.2.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:951507b3d77a64c907afe893e01e09b41051fd7e27e9462f450fb8bb64bc22b0"}, + {file = "psycopg_binary-3.2.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ec4986c4ac2503e865acd3943d179531c3bbfa5a1c8ee81fcfccb551dad645f"}, + {file = "psycopg_binary-3.2.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b32b0e838841d5b109d32fc706b8bc64e50c161fee3f1371ccf696e5598bc49"}, + {file = "psycopg_binary-3.2.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fdc74a83348477b28bea9e7b391c9fc189b480fe3cd0e46bb989514410b64d60"}, + {file = "psycopg_binary-3.2.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9efe0ca78be4a573b4b81226904c711cfadc4783d64bfdf58a3394da7c1a1354"}, + {file = "psycopg_binary-3.2.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:51f56ae2898acaa33623adad96ddc5acbb5e2f72f2fc020065c8be05c0e01dce"}, + {file = "psycopg_binary-3.2.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:43b209be0424e8abece428a884cb711f504e3526dfbcb0bf51529907a55eda15"}, + {file = "psycopg_binary-3.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:d3c147eea9f3950a34133dc187e8d3534e54ff4a178a4ebd8993b2c97e123200"}, + {file = "psycopg_binary-3.2.2-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:6c7b6a8d4e1b77cdb50192b61235b33fc2f1d28c67627fc93a1d43e9130dd479"}, + {file = "psycopg_binary-3.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e234edc4bb746d8ac3daae8753ee38eaa7af2ee333a1d35ce6b02a02874aed18"}, + {file = "psycopg_binary-3.2.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f12640ba92c538b3b64a199a918d3bb0cc0d7f7123c6ba93cb065e1a2d049f0"}, + {file = "psycopg_binary-3.2.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8937dc548621b336b0d8383a3470fb7192b42a108c760a152282909867bf5b26"}, + {file = "psycopg_binary-3.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4afbb97d64cd8078edec859b07859a18ef3de7261a3a873ba52f32548373ae92"}, + {file = "psycopg_binary-3.2.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c432710bdf8ccfdd75b0bc9cdf1fd21ff394363e4daec099c667f3c5f1721e2b"}, + {file = "psycopg_binary-3.2.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:366cc4e194f7feb4e3038d6775fd4b69835e7d923972aee5baec986de972abd6"}, + {file = "psycopg_binary-3.2.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b286ed65a891928bd457ffa0cd5fec09b9b5208bfd096d087e45369f07c5cb85"}, + {file = "psycopg_binary-3.2.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9fee41c99312002e5d1f7462b1954aefed44c6efe5f021c3eac311640c16f6b7"}, + {file = "psycopg_binary-3.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:87cceaf07760a04023596f9ca1d4e929d38ae8d778161cb3e8d27a0f990dd264"}, ] [[package]] @@ -1331,4 +1342,4 @@ brotli = ["brotli"] [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "55d85eb75dbdf932a6015abb4287cc3932dc4d54e4106414b9cb529a3a5da818" +content-hash = "c6a2ea76037d0cc5a3d6f6892b561eea3063acfc12bbdd0c6cdb1418c3c7f93f" diff --git a/pyproject.toml b/pyproject.toml index c1fd665..751b604 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "resource_tracking" -version = "1.4.16" +version = "1.4.17" description = "DBCA internal corporate application to download and serve data from remote tracking devices." authors = ["DBCA OIM "] license = "Apache-2.0" @@ -9,7 +9,7 @@ package-mode = false [tool.poetry.dependencies] python = "^3.12" django = "4.2.15" -psycopg = { version = "3.2.1", extras = ["binary", "pool"] } +psycopg = { version = "3.2.2", extras = ["binary", "pool"] } dbca-utils = "2.0.2" python-dotenv = "1.0.1" dj-database-url = "2.2.0" From bb866e857f4ab1a44af41fdab80c1f96ab2c891a Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Fri, 20 Sep 2024 11:13:55 +0800 Subject: [PATCH 7/9] Alpine-based Dockerfile. --- Dockerfile | 51 ++++++++++++++++++++++++++++++----------------- Dockerfile.debian | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 18 deletions(-) create mode 100644 Dockerfile.debian diff --git a/Dockerfile b/Dockerfile index 7956b36..98389e5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,37 +1,52 @@ # syntax=docker/dockerfile:1 # Prepare the base environment. -FROM python:3.12.4-slim AS builder_base_rt +FROM python:3.12.6-alpine AS builder_base LABEL org.opencontainers.image.authors=asi@dbca.wa.gov.au LABEL org.opencontainers.image.source=https://github.com/dbca-wa/resource_tracking -RUN apt-get update -y \ - && apt-get upgrade -y \ - && apt-get install -y libmagic-dev gcc binutils gdal-bin proj-bin python3-dev libpq-dev curl \ - && rm -rf /var/lib/apt/lists/* \ - && pip install --root-user-action=ignore --upgrade pip +# Install system requirements to build Python packages. +RUN apk add --no-cache \ + gcc \ + libressl-dev \ + musl-dev \ + libffi-dev +# Create a non-root user to run the application. +ARG UID=10001 +ARG GID=10001 +RUN addgroup -g ${GID} appuser \ + && adduser -H -D -u ${UID} -G appuser appuser # Install Python libs using Poetry. -FROM builder_base_rt AS python_libs_rt +FROM builder_base AS python_libs_resourcetracking +# Add system dependencies required to use GDAL +# Ref: https://stackoverflow.com/a/59040511/14508 +RUN apk add --no-cache \ + gdal \ + geos \ + proj \ + binutils \ + && ln -s /usr/lib/libproj.so.25 /usr/lib/libproj.so \ + && ln -s /usr/lib/libgdal.so.35 /usr/lib/libgdal.so \ + && ln -s /usr/lib/libgeos_c.so.1 /usr/lib/libgeos_c.so WORKDIR /app -ARG POETRY_VERSION=1.8.3 -RUN pip install --no-cache-dir --root-user-action=ignore poetry==${POETRY_VERSION} COPY poetry.lock pyproject.toml ./ -RUN poetry config virtualenvs.create false \ +ARG POETRY_VERSION=1.8.3 +RUN pip install --no-cache-dir --root-user-action=ignore poetry==${POETRY_VERSION} \ + && poetry config virtualenvs.create false \ && poetry install --no-interaction --no-ansi --only main - -# Create a non-root user. -ARG UID=10001 -ARG GID=10001 -RUN groupadd -g ${GID} appuser \ - && useradd --no-create-home --no-log-init --uid ${UID} --gid ${GID} appuser +# Remove system libraries, no longer required. +RUN apk del \ + gcc \ + libressl-dev \ + musl-dev \ + libffi-dev # Install the project. -FROM python_libs_rt +FROM python_libs_resourcetracking AS project_resourcetracking COPY gunicorn.py manage.py ./ COPY resource_tracking ./resource_tracking COPY tracking ./tracking RUN python manage.py collectstatic --noinput - USER ${UID} EXPOSE 8080 CMD ["gunicorn", "resource_tracking.wsgi", "--config", "gunicorn.py"] diff --git a/Dockerfile.debian b/Dockerfile.debian new file mode 100644 index 0000000..7956b36 --- /dev/null +++ b/Dockerfile.debian @@ -0,0 +1,37 @@ +# syntax=docker/dockerfile:1 +# Prepare the base environment. +FROM python:3.12.4-slim AS builder_base_rt +LABEL org.opencontainers.image.authors=asi@dbca.wa.gov.au +LABEL org.opencontainers.image.source=https://github.com/dbca-wa/resource_tracking + +RUN apt-get update -y \ + && apt-get upgrade -y \ + && apt-get install -y libmagic-dev gcc binutils gdal-bin proj-bin python3-dev libpq-dev curl \ + && rm -rf /var/lib/apt/lists/* \ + && pip install --root-user-action=ignore --upgrade pip + +# Install Python libs using Poetry. +FROM builder_base_rt AS python_libs_rt +WORKDIR /app +ARG POETRY_VERSION=1.8.3 +RUN pip install --no-cache-dir --root-user-action=ignore poetry==${POETRY_VERSION} +COPY poetry.lock pyproject.toml ./ +RUN poetry config virtualenvs.create false \ + && poetry install --no-interaction --no-ansi --only main + +# Create a non-root user. +ARG UID=10001 +ARG GID=10001 +RUN groupadd -g ${GID} appuser \ + && useradd --no-create-home --no-log-init --uid ${UID} --gid ${GID} appuser + +# Install the project. +FROM python_libs_rt +COPY gunicorn.py manage.py ./ +COPY resource_tracking ./resource_tracking +COPY tracking ./tracking +RUN python manage.py collectstatic --noinput + +USER ${UID} +EXPOSE 8080 +CMD ["gunicorn", "resource_tracking.wsgi", "--config", "gunicorn.py"] From e6b38681cf5fd62deecfb8e82b708698eac6387d Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Fri, 20 Sep 2024 11:31:43 +0800 Subject: [PATCH 8/9] Update README --- README.md | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 339ba14..1b2c55b 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,13 @@ environment. With Poetry installed, change into the project directory and run: poetry install -To run Python commands in the virtualenv, thereafter run them like so: +Activate the virtualenv like so: - poetry run python manage.py + poetry shell + +To run Python commands in the activated virtualenv, thereafter run them as normal: + + python manage.py Manage new or updating project dependencies with Poetry also, like so: @@ -28,23 +32,34 @@ The following variables are required for the project to run: SECRET_KEY="ThisIsASecretKey" Other environment variables will be required to run the project in production -(these are context-dependent). +(these are context-dependent). These variables include: + + ALLOWED_HOSTS + CSRF_TRUSTED_ORIGINS + EMAIL_HOST + EMAIL_USER + EMAIL_PASSWORD + TRACPLUS_URL + DFES_URL + DFES_USER + DFES_PASS + GEOSERVER_URL ## Running Use `runserver` to run a local copy of the application: - poetry run python manage.py runserver 0:8080 + python manage.py runserver 0:8080 Run console commands manually: - poetry run python manage.py shell_plus + python manage.py shell_plus ## Unit tests Run unit tests like so: - poetry run python manage.py test --keepdb -v2 + python manage.py test --keepdb -v2 ## Docker image From d218b051e13365948c648e1584970e9df7955dde Mon Sep 17 00:00:00 2001 From: Ashley Felton Date: Fri, 20 Sep 2024 11:32:25 +0800 Subject: [PATCH 9/9] Prod deployment variables: remove unused, add PROD_SCARY_WARNING. --- kustomize/overlays/prod/deployment_patch.yaml | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/kustomize/overlays/prod/deployment_patch.yaml b/kustomize/overlays/prod/deployment_patch.yaml index cb2ceb4..77dda8e 100644 --- a/kustomize/overlays/prod/deployment_patch.yaml +++ b/kustomize/overlays/prod/deployment_patch.yaml @@ -17,6 +17,8 @@ spec: - name: resourcetracking imagePullPolicy: IfNotPresent env: + - name: PROD_SCARY_WARNING + value: "True" - name: DATABASE_URL valueFrom: secretKeyRef: @@ -27,21 +29,6 @@ spec: secretKeyRef: name: resourcetracking-env-prod key: SECRET_KEY - - name: DFES_PASS - valueFrom: - secretKeyRef: - name: resourcetracking-env-prod - key: DFES_PASS - - name: DFES_URL - valueFrom: - secretKeyRef: - name: resourcetracking-env-prod - key: DFES_URL - - name: DFES_USER - valueFrom: - secretKeyRef: - name: resourcetracking-env-prod - key: DFES_USER - name: EMAIL_HOST valueFrom: secretKeyRef: @@ -57,16 +44,21 @@ spec: secretKeyRef: name: resourcetracking-env-prod key: EMAIL_USER - - name: FLEETCARE_CONNECTION_STRING + - name: DFES_PASS + valueFrom: + secretKeyRef: + name: resourcetracking-env-prod + key: DFES_PASS + - name: DFES_URL valueFrom: secretKeyRef: name: resourcetracking-env-prod - key: FLEETCARE_CONNECTION_STRING - - name: FLEETCARE_CONTAINER + key: DFES_URL + - name: DFES_USER valueFrom: secretKeyRef: name: resourcetracking-env-prod - key: FLEETCARE_CONTAINER + key: DFES_USER - name: TRACPLUS_URL valueFrom: secretKeyRef: