diff --git a/.envs/.example b/.envs/.example
new file mode 100644
index 00000000..ff7e1fe1
--- /dev/null
+++ b/.envs/.example
@@ -0,0 +1,40 @@
+# Use this file to create a .env with filled variables
+# Django Variables
+DJANGO_DEBUG=True
+DEBUG_TOOLBAR=True
+DJANGO_SECRET_KEY=change_me
+USE_MINIO=True
+
+# Sentry Variables
+DJANGO_ADMIN_URL=jandig-admin/
+ENABLE_SENTRY=False
+SENTRY_DSN=
+HEALTH_CHECK_URL=api/v1/status/
+SENTRY_TRACES_SAMPLE_RATE=0.1
+
+## Amazon AWS Variables
+AWS_ACCESS_KEY_ID=minio
+AWS_SECRET_ACCESS_KEY=minio123
+MINIO_ROOT_USER=minio
+MINIO_ROOT_PASSWORD=minio123
+AWS_STORAGE_BUCKET_NAME=jandig-cdn
+AWS_PRIVATE_STORAGE_BUCKET_NAME=jandig-private-cdn
+AWS_S3_REGION_NAME=us-east-2
+AWS_STATIC_LOCATION=static
+MINIO_S3_ENDPOINT_URL=http://storage:9000
+MINIO_SITE_REGION=us-east-2
+MINIO_USER_ACCESS_KEY=minio-access-key
+MINIO_USER_SECRET_KEY=minio-secret-key
+
+## Postgres variables
+POSTGRES_HOST=postgres
+POSTGRES_PORT=5432
+POSTGRES_DB=jandig
+POSTGRES_USER=jandig
+POSTGRES_PASSWORD=secret
+
+# Email server variables
+SMTP_SERVER=smtp.gmail.com
+SMTP_PORT=587
+JANDIG_EMAIL=local_jandig@jandig.com
+JANDIG_EMAIL_PASSWORD=local_password
diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md
index b4823e2b..7f203b91 100644
--- a/.github/CODE_OF_CONDUCT.md
+++ b/.github/CODE_OF_CONDUCT.md
@@ -2,45 +2,66 @@
## Our Pledge
-In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
-Examples of behavior that contributes to creating a positive environment include:
+Examples of behavior that contributes to a positive environment for our community include:
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
+- Demonstrating empathy and kindness toward other people
+- Being respectful of differing opinions, viewpoints, and experiences
+- Giving and gracefully accepting constructive feedback
+- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
+- Focusing on what is best not just for us as individuals, but for the overall community
-Examples of unacceptable behavior by participants include:
+Examples of unacceptable behavior include:
-* The use of sexualized language or imagery and unwelcome sexual attention or advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a professional setting
+- The use of sexualized language or imagery, and sexual attention or advances of any kind
+- Trolling, insulting or derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others’ private information, such as a physical or email address, without their explicit permission
+- Other conduct which could reasonably be considered inappropriate in a professional setting
-## Our Responsibilities
+## Enforcement Responsibilities
-Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
-Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
-This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Enforcement
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contato@memelab.com.br. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at jandig@memelab.com.br. All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the reporter of any incident.
+
+## Enforcement Guidelines
+Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
+
+1. Correction
+**Community Impact:** Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
+**Consequence:** A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
+
+2. Warning
+**Community Impact:** A violation through a single incident or series of actions.
+**Consequence:** A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
+
+3. Temporary Ban
+**Community Impact:** A serious violation of community standards, including sustained inappropriate behavior.
+**Consequence:** A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
-Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+4. Permanent Ban
+**Community Impact:** Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
+**Consequence:** A permanent ban from any sort of public interaction within the community.
## Attribution
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+This Code of Conduct is adapted from the [Contributor Covenant][homepage] version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][version].
[homepage]: http://contributor-covenant.org
-[version]: http://contributor-covenant.org/version/1/4/
+[version]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..e688e4cb
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,88 @@
+name: CI pipeline
+
+on: push
+
+jobs:
+ linter:
+ name: run / linter
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out code from Github
+ uses: actions/checkout@v3
+ - name: Set up Python 3.10
+ uses: actions/setup-python@v4
+ with:
+ python-version: "3.10"
+ - name: Installing flake8
+ run: |
+ python -m pip install --upgrade pip
+ pip install flake8
+ - name: Run flake8 linter
+ run: |
+ flake8 --max-line-length=200 --exclude=*/migrations src/
+
+ build:
+ name: run / build
+ runs-on: ubuntu-latest
+ needs: linter
+ steps:
+ - name: Check out code from Github
+ uses: actions/checkout@v3
+ - name: Build image
+ run: |
+ # docker login -u $DOCKER_HUB_USER -p $DOCKER_HUB_PASS
+ docker build . -t jandigarte/django:$GITHUB_SHA
+ docker save -o docker_image_$GITHUB_SHA jandigarte/django:$GITHUB_SHA
+ - name: Caching image
+ uses: actions/cache@v3
+ with:
+ key: jandigarte
+ path: docker_image_${{ github.sha }}
+
+ migrations:
+ name: test / migrations
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Check out code from Github
+ uses: actions/checkout@v3
+ - name: Restoring cached image
+ uses: actions/cache@v3
+ with:
+ key: jandigarte
+ path: docker_image_${{ github.sha }}
+ - name: Running container
+ env:
+ IMAGE_NAME: jandigarte/django:${{ github.sha }}
+ run: |
+ cp .envs/.example .envs/.env
+ docker load -i docker_image_$GITHUB_SHA
+ docker-compose -f docker-compose.ci.yml -p jandigarte_$GITHUB_SHA up --no-build -d
+ - name: Test migrations
+ run: |
+ docker exec jandigarte_${{ github.sha }}_django_1 sh -c "\
+ poetry run src/manage.py makemigrations --check --dry-run"
+
+ test:
+ name: test / unity
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Check out code from Github
+ uses: actions/checkout@v3
+ - name: Restoring cached image
+ uses: actions/cache@v3
+ with:
+ key: jandigarte
+ path: docker_image_${{ github.sha }}
+ - name: Running container
+ env:
+ IMAGE_NAME: jandigarte/django:${{ github.sha }}
+ run: |
+ cp .envs/.example .envs/.env
+ docker load -i docker_image_$GITHUB_SHA
+ docker-compose -f docker-compose.ci.yml -p jandigarte_$GITHUB_SHA up --no-build -d
+ - name: Running users tests
+ run: |
+ docker exec jandigarte_${{ github.sha }}_django_1 sh -c "\
+ poetry run src/manage.py test"
\ No newline at end of file
diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml
new file mode 100644
index 00000000..d44d267f
--- /dev/null
+++ b/.github/workflows/dependencies.yml
@@ -0,0 +1,21 @@
+name: Dependencies pipeline
+
+on:
+ push:
+ paths:
+ - 'pyproject.toml'
+
+jobs:
+ dependencies:
+ name: test / dependencies
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out code from Github
+ uses: actions/checkout@v3
+ - name: Check diff
+ id: diff_lock
+ run: |
+ echo "::set-output name=dependencies::$(git diff --name-only | grep poetry.lock -c)"
+ - name: Check poetry lock
+ if: ${{ steps.diff_lock.outputs.dependencies == 0 }}
+ run: exit 1
diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml
new file mode 100644
index 00000000..ebb9996b
--- /dev/null
+++ b/.github/workflows/push.yml
@@ -0,0 +1,24 @@
+name: Docker pipeline
+
+on:
+ push:
+ branches:
+ - develop
+
+# TODO: Change environment and login envs
+jobs:
+ django:
+ name: push / django
+ environment: testes
+ runs-on: ubuntu-latest
+ needs: dependencies
+ steps:
+ - name: Check out code from Github
+ uses: actions/checkout@v3
+ - name: Build django image
+ run: |
+ docker build . -t jandigarte/django:latest
+ - name: Push django image
+ run: |
+ docker login -u ${{ secrets.DOCKER_HUB_USER }} -p ${{ secrets.DOCKER_HUB_PASS }}
+ docker push jandigarte/django:latest
diff --git a/.gitignore b/.gitignore
index 5e7d1ba2..865d2101 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,9 +2,6 @@
src/ARte/config/__pycache__/
*.pyc
-##vscode
-\.vscode/
-
##sqlite
*.sqlite3
@@ -25,4 +22,4 @@ docker/media/
*.mo
*.po~
-src/.envs/.env
+*/**/.env
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a51586c9..200c388e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -8,10 +8,10 @@ stages:
- docker:dind
script:
- docker login -u $DOCKER_HUB_USER -p $DOCKER_HUB_PASS
- - docker build . -f docker/Dockerfile -t jandigarte/django:$DOCKER_TAG --cache-from jandigarte/django:$DOCKER_TAG
+ - docker build . -t jandigarte/django:$DOCKER_TAG --cache-from jandigarte/django:$DOCKER_TAG
- docker push jandigarte/django:$DOCKER_TAG
tags:
- - docker
+ - gitlab-org-docker
build develop:
extends: .build
@@ -32,7 +32,7 @@ build tag:
environment: production
script:
- docker login -u $DOCKER_HUB_USER -p $DOCKER_HUB_PASS
- - "docker build . -f docker/Dockerfile
+ - "docker build .
-t jandigarte/django:$CI_COMMIT_TAG
-t jandigarte/django:$DOCKER_TAG
-t jandigarte/django:latest"
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 00000000..1a7d670e
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,8 @@
+{
+ "python.testing.pytestArgs": [
+ "src",
+ "--ds=config.test_settings",
+ ],
+ "python.testing.unittestEnabled": false,
+ "python.testing.pytestEnabled": true
+}
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..e62822d6
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,49 @@
+FROM python:3.10-slim-bullseye
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ gettext \
+ docutils-common \
+ curl \
+ wget
+
+COPY ./pyproject.toml /pyproject.toml
+COPY ./poetry.lock /poetry.lock
+
+ENV PATH="$PATH:/root/.local/bin" \
+ POETRY_NO_INTERACTION=1 \
+ POETRY_VIRTUALENVS_CREATE=false \
+ POETRY_CACHE_DIR='/var/cache/pypoetry' \
+ TINI_VERSION=v0.19.0 \
+ # poetry:
+ POETRY_VERSION=1.3.1
+
+# Installing `poetry` package manager:
+# https://github.com/python-poetry/poetry
+RUN curl -sSL https://install.python-poetry.org | python3 - \
+ && poetry --version
+
+RUN pip install --upgrade pip
+RUN poetry install
+
+RUN dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
+ && wget "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${dpkgArch}" -O /usr/local/bin/tini \
+ && chmod +x /usr/local/bin/tini && tini --version
+
+
+RUN mkdir -p /jandig/src /jandig/locale /jandig/docs /jandig/static /jandig/build
+
+WORKDIR /jandig
+
+COPY ./src/ /jandig/src/
+COPY ./docs/ /jandig/docs/
+COPY ./locale/ /jandig/locale/
+COPY ./tasks.py /jandig/tasks.py
+COPY ./run.sh /jandig/run.sh
+COPY ./etc/ /jandig/etc/
+
+
+RUN find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
+
+
+ENTRYPOINT ["tini", "--"]
\ No newline at end of file
diff --git a/Makefile b/Makefile
index d552bd7e..99c09b28 100644
--- a/Makefile
+++ b/Makefile
@@ -1,40 +1,30 @@
-BACKUP_DIR = backup_$(shell date +'%d_%m_%Y-%H_%M_%S')
-PASSWORD =
-ROOT =
-IP =
-DESTINATION =
-DOMAIN = staging.jandig.app
-CERTPATH = /etc/letsencrypt/live/$(DOMAIN)
-EMAIL = email@example.com
-backup:
- #sudo docker-compose -f docker/docker-compose.deploy.yml stop
- mkdir $(BACKUP_DIR)
+RUNNING_CONTAINER := $(shell docker compose ps --services --filter "status=running" | grep django )
- #sudo cp -r /var/lib/docker/volumes/ $(BACKUP_DIR)/volumes
- sudo cp -r ./docker/media/ $(BACKUP_DIR)/media
+test:
+ @if [[ -n "${RUNNING_CONTAINER}" ]]; then \
+ docker compose exec django poetry run pytest src/core src/users; \
+ else \
+ docker compose run --rm django poetry run pytest src/core src/users;\
+ fi
- sudo chmod 755 $(BACKUP_DIR)
- zip -r $(BACKUP_DIR).zip $(BACKUP_DIR)
+test-ui:
+ docker compose up -d
+ poetry run pytest src/tests
- sudo cp -r $(BACKUP_DIR).zip ./backups
- sudo rm -rf ./$(BACKUP_DIR).zip
- sudo rm -rf $(BACKUP_DIR)
- #sudo docker-compose -f docker/docker-compose.deploy.yml up
+lint:
+ poetry run black --line-length=200 src
+ poetry run isort src
+flake8:
+ poetry run flake8 --max-line-length=200 --exclude=*/migrations src
-
+migrations:
+ poetry run python src/manage.py makemigrations
+migrate:
+ poetry run python src/manage.py migrate
- sshpass -p $(PASSWORD) scp ./backups/backup_$(shell date +'%d_%m_%Y-%H_%M_%S').zip $(ROOT)@$(IP):$(DESTINATION)
- echo 'Send via scp'
-fake-cert:
- mkdir -p $(CERTPATH)
- curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "$(CERTPATH)/../../options-ssl-nginx.conf"
+gen:
+ poetry run playwright codegen -b chromium --target python-pytest localhost:8000
- curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "$(CERTPATH)/../../ssl-dhparams.pem"
- openssl req -x509 -nodes -newkey rsa:1024 -days 1 -keyout '$(CERTPATH)/privkey.pem' -out '$(CERTPATH)/fullchain.pem' -subj '/CN=localhost'
-
-cert:
- rm -Rf /etc/letsencrypt/live/$(DOMAIN)
- sudo rm -Rf /etc/letsencrypt/archive/$(DOMAIN)
- sudo rm -Rf /etc/letsencrypt/renewal/$(DOMAIN).conf
- certbot certonly --webroot -w /var/www/certbot --staging --email $(EMAIL) -d $(DOMAIN) --rsa-key-size 4096 --agree-tos --force-renewal
\ No newline at end of file
+translate_es:
+ poetry run inv i18n -l es_ES
diff --git a/README.md b/README.md
index 24971710..9993c655 100644
--- a/README.md
+++ b/README.md
@@ -41,26 +41,31 @@ You can find interviews and references to Jandig in the press [here](http://meme
To contribute to Jandig ARte it would be awesome if you read [Contributing](https://github.com/memeLab/ARte/blob/master/.github/CONTRIBUTING.md) and our [Code of conduct](https://github.com/memeLab/ARte/blob/master/.github/CODE_OF_CONDUCT.md). After a good read you are ready to move foward!
### Prerequisites
-We use docker and docker-compose to ensure a consistent development environment and to make the deploy process as painless as possible, so all you need on your development tools to run Jandig ARte is [Docker](https://www.docker.com/) and [Docker-Compose](https://docs.docker.com/compose/overview/).
+We use docker and docker-compose to ensure a consistent development environment and to make the deploy process as painless as possible, so all you need on your development tools to run Jandig ARte is [Docker](https://www.docker.com/) and [Docker-Compose](https://docs.docker.com/compose/overview/).
+ On Windows [Docker Desktop](https://docs.docker.com/desktop/windows/install/) also includes Docker Compose along with other Docker apps.
### Installing
-Docker has good documentation on their website for installing docker and docker-compose for different operating systems like [Ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu/) and [Debian](https://docs.docker.com/install/linux/docker-ce/debian/). To install docker-compose choose your operating system [here](https://docs.docker.com/compose/install/).
+Docker has good documentation on their website for installing docker and docker-compose for different operating systems like [Ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu/) and [Debian](https://docs.docker.com/install/linux/docker-ce/debian/). To install docker-compose choose your operating system [here](https://docs.docker.com/compose/install/).
+On Windows, you'll only need install [Docker Desktop](https://docs.docker.com/desktop/windows/install/) and [WSL2](https://docs.docker.com/desktop/windows/install/#wsl-2-backend).
### Running
+
+#### Linux OS
+
To run Jandig ARte all you need to do is:
- Clone this repo
- Navigate to the repository folder
-- Run docker-compose passing the docker-compose.yml
+- Run docker-compose
- Voila!
-```
+```bash
git clone https://github.com/memeLab/Jandig
cd Jandig
-docker-compose -f docker/docker-compose.yml up
+docker-compose up
```
If you get any error saying ``permission denied`` try run the command with sudo.
```
-sudo docker-compose -f docker/docker-compose.yml up
+sudo docker-compose up
```
Jandig ARte server will run at localhost. To test modifications you just need to run a web browser and access [localhost:8000](localhost:8000). If you want to test on a mobile device, you will need a https connection, we recommend [ngrok](https://www.npmjs.com/package/ngrok) to generate a https link for you.
@@ -75,3 +80,34 @@ ngrok will prompt 3 links:
![usage](https://user-images.githubusercontent.com/12930004/54871980-ab41da00-4d9b-11e9-8b80-bb1d4bec420d.png)
Select the one with `https` at beginning.
+
+#### Windows OS
+
+To run Jandig ARte all you need to do is:
+- Clone this repo
+- Navigate to the repository folder using WSL2
+- Run the conteiners 'jandigarte/django' and 'jandigarte/requirements' on Docker Desktop
+- Run docker-compose passing the docker-compose.yml
+- Voila!
+
+```bash
+git clone https://github.com/memeLab/Jandig
+cd Jandig
+docker-compose up
+```
+If you get any error saying ``permission denied`` try run the command with sudo.
+```
+sudo docker-compose up
+```
+
+Jandig ARte server will run at localhost, but by default WSL2 enables wsl localhost to accessible from windows, but no vice versa. To access you'll need to use windows system IP from wsl2.
+
+- Run this command on terminal:
+```
+vim /etc/resolv.conf
+```
+- Get Network Interface (WSL) IP. It should be like:
+```
+nameserver 172.21.176.1
+```
+- Access the localhost using this IP (e.g.: 172.21.176.1:8000)
\ No newline at end of file
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000..d2b60f4d
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,14 @@
+# Security Policy
+
+This document aims to provide instructions about how to report security vulnerabilities. Jandig, as an open-source community, prizes this kind of interaction since we'll use these pieces of information for tracking and correcting defects.
+
+
+## Reporting Security Issues
+
+At Jandig, we value keeping the security integrity of the platform. Therefore, vulnerabilities reports and issues related to security are welcome and must be made through GitHub issues.
+Before creating a report issue, you must collect data about the vulnerability, such as print screens and paths for reaching the problem. Once you have collected all the information needed to reproduce the error, you must now describe it as a bug report issue. You can find more details about how to create a issue on [CONTRIBUTING](https://github.com/memeLab/Jandig/blob/develop/.github/CONTRIBUTING.md) document.
+
+
+## Language
+
+We prefer to keep all internal communication of the project in English.
diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml
new file mode 100644
index 00000000..683b5f72
--- /dev/null
+++ b/docker-compose.ci.yml
@@ -0,0 +1,63 @@
+version: '3.5'
+
+services:
+ django:
+ image: "${IMAGE_NAME}"
+ ports:
+ - 8000:8000
+ links:
+ - "postgres:postgres"
+ - "storage:storage"
+ - "createbuckets:createbuckets"
+ volumes:
+ - ./src/:/src/
+ - ./docs/:/src/docs/
+ - ./etc/:/src/etc/
+ - ./locale/:/src/locale/
+ - ./run.sh:/src/run.sh
+ - ./tasks.py:/src/tasks.py
+ env_file:
+ - .envs/.env
+ command: ./run.sh
+
+ postgres:
+ image: postgres:12.6
+ env_file:
+ - .envs/.env
+ command: postgres -c max_connections=10000
+ ports:
+ - "5432:5432"
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+
+ storage:
+ image: minio/minio:latest
+ ports:
+ - 9000:9000
+ - 9001:9001
+ volumes:
+ - storage:/storage
+ env_file:
+ - .envs/.env
+ command: server /storage --console-address ":9001"
+
+ createbuckets:
+ image: minio/mc
+ depends_on:
+ - storage
+ env_file:
+ - .envs/.env
+ entrypoint: >
+ /bin/sh -c "
+ until (/usr/bin/mc config host add myminio $${MINIO_S3_ENDPOINT_URL} $${MINIO_ROOT_USER} $${MINIO_ROOT_PASSWORD}) do echo '...waiting...' && sleep 1; done;
+ /usr/bin/mc mb myminio/$${AWS_STORAGE_BUCKET_NAME};
+ /usr/bin/mc policy set download myminio/$${AWS_STORAGE_BUCKET_NAME};
+ /usr/bin/mc mb myminio/$${AWS_PRIVATE_STORAGE_BUCKET_NAME};
+ /usr/bin/mc admin user add myminio $${MINIO_USER_ACCESS_KEY} $${MINIO_USER_SECRET_KEY};
+ /usr/bin/mc admin policy set myminio readwrite user=$${MINIO_USER_ACCESS_KEY};
+ exit 0;
+ "
+
+volumes:
+ postgres_data:
+ storage:
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..555e958e
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,74 @@
+services:
+ django:
+ build:
+ dockerfile: Dockerfile
+ context: .
+ ports:
+ - 8000:8000
+ volumes:
+ - ./src/:/jandig/src/
+ - ./docs/:/jandig/docs/
+ - ./etc/:/jandig/etc/
+ - ./locale/:/jandig/locale/
+ - ./run.sh:/jandig/run.sh
+ - ./tasks.py:/jandig/tasks.py
+ env_file:
+ - .envs/.example
+ depends_on:
+ storage:
+ condition: service_started
+ createbuckets:
+ condition: service_started
+ postgres:
+ condition: service_healthy
+ command: /jandig/run.sh
+
+ postgres:
+ image: postgres:15.4
+ env_file:
+ - .envs/.example
+ environment:
+ PGUSER: jandig
+ command: postgres -c max_connections=10000
+ ports:
+ - "5432:5432"
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready", "-d", "jandig"]
+ interval: 5s
+ timeout: 60s
+ retries: 20
+ start_interval: 5s
+
+ storage:
+ image: minio/minio:latest
+ ports:
+ - 9000:9000
+ - 9001:9001
+ volumes:
+ - media_data:/storage
+ env_file:
+ - .envs/.env
+ command: server /storage --console-address ":9001"
+
+ createbuckets:
+ image: minio/mc:RELEASE.2022-09-16T09-16-47Z
+ depends_on:
+ - storage
+ env_file:
+ - .envs/.env
+ entrypoint: >
+ /bin/sh -c "
+ until (/usr/bin/mc config host add myminio $${MINIO_S3_ENDPOINT_URL} $${MINIO_ROOT_USER} $${MINIO_ROOT_PASSWORD}) do echo '...waiting...' && sleep 1; done;
+ /usr/bin/mc mb myminio/$${AWS_STORAGE_BUCKET_NAME};
+ /usr/bin/mc policy set download myminio/$${AWS_STORAGE_BUCKET_NAME};
+ /usr/bin/mc mb myminio/$${AWS_PRIVATE_STORAGE_BUCKET_NAME};
+ /usr/bin/mc admin user add myminio $${MINIO_USER_ACCESS_KEY} $${MINIO_USER_SECRET_KEY};
+ /usr/bin/mc admin policy set myminio readwrite user=$${MINIO_USER_ACCESS_KEY};
+ exit 0;
+ "
+
+volumes:
+ postgres_data:
+ media_data:
\ No newline at end of file
diff --git a/docker/Dockerfile b/docker/Dockerfile
deleted file mode 100644
index b59f6441..00000000
--- a/docker/Dockerfile
+++ /dev/null
@@ -1,12 +0,0 @@
-FROM jandigarte/requirements:latest
-
-RUN mkdir -p /ARte
-WORKDIR /ARte
-COPY docs/ /ARte/docs/
-COPY ./src/ARte /ARte/src/ARte/
-COPY ./locale/ /ARte/locale/
-COPY ./tasks.py /ARte/tasks.py
-COPY ./run.sh /ARte/run.sh
-COPY ./etc/ /ARte/etc/
-
-RUN find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
diff --git a/docker/base.Dockerfile b/docker/base.Dockerfile
deleted file mode 100644
index a47841ff..00000000
--- a/docker/base.Dockerfile
+++ /dev/null
@@ -1,15 +0,0 @@
-FROM debian:buster-slim
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- python3 \
- python3-pip \
- python3-setuptools \
- gettext \
- docutils-common
-COPY ./src/requirements.txt /src/requirements.txt
-
-RUN pip3 install --upgrade pip
-RUN pip3 install --no-cache-dir toolz
-RUN pip3 install --no-cache-dir -r /src/requirements.txt
-
-RUN rm -rf ~/.cache/pip
diff --git a/docker/build-base.sh b/docker/build-base.sh
deleted file mode 100755
index c782a0dc..00000000
--- a/docker/build-base.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-
-set -o errexit
-set -o pipefail
-set -o nounset
-
-# Build base image
-docker build ../ -f base.Dockerfile -t jandigarte/requirements:latest
-
-# Check if user wants to publish
-if [ $# -eq 1 ]; then
- if [ "$1" = "publish" ]; then
- echo; echo; echo "PUBLISHING IMAGES"
- docker push jandigarte/requirements:latest;
- fi
-else
- echo "Execute 'sh build.sh publish' to publish images"
-fi
diff --git a/docker/docker-compose.deploy.yml b/docker/docker-compose.deploy.yml
deleted file mode 100644
index c523a3c5..00000000
--- a/docker/docker-compose.deploy.yml
+++ /dev/null
@@ -1,136 +0,0 @@
-version: '3.5'
-
-services:
- nginx:
- image: nginx:1.15-alpine
- ports:
- - "80:80"
- - "443:443"
- volumes:
- - ../src/data/nginx:/etc/nginx/conf.d
- - ../src/data/certbot/conf:/etc/letsencrypt
- - ../src/data/certbot/www:/var/www/certbot
- - static_dev_files:/usr/share/nginx/html/static/dev
- - static_staging_files:/usr/share/nginx/html/static/staging
- - static_prod_files:/usr/share/nginx/html/static/prod
- command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
- depends_on:
- - dev_django
- - staging_django
- - prod_django
- labels:
- - "com.centurylinklabs.watchtower.enable=false"
-
- certbot:
- image: certbot/certbot
- volumes:
- - ../src/data/certbot/conf:/etc/letsencrypt
- - ../src/data/certbot/www:/var/www/certbot
- entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
- labels:
- - "com.centurylinklabs.watchtower.enable=false"
-
- # DEV ------------------------------------------------------------------------------------------ #
-
- dev_django:
- image: jandigarte/django:dev
- ports:
- - 8000:8000
- env_file:
- - ../src/.envs/.dev_deploy
- depends_on:
- - dev_postgres
- volumes:
- - static_dev_files:/collect/
- - ./media/dev/:/ARte/src/ARte/users/media/
- command: inv db -p docs collect run -g -p
- labels:
- - "com.centurylinklabs.watchtower.enable=true"
-
- dev_postgres:
- image: postgres:11.6
- env_file:
- - ../src/.envs/.dev_deploy
- volumes:
- - postgres_dev_data:/var/lib/postgresql/data
- ports:
- - "5432:5432"
- labels:
- - "com.centurylinklabs.watchtower.enable=false"
- # ------------------------------------------------------------------------------------------ #
-
- # STAGING ------------------------------------------------------------------------------------------ #
-
- staging_django:
- image: jandigarte/django:staging
- ports:
- - 8001:8000
- env_file:
- - ../src/.envs/.staging_deploy
- depends_on:
- - staging_postgres
- volumes:
- - static_staging_files:/collect/
- - ./media/staging/:/ARte/src/ARte/users/media/
- command: inv db -p docs collect run -g -p
- labels:
- - "com.centurylinklabs.watchtower.enable=true"
-
- staging_postgres:
- image: postgres:11.6
- env_file:
- - ../src/.envs/.staging_deploy
- volumes:
- - postgres_staging_data:/var/lib/postgresql/data
- ports:
- - "5433:5432"
- labels:
- - "com.centurylinklabs.watchtower.enable=false"
-
- # ------------------------------------------------------------------------------------------ #
-
- # PROD ------------------------------------------------------------------------------------------ #
-
- prod_django:
- image: jandigarte/django:latest
- ports:
- - 8002:8000
- env_file:
- - ../src/.envs/.prod_deploy
- depends_on:
- - prod_postgres
- volumes:
- - static_prod_files:/collect/
- - ./media/prod/:/ARte/src/ARte/users/media/
- command: inv db -p docs collect run -g -p
- labels:
- - "com.centurylinklabs.watchtower.enable=true"
-
- prod_postgres:
- image: postgres:11.6
- env_file:
- - ../src/.envs/.prod_deploy
- volumes:
- - postgres_prod_data:/var/lib/postgresql/data
- ports:
- - "5434:5432"
- labels:
- - "com.centurylinklabs.watchtower.enable=false"
-
- # ------------------------------------------------------------------------------------------ #
-
- watchtower:
- image: containrrr/watchtower
- volumes:
- - /var/run/docker.sock:/var/run/docker.sock
- command: --interval 30
- labels:
- - "com.centurylinklabs.watchtower.enable=false"
-
-volumes:
- postgres_dev_data:
- postgres_staging_data:
- postgres_prod_data:
- static_dev_files:
- static_staging_files:
- static_prod_files:
\ No newline at end of file
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
deleted file mode 100644
index a5f4e9cb..00000000
--- a/docker/docker-compose.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-version: '3.5'
-
-services:
- django:
- image: jandigarte/django:latest
- restart: always
- build:
- context: ../
- dockerfile: ./docker/Dockerfile
- ports:
- - 8000:8000
- volumes:
- - ../src/ARte/:/ARte/src/ARte/
- - ../locale/:/ARte/locale/
- - ./media/:/ARte/src/ARte/users/media/
- env_file:
- - ../src/.envs/.env
- depends_on:
- - postgres
- command: ./run.sh
-
- postgres:
- image: postgres:12.6
- env_file:
- - ../src/.envs/.env
- command: postgres -c max_connections=10000
- ports:
- - "5432:5432"
- volumes:
- - postgres_data:/var/lib/postgresql/data
-
-volumes:
- postgres_data:
diff --git a/docker/init-production.sh b/docker/init-production.sh
deleted file mode 100755
index 63e2cfc9..00000000
--- a/docker/init-production.sh
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/bin/bash
-
-domains=(dev.jandig.app staging.jandig.app jandig.app)
-rsa_key_size=4096
-data_path="../src/data/certbot"
-email="" # Adding a valid address is strongly recommended
-staging=1 # Set to 1 if you're testing your setup to avoid hitting request limits
-composefile=./docker-compose.deploy.yml
-
-
-if [ -d "$data_path" ]; then
- read -p "Existing data found for $domains. Continue and replace existing certificate? (y/N) " decision
- if [ "$decision" != "Y" ] && [ "$decision" != "y" ]; then
- docker-compose -f $composefile down
- docker-compose -f $composefile up -d nginx
- exit
- fi
-fi
-
-
-if [ ! -e "$data_path/conf/options-ssl-nginx.conf" ] || [ ! -e "$data_path/conf/ssl-dhparams.pem" ]; then
- echo "### Downloading recommended TLS parameters ..."
- mkdir -p "$data_path/conf"
- curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/options-ssl-nginx.conf > "$data_path/conf/options-ssl-nginx.conf"
- curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/ssl-dhparams.pem > "$data_path/conf/ssl-dhparams.pem"
- echo
-fi
-
-
-for domain in ${domains[@]}
-do
- echo "### Creating dummy certificate for $domain ..."
- path="/etc/letsencrypt/live/$domain"
- mkdir -p "$data_path/conf/live/$domain"
- docker-compose -f $composefile run --rm --entrypoint "\
- openssl req -x509 -nodes -newkey rsa:1024 -days 1\
- -keyout '$path/privkey.pem' \
- -out '$path/fullchain.pem' \
- -subj '/CN=localhost'" certbot
- echo
-done
-
-echo "### Starting nginx ..."
-docker-compose -f $composefile up --force-recreate -d nginx
-echo
-
-for domain in ${domains[@]}
-do
- echo "### Deleting dummy certificate for $domain ..."
- docker-compose -f $composefile run --rm --entrypoint "\
- rm -Rf /etc/letsencrypt/live/$domain && \
- rm -Rf /etc/letsencrypt/archive/$domain && \
- rm -Rf /etc/letsencrypt/renewal/$domain.conf" certbot
- echo
-done
-
-
-
-# Select appropriate email arg
-case "$email" in
- "") email_arg="--register-unsafely-without-email" ;;
- *) email_arg="--email $email" ;;
-esac
-
-# Enable staging mode if needed
-if [ $staging != "0" ]; then staging_arg="--staging"; fi
-
-#Join $domains to -d args
-for domain in "${domains[@]}"
-do
- domain_arg="-d $domain"
- echo "### Requesting Let's Encrypt certificate for $domain ..."
- docker-compose -f $composefile run --rm --entrypoint "\
- certbot certonly --webroot -w /var/www/certbot \
- $staging_arg \
- $email_arg \
- $domain_arg \
- --rsa-key-size $rsa_key_size \
- --agree-tos \
- --force-renewal" certbot
- echo
-done
-
-echo "### Reloading nginx ..."
-docker-compose -f $composefile exec nginx nginx -s reload
diff --git a/docker/nonginx.yml b/docker/nonginx.yml
deleted file mode 100644
index 762d88ef..00000000
--- a/docker/nonginx.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-version: "3.5"
-
-services:
-
- prod_django:
- image: jandigarte/django:latest
- ports:
- - 8000:8000
- build:
- context: ../
- dockerfile: ./docker/Dockerfile
- env_file:
- - ../src/.envs/.prod_deploy
- depends_on:
- - prod_postgres
- volumes:
- - ./static/:/ARte/collect/
- - ./media/prod/:/ARte/src/ARte/users/media/
- command: inv db -p docs collect run -g -p
-
- prod_postgres:
- image: postgres:11.6
- env_file:
- - ../src/.envs/.prod_deploy
- command: postgres -c max_connections=10000
- volumes:
- - postgres_prod_data:/var/lib/postgresql/data
- ports:
- - "5432:5432"
-
-volumes:
- postgres_prod_data:
- static_prod_files:
\ No newline at end of file
diff --git a/docker/taskfile.sh b/docker/taskfile.sh
deleted file mode 100644
index d9a606c4..00000000
--- a/docker/taskfile.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/bash
-
-data_path="../src/data/certbot"
-
-rsa_key_size=4096
-email="" # Adding a valid address is strongly recommended
-staging=0 # Set to 1 if you're testing your setup to avoid hitting request limits
-composefile=./docker-compose.deploy.yml
-
-function fake-cert {
- path="/etc/letsencrypt/live/$1"
- echo "### Creating dummy certificate for $1 ..."
- mkdir -p "$data_path/conf/live/$1"
- docker-compose -f $composefile run --rm --entrypoint "\
- openssl req -x509 -nodes -newkey rsa:1024 -days 1\
- -keyout '$path/privkey.pem' \
- -out '$path/fullchain.pem' \
- -subj '/CN=localhost'" certbot
- echo
- chmod 644 '$path/privkey.pem'
-}
-
-function delete-cert {
- echo "### Deleting dummy certificate for $1 ..."
- docker-compose -f $composefile run --rm --entrypoint "\
- rm -Rf /etc/letsencrypt/live/$1 && \
- rm -Rf /etc/letsencrypt/archive/$1 && \
- rm -Rf /etc/letsencrypt/renewal/$1.conf" certbot
- echo
-}
-
-function download-params {
- if [ ! -e "$data_path/conf/options-ssl-nginx.conf" ] || [ ! -e "$data_path/conf/ssl-dhparams.pem" ]; then
- echo "### Downloading recommended TLS parameters ..."
- mkdir -p "$data_path/conf"
- curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/options-ssl-nginx.conf > "$data_path/conf/options-ssl-nginx.conf"
- curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/ssl-dhparams.pem > "$data_path/conf/ssl-dhparams.pem"
- echo
- fi
-}
-
-function request-cert {
- # Select appropriate email arg
- case "$email" in
- "") email_arg="--register-unsafely-without-email" ;;
- *) email_arg="--email $email" ;;
- esac
-
- # Enable staging mode if needed
- if [ $staging != "0" ]; then staging_arg="--staging"; fi
-
- domain_arg="-d $1"
- echo "### Requesting Let's Encrypt certificate for $1 ..."
- docker-compose -f $composefile run --rm --entrypoint "\
- certbot certonly --webroot -w /var/www/certbot \
- $staging_arg \
- $email_arg \
- $domain_arg \
- --rsa-key-size $rsa_key_size \
- --agree-tos \
- --force-renewal" certbot
- echo
-}
-
-
-"$@"
\ No newline at end of file
diff --git a/docs/animacoes-ingles.rst b/docs/animacoes-ingles.rst
new file mode 100644
index 00000000..bc1c6361
--- /dev/null
+++ b/docs/animacoes-ingles.rst
@@ -0,0 +1,103 @@
+Tips for producing animation
+=============================
+This document contains technical guidelines and best practices for
+production of augmented reality animations for Jandig. Lots of
+of these guidelines can be used to produce content for
+other platforms.
+
+In addition to producing a version considering the following limitations,
+it is recommended that an “ideal” version be produced, which can be
+used in controlled environments and/or in the future (as these
+limitations will decrease).
+
+File format
+~~~~~~~~~~~~~~~~~~
+
+Currently, the only supported format is GIF.
+
+Details
+~~~~~~~~
+
+Use as few details and small elements as possible,
+as they may not be identifiable by the public.
+
+One way to test here is to save the storyboard images to
+300x300px and see if you can identify all the elements. It's
+important to remember that the public can see the animation from a distance,
+so that it looks very small on the phone screen.
+
+Amount of colors
+~~~~~~~~~~~~~~~~~~~
+
+The recommendation is to reduce as much as possible, so it will not
+compromise the original colors.
+
+To optimize these values, we recommend minimizing the use of color degradation and
+avoid fade transitions.
+
+A technique to plan this usage before producing the animation is
+export the storyboard images to GIF with different amounts of
+Colors.
+
+Resolution
+~~~~~~~~~
+
+To increase device compatibility, we limit the resolution
+of the display frame (which appears in full screen on the smartphone) in
+640x480 pixels. As the animation will only appear in a part of this
+framework, we recommend creating the content at 300x300px.
+
+Framerate
+~~~~~~~~~
+
+The frame rate (measured in frames per second)
+recommended is a maximum of 12 fps.
+
+Loop
+~~~~
+
+To create the illusion of continuity, the animation must be looped. In other words, the transition from the last to the first frame must be imperceptible.
+
+Time
+~~~~~
+
+The shorter the animation, the better. This will allow for better quality
+of images and ensure that the public watches all the material. So far, the longest animation made for Jandig is approximately
+20 seconds. The recommendation is that it should have up to 15 seconds.
+
+File size
+~~~~~~~~~~~~~~~~~~
+
+While the following parameters have flexibility as to guidelines,
+this is the toughest. Files should ideally be up to 500 kB and should not exceed 1 MB. This is a decisive factor in the choice of works to be
+included in an exhibition, the smaller the better.
+
+This limitation exists mainly for the following reasons: - We do not have
+control of the public connection speed when accessing the content,
+which can cause the download of all works to take time. - Not
+we want to burden the public's data plan. - Smaller files are more
+lightweight require less processing, making the
+platform compatible with a greater number of phones.
+
+Conclusion
+~~~~~~~~~
+
+To reach an optimal result, the ideal is to test the parameters together.
+
+A recommended process is exporting the parameters, limiting them as much as possible.
+(8 colors, 200x200px, 5 fps) and also with the minimum recommendations of
+limitation (256 colors, 300x300px, 12 fps) and compare.
+
+From there, modify one parameter at a time from the minimum limitations,
+reducing only the framerate/resolution/colors to see what is the minimum
+that works fine.
+
+If, after reducing the 3 to the minimum that works well, the file is still
+large, keep decreasing the parameters in different combinations
+to reach an optimal result. Also remember to keep the
+high resolution version. Here the recommendation is to save with 1000x1000px and
+24fps.
+
+In case you use Adobe Media encoder, there is a tutorial that was developed
+by UEMG for `download in
+PDF `__.
diff --git a/docs/animacoes.rst b/docs/animacoes-portugues.rst
similarity index 100%
rename from docs/animacoes.rst
rename to docs/animacoes-portugues.rst
diff --git a/docs/architecture-document.md b/docs/architecture-document.md
index 94f17f36..a095ca21 100644
--- a/docs/architecture-document.md
+++ b/docs/architecture-document.md
@@ -4,6 +4,13 @@
|--------|------------|-----------|------|
|1.0|Initial version|Victor Gomide & Emanuel Holanda|05/10/2020|
|1.1|New diagrams in PlantUml| VIctor Gomide & Emanuel Holanda |24/10/2020|
+|1.2|Reference the Plant UML source code in the doc|Gabrielle Ribeiro, Gustavo Duarte & Victor Amaral|09/02/2022|
+|1.3|Refactor the architectural reference topic|Hugo Sobral, Sofia Patrocínio|10/02/2022|
+|1.4|Fix typos|Sofia Patrocínio, Hugo Sobral|10/02/2022|
+|1.5|Update package diagram logic view Plant UML|João Pedro Guedes|10/02/2022|
+|1.6|Add images to technologies and links to their documentation|João Pedro Guedes|15/02/2022|
+|1.7|Add description of the actors present in the use case view|Sofia Patrocinio|21/02/2022|
+|1.7|Add description in logical view and write implementation view|João Pedro Guedes|23/02/2022|
# Software Architecture Document (SAD)
@@ -21,8 +28,9 @@ This document is extremely important for understanding the project as a whole, s
- **SAD:** Software Architecture Document
- **App:** Application
-- **MTV:** Model-Template-View
+- **MTV:** Model-View-Template
- **PWA:** Progressive Web App
+- **MVC:** Model-View-Controller
### References
@@ -33,6 +41,7 @@ This document is extremely important for understanding the project as a whole, s
- [Documento de Arquitetura de Software RDI-AEE](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwiE78LEr5zsAhV7GLkGHSWyAVMQFjAAegQIBRAC&url=http%3A%2F%2Frepositorio.aee.edu.br%2Fbitstream%2Faee%2F1106%2F3%2FTCC2_2018_2_GabrielLeiteDias_MatheusLimadeAlbuquerque_Apendice2.pdf&usg=AOvVaw2wXEOkYpBHmN32ChHHDgOh)
- [The Django Book: Django's Structure](https://djangobook.com/mdj2-django-structure/)
+
### Overview
In order to explain Jandig ARte's architecture from different points of views, here's an approach of the next topics:
@@ -45,12 +54,43 @@ In order to explain Jandig ARte's architecture from different points of views, h
## Architectural Representation
-Project's main programming language is Python, through Django framework. Django uses an exclusive architecture called **MTV (Model-Template-View)**, in which **Model** represents the data layer, **Template** represents user's interface and **View** acts as an intermediary layer between them:
-
-![](images/mtv-architecture-diagram.png)
+Project's main programming language is Python, through Django framework. Django uses an exclusive architecture called **MVT (Model-View-Template)**, in which **Model** represents the data layer, **Template** represents user's interface and **View** acts as an intermediary layer. Jandig also uses **Jinja** for enhancing Django's Template view for MVT architecture.
Jandig ARte is a **Progressive Web App (PWA)**, which means it is an web app that has a similar use to a native mobile app. It uses **PostgreSQL** as database.
+### Django Framework
+
+![django-icon](https://www.djangoproject.com/m/img/logos/django-logo-negative.png)
+
+Django is a Python based web framework that provides a rapid, clean and pragmatic development. Django also offers a bunch of benefits that can take care of the hassle of web development, *i.e.*, Django is a fast, secure and scalable tool. You can read more about it [here](https://www.djangoproject.com/start/overview/)
+
+### Model-View-Template
+
+Model-View-Template (also called MVT) is a specific Django architecture focused on web applications. Although it seems similar to *MVC* architecture, *MVT* is slightly different. The design model determines the workflow of a Django app. The specific Jandig structure can be seen in the following picture:
+
+![mtv-architecture-diagram](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/memeLab/Jandig/develop/docs/images/plantUML/mtv-architecture-diagram.puml)
+
+**Model** stands for the data representation in the app. It's commonly represented as the database tables.
+**View** is responsible for the HTTP communication, including requests as well as responses.
+**Template** stands for the visualization layer and can be seen as the front-end dynamic component of Django.
+
+### Jinja
+![jinja-logo](https://jinja.palletsprojects.com/en/3.0.x/_images/jinja-logo.png)
+
+Jinja is a Python based web template engine. Jinja can generate any markup as source code and also provides Python-like expressions for templates. The engine template allows customization of tags, filters, tests and global settings, and unlike the Django template engine, Jinja allows the template designer to call functions with arguments on objects. You can read more about it [here](https://jinja.palletsprojects.com/en/3.0.x/intro/)
+
+### Progressive Web App
+
+A progressive Web App is a subtype of web software applications that is built to deliver enhanced capabilities, reliability and installability while reaching anyone, anywhere on any device with a standards-compilant browser (this includes desktop as well as mobile devices).
+
+This kind of application offers a bunch of benefits to projects, since PWA's are ever-present, on home screens, docks and taskbars. They can also read and write files from the local file system, interact with data stored on device and even access the device hardware.
+
+### PostgreSQL
+
+![postgreSQL](https://miro.medium.com/max/800/0*z58cqZWxu2_4q5-g.jpg)
+
+PostgreSQL is an advanced version of SQL. In short, PostgreSQL is an open source relational database system that supports both SQL and JSON querying, it also provides support to different functions of SQL-like statements, such as foreign keys, subqueries, triggers and many different user-defined types and functions. You can read more about it [here](https://www.postgresql.org/)
+
## Architectural Goals and Constraints
@@ -61,53 +101,53 @@ Jandig was created for providing a low-cost and easy-to-use augmented reality ex
- No previous knowledge of programming necessary for using it;
- Free, or cheap enough;
- Available in different languages, so people around the world can use it;
-- Open Source, so community can work together for making it awesome!
+- Open Source, so the community can work together to make it awesome!
## Use-Case View
### Account Access and Management
-The diagram below shows how account access and management is done, with users and system as actors. Please note that Visitor is an user that hasn't log in the app.
-
-![](images/use-case-diagram-user.png)
+The diagram below shows how account access and management is done, with users and system as actors. Please note that Visitor is a user that hasn't log in the app to access an exhibition.
+![use-case-diagram-user](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/memeLab/Jandig/develop/docs/images/plantUML/use-case-diagram-user.puml)
### Artist Role
-The following diagram shows the application's features focused on the Artist's role.
-
-
-![](images/use-case-diagram-artist.png)
+The following diagram shows the application's features focused on the Artist's role. The Artist's role can share their artworks and exhibitions.
+![use-case-diagram-artist](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/memeLab/Jandig/develop/docs/images/plantUML/use-case-diagram-artist.puml)
### Other Features
-Below are shown some other interesting features from Jandig ARte:
+Below are shown some other interesting features from Jandig ARte that doesn't need log in:
-![](images/use-case-diagram-features.png)
+![use-case-diagram-features](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/memeLab/Jandig/develop/docs/images/plantUML/use-case-diagram-features.puml)
## Logical View
-### Overview
+The logical view describe the system scructure, showning how the system is organized in terms of packages, intefaces etc.
+### Package Diagram
Since the software is Django-based, it contains projects, apps and layers. in Jandig ARte case, we have two main apps: "core" and "users".
-![](images/package-diagram-logical-view.png)
-
+![package-diagram-logical-view](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/memeLab/Jandig/develop/docs/images/plantUML/package-diagram-logical-view.puml)
-### Architecturally Significant Design Packages
+## Implementation View
+The implementation view describes how the system will be implemented. One of its main features is the Class Diagram.
+
+### Architecturally Significant Design Packages
#### "Profile" Class Diagram
-![](images/class-diagram-profile.png)
+![Profile-class-diagram](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/memeLab/Jandig/develop/docs/images/plantUML/class-diagram-profile.puml)
#### "Marker" Class Diagram
-![](images/class-diagram-marker.png)
+![Marker-class-diagram](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/memeLab/Jandig/develop/docs/images/plantUML/class-diagram-marker.puml)
#### "Artwork" Class Diagram
-![](images/class-diagram-artwork.png)
+![Artwork-class-diagram](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/memeLab/Jandig/develop/docs/images/plantUML/class-diagram-artwork.puml)
#### "Object" Class Diagram
-![](images/class-diagram-object.png)
+![Object-class-diagram](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/memeLab/Jandig/develop/docs/images/plantUML/class-diagram-object.puml)
#### "Exhibit" Class Diagram
-![](images/class-diagram-exhibit.png)
+![Exhibit-class-diagram](http://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/memeLab/Jandig/develop/docs/images/plantUML/class-diagram-exhibit.puml)
diff --git a/docs/conf.py b/docs/conf.py
index 453f7feb..8ade9a1e 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -58,5 +58,21 @@
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
+html_theme_options = {
+ 'logo': 'logo.png',
+ 'github_user': 'memeLab',
+ 'github_repo': 'Jandig',
+ 'html_sidebars': {
+ '**': [
+ 'search.html',
+ 'navigation.html',
+ ]
+ },
+ 'extra_nav_links': {
+ 'Official Site': 'https://jandig.app',
+ 'Github': 'https://github.com/memelab/Jandig'
+ },
+}
+
def setup(app):
app.add_css_file('reset.css')
\ No newline at end of file
diff --git a/docs/fix-code-smells.md b/docs/fix-code-smells.md
new file mode 100644
index 00000000..cb1e4799
--- /dev/null
+++ b/docs/fix-code-smells.md
@@ -0,0 +1,29 @@
+# Fixing code smells on project
+
+To identify and map python code smells on Jandig project, the development team uses [Prospector](https://github.com/PyCQA/prospector). Prospector is a Python tool used to output information about errors, unnecessary code complexity and convention violations for the language.
+
+
+## Installation
+
+Before installing Prospector, you need to assure that pip is properly installed on your machine. Once you have pip, you can simply type the command
+
+```
+pip install prospector
+```
+
+You can also follow the [official Prospector installation guide](https://github.com/PyCQA/prospector#installation).
+
+
+## Running Prospector on Jandig
+
+To get the information about code smells you need just to run the following command on the root directory of Jandig:
+
+```
+prospector
+```
+
+If you want to store the output on a ```.txt``` file, you can must the following command:
+
+```
+prospector > filename.txt
+```
\ No newline at end of file
diff --git a/docs/images/installation-guide-createFile.png b/docs/images/installation-guide-createFile.png
new file mode 100644
index 00000000..4c07fe8b
Binary files /dev/null and b/docs/images/installation-guide-createFile.png differ
diff --git a/docs/images/installation-guide-duplicate-dependency.png b/docs/images/installation-guide-duplicate-dependency.png
new file mode 100644
index 00000000..3c0bcd2c
Binary files /dev/null and b/docs/images/installation-guide-duplicate-dependency.png differ
diff --git a/docs/images/installation-guide-expected-window.png b/docs/images/installation-guide-expected-window.png
new file mode 100644
index 00000000..817e4556
Binary files /dev/null and b/docs/images/installation-guide-expected-window.png differ
diff --git a/docs/images/installation-guide-migration.png b/docs/images/installation-guide-migration.png
new file mode 100644
index 00000000..65ccb283
Binary files /dev/null and b/docs/images/installation-guide-migration.png differ
diff --git a/docs/images/installation-guide-minio.png b/docs/images/installation-guide-minio.png
new file mode 100644
index 00000000..5e788c21
Binary files /dev/null and b/docs/images/installation-guide-minio.png differ
diff --git a/docs/images/installation-guide-terminal-expected.png b/docs/images/installation-guide-terminal-expected.png
new file mode 100644
index 00000000..957662e2
Binary files /dev/null and b/docs/images/installation-guide-terminal-expected.png differ
diff --git a/docs/images/plantUML/mtv-architecture-diagram.puml b/docs/images/plantUML/mtv-architecture-diagram.puml
index 24c079b2..56a6889e 100644
--- a/docs/images/plantUML/mtv-architecture-diagram.puml
+++ b/docs/images/plantUML/mtv-architecture-diagram.puml
@@ -3,7 +3,7 @@
left to right direction
rectangle "Client Side" as C {
- rectangle "Django Template" as DT
+ rectangle "Jinja Template" as DT
}
rectangle "Server Side" as S {
diff --git a/docs/images/plantUML/package-diagram-logical-view.puml b/docs/images/plantUML/package-diagram-logical-view.puml
index 78318bf7..68d41145 100644
--- a/docs/images/plantUML/package-diagram-logical-view.puml
+++ b/docs/images/plantUML/package-diagram-logical-view.puml
@@ -3,6 +3,42 @@
hide circle
package ArTE <> {
+ package config {
+
+ }
+
+ package core <> {
+ package "models.py" as M2 {
+ class Exhibit
+ }
+
+ package jinja2 {
+ package users {
+
+ }
+ }
+
+ package migrations {
+
+ }
+
+ package static {
+ package css {
+
+ }
+ package image {
+
+ }
+ package js {
+
+ }
+ }
+
+ package view_s {
+
+ }
+ }
+
package users <> {
package "models.py" as M1 {
class Profile
@@ -10,13 +46,28 @@ package ArTE <> {
class Artwork
class Object
}
- }
+ package jinja2 {
+ package users {
- package core <> {
- package "models.py" as M2 {
- class Exhibit
+ }
+ }
+ package media {
+ package markers {
+
+ }
+ }
+ package migrations {
+
+ }
+ package services {
+
+ }
+ package statics {
+ package css {
+ }
}
}
+
}
@enduml
diff --git a/docs/index.rst b/docs/index.rst
index b051a821..d282568a 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -9,7 +9,9 @@ Ajuda
.. toctree::
:maxdepth: 2
- animacoes
- marcadores
- publicando-obras-ingles
+ animacoes-portugues
+ marcadores-portugues
publicando-obras-portugues
+ animacoes-ingles
+ marcadores-ingles
+ publicando-obras-ingles
diff --git a/docs/installation-guide.md b/docs/installation-guide.md
new file mode 100644
index 00000000..5f1dbc02
--- /dev/null
+++ b/docs/installation-guide.md
@@ -0,0 +1,77 @@
+## Revision History
+
+|Version | description| Author(s) | date |
+|--------|------------|-----------|------|
+|1.0|Initial version|João Victor Valadão|15/07/2022|
+|1.1|Migration problems|Marcelo Araújo dos Santos|18/07/2022|
+|1.2|applying the requested changes|João Victor Valadão|22/07/2022|
+
+
+# Installation Guide
+
+## Introduction
+
+This document provides an assistance guide with the details (step by step) of the installation of the Jandig and how to fix the most common bugs that may appear when beginners are trying to set up the environment, and start contributing to the Jandig project. So, as mentioned earlier, the purpose of this document is to help new contributors interact with the code, especially new developers that are interested in the application. Make sure to check the prerequisites to run Jandig ARte, because they are tools that you will need in your development workspace that you can access in the [description](http://memelab.com.br/jandig/README.md/) of the repository.
+
+## Step 1 - Cloning the Repository
+
+The first step after downloading the prerequisites is clone the repository, so we are going to need the following code:
+```
+git clone https://github.com/memeLab/Jandig
+cd Jandig
+```
+If you are having any problems with the git commands consider checking the Github documentation for problems with the [cloning](https://docs.github.com/pt/repositories/creating-and-managing-repositories/troubleshooting-cloning-errors) or your user [authentication](https://docs.github.com/pt/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-email-preferences/setting-your-commit-email-address)
+
+## Step 2 - Running the Docker
+
+Jandig uses docker and docker-compose to ensure a consistent development environment and to make the deploy process as painless as possible, so we are going to initialize the docker and then run the docker-compose.yml
+```
+docker-compose -f docker/docker-compose.yml up
+```
+
+### ERROR - Env file not found
+
+If you receive an error message saying it couldn't find env file, you probably didn't create the .env file yet. So navigate to **Jandig\src\\.envs\\** and create a file named **.env** and copy the content of **.example** and paste it in this file. Then run the above code again.
+
+### ERROR - System could't find CreateFile
+If you are receiving the following error using Windows and Docker, that means your Docker has problems to initiate. Try to initialize the Docker Desktop manually with admin privileges, you can check the Docker Desktop running in your toolbar. If your docker isn't open yet consult the [Docker Desktop](https://docs.microsoft.com/pt-br/windows/wsl/tutorials/wsl-containers) documentation.
+
+![env-file](./images/installation-guide-createFile.png)
+
+
+### ERROR - Minio
+If you encounter a screen as the image below, or some error message related to Minio, it's very likely that the `USE_MINIO` in **.env** file is set to True. To correct this, set it to False (`USE_MINIO=False`).
+
+![env-file](./images/installation-guide-minio.png)
+
+### ERROR - Migration
+
+
+Jandig implemented Invoke with some "recipes" to make our lives as developers easier. So in order to solve the backend issue with migrations (image below) try doing the following code to run the migrations on our containers:
+```
+cd docker/
+docker-compose run django inv db
+# or if you already have a django container running
+docker-compose exec django inv db
+```
+
+![env-file](./images/installation-guide-migration.png)
+
+If the problem isn't fixed do the following steps, as @GustavoAPS commented [here](https://github.com/memeLab/Jandig/issues/436#issuecomment-1034420328):
+1. Run the container.
+2. Open a new terminal and list the containers with "docker ps"
+3. Enter the project container with "docker exec -it docker_django_1 bash"
+4. Inside the container make the migrations with: `python3 src/ARte/manage.py migrate`
+5. After the migrations, the problem should be solved.
+
+## Step 3 - Jandig ARte in the localhost
+After these steps you should have Jandig ARte running in your localhost, by default the project uses the **localhost:8000**. To access it you can copy the instruction above and paste in your browser or click [here](http://localhost:8000/)
+
+![env-file](./images/installation-guide-terminal-expected.png)
+
+The expected web page is shown below
+
+![env-file](./images/installation-guide-expected-window.png)
+
+
+Need more help? consult the issue "Problem to run Jandig ARte #436" [here](https://github.com/memeLab/Jandig/issues/436).
diff --git a/docs/marcadores-ingles.rst b/docs/marcadores-ingles.rst
new file mode 100644
index 00000000..86ec6594
--- /dev/null
+++ b/docs/marcadores-ingles.rst
@@ -0,0 +1,59 @@
+Hints to produce Tags
+==============================
+
+This document contains tecnical, aesthetics and good practices guidelines to the production of Tags of augmented reality Jandig.
+
+Borders
+------
+
+The borders are graphic elements that trigger the recognition of the object associated with each tag. For this reason, one should not cover them and them must always
+be
+seen completely by the camera. Put the finger over the border or approach the camera too close to the tag will derail the recognition, for example. This feature should
+be always taken into account in the production and application of the tags.
+
+We use by default 20% of width from the border in the Jandig tags, that is in a tag with 10 centimeters of width, we will have a border of 2 centimeters of width.
+
+The central image of the Tag should not touch the borders. The minimum distance of the imagen to the internal margin of the border should be 2% of the total width of
+the Tag.
+
+Although little texts (exhibition name, app url) can be applied over the border without prejudice in the recognition, is recomended the height of the text never
+overtake the total porcentage of the border.
+
+.. image:: images/MarkerGuide.png
+ :width: 320px
+ :align: center
+
+Symmetry
+--------
+
+Considering that the visualization of the object depends on the position of the Tag in relation of the camera, we avoid using images with symmetry vertical as well as
+horizantal. This rule aim avoid that the recognition system get confused about which orientation it must show the image.
+
+Colors and gradient
+------------------
+
+To ensure endless possibilities of application of the Tags, we dont use colors or gradients in the central images. The only color used is 100% black, without
+utilization of tones.
+
+This is not a limitation of the system. It is possible to use any image as a Tag, following other recomedations of this document.
+
+Printing and about that
+-----------------
+
+Reflexes, including over the borders, can impede that your Tags be recognized as a Tag. So that thay are recognized more easily by the system, they should utilize
+opaque paints and materials in them production.
+
+It's important that the external and internal margins of the border be always well delimited. In case of stickers or background application more dark, guarantee a
+white margin around the black border. This reservation of space must be at least 3% of the total marker width.
+
+Illumination
+----------
+
+The quality and color of ambient lighting can influence the Tag reading. For a good visualization, prefer a well distributed illumination, that does not generate
+reflections and avoid using amber colored lighting.
+
+Stickers
+--------
+
+Although Tags can be recognized even in very small formats, we usually produce Jandig Tags stickers with 5 x 5 centimeters. This dimension associates good perfomance
+with good readability of all elements, including the text.
diff --git a/docs/marcadores.rst b/docs/marcadores-portugues.rst
similarity index 100%
rename from docs/marcadores.rst
rename to docs/marcadores-portugues.rst
diff --git a/docs/old hotsite/css/style.css b/docs/old hotsite/css/style.css
index a42f5e70..28b125b2 100644
--- a/docs/old hotsite/css/style.css
+++ b/docs/old hotsite/css/style.css
@@ -41,7 +41,7 @@ h3 {
font-size: 18px;
}
-.button:hover {
+button.button:hover {
background: #93e3e5;
cursor: pointer;
}
@@ -84,11 +84,13 @@ h3 {
}
}
-}
+
@media screen and (max-width: 600px) {
.footer {padding: 0 0% 0 0%;}
.row {padding: 0 0 0 0;
}
+}
+
/*.row {
display: flex;
justify-content: space-between;
diff --git a/docs/real_docs/development-server.md b/docs/real_docs/development-server.md
index 8397e5e8..bdbed3d3 100644
--- a/docs/real_docs/development-server.md
+++ b/docs/real_docs/development-server.md
@@ -1,9 +1,9 @@
## Welcome to the development server guide
-Run the local development server using sqlite as database and serving static files with whitenoise (-w flag). The server will be available at http://localhost:8000.
+Run the local development server. The server will be available at http://localhost:8000.
```shell
-$ inv db collect run -w
+$ inv db -p collect run -w
```
With the previous command you can use ARte only on the local machine running the server. Because of security protocols, other devices must access through a ssl (https) connection. To do this, we use [ngrok](https://ngrok.com/download). The ngrok will generate a https url pointing to your local server, so you can access ARte through external devices.
diff --git a/etc/nginx.conf b/etc/nginx.conf
deleted file mode 100644
index c28b89e5..00000000
--- a/etc/nginx.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-user nginx;
-worker_processes 14;
-worker_rlimit_nofile 65535;
-
-error_log /var/log/nginx/error.log warn;
-pid /var/run/nginx.pid;
-
-
-events {
- worker_connections 999999;
-}
-
-
-http {
- include /etc/nginx/mime.types;
- default_type application/octet-stream;
-
- log_format main '$remote_addr - $remote_user [$time_local] "$request" '
- '$status $body_bytes_sent "$http_referer" '
- '"$http_user_agent" "$http_x_forwarded_for"';
-
- access_log /var/log/nginx/access.log main;
-
- sendfile on;
- #tcp_nopush on;
-
- keepalive_timeout 65;
-
- gzip on;
- proxy_cache_path /home/ubuntu/cache levels=1:2 keys_zone=jandigcache:1024m max_size=10g;
-
- include /etc/nginx/conf.d/*.conf;
-}
\ No newline at end of file
diff --git a/etc/nginx_server.conf b/etc/nginx_server.conf
deleted file mode 100644
index 05aaa2f3..00000000
--- a/etc/nginx_server.conf
+++ /dev/null
@@ -1,69 +0,0 @@
-server {
- listen 80;
- server_name localhost;
-
- location / {
- root /usr/share/nginx/html;
- index index.html index.htm;
- }
-
- error_page 500 502 503 504 /50x.html;
- location = /50x.html {
- root /usr/share/nginx/html;
- }
-}
-
-server {
- listen 80 backlog=65536;
- server_name jandig.app;
-
- #location / {
- # proxy_set_header Host $http_host;
- # proxy_set_header X-Real-IP $remote_addr;
- # proxy_pass http://localhost:8000/;
- #}
-
- location / {
- return 301 https://$host$request_uri;
- }
-
- location /.well-known/acme-challenge/ {
- root /etc/letsencrypt;
- }
-}
-
-server {
- listen 443 ssl backlog=65536;
- server_name jandig.app;
-
- ssl_certificate /etc/letsencrypt/live/jandig.app/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/jandig.app/privkey.pem;
-
- include /etc/letsencrypt/options-ssl-nginx.conf;
- ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
-
- proxy_buffers 32 16k;
- proxy_buffer_size 16k;
- proxy_busy_buffers_size 64k;
- proxy_buffering on;
- proxy_cache jandigcache;
-
- location / {
- proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
- proxy_cache_revalidate on;
- proxy_cache_background_update on;
- proxy_cache_lock on;
-
- proxy_set_header Host $http_host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_pass http://localhost:8000/;
- }
-
- location /static {
- sendfile on;
- sendfile_max_chunk 5m;
- alias /home/ubuntu/jandig2/docker/volumes/docker_static_prod_files/_data/;
- }
- charset utf-8;
- client_max_body_size 0;
-}
diff --git a/etc/scripts/compilemessages.py b/etc/scripts/compilemessages.py
index 2a2c285b..2af14779 100644
--- a/etc/scripts/compilemessages.py
+++ b/etc/scripts/compilemessages.py
@@ -24,12 +24,12 @@ def main():
# Build locale list
all_locales = []
for basedir in basedirs:
- locale_dirs = filter(os.path.isdir, glob.glob('%s/*' % basedir))
+ locale_dirs = filter(os.path.isdir, glob.glob(f'{basedir}/*'))
all_locales.extend(map(os.path.basename, locale_dirs))
locales = set(all_locales)
for basedir in basedirs:
- dirs = [os.path.join(basedir, l, 'LC_MESSAGES') for l in locales]
+ dirs = [os.path.join(basedir, locale, 'LC_MESSAGES') for locale in locales]
locations = []
for ldir in dirs:
for dirpath, dirnames, filenames in os.walk(ldir):
@@ -41,8 +41,8 @@ def compile_messages(locations):
"""
Locations is a list of tuples: [(directory, file), ...]
"""
- for i, (dirpath, f) in enumerate(locations):
- print('processing file %s in %s\n' % (f, dirpath))
+ for _, (dirpath, f) in enumerate(locations):
+ print(f'processing file {f} in {dirpath}\n')
# Program args
po_path = os.path.join(dirpath, f)
@@ -51,12 +51,12 @@ def compile_messages(locations):
args = [program] + program_options + extra_args
# Execute command
- output, errors, status = popen_wrapper(args)
+ __, errors, status = popen_wrapper(args)
if status:
if errors:
- msg = "Execution of %s failed: %s" % (program, errors)
+ msg = f'Execution of {program} failed: {errors}'
else:
- msg = "Execution of %s failed" % program
+ msg = f'Execution of {program} failed'
raise RuntimeError(msg)
@@ -65,13 +65,11 @@ def popen_wrapper(args, os_err_exc_type=RuntimeError):
Friendly wrapper around Popen.
Return stdout output, stderr output, and OS status code.
"""
- try:
- p = Popen(args, shell=False, stdout=PIPE, stderr=PIPE, close_fds=True)
- except OSError as err:
- raise os_err_exc_type('Error executing %s' % args[0]) from err
- output, errors = p.communicate()
- return output, errors, p.returncode
+ with Popen(args, shell=False, stdout=PIPE, stderr=PIPE, close_fds=True) as p:
+ output, errors = p.communicate()
+ return output, errors, p.returncode
+ raise os_err_exc_type('Error executing')
if __name__ == '__main__':
- main()
\ No newline at end of file
+ main()
diff --git a/etc/ulimits.conf b/etc/ulimits.conf
deleted file mode 100644
index 8160f20a..00000000
--- a/etc/ulimits.conf
+++ /dev/null
@@ -1,64 +0,0 @@
-# /etc/security/limits.d/jandig.conf
-#
-#Each line describes a limit for a user in the form:
-#
-#
-#
-#Where:
-# can be:
-# - a user name
-# - a group name, with @group syntax
-# - the wildcard *, for default entry
-# - the wildcard %, can be also used with %group syntax,
-# for maxlogin limit
-# - NOTE: group and wildcard limits are not applied to root.
-# To apply a limit to the root user, must be
-# the literal username root.
-#
-# can have the two values:
-# - "soft" for enforcing the soft limits
-# - "hard" for enforcing hard limits
-#
-# can be one of the following:
-# - core - limits the core file size (KB)
-# - data - max data size (KB)
-# - fsize - maximum filesize (KB)
-# - memlock - max locked-in-memory address space (KB)
-# - nofile - max number of open files
-# - rss - max resident set size (KB)
-# - stack - max stack size (KB)
-# - cpu - max CPU time (MIN)
-# - nproc - max number of processes
-# - as - address space limit (KB)
-# - maxlogins - max number of logins for this user
-# - maxsyslogins - max number of logins on the system
-# - priority - the priority to run user process with
-# - locks - max number of file locks the user can hold
-# - sigpending - max number of pending signals
-# - msgqueue - max memory used by POSIX message queues (bytes)
-# - nice - max nice priority allowed to raise to values: [-20, 19]
-# - rtprio - max realtime priority
-# - chroot - change root to directory (Debian-specific)
-#
-#
-#
-
-#* soft core 0
-#root hard core 100000
-#* hard rss 10000
-#@student hard nproc 20
-#@faculty soft nproc 20
-#@faculty hard nproc 50
-#ftp hard nproc 0
-#ftp - chroot /ftp
-#@student - maxlogins 4
-
-
-root hard nofile 1000000
-root soft nofile 1000000
-ubuntu hard nofile 1000000
-ubuntu soft nofile 1000000
-nginx hard nofile 1000000
-nginx soft nofile 1000000
-
-# End of file
\ No newline at end of file
diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po
index 5a40018d..f20300e3 100644
--- a/locale/en_US/LC_MESSAGES/django.po
+++ b/locale/en_US/LC_MESSAGES/django.po
@@ -336,8 +336,44 @@ msgstr ""
msgid "Your Exhibitions"
msgstr ""
+#: src/ARte/core/jinja2/core/community.jinja2:7
+msgid "An art experimentation for digital exhibtions in physical spaces"
+msgstr "Uma experimentação de arte para exibições digitais em espaços físicos"
+
+#: src/ARte/core/jinja2/core/community.jinja2:9
+msgid "Cell phones and tablets are used to read markers and thus open “windows” where other art objects can be found. The public is invited to transcend the exhibition space, taking stickers with markers to be pasted in other places, creating Temporary Autonomous Zones (TAZes). The public becomes a co-author, and markers and digital works are reconfigured by spaces."
+msgstr "Celulares e tablets são usados para ler marcadores e assim abrir “janelas” onde se encontram outros objetos de arte. O público é convidado a transcender o espaço de exposição, levando adesivos com marcadores para serem colados em outros locais, criando Zonas Autônomas Temporárias (TAZes). O público se torna co-autor, e os marcadores e obras digitais são reconfigurados pelos espaços."
+
+#: src/ARte/core/jinja2/core/community.jinja2:12
+msgid "Know"
+msgstr "Entenda"
+
+#: src/ARte/core/jinja2/core/community.jinja2:14
+msgid "The Jandig project is an investigation into the intervention of markers for viewing works through augmented reality on urban space. It is a collaborative digital art project that proposes the creation of Temporary Autonomous Zones (TAZes) in each space where it is installed. These TAZes are formed through markers spread across a space by artists and the public – who thus become co-creators of that experience. Users interact with markers, using mobile devices to open real-world windows to view digital creations (Licensed under Creative Commons)."
+msgstr "O projeto Jandig é uma investigação a respeito da intervenção de marcadores para visualização de obras por meio de realidade aumentada sobre o espaço urbano. Trata-se de um projeto colaborativo de arte digital que propõe a criação de Zonas Autônomas Temporárias (TAZes) em cada espaço em que é instalado. Essas TAZes são formadas através de marcadores espalhados por um espaço por artistas e pelo público – que assim torna-se co-criador daquela experiência. Os usuários interagem com marcadores, utilizando dispositivos móveis para abrir janelas no mundo real para visualizar criações digitais (cedidas através de licença Creative Commons)."
+
+#: src/ARte/core/jinja2/core/community.jinja2:18
+msgid "Our goals"
+msgstr "Nossos objetivos"
+
+#: src/ARte/core/jinja2/core/community.jinja2:20
+msgid "The Jandig platform makes exhibitions possible using augmented reality."
+msgstr "A plataforma Jandig viabiliza a realização de exposições com o uso de realidade aumentada."
+
+#: src/ARte/core/jinja2/core/community.jinja2:22
+msgid "Each exhibition is made from the arrangement of several markers, which use adhesives, stencil images, stamps, or others, in different sizes as support. These supports are also delivered to the public that circulate through the space, so that they can make local interference and that it is possible to “viralize” the markers while the exhibition is available, leaving traces and providing interactions between participants/visitors."
+msgstr "Cada exposição é feita a partir da disposição de diversos marcadores, que utilizam como suporte adesivos, imagens de stencil, de carimbos, ou outras, em diferentes tamanhos. Esses suportes são também entregues ao público que circulam pelo espaço, de modo que possam fazer interferências locais e que seja possível “viralizar” os marcadores enquanto a exposição estiver disponível, deixando rastros e proporcionando interações entre os participantes/visitantes."
+
+#: src/ARte/core/jinja2/core/community.jinja2:24
+msgid "To see through the “windows” and see what the fabulous images reveal, the public must point their devices at the markers, so that the Jandig platform viewer can read them and show the content in augmented reality."
+msgstr "Para enxergar através das “janelas” e ver as imagens fabulosas o que elas revelam, o público deverá apontar seus dispositivos para os marcadores, para que o visualizador da plataforma Jandig ufaça a leitura dos mesmos e mostre o conteúdo em realidade aumentada."
+
+#: src/ARte/core/jinja2/core/community.jinja2:26
+msgid "Borders are the graphic elements that trigger the recognition of the object associated with each marker. For this reason, they should not be covered and they should always be seen completely by the camera. Placing your finger on one of the edges or bringing the camera too close to the marker makes recognition impossible, for example. This characteristic must always be taken into account in the production and application of markers."
+msgstr "As bordas são os elementos gráficos que engatilham o reconhecimento do objeto associado a cada marcador. Por esse motivo, não se deve cobri-las e elas devem sempre ser vistas completamente pela câmera. Colocar o dedo sobre uma das bordas ou aproximar demais a câmera do marcador inviabiliza o reconhecimento, por exemplo. Essa característica deve sempre ser levada em consideração na produção e aplicação dos marcadores."
+
#: src/ARte/users/jinja2/users/profile.jinja2:21
-msgid "You have no exhibits :c"
+msgid "You have no Exhibitions. :c"
msgstr ""
#: src/ARte/users/jinja2/users/profile.jinja2:22
@@ -351,7 +387,7 @@ msgid "Your Artworks"
msgstr ""
#: src/ARte/users/jinja2/users/profile.jinja2:32
-msgid "You have no artworks :c"
+msgid "You have no Artworks. :c"
msgstr ""
#: src/ARte/users/jinja2/users/profile.jinja2:36
@@ -359,7 +395,7 @@ msgid "Your Markers"
msgstr ""
#: src/ARte/users/jinja2/users/profile.jinja2:43
-msgid "You have no markers :c"
+msgid "You have no Markers. :c"
msgstr ""
#: src/ARte/users/jinja2/users/profile.jinja2:47
@@ -367,7 +403,7 @@ msgid "Your Objects"
msgstr ""
#: src/ARte/users/jinja2/users/profile.jinja2:54
-msgid "You have no objects :c"
+msgid "You have no Objects. :c"
msgstr ""
#: src/ARte/users/jinja2/users/profile.jinja2:55
diff --git a/locale/pt_BR/LC_MESSAGES/django.po b/locale/pt_BR/LC_MESSAGES/django.po
index b866b9f2..52101bf2 100644
--- a/locale/pt_BR/LC_MESSAGES/django.po
+++ b/locale/pt_BR/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-02-17 21:09+0000\n"
+"POT-Creation-Date: 2024-07-06 15:42+0000\n"
"PO-Revision-Date: 2020-02-17 18:13-0300\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -18,312 +18,337 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 2.3\n"
-#: src/ARte/config/settings.py:146
+#: src/config/settings.py:179
msgid "English"
msgstr "Inglês"
-#: src/ARte/config/settings.py:147
+#: src/config/settings.py:180
msgid "Brazilian Portuguese"
msgstr "Português do Brasil"
-#: src/ARte/users/forms.py:24 src/ARte/users/forms.py:85
+#: src/users/forms.py:32 src/users/forms.py:93
msgid "Your e-mail address"
msgstr "Seu endereço de e-mail"
-#: src/ARte/users/forms.py:29 src/ARte/users/forms.py:89
+#: src/users/forms.py:37 src/users/forms.py:97
msgid "Your username"
msgstr "Seu nome de usuário"
-#: src/ARte/users/forms.py:35
+#: src/users/forms.py:43
msgid "email"
msgstr "email"
-#: src/ARte/users/forms.py:36
+#: src/users/forms.py:44
msgid "chosen username"
msgstr "nome de usuário escolhido"
-#: src/ARte/users/forms.py:37 src/ARte/users/forms.py:123
+#: src/users/forms.py:45 src/users/forms.py:129
msgid "password"
msgstr "senha"
-#: src/ARte/users/forms.py:38
+#: src/users/forms.py:46
msgid "confirm password"
msgstr "confirmar senha"
-#: src/ARte/users/forms.py:48
+#: src/users/forms.py:56
msgid "E-mail taken"
msgstr "E-mail já existente"
-#: src/ARte/users/forms.py:57
+#: src/users/forms.py:64
msgid "Old Password"
msgstr "Senha antiga"
-#: src/ARte/users/forms.py:58
+#: src/users/forms.py:65
msgid "New Password"
msgstr "Nova senha"
-#: src/ARte/users/forms.py:59
+#: src/users/forms.py:66
msgid "New Password Again"
msgstr "Nova senha novamente"
-#: src/ARte/users/forms.py:78
+#: src/users/forms.py:86
msgid "E-mail"
msgstr "E-mail"
-#: src/ARte/users/forms.py:79
+#: src/users/forms.py:87
msgid "Username"
msgstr "Usuário"
-#: src/ARte/users/forms.py:80 src/ARte/users/forms.py:99
+#: src/users/forms.py:88 src/users/forms.py:104
msgid "Personal Bio / Description"
msgstr "Biografia / Descrição"
-#: src/ARte/users/forms.py:81 src/ARte/users/forms.py:103
+#: src/users/forms.py:89 src/users/forms.py:108
msgid "Personal Website"
msgstr "Site pessoal"
-#: src/ARte/users/forms.py:109
+#: src/users/forms.py:114
msgid "Username already in use"
msgstr "Nome de usuário já em uso"
-#: src/ARte/users/forms.py:115
+#: src/users/forms.py:120
msgid "Email address must be unique"
msgstr "O endereço de e-mail deve ser único"
-#: src/ARte/users/forms.py:122
+#: src/users/forms.py:128
msgid "username / email"
msgstr "nome de usuário / email"
-#: src/ARte/users/forms.py:130 src/ARte/users/forms.py:136
+#: src/users/forms.py:135 src/users/forms.py:141
msgid "Username/email not found"
msgstr "Nome de usuário / email não encontrado"
-#: src/ARte/users/forms.py:152
-msgid "Wrong password"
+#: src/users/forms.py:167
+#, fuzzy
+msgid "Wrong password!"
msgstr "Senha errada"
-#: src/ARte/users/forms.py:169 src/ARte/users/forms.py:171
-#: src/ARte/users/forms.py:187
+#: src/users/forms.py:185 src/users/forms.py:222
msgid "browse file"
msgstr "procurar arquivo"
-#: src/ARte/users/forms.py:173 src/ARte/users/forms.py:189
-#: src/ARte/users/forms.py:215 src/ARte/users/forms.py:216
+#: src/users/forms.py:187 src/users/forms.py:224 src/users/forms.py:257
+#: src/users/forms.py:258
msgid "declare different author name"
msgstr "declarar outro autor"
-#: src/ARte/users/forms.py:174
+#: src/users/forms.py:188
msgid "Marker's title"
msgstr "Título do Marcador"
-#: src/ARte/users/forms.py:193
+#: src/users/forms.py:228
msgid "Object's title"
msgstr "Título do Objeto"
-#: src/ARte/users/forms.py:217
+#: src/users/forms.py:259
msgid "Artwork title"
msgstr "Título da Obra"
-#: src/ARte/users/forms.py:218
+#: src/users/forms.py:260
msgid "Artwork description"
msgstr "Descrição da Obra"
-#: src/ARte/users/forms.py:239
+#: src/users/forms.py:274
+#, fuzzy
+msgid "Url can't contain spaces or special characters"
+msgstr "Urls não podem conter espaços ou caracteres especiais (i.e: .:, /)"
+
+#: src/users/forms.py:280
msgid "Exhibit Title"
msgstr "Título da Exposição"
-#: src/ARte/users/forms.py:240
-msgid "Exhibit URL"
-msgstr "URL da exposição"
-
-#: src/ARte/users/forms.py:251
+#: src/users/forms.py:281
msgid "Complete with your Exhibit URL here"
msgstr "Complete sua URL de exibição aqui"
-#: src/ARte/core/jinja2/core/base.jinja2:44
+#: src/blog/jinja2/blog/category.jinja2:8 src/blog/jinja2/blog/detail.jinja2:5
#, fuzzy
-msgid "Please override the \"content\" block of your template!"
-msgstr "Por favor sobrescreva o bloco \"conteúdo\" de seu modelo!"
+msgid "< Back to Blog"
+msgstr "Página inicial"
-#: src/ARte/core/jinja2/core/collection.jinja2:13
-#, fuzzy
-msgid "Jandig Exhibitions"
-msgstr "Exposições Jandig"
+#: src/blog/jinja2/blog/clipping.jinja2:12
+#: src/core/jinja2/core/useful_links.jinja2:15
+msgid "Clipping"
+msgstr "Clipping"
-#: src/ARte/core/jinja2/core/collection.jinja2:18
-msgid "All Exhibits"
-msgstr "Todas Exposições"
+#: src/blog/jinja2/blog/clipping.jinja2:14
+msgid "The content below is in the original languages."
+msgstr "Os conteúdos abaixo estão em suas linguas originais"
-#: src/ARte/core/jinja2/core/collection.jinja2:23
-#, fuzzy
-msgid "Jandig Artworks"
-msgstr "Obras Jandig"
+#: src/blog/jinja2/blog/clipping.jinja2:22
+msgid "View as PDF"
+msgstr "Ver como PDF"
-#: src/ARte/core/jinja2/core/collection.jinja2:28
-msgid "All Artworks"
-msgstr "Todas as Obras"
+#: src/blog/jinja2/blog/clipping.jinja2:24
+msgid "View as JPG"
+msgstr "Ver como JPG"
-#: src/ARte/core/jinja2/core/collection.jinja2:33
-#, fuzzy
-msgid "Jandig Markers"
-msgstr "Marcadores Jandig"
+#: src/blog/jinja2/blog/clipping.jinja2:26
+msgid "View File"
+msgstr "Ver Arquivo"
-#: src/ARte/core/jinja2/core/collection.jinja2:38
-msgid "All Markers"
-msgstr "Todos os Marcadores"
+#: src/blog/jinja2/blog/detail.jinja2:13
+msgid "Categories:"
+msgstr "Categorias"
-#: src/ARte/core/jinja2/core/collection.jinja2:43
+#: src/blog/jinja2/blog/detail.jinja2:35
#, fuzzy
-msgid "Jandig Objects"
-msgstr "Objetos Jandig"
+msgid "Back to Top"
+msgstr "Página inicial"
-#: src/ARte/core/jinja2/core/collection.jinja2:48
-msgid "All Objects"
-msgstr "Todos os Objetos"
+#: src/blog/jinja2/blog/index.jinja2:12
+#: src/core/jinja2/core/useful_links.jinja2:12
+msgid "Memories"
+msgstr "Memórias"
-#: src/ARte/core/jinja2/core/exhibit_detail.jinja2:11
-msgid "See this exhibition"
-msgstr "Ver essa exposição"
+#: src/blog/jinja2/blog/post_preview.jinja2:4
+msgid "Read More"
+msgstr "Ler Mais"
+
+#: src/blog/jinja2/blog/post_preview.jinja2:8
+msgid "See more"
+msgstr "Ver mais"
-#: src/ARte/core/jinja2/core/exhibit_detail.jinja2:12
-#: src/ARte/users/jinja2/users/components/item-list.jinja2:60
+#: src/core/jinja2/core/base.jinja2:44
+#, fuzzy
+msgid "Please override the \"content\" block of your template!"
+msgstr "Por favor sobrescreva o bloco \"conteúdo\" de seu modelo!"
+
+#: src/core/jinja2/core/collection.jinja2:50
+msgid "We found no content on your Collection, try uploading an object."
+msgstr "Não encontramos nenhum objeto por aqui :( Tente fazer upload."
+
+#: src/core/jinja2/core/exhibit_detail.jinja2:9
+#: src/users/jinja2/users/components/item-list.jinja2:75
+#: src/users/jinja2/users/components/moderator-item-list.jinja2:31
msgid "Created by "
msgstr "Criado por "
-#: src/ARte/core/jinja2/core/exhibit_detail.jinja2:15
+#: src/core/jinja2/core/exhibit_detail.jinja2:10
+#: src/users/jinja2/users/components/moderator-item-list.jinja2:34
+msgid "See this exhibition"
+msgstr "Ver essa exposição"
+
+#: src/core/jinja2/core/exhibit_detail.jinja2:12
msgid "Exhibition Artworks"
msgstr "Obras dessa Exposição"
-#: src/ARte/core/jinja2/core/exhibit_select.jinja2:14
+#: src/core/jinja2/core/exhibit_select.jinja2:16
msgid "Choose the Exhibition you're seeing"
msgstr "Escolha a Exposição que está vendo"
-#: src/ARte/core/jinja2/core/exhibit_select.jinja2:23
-#: src/ARte/users/jinja2/users/login.jinja2:37
-#: src/ARte/users/jinja2/users/password-change.jinja2:26
-#: src/ARte/users/jinja2/users/profile-edit.jinja2:31
-#: src/ARte/users/jinja2/users/recover-edit-password.jinja2:26
-#: src/ARte/users/jinja2/users/recover-password-code.jinja2:26
-#: src/ARte/users/jinja2/users/recover-password.jinja2:26
-#: src/ARte/users/jinja2/users/signup.jinja2:32
-#: src/ARte/users/jinja2/users/upload.jinja2:93
+#: src/core/jinja2/core/exhibit_select.jinja2:28
+#: src/users/jinja2/users/edit-marker.jinja2:26
+#: src/users/jinja2/users/edit-object.jinja2:63
+#: src/users/jinja2/users/login.jinja2:40
+#: src/users/jinja2/users/password-change.jinja2:26
+#: src/users/jinja2/users/profile-edit.jinja2:31
+#: src/users/jinja2/users/recover-edit-password.jinja2:26
+#: src/users/jinja2/users/recover-password-code.jinja2:26
+#: src/users/jinja2/users/recover-password.jinja2:26
+#: src/users/jinja2/users/signup.jinja2:32
+#: src/users/jinja2/users/upload-marker.jinja2:52
+#: src/users/jinja2/users/upload-object.jinja2:88
+#: src/users/jinja2/users/upload.jinja2:107
msgid "Submit"
msgstr "Enviar"
-#: src/ARte/core/jinja2/core/footer.jinja2:3
+#: src/core/jinja2/core/footer.jinja2:3
msgid "About Us"
msgstr "Sobre Nós"
-#: src/ARte/core/jinja2/core/footer.jinja2:4
-#: src/ARte/core/jinja2/core/footer.jinja2:9
-msgid "Jandig on Github"
-msgstr "Jandig no GitHub"
-
-#: src/ARte/core/jinja2/core/footer.jinja2:6
+#: src/core/jinja2/core/footer.jinja2:5
msgid "Jandig on Instagram"
msgstr "Jandig no Instagram"
-#: src/ARte/core/jinja2/core/footer.jinja2:7
+#: src/core/jinja2/core/footer.jinja2:6
msgid "Jandig on Twitter"
msgstr "Jandig no Twitter"
-#: src/ARte/core/jinja2/core/footer.jinja2:8
+#: src/core/jinja2/core/footer.jinja2:7
msgid "Jandig on Facebook"
msgstr "Jandig no Facebook"
-#: src/ARte/core/jinja2/core/footer.jinja2:10
+#: src/core/jinja2/core/footer.jinja2:8
+msgid "Jandig on Github"
+msgstr "Jandig no GitHub"
+
+#: src/core/jinja2/core/footer.jinja2:9
msgid "Jandig on Telegram"
msgstr "Jandig no Telegram"
-#: src/ARte/core/jinja2/core/footer.jinja2:14
+#: src/core/jinja2/core/footer.jinja2:13
msgid "Content under CC BY-SA 4.0 unless otherwise noted."
msgstr ""
"Conteúdo sob licenciamento CC BY-SA 4.0, a não ser quando explicitado o "
"contrário."
-#: src/ARte/core/jinja2/core/header.jinja2:21
+#: src/core/jinja2/core/header.jinja2:19
msgid "Welcome, "
msgstr "Olá, "
-#: src/ARte/core/jinja2/core/header.jinja2:28
-#: src/ARte/users/jinja2/users/login.jinja2:21
-#: src/ARte/users/jinja2/users/signup.jinja2:14
+#: src/core/jinja2/core/header.jinja2:26 src/users/jinja2/users/login.jinja2:21
+#: src/users/jinja2/users/signup.jinja2:14
msgid "Sign up"
msgstr "Cadastro"
-#: src/ARte/core/jinja2/core/header.jinja2:31
-#: src/ARte/users/jinja2/users/signup.jinja2:15
+#: src/core/jinja2/core/header.jinja2:29
+#: src/users/jinja2/users/signup.jinja2:15
msgid "Log in"
msgstr "Entrar"
-#: src/ARte/core/jinja2/core/home.jinja2:37
+#: src/core/jinja2/core/home.jinja2:41
msgid "Welcome to Jandig"
msgstr "Bem vindo ao Jandig"
-#: src/ARte/core/jinja2/core/home.jinja2:38
+#: src/core/jinja2/core/home.jinja2:42
#, fuzzy
msgid "An Open Source Augmented Reality art community."
msgstr "Uma comunidade open source de arte em Realidade Aumentada."
-#: src/ARte/core/jinja2/core/home.jinja2:39
+#: src/core/jinja2/core/home.jinja2:43
msgid "To see the Artworks you need to grant camera access to the app."
msgstr "Para ver as Obras você precisa dar acesso a câmera no aplicativo."
-#: src/ARte/core/jinja2/core/home.jinja2:41
+#: src/core/jinja2/core/home.jinja2:45
msgid "Go to camera"
msgstr "Ir para câmera"
-#: src/ARte/core/jinja2/core/language-select-modal.jinja2:3
+#: src/core/jinja2/core/language-select-modal.jinja2:3
msgid "Select your language"
msgstr "Selecione seu idioma"
-#: src/ARte/core/jinja2/core/language-select-modal.jinja2:16
+#: src/core/jinja2/core/language-select-modal.jinja2:16
msgid "Ok"
msgstr "Ok"
-#: src/ARte/core/jinja2/core/ui.jinja2:4
+#: src/core/jinja2/core/ui.jinja2:4
msgid "Change exhibition"
msgstr "Alterar exposição"
-#: src/ARte/core/jinja2/core/ui.jinja2:5
+#: src/core/jinja2/core/ui.jinja2:5
msgid "Back to home"
msgstr "Página inicial"
-#: src/ARte/core/jinja2/core/useful_links.jinja2:5
+#: src/core/jinja2/core/useful_links.jinja2:5
msgid "AR Viewer"
msgstr "Visualizador RA"
-#: src/ARte/core/jinja2/core/useful_links.jinja2:9
+#: src/core/jinja2/core/useful_links.jinja2:9
msgid "Collection"
msgstr "Coleção"
-#: src/ARte/core/jinja2/core/useful_links.jinja2:12
-msgid "My Stuff"
-msgstr "Minhas Coisas"
+#: src/core/jinja2/core/useful_links.jinja2:18
+msgid "My Creations"
+msgstr "Minhas Criações"
-#: src/ARte/core/jinja2/core/useful_links.jinja2:15
+#: src/core/jinja2/core/useful_links.jinja2:21
msgid "Help"
msgstr "Ajuda"
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:11
-#: src/ARte/users/jinja2/users/components/createbox.jinja2:13
+#: src/users/jinja2/users/artwork.jinja2:11
+msgid "Edit Jandig Artwork"
+msgstr "Editar Obra Jandig"
+
+#: src/users/jinja2/users/artwork.jinja2:11
+#: src/users/jinja2/users/components/createbox.jinja2:13
msgid "Create Jandig Artwork"
msgstr "Criar Obra Jandig"
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:13
+#: src/users/jinja2/users/artwork.jinja2:13
msgid "Select Marker"
msgstr "Escolher Marcador"
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:16
+#: src/users/jinja2/users/artwork.jinja2:16
msgid "Select Object"
msgstr "Escolher Objeto"
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:22
+#: src/users/jinja2/users/artwork.jinja2:22
msgid "Select Marker (1/3)"
msgstr "Escolher Marcador (1/3)"
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:48
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:83
+#: src/users/jinja2/users/artwork.jinja2:36
+#: src/users/jinja2/users/artwork.jinja2:58
msgid ""
"I agree to share this content under CC BY-SA 4.0 and I'm aware that, once "
"uploaded, I cannot remove it. "
@@ -331,206 +356,291 @@ msgstr ""
"Concordo em publicar esse conteúdo sob CC BY-SA 4.0 e entendo que, uma vez "
"publicado, não posso mais removê-lo. "
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:53
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:87
-#: src/ARte/users/jinja2/users/exhibit-create.jinja2:33
+#: src/users/jinja2/users/artwork.jinja2:41
+#: src/users/jinja2/users/artwork.jinja2:62
+#: src/users/jinja2/users/exhibit-create.jinja2:44
+#: src/users/jinja2/users/exhibit-edit.jinja2:34
msgid "Next"
msgstr "Próximo"
-#: src/ARte/users/jinja2/users/exhibit-create.jinja2:43
-msgid "Your exhibit URL will look like this"
-msgstr "Sua URL de exibição vai se parecer com isso."
-
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:57
+#: src/users/jinja2/users/artwork.jinja2:45
msgid "Select Object (2/3)"
msgstr "Selecione Objeto (2/3)"
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:91
+#: src/users/jinja2/users/artwork.jinja2:66
msgid "About your artwork (3/3)"
msgstr "Sobre sua obra (3/3)"
-#: src/ARte/users/jinja2/users/artwork-create.jinja2:100
+#: src/users/jinja2/users/artwork.jinja2:75
+msgid "Edit Artwork"
+msgstr "Editar Obra"
+
+#: src/users/jinja2/users/artwork.jinja2:75
msgid "Publish artwork"
msgstr "Publicar obra"
-#: src/ARte/users/jinja2/users/exhibit-create.jinja2:11
-msgid "Create Jandig Exhibition"
-msgstr "Criar Exposição Jandig"
+#: src/users/jinja2/users/edit-marker.jinja2:9
+#: src/users/jinja2/users/edit-object.jinja2:9
+#, fuzzy
+msgid "Edit object"
+msgstr "objeto"
-#: src/ARte/users/jinja2/users/artwork-edit.jinja2:11
-msgid "Edit Jandig Artwork"
-msgstr "Editar Obra Jandig"
+#: src/users/jinja2/users/edit-marker.jinja2:15
+#, fuzzy
+msgid "Edit Marker's title"
+msgstr "Título do Marcador"
-#: src/ARte/users/jinja2/users/artwork-edit.jinja2:75
-msgid "Edit Artwork"
-msgstr "Editar Obra"
+#: src/users/jinja2/users/edit-marker.jinja2:19
+msgid ""
+"You can't edit the marker patt and the png for now, but hopefully soon "
+"enough it will be possible!"
+msgstr ""
+"Você não pode editar o arquivo patt ou png de um marcador agora, mas devemos "
+"atualizar isto assim que possível."
-#: src/ARte/users/jinja2/users/exhibit-edit.jinja2:12
-msgid "Edit Jandig Exhibition"
-msgstr "Editar Exposição Jandig"
+#: src/users/jinja2/users/edit-object.jinja2:15
+#, fuzzy
+msgid "Edit Object's title"
+msgstr "Título do Objeto"
-#: src/ARte/users/jinja2/users/exhibit-edit.jinja2:49
-msgid "Edit Exhibit"
-msgstr "Editar Exposição"
+#: src/users/jinja2/users/edit-object.jinja2:19
+#: src/users/jinja2/users/upload-object.jinja2:27
+#: src/users/jinja2/users/upload.jinja2:29
+msgid "Choose Object"
+msgstr "Escolher Objeto"
-#: src/ARte/users/jinja2/users/exhibit-create.jinja2:13
+#: src/users/jinja2/users/edit-object.jinja2:26
+#: src/users/jinja2/users/upload-object.jinja2:36
+#: src/users/jinja2/users/upload.jinja2:47
+msgid "Adjust scale"
+msgstr "Ajustar escala"
+
+#: src/users/jinja2/users/edit-object.jinja2:29
+#: src/users/jinja2/users/upload-object.jinja2:39
+#: src/users/jinja2/users/upload.jinja2:50
+msgid ""
+"Scale should be adjusted relative to Marker size on the screen. A scale of 2 "
+"will render an Object twice the size of the Marker."
+msgstr ""
+"A escala deve ser ajustada relativa ao tamanho do Marcador na tela. Uma "
+"escala de 2 irá renderizar um Objeto duas vezes o tamanho do Marcador."
+
+#: src/users/jinja2/users/edit-object.jinja2:36
+#: src/users/jinja2/users/upload-object.jinja2:46
+#: src/users/jinja2/users/upload.jinja2:57
+msgid "Adjust position"
+msgstr "Ajustar posição"
+
+#: src/users/jinja2/users/exhibit-create.jinja2:12
+msgid "Create Jandig Exhibition"
+msgstr "Criar Exposição Jandig"
+
+#: src/users/jinja2/users/exhibit-create.jinja2:14
+#: src/users/jinja2/users/exhibit-edit.jinja2:14
msgid "Select Artworks"
msgstr "Escolher Obras"
-#: src/ARte/users/jinja2/users/exhibit-create.jinja2:20
+#: src/users/jinja2/users/exhibit-create.jinja2:21
+#: src/users/jinja2/users/exhibit-edit.jinja2:21
msgid "Select Artworks (1/2)"
msgstr "Escolher Obras (1/2)"
-#: src/ARte/users/jinja2/users/exhibit-create.jinja2:22
+#: src/users/jinja2/users/exhibit-create.jinja2:24
+#: src/users/jinja2/users/exhibit-edit.jinja2:23
msgid "Choose from your repository"
msgstr "Escolha de seu repositório"
-#: src/ARte/users/jinja2/users/exhibit-create.jinja2:37
+#: src/users/jinja2/users/exhibit-create.jinja2:28
+#: src/users/jinja2/users/profile.jinja2:43
+msgid "You have no Artworks. :c"
+msgstr "Você não tem Obras. :c"
+
+#: src/users/jinja2/users/exhibit-create.jinja2:30
+#: src/users/jinja2/users/profile.jinja2:29
+#: src/users/jinja2/users/profile.jinja2:44
+msgid "Create one"
+msgstr "Criar"
+
+#: src/users/jinja2/users/exhibit-create.jinja2:48
+#: src/users/jinja2/users/exhibit-edit.jinja2:38
msgid "Exhibit Information (2/2)"
msgstr "Informações da Exposição (2/2)"
-#: src/ARte/users/jinja2/users/exhibit-create.jinja2:46
+#: src/users/jinja2/users/exhibit-create.jinja2:53
+#: src/users/jinja2/users/exhibit-edit.jinja2:43
+msgid "Your exhibit URL will look like this"
+msgstr "Sua URL de exibição vai se parecer com isso."
+
+#: src/users/jinja2/users/exhibit-create.jinja2:59
msgid "Publish Exhibit"
msgstr "Publicar Exposição"
-#: src/ARte/users/jinja2/users/exhibit-create.jinja2:82
+#: src/users/jinja2/users/exhibit-create.jinja2:95
+#, fuzzy
msgid "Urls can't contain spaces or special characters (i.e: .:, /)"
msgstr "Urls não podem conter espaços ou caracteres especiais (i.e: .:, /)"
-#: src/ARte/users/jinja2/users/invalid-recovering-email.jinja2:14
+#: src/users/jinja2/users/exhibit-edit.jinja2:12
+msgid "Edit Jandig Exhibition"
+msgstr "Editar Exposição Jandig"
+
+#: src/users/jinja2/users/exhibit-edit.jinja2:49
+msgid "Edit Exhibit"
+msgstr "Editar Exposição"
+
+#: src/users/jinja2/users/invalid-recovering-email.jinja2:14
msgid "There is no user with this e-mail/username."
msgstr "Não há usuário com esse e-mail/nome."
-#: src/ARte/users/jinja2/users/invalid-recovering-email.jinja2:18
-#: src/ARte/users/jinja2/users/wrong-verification-code.jinja2:18
+#: src/users/jinja2/users/invalid-recovering-email.jinja2:18
+#: src/users/jinja2/users/wrong-verification-code.jinja2:18
msgid "Click here to return"
msgstr "Clique aqui para voltar"
-#: src/ARte/users/jinja2/users/login.jinja2:20
+#: src/users/jinja2/users/login.jinja2:20
msgid "Login to continue"
msgstr "Faça login para continuar"
-#: src/ARte/users/jinja2/users/login.jinja2:40
+#: src/users/jinja2/users/login.jinja2:36
+#: src/users/jinja2/users/signup.jinja2:29
+msgid "Remember me"
+msgstr "Lembre-se de mim"
+
+#: src/users/jinja2/users/login.jinja2:43
msgid "Recover password"
msgstr "Recuperar senha"
-#: src/ARte/users/jinja2/users/password-change.jinja2:14
+#: src/users/jinja2/users/moderator-page.jinja2:12
+#, fuzzy
+msgid "Jandig Exhibits"
+msgstr "Exposições Jandig"
+
+#: src/users/jinja2/users/moderator-page.jinja2:18
+#, fuzzy
+msgid "Jandig Artworks"
+msgstr "Obras Jandig"
+
+#: src/users/jinja2/users/moderator-page.jinja2:24
+#, fuzzy
+msgid "Jandig Markers"
+msgstr "Marcadores Jandig"
+
+#: src/users/jinja2/users/moderator-page.jinja2:30
+#, fuzzy
+msgid "Jandig Objects"
+msgstr "Objetos Jandig"
+
+#: src/users/jinja2/users/password-change.jinja2:14
msgid "Type your new password."
msgstr "Digite sua nova senha."
-#: src/ARte/users/jinja2/users/profile-edit.jinja2:7
+#: src/users/jinja2/users/permission-denied.jinja2:4
+msgid ""
+"You dont have permission to be here, please click on the button to go back."
+msgstr ""
+
+#: src/users/jinja2/users/permission-denied.jinja2:5
+msgid "Take me back to where I belong!"
+msgstr ""
+
+#: src/users/jinja2/users/components/userbox.jinja2:23
+#: src/users/jinja2/users/profile-edit.jinja2:7
msgid "Log out"
msgstr "Sair"
-#: src/ARte/users/jinja2/users/profile-edit.jinja2:8
+#: src/users/jinja2/users/profile-edit.jinja2:8
msgid "Remove account"
msgstr "Remover conta"
-#: src/ARte/users/jinja2/users/profile-edit.jinja2:19
+#: src/users/jinja2/users/profile-edit.jinja2:19
msgid "Change Password"
msgstr "Trocar Senha"
-#: src/ARte/users/jinja2/users/profile.jinja2:16
+#: src/users/jinja2/users/profile.jinja2:18
msgid "Your Exhibitions"
msgstr "Suas Exposições"
-#: src/ARte/users/jinja2/users/profile.jinja2:23
-msgid "You have no Exhibitions. :("
-msgstr "Você não tem Exposições. :("
+#: src/users/jinja2/users/profile.jinja2:20
+msgid "Exhibitions"
+msgstr "Exposições"
-#: src/ARte/users/jinja2/users/profile.jinja2:24
-#: src/ARte/users/jinja2/users/profile.jinja2:35
-msgid "Create one"
-msgstr "Criar"
+#: src/users/jinja2/users/profile.jinja2:28
+msgid "You have no Exhibitions. :c"
+msgstr "Você não tem Exposições. :c"
-#: src/ARte/users/jinja2/users/profile.jinja2:27
+#: src/users/jinja2/users/profile.jinja2:33
msgid "Your Artworks"
msgstr "Suas Obras"
-#: src/ARte/users/jinja2/users/profile.jinja2:34
-msgid "You have no Artworks. :("
-msgstr "Você não tem Obras. :("
+#: src/users/jinja2/users/profile.jinja2:35
+msgid "Artworks"
+msgstr "Obras"
-#: src/ARte/users/jinja2/users/profile.jinja2:38
+#: src/users/jinja2/users/profile.jinja2:48
msgid "Your Markers"
msgstr "Seus Marcadores"
-#: src/ARte/users/jinja2/users/profile.jinja2:45
-msgid "You have no markers. :("
-msgstr "Você não tem marcadores. :("
+#: src/users/jinja2/users/profile.jinja2:50
+msgid "Markers"
+msgstr "Marcadores"
-#: src/ARte/users/jinja2/users/profile.jinja2:46
-#: src/ARte/users/jinja2/users/profile.jinja2:57
+#: src/users/jinja2/users/profile.jinja2:58
+msgid "You have no Markers. :c"
+msgstr "Você não tem Marcadores. :c"
+
+#: src/users/jinja2/users/profile.jinja2:59
+#: src/users/jinja2/users/profile.jinja2:74
msgid "Upload one"
msgstr "Enviar"
-#: src/ARte/users/jinja2/users/profile.jinja2:49
+#: src/users/jinja2/users/profile.jinja2:63
msgid "Your Objects"
msgstr "Seus Objetos"
-#: src/ARte/users/jinja2/users/profile.jinja2:56
-msgid "You have no objects. :("
-msgstr "Você não tem objetos. :("
+#: src/users/jinja2/users/profile.jinja2:65
+msgid "Objects"
+msgstr "Objetos"
+
+#: src/users/jinja2/users/profile.jinja2:73
+msgid "You have no Objects. :c"
+msgstr "Você não tem Objetos. :c"
-#: src/ARte/users/jinja2/users/recover-edit-password.jinja2:14
+#: src/users/jinja2/users/recover-edit-password.jinja2:14
msgid "Choose a new password and repeat it."
msgstr "Escolha uma nova senha e repita."
-#: src/ARte/users/jinja2/users/recover-password-code.jinja2:14
+#: src/users/jinja2/users/recover-password-code.jinja2:14
msgid "Insert the code you have received on e-mail."
msgstr "Digite o código que você recebeu em seu e-mail."
-#: src/ARte/users/jinja2/users/recover-password.jinja2:14
+#: src/users/jinja2/users/recover-password.jinja2:14
msgid "Type your username or e-mail"
msgstr "Digite seu nome de usuário ou email"
-#: src/ARte/users/jinja2/users/signup.jinja2:29
-msgid "Remember me"
-msgstr "Lembre-se de mim"
-
-#: src/ARte/users/jinja2/users/components/createbox.jinja2:5
-#: src/ARte/users/jinja2/users/upload.jinja2:10
+#: src/users/jinja2/users/components/createbox.jinja2:5
+#: src/users/jinja2/users/upload-marker.jinja2:11
+#: src/users/jinja2/users/upload.jinja2:10
msgid "Upload Marker"
msgstr "Enviar Marcador"
-#: src/ARte/users/jinja2/users/components/createbox.jinja2:8
-#: src/ARte/users/jinja2/users/upload.jinja2:12
-msgid "Upload Object"
-msgstr "Enviar Objeto"
-
-#: src/ARte/users/jinja2/users/upload.jinja2:20
-msgid "Choose Object"
-msgstr "Escolher Objeto"
+#: src/users/jinja2/users/upload-marker.jinja2:19
+#: src/users/jinja2/users/upload.jinja2:36
+msgid "Choose Marker's title"
+msgstr "Escolha o título do seu Marcador"
-#: src/ARte/users/jinja2/users/upload.jinja2:26
+#: src/users/jinja2/users/upload-marker.jinja2:23
+#: src/users/jinja2/users/upload.jinja2:40
msgid "Choose Marker image"
msgstr "Selecione uma imagem de Marcador"
-#: src/ARte/users/jinja2/users/upload.jinja2:40
-msgid "Adjust scale"
-msgstr "Ajustar escala"
-
-#: src/ARte/users/jinja2/users/upload.jinja2:45
-msgid "Adjust position"
-msgstr "Ajustar posição"
-
-#: src/ARte/users/jinja2/users/upload.jinja2:53
-msgid "Adjust rotation"
-msgstr "Ajustar rotação"
-
-#: src/ARte/users/jinja2/users/upload.jinja2:65
-msgid "Choose .patt file"
-msgstr "Selecione um arquivo .patt"
-
-#: src/ARte/users/jinja2/users/upload.jinja2:77
+#: src/users/jinja2/users/upload-marker.jinja2:35
+#: src/users/jinja2/users/upload.jinja2:89
msgid "I'm this Marker author"
msgstr "Sou autor/a desse Marcador"
-#: src/ARte/users/jinja2/users/upload.jinja2:79
-msgid "I'm this Object author"
-msgstr "Sou autor/a desse Objeto"
-
-#: src/ARte/users/jinja2/users/upload.jinja2:90
+#: src/users/jinja2/users/upload-marker.jinja2:48
+#: src/users/jinja2/users/upload-object.jinja2:84
+#: src/users/jinja2/users/upload.jinja2:103
msgid ""
"I agree to have this content under CC BY-SA 4.0 and I'm "
@@ -540,127 +650,177 @@ msgstr ""
"creativecommons.org/licenses/by-sa/4.0/legalcode\">CC BY-SA 4.0 e estou "
"ciente que não posso removê-lo depois que outras pessoas o estiverem usando."
-#: src/ARte/users/jinja2/users/wrong-verification-code.jinja2:14
+#: src/users/jinja2/users/components/createbox.jinja2:8
+#: src/users/jinja2/users/upload-object.jinja2:10
+#: src/users/jinja2/users/upload.jinja2:12
+msgid "Upload Object"
+msgstr "Enviar Objeto"
+
+#: src/users/jinja2/users/upload-object.jinja2:12
+#: src/users/jinja2/users/upload.jinja2:14
+#, fuzzy
+msgid "Edit_object"
+msgstr "objeto"
+
+#: src/users/jinja2/users/upload-object.jinja2:20
+#: src/users/jinja2/users/upload.jinja2:22
+msgid "Choose Object's title"
+msgstr "Escolha o título do Objeto"
+
+#: src/users/jinja2/users/upload-object.jinja2:72
+#: src/users/jinja2/users/upload.jinja2:92
+msgid "I'm this Object author"
+msgstr "Sou autor/a desse Objeto"
+
+#: src/users/jinja2/users/upload.jinja2:80
+msgid "Choose .patt file"
+msgstr "Selecione um arquivo .patt"
+
+#: src/users/jinja2/users/wrong-verification-code.jinja2:14
msgid "Your verification code is invalid."
msgstr "Seu código de verificação é inválido."
-#: src/ARte/users/jinja2/users/components/createbox.jinja2:2
+#: src/users/jinja2/users/components/createbox.jinja2:2
msgid "Come on! Create new content now!"
msgstr "Vem cá! Crie conteúdo agora!"
-#: src/ARte/users/jinja2/users/components/createbox.jinja2:16
+#: src/users/jinja2/users/components/createbox.jinja2:16
msgid "Create Exhibition"
msgstr "Criar Exposição"
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:20
+#: src/users/jinja2/users/components/elements-modal.jinja2:18
msgid "by "
msgstr "por "
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:25
+#: src/users/jinja2/users/components/elements-modal.jinja2:24
msgid "Uploaded by "
msgstr "Publicado por "
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:27
+#: src/users/jinja2/users/components/elements-modal.jinja2:26
msgid "in "
msgstr "em "
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:34
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:51
+#: src/users/jinja2/users/components/elements-modal.jinja2:33
+#: src/users/jinja2/users/components/elements-modal.jinja2:50
msgid " Used in "
msgstr " Usado em "
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:35
+#: src/users/jinja2/users/components/elements-modal.jinja2:34
msgid " artworks"
msgstr " Obras"
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:36
+#: src/users/jinja2/users/components/elements-modal.jinja2:35
msgid " and in "
msgstr " e em "
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:37
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:53
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:48
+#: src/users/jinja2/users/components/elements-modal.jinja2:36
+#: src/users/jinja2/users/components/elements-modal.jinja2:52
+#: src/users/jinja2/users/components/userbox.jinja2:49
msgid " Exhibits"
msgstr " Exposições"
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:88
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:92
+#: src/users/jinja2/users/components/elements-modal.jinja2:88
+#: src/users/jinja2/users/components/elements-modal.jinja2:92
msgid "This is a Jandig "
msgstr "Isso é um "
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:100
+#: src/users/jinja2/users/components/elements-modal.jinja2:100
msgid "Share this "
msgstr "Compartilhe "
-#: src/ARte/users/jinja2/users/components/elements-modal.jinja2:103
+#: src/users/jinja2/users/components/elements-modal.jinja2:103
msgid "Create artwork with this "
msgstr "Criar obra com "
-#: src/ARte/users/jinja2/users/components/item-list.jinja2:18
-#: src/ARte/users/jinja2/users/components/item-list.jinja2:21
-#: src/ARte/users/jinja2/users/components/item-list.jinja2:49
-#: src/ARte/users/jinja2/users/components/item-list.jinja2:68
-msgid "Delete"
-msgstr "Excluir"
-
-#: src/ARte/users/jinja2/users/components/item-list.jinja2:62
+#: src/users/jinja2/users/components/item-list.jinja2:77
#, fuzzy
msgid "Artwork(s)"
msgstr "Obra(s)"
-#: src/ARte/users/jinja2/users/components/item-list.jinja2:63
+#: src/users/jinja2/users/components/item-list.jinja2:81
msgid "See this Exhibition"
msgstr "Ver essa Exposição"
-#: src/ARte/users/jinja2/users/components/item-list.jinja2:65
+#: src/users/jinja2/users/components/item-list.jinja2:88
+#: src/users/jinja2/users/components/moderator-item-list.jinja2:13
+#: src/users/jinja2/users/components/moderator-item-list.jinja2:22
+#: src/users/jinja2/users/components/moderator-item-list.jinja2:36
+msgid "Delete"
+msgstr "Excluir"
+
+#: src/users/jinja2/users/components/item-list.jinja2:114
+#, fuzzy
+msgid "Preview Artwork"
+msgstr "Editar Obra"
+
+#: src/users/jinja2/users/components/item-list.jinja2:125
msgid "Edit"
msgstr "Editar"
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:9
+#: src/users/jinja2/users/components/moderator-item-list.jinja2:33
+#, fuzzy
+msgid "artwork(s)"
+msgstr "Obra(s)"
+
+#: src/users/jinja2/users/components/userbox.jinja2:9
msgid " marker(s)"
msgstr " marcador(es)"
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:11
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:18
+#: src/users/jinja2/users/components/userbox.jinja2:11
+#: src/users/jinja2/users/components/userbox.jinja2:18
msgid "No uploads yet."
-msgstr "Ainda sem conteúdo."
+msgstr "Sem conteúdo."
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:16
+#: src/users/jinja2/users/components/userbox.jinja2:16
msgid " Object(s)"
msgstr " Objeto(s)"
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:22
+#: src/users/jinja2/users/components/userbox.jinja2:22
msgid "Edit profile"
msgstr "Editar perfil"
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:27
+#: src/users/jinja2/users/components/userbox.jinja2:28
msgid "Jandig Artist"
msgstr "Artista Jandig"
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:30
+#: src/users/jinja2/users/components/userbox.jinja2:31
msgid " Artworks"
msgstr " Obras"
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:34
+#: src/users/jinja2/users/components/userbox.jinja2:35
msgid "No Artworks yet."
-msgstr "Sem Obras ainda."
+msgstr "Sem Obras."
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:38
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:56
+#: src/users/jinja2/users/components/userbox.jinja2:39
+#: src/users/jinja2/users/components/userbox.jinja2:57
msgid "Create your first!"
msgstr "Crie sua primeira!"
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:45
+#: src/users/jinja2/users/components/userbox.jinja2:46
msgid "Jandig Curator"
msgstr "Curador Jandig"
-#: src/ARte/users/jinja2/users/components/userbox.jinja2:52
+#: src/users/jinja2/users/components/userbox.jinja2:53
msgid "No Exhibitions yet."
-msgstr "Sem Exposições ainda."
+msgstr "Sem Exposições."
+
+#~ msgid "Exhibit URL"
+#~ msgstr "URL da exposição"
+
+#~ msgid "All Exhibits"
+#~ msgstr "Todas Exposições"
-#: src/ARte/users/jinja2/users/edit-object.jinja2:31
-msgid "Scale should be adjusted relative to Marker size on the screen. A scale of 2 will render an Object twice the size of the Marker."
-msgstr "A escala deve ser ajustada relativa ao tamanho do Marcador na tela. Uma escala de 2 irá renderizar um Objeto duas vezes o tamanho do Marcador."
+#~ msgid "All Artworks"
+#~ msgstr "Todas as Obras"
+
+#~ msgid "All Markers"
+#~ msgstr "Todos os Marcadores"
+
+#~ msgid "All Objects"
+#~ msgstr "Todos os Objetos"
+
+#~ msgid "Adjust rotation"
+#~ msgstr "Ajustar rotação"
#~ msgid " exhibits"
#~ msgstr " exposições"
@@ -689,9 +849,6 @@ msgstr "A escala deve ser ajustada relativa ao tamanho do Marcador na tela. Uma
#~ msgid "Authorize camera"
#~ msgstr "Autorizar câmera"
-#~ msgid "object"
-#~ msgstr "objeto"
-
#~ msgid "Footer links"
#~ msgstr "Links do rodapé"
@@ -702,13 +859,13 @@ msgstr "A escala deve ser ajustada relativa ao tamanho do Marcador na tela. Uma
#~ msgstr "Atrubuição-CompartilhaIgual 4.0 Internacional (CC BY-SA 4.0)"
#~ msgid "No objects yet."
-#~ msgstr "Ainda sem objetos."
+#~ msgstr "Sem objetos."
#~ msgid "No markers yet."
-#~ msgstr "Ainda sem marcadores."
+#~ msgstr "Sem marcadores."
#~ msgid "No exhibits yet."
-#~ msgstr "Ainda sem exposições."
+#~ msgstr "Sem exposições."
#~ msgid "Create exhibit"
#~ msgstr "Criar exposição"
@@ -724,3 +881,14 @@ msgstr "A escala deve ser ajustada relativa ao tamanho do Marcador na tela. Uma
#~ msgid " author"
#~ msgstr " autor"
+
+#~ msgid ""
+#~ "Position should be adjusted relative to the Marker's size on the screen. "
+#~ "If horizontal position is 2, the center of the Object will be in a "
+#~ "distance 2 times the size of its Marker's side to the right. If it's -1, "
+#~ "it will be shown to the left."
+#~ msgstr ""
+#~ "A posição deve ser ajustada em relação ao tamanho do marcador na tela. Se "
+#~ "a posição horizontal for 2, o centro do Objeto estará a uma distância de "
+#~ "2 vezes o tamanho do lado do seu Marcador à direita. Se for -1, será "
+#~ "mostrado à esquerda."
diff --git a/locustfile.py b/locustfile.py
index b9ea8519..cd1bbdea 100644
--- a/locustfile.py
+++ b/locustfile.py
@@ -1,13 +1,13 @@
from locust import HttpLocust, Set, between
-def index(l):
- l.client.get("/")
+def index(load):
+ load.client.get("/")
-def load_gifs(l):
- l.client.get("/collection/")
+def load_gifs(load):
+ load.client.get("/collection/")
-def exhibit(l):
- l.client.get("/longavida/")
+def exhibit(load):
+ load.client.get("/longavida/")
class UserBehavior(Set):
s = {exhibit:1}
diff --git a/makefile.py b/makefile.py
deleted file mode 100644
index 63cba821..00000000
--- a/makefile.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import schedule
-import time
-import subprocess
-import os
-
-def job():
- sudoPassword = ''
- command = 'make backup'
- os.system('echo %s|sudo -S %s' % (sudoPassword, command))
-
- print("backup done")
-
-
-schedule.every().day.at("22:00").do(job)
-
-while 1:
- schedule.run_pending()
- time.sleep(1)
-
-
-
diff --git a/poetry.lock b/poetry.lock
new file mode 100644
index 00000000..3a193c17
--- /dev/null
+++ b/poetry.lock
@@ -0,0 +1,1813 @@
+# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
+
+[[package]]
+name = "alabaster"
+version = "0.7.13"
+description = "A configurable sidebar-enabled Sphinx theme"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"},
+ {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"},
+]
+
+[[package]]
+name = "asgiref"
+version = "3.6.0"
+description = "ASGI specs, helper code, and adapters"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "asgiref-3.6.0-py3-none-any.whl", hash = "sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac"},
+ {file = "asgiref-3.6.0.tar.gz", hash = "sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506"},
+]
+
+[package.extras]
+tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
+
+[[package]]
+name = "attrs"
+version = "22.2.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"},
+ {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"},
+]
+
+[package.extras]
+cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"]
+dev = ["attrs[docs,tests]"]
+docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"]
+tests = ["attrs[tests-no-zope]", "zope.interface"]
+tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"]
+
+[[package]]
+name = "babel"
+version = "2.11.0"
+description = "Internationalization utilities"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "Babel-2.11.0-py3-none-any.whl", hash = "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe"},
+ {file = "Babel-2.11.0.tar.gz", hash = "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6"},
+]
+
+[package.dependencies]
+pytz = ">=2015.7"
+
+[[package]]
+name = "black"
+version = "22.12.0"
+description = "The uncompromising code formatter."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"},
+ {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"},
+ {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"},
+ {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"},
+ {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"},
+ {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"},
+ {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"},
+ {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"},
+ {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"},
+ {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"},
+ {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"},
+ {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"},
+]
+
+[package.dependencies]
+click = ">=8.0.0"
+mypy-extensions = ">=0.4.3"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""}
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.7.4)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "boto3"
+version = "1.26.60"
+description = "The AWS SDK for Python"
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "boto3-1.26.60-py3-none-any.whl", hash = "sha256:5fd2810217a74a38078a19fb85a9e5d6934d0c146eb060967a3ffd7ab33cdf00"},
+ {file = "boto3-1.26.60.tar.gz", hash = "sha256:f0824b3bcf803800d3ecef903b4840427e4b3d37a069f6fc9a86310f7e036ad5"},
+]
+
+[package.dependencies]
+botocore = ">=1.29.60,<1.30.0"
+jmespath = ">=0.7.1,<2.0.0"
+s3transfer = ">=0.6.0,<0.7.0"
+
+[package.extras]
+crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
+
+[[package]]
+name = "botocore"
+version = "1.29.60"
+description = "Low-level, data-driven core of boto 3."
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "botocore-1.29.60-py3-none-any.whl", hash = "sha256:c4ae251e7df0cf01d893eb945bc8f23c14989ed349775a8e16c949f08a068f9a"},
+ {file = "botocore-1.29.60.tar.gz", hash = "sha256:a21217ccf4613c9ebbe4c3192e13ba91d46be642560e39a16406662a398a107b"},
+]
+
+[package.dependencies]
+jmespath = ">=0.7.1,<2.0.0"
+python-dateutil = ">=2.1,<3.0.0"
+urllib3 = ">=1.25.4,<1.27"
+
+[package.extras]
+crt = ["awscrt (==0.15.3)"]
+
+[[package]]
+name = "certifi"
+version = "2022.12.7"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
+ {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
+]
+
+[[package]]
+name = "cffi"
+version = "1.15.1"
+description = "Foreign Function Interface for Python calling C code."
+optional = false
+python-versions = "*"
+files = [
+ {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"},
+ {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"},
+ {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"},
+ {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"},
+ {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"},
+ {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"},
+ {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"},
+ {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"},
+ {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"},
+ {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"},
+ {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"},
+ {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"},
+ {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"},
+ {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"},
+ {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"},
+ {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"},
+ {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"},
+ {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"},
+ {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"},
+ {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"},
+ {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"},
+ {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"},
+ {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"},
+ {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"},
+ {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"},
+ {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"},
+ {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"},
+ {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"},
+ {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"},
+ {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"},
+ {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"},
+ {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"},
+ {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"},
+ {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"},
+ {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"},
+]
+
+[package.dependencies]
+pycparser = "*"
+
+[[package]]
+name = "charset-normalizer"
+version = "3.0.1"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+optional = false
+python-versions = "*"
+files = [
+ {file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"},
+ {file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"},
+ {file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"},
+ {file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"},
+ {file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"},
+ {file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"},
+ {file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"},
+ {file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"},
+]
+
+[[package]]
+name = "click"
+version = "8.1.3"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
+ {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "dj-inmemorystorage"
+version = "2.1.0"
+description = "A non-persistent in-memory data storage backend for Django."
+optional = false
+python-versions = "*"
+files = [
+ {file = "dj-inmemorystorage-2.1.0.tar.gz", hash = "sha256:1771801613414262803a1a1e97dafd2b7a563e78fbcbfa2b6f841c9d8e7b872a"},
+ {file = "dj_inmemorystorage-2.1.0-py2.py3-none-any.whl", hash = "sha256:81aa007a7cdb1899b3cd92404f656c82cd690a831b8698a43045f859d7276945"},
+]
+
+[package.dependencies]
+Django = ">=1.11"
+six = ">=1.10"
+
+[[package]]
+name = "django"
+version = "4.1.5"
+description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "Django-4.1.5-py3-none-any.whl", hash = "sha256:4b214a05fe4c99476e99e2445c8b978c8369c18d4dea8e22ec412862715ad763"},
+ {file = "Django-4.1.5.tar.gz", hash = "sha256:ff56ebd7ead0fd5dbe06fe157b0024a7aaea2e0593bb3785fb594cf94dad58ef"},
+]
+
+[package.dependencies]
+asgiref = ">=3.5.2,<4"
+sqlparse = ">=0.2.2"
+tzdata = {version = "*", markers = "sys_platform == \"win32\""}
+
+[package.extras]
+argon2 = ["argon2-cffi (>=19.1.0)"]
+bcrypt = ["bcrypt"]
+
+[[package]]
+name = "django-boogie"
+version = "0.13.3"
+description = "Django with swagger: better managers, APIs, configurations and url mappers."
+optional = false
+python-versions = "*"
+files = [
+ {file = "django-boogie-0.13.3.tar.gz", hash = "sha256:657799ae308a04ab32ac153c4204c5f7b8d12c032e89146d9112e662baa08c3a"},
+]
+
+[package.dependencies]
+django = ">=2.0"
+sidekick = ">=0.5.0,<0.6.0"
+
+[package.extras]
+configurations = ["django-environ (>=0.4,<1.0)"]
+dev-stack = ["django-boogie[stack]", "django-boogie[test]", "django-debug-toolbar", "django-spaghetti-and-meatballs", "docutils (>=0.14,<1.0)", "flake8 (>=3.5)", "hyperpython (>=1.1.0,<1.2.0)", "invoke (>=1.0)", "manuel (>=1.10)", "sphinx-autobuild (>=0.7,<1.0)"]
+extra = ["django-bulk-update (>=2.2)", "django-manager-utils (>=1.1)", "django-model-utils (>=3.0)", "django-polymorphic (>=2.0,<3.0)"]
+pandas = ["django-pandas (>=0.5.0,<0.6.0)", "pandas (>=0.22,<1.0)"]
+rest = ["django-filter (>=1.1,<2.0)", "djangorestframework (>=3.8,<4.0)"]
+rules = ["rules (<2)"]
+stack = ["django-bulk-update (>=2.2)", "django-environ (>=0.4,<1.0)", "django-extensions (>=2.1,<3.0)", "django-filter (>=1.1,<2.0)", "django-manager-utils (>=1.1)", "django-model-utils (>=3.0)", "django-pandas (>=0.5.0,<0.6.0)", "django-polymorphic (>=2.0,<3.0)", "djangorestframework (>=3.8,<4.0)", "pandas (>=0.22,<1.0)", "rules (<2)"]
+test = ["beautifulsoup4 (>=4.6,<5.0)", "django-stubs (>=0.12.1,<0.13.0)", "factory_boy (>=2.0,<3.0)", "faker", "model_mommy (>=1.6,<2.0)", "mypy (>=0.701,<1.0)", "pytest (>=3.8,<4.0)", "pytest-cov (>=2.6,<3.0)", "pytest-django (>=3.1,<4.0)"]
+
+[[package]]
+name = "django-cors-headers"
+version = "3.13.0"
+description = "django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS)."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "django-cors-headers-3.13.0.tar.gz", hash = "sha256:f9dc6b4e3f611c3199700b3e5f3398c28757dcd559c2f82932687f3d0443cfdf"},
+ {file = "django_cors_headers-3.13.0-py3-none-any.whl", hash = "sha256:37e42883b5f1f2295df6b4bba96eb2417a14a03270cb24b2a07f021cd4487cf4"},
+]
+
+[package.dependencies]
+Django = ">=3.2"
+
+[[package]]
+name = "django-debug-toolbar"
+version = "3.8.1"
+description = "A configurable set of panels that display various debug information about the current request/response."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "django_debug_toolbar-3.8.1-py3-none-any.whl", hash = "sha256:879f8a4672d41621c06a4d322dcffa630fc4df056cada6e417ed01db0e5e0478"},
+ {file = "django_debug_toolbar-3.8.1.tar.gz", hash = "sha256:24ef1a7d44d25e60d7951e378454c6509bf536dce7e7d9d36e7c387db499bc27"},
+]
+
+[package.dependencies]
+django = ">=3.2.4"
+sqlparse = ">=0.2"
+
+[[package]]
+name = "django-environ"
+version = "0.9.0"
+description = "A package that allows you to utilize 12factor inspired environment variables to configure your Django application."
+optional = false
+python-versions = ">=3.4,<4"
+files = [
+ {file = "django-environ-0.9.0.tar.gz", hash = "sha256:bff5381533056328c9ac02f71790bd5bf1cea81b1beeb648f28b81c9e83e0a21"},
+ {file = "django_environ-0.9.0-py2.py3-none-any.whl", hash = "sha256:f21a5ef8cc603da1870bbf9a09b7e5577ab5f6da451b843dbcc721a7bca6b3d9"},
+]
+
+[package.extras]
+develop = ["coverage[toml] (>=5.0a4)", "furo (>=2021.8.17b43,<2021.9.dev0)", "pytest (>=4.6.11)", "sphinx (>=3.5.0)", "sphinx-notfound-page"]
+docs = ["furo (>=2021.8.17b43,<2021.9.dev0)", "sphinx (>=3.5.0)", "sphinx-notfound-page"]
+testing = ["coverage[toml] (>=5.0a4)", "pytest (>=4.6.11)"]
+
+[[package]]
+name = "django-extensions"
+version = "3.2.1"
+description = "Extensions for Django"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "django-extensions-3.2.1.tar.gz", hash = "sha256:2a4f4d757be2563cd1ff7cfdf2e57468f5f931cc88b23cf82ca75717aae504a4"},
+ {file = "django_extensions-3.2.1-py3-none-any.whl", hash = "sha256:421464be390289513f86cb5e18eb43e5dc1de8b4c27ba9faa3b91261b0d67e09"},
+]
+
+[package.dependencies]
+Django = ">=3.2"
+
+[[package]]
+name = "django-htmx"
+version = "1.18.0"
+description = "Extensions for using Django with htmx."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "django_htmx-1.18.0-py3-none-any.whl", hash = "sha256:48f3b8a784467bfcc30562067b87ecbc4ad9b739cc269eec5f3789c16d2cb2ce"},
+ {file = "django_htmx-1.18.0.tar.gz", hash = "sha256:db8a0cc15bcd0f7ae929bcb9108d9e6be228843092aca7956d977c31c4d95aae"},
+]
+
+[package.dependencies]
+asgiref = ">=3.6"
+django = ">=3.2"
+
+[[package]]
+name = "django-storages"
+version = "1.13.2"
+description = "Support for many storage backends in Django"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "django-storages-1.13.2.tar.gz", hash = "sha256:cbadd15c909ceb7247d4ffc503f12a9bec36999df8d0bef7c31e57177d512688"},
+ {file = "django_storages-1.13.2-py3-none-any.whl", hash = "sha256:31dc5a992520be571908c4c40d55d292660ece3a55b8141462b4e719aa38eab3"},
+]
+
+[package.dependencies]
+Django = ">=3.2"
+
+[package.extras]
+azure = ["azure-storage-blob (>=12.0.0)"]
+boto3 = ["boto3 (>=1.4.4)"]
+dropbox = ["dropbox (>=7.2.1)"]
+google = ["google-cloud-storage (>=1.27.0)"]
+libcloud = ["apache-libcloud"]
+sftp = ["paramiko (>=1.10.0)"]
+
+[[package]]
+name = "djangorestframework"
+version = "3.14.0"
+description = "Web APIs for Django, made easy."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "djangorestframework-3.14.0-py3-none-any.whl", hash = "sha256:eb63f58c9f218e1a7d064d17a70751f528ed4e1d35547fdade9aaf4cd103fd08"},
+ {file = "djangorestframework-3.14.0.tar.gz", hash = "sha256:579a333e6256b09489cbe0a067e66abe55c6595d8926be6b99423786334350c8"},
+]
+
+[package.dependencies]
+django = ">=3.0"
+pytz = "*"
+
+[[package]]
+name = "docutils"
+version = "0.19"
+description = "Docutils -- Python Documentation Utilities"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"},
+ {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"},
+]
+
+[[package]]
+name = "drf-nested-routers"
+version = "0.93.4"
+description = "Nested resources for the Django Rest Framework"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "drf-nested-routers-0.93.4.tar.gz", hash = "sha256:01aa556b8c08608bb74fb34f6ca065a5183f2cda4dc0478192cc17a2581d71b0"},
+ {file = "drf_nested_routers-0.93.4-py2.py3-none-any.whl", hash = "sha256:996b77f3f4dfaf64569e7b8f04e3919945f90f95366838ca5b8bed9dd709d6c5"},
+]
+
+[package.dependencies]
+Django = ">=1.11"
+djangorestframework = ">=3.6.0"
+
+[[package]]
+name = "exceptiongroup"
+version = "1.1.0"
+description = "Backport of PEP 654 (exception groups)"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"},
+ {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"},
+]
+
+[package.extras]
+test = ["pytest (>=6)"]
+
+[[package]]
+name = "execnet"
+version = "1.9.0"
+description = "execnet: rapid multi-Python deployment"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"},
+ {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"},
+]
+
+[package.extras]
+testing = ["pre-commit"]
+
+[[package]]
+name = "factory-boy"
+version = "3.2.1"
+description = "A versatile test fixtures replacement based on thoughtbot's factory_bot for Ruby."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "factory_boy-3.2.1-py2.py3-none-any.whl", hash = "sha256:eb02a7dd1b577ef606b75a253b9818e6f9eaf996d94449c9d5ebb124f90dc795"},
+ {file = "factory_boy-3.2.1.tar.gz", hash = "sha256:a98d277b0c047c75eb6e4ab8508a7f81fb03d2cb21986f627913546ef7a2a55e"},
+]
+
+[package.dependencies]
+Faker = ">=0.7.0"
+
+[package.extras]
+dev = ["Django", "Pillow", "SQLAlchemy", "coverage", "flake8", "isort", "mongoengine", "tox", "wheel (>=0.32.0)", "zest.releaser[recommended]"]
+doc = ["Sphinx", "sphinx-rtd-theme", "sphinxcontrib-spelling"]
+
+[[package]]
+name = "faker"
+version = "16.6.1"
+description = "Faker is a Python package that generates fake data for you."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "Faker-16.6.1-py3-none-any.whl", hash = "sha256:2375d0bbaf405dc4f1cbc771485a78ad952c776798e5c228eef3e7b337f78868"},
+ {file = "Faker-16.6.1.tar.gz", hash = "sha256:b76e5d2405470e3d38d37d1bfaa9d9bbf171bdf41c814f5bbd8117b121f6bccb"},
+]
+
+[package.dependencies]
+python-dateutil = ">=2.4"
+
+[[package]]
+name = "flake8"
+version = "5.0.4"
+description = "the modular source code checker: pep8 pyflakes and co"
+optional = false
+python-versions = ">=3.6.1"
+files = [
+ {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"},
+ {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"},
+]
+
+[package.dependencies]
+mccabe = ">=0.7.0,<0.8.0"
+pycodestyle = ">=2.9.0,<2.10.0"
+pyflakes = ">=2.5.0,<2.6.0"
+
+[[package]]
+name = "gevent"
+version = "23.9.1"
+description = "Coroutine-based network library"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "gevent-23.9.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:a3c5e9b1f766a7a64833334a18539a362fb563f6c4682f9634dea72cbe24f771"},
+ {file = "gevent-23.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b101086f109168b23fa3586fccd1133494bdb97f86920a24dc0b23984dc30b69"},
+ {file = "gevent-23.9.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36a549d632c14684bcbbd3014a6ce2666c5f2a500f34d58d32df6c9ea38b6535"},
+ {file = "gevent-23.9.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:272cffdf535978d59c38ed837916dfd2b5d193be1e9e5dcc60a5f4d5025dd98a"},
+ {file = "gevent-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcb8612787a7f4626aa881ff15ff25439561a429f5b303048f0fca8a1c781c39"},
+ {file = "gevent-23.9.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:d57737860bfc332b9b5aa438963986afe90f49645f6e053140cfa0fa1bdae1ae"},
+ {file = "gevent-23.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5f3c781c84794926d853d6fb58554dc0dcc800ba25c41d42f6959c344b4db5a6"},
+ {file = "gevent-23.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:dbb22a9bbd6a13e925815ce70b940d1578dbe5d4013f20d23e8a11eddf8d14a7"},
+ {file = "gevent-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:707904027d7130ff3e59ea387dddceedb133cc742b00b3ffe696d567147a9c9e"},
+ {file = "gevent-23.9.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:45792c45d60f6ce3d19651d7fde0bc13e01b56bb4db60d3f32ab7d9ec467374c"},
+ {file = "gevent-23.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e24c2af9638d6c989caffc691a039d7c7022a31c0363da367c0d32ceb4a0648"},
+ {file = "gevent-23.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e1ead6863e596a8cc2a03e26a7a0981f84b6b3e956101135ff6d02df4d9a6b07"},
+ {file = "gevent-23.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65883ac026731ac112184680d1f0f1e39fa6f4389fd1fc0bf46cc1388e2599f9"},
+ {file = "gevent-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf7af500da05363e66f122896012acb6e101a552682f2352b618e541c941a011"},
+ {file = "gevent-23.9.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:c3e5d2fa532e4d3450595244de8ccf51f5721a05088813c1abd93ad274fe15e7"},
+ {file = "gevent-23.9.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c84d34256c243b0a53d4335ef0bc76c735873986d478c53073861a92566a8d71"},
+ {file = "gevent-23.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ada07076b380918829250201df1d016bdafb3acf352f35e5693b59dceee8dd2e"},
+ {file = "gevent-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:921dda1c0b84e3d3b1778efa362d61ed29e2b215b90f81d498eb4d8eafcd0b7a"},
+ {file = "gevent-23.9.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ed7a048d3e526a5c1d55c44cb3bc06cfdc1947d06d45006cc4cf60dedc628904"},
+ {file = "gevent-23.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c1abc6f25f475adc33e5fc2dbcc26a732608ac5375d0d306228738a9ae14d3b"},
+ {file = "gevent-23.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4368f341a5f51611411ec3fc62426f52ac3d6d42eaee9ed0f9eebe715c80184e"},
+ {file = "gevent-23.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:52b4abf28e837f1865a9bdeef58ff6afd07d1d888b70b6804557e7908032e599"},
+ {file = "gevent-23.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52e9f12cd1cda96603ce6b113d934f1aafb873e2c13182cf8e86d2c5c41982ea"},
+ {file = "gevent-23.9.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:de350fde10efa87ea60d742901e1053eb2127ebd8b59a7d3b90597eb4e586599"},
+ {file = "gevent-23.9.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fde6402c5432b835fbb7698f1c7f2809c8d6b2bd9d047ac1f5a7c1d5aa569303"},
+ {file = "gevent-23.9.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:dd6c32ab977ecf7c7b8c2611ed95fa4aaebd69b74bf08f4b4960ad516861517d"},
+ {file = "gevent-23.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:455e5ee8103f722b503fa45dedb04f3ffdec978c1524647f8ba72b4f08490af1"},
+ {file = "gevent-23.9.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:7ccf0fd378257cb77d91c116e15c99e533374a8153632c48a3ecae7f7f4f09fe"},
+ {file = "gevent-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d163d59f1be5a4c4efcdd13c2177baaf24aadf721fdf2e1af9ee54a998d160f5"},
+ {file = "gevent-23.9.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7532c17bc6c1cbac265e751b95000961715adef35a25d2b0b1813aa7263fb397"},
+ {file = "gevent-23.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:78eebaf5e73ff91d34df48f4e35581ab4c84e22dd5338ef32714264063c57507"},
+ {file = "gevent-23.9.1-cp38-cp38-win32.whl", hash = "sha256:f632487c87866094546a74eefbca2c74c1d03638b715b6feb12e80120960185a"},
+ {file = "gevent-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:62d121344f7465e3739989ad6b91f53a6ca9110518231553fe5846dbe1b4518f"},
+ {file = "gevent-23.9.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:bf456bd6b992eb0e1e869e2fd0caf817f0253e55ca7977fd0e72d0336a8c1c6a"},
+ {file = "gevent-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43daf68496c03a35287b8b617f9f91e0e7c0d042aebcc060cadc3f049aadd653"},
+ {file = "gevent-23.9.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:7c28e38dcde327c217fdafb9d5d17d3e772f636f35df15ffae2d933a5587addd"},
+ {file = "gevent-23.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fae8d5b5b8fa2a8f63b39f5447168b02db10c888a3e387ed7af2bd1b8612e543"},
+ {file = "gevent-23.9.1-cp39-cp39-win32.whl", hash = "sha256:2c7b5c9912378e5f5ccf180d1fdb1e83f42b71823483066eddbe10ef1a2fcaa2"},
+ {file = "gevent-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:a2898b7048771917d85a1d548fd378e8a7b2ca963db8e17c6d90c76b495e0e2b"},
+ {file = "gevent-23.9.1.tar.gz", hash = "sha256:72c002235390d46f94938a96920d8856d4ffd9ddf62a303a0d7c118894097e34"},
+]
+
+[package.dependencies]
+cffi = {version = ">=1.12.2", markers = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\""}
+greenlet = [
+ {version = ">=2.0.0", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""},
+ {version = ">=3.0rc3", markers = "platform_python_implementation == \"CPython\" and python_version >= \"3.11\""},
+]
+"zope.event" = "*"
+"zope.interface" = "*"
+
+[package.extras]
+dnspython = ["dnspython (>=1.16.0,<2.0)", "idna"]
+docs = ["furo", "repoze.sphinx.autointerface", "sphinx", "sphinxcontrib-programoutput", "zope.schema"]
+monitor = ["psutil (>=5.7.0)"]
+recommended = ["cffi (>=1.12.2)", "dnspython (>=1.16.0,<2.0)", "idna", "psutil (>=5.7.0)"]
+test = ["cffi (>=1.12.2)", "coverage (>=5.0)", "dnspython (>=1.16.0,<2.0)", "idna", "objgraph", "psutil (>=5.7.0)", "requests", "setuptools"]
+
+[[package]]
+name = "greenlet"
+version = "3.0.3"
+description = "Lightweight in-process concurrent programming"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"},
+ {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"},
+ {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"},
+ {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"},
+ {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"},
+ {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"},
+ {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"},
+ {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"},
+ {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"},
+ {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"},
+ {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"},
+ {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"},
+ {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"},
+ {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"},
+ {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"},
+ {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"},
+ {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"},
+ {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"},
+ {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"},
+ {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"},
+ {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"},
+ {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"},
+ {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"},
+ {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"},
+ {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"},
+ {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"},
+ {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"},
+ {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"},
+ {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"},
+ {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"},
+ {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"},
+ {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"},
+ {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"},
+ {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"},
+]
+
+[package.extras]
+docs = ["Sphinx", "furo"]
+test = ["objgraph", "psutil"]
+
+[[package]]
+name = "gunicorn"
+version = "20.1.0"
+description = "WSGI HTTP Server for UNIX"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"},
+ {file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"},
+]
+
+[package.dependencies]
+setuptools = ">=3.0"
+
+[package.extras]
+eventlet = ["eventlet (>=0.24.1)"]
+gevent = ["gevent (>=1.4.0)"]
+setproctitle = ["setproctitle"]
+tornado = ["tornado (>=0.2)"]
+
+[[package]]
+name = "idna"
+version = "3.4"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
+ {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
+]
+
+[[package]]
+name = "imagesize"
+version = "1.4.1"
+description = "Getting image size from png/jpeg/jpeg2000/gif file"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
+ {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
+
+[[package]]
+name = "invoke"
+version = "1.7.3"
+description = "Pythonic task execution"
+optional = false
+python-versions = "*"
+files = [
+ {file = "invoke-1.7.3-py3-none-any.whl", hash = "sha256:d9694a865764dd3fd91f25f7e9a97fb41666e822bbb00e670091e3f43933574d"},
+ {file = "invoke-1.7.3.tar.gz", hash = "sha256:41b428342d466a82135d5ab37119685a989713742be46e42a3a399d685579314"},
+]
+
+[[package]]
+name = "isort"
+version = "5.12.0"
+description = "A Python utility / library to sort Python imports."
+optional = false
+python-versions = ">=3.8.0"
+files = [
+ {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
+ {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
+]
+
+[package.extras]
+colors = ["colorama (>=0.4.3)"]
+pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
+plugins = ["setuptools"]
+requirements-deprecated-finder = ["pip-api", "pipreqs"]
+
+[[package]]
+name = "jinja2"
+version = "3.1.2"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
+ {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "jmespath"
+version = "1.0.1"
+description = "JSON Matching Expressions"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"},
+ {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"},
+]
+
+[[package]]
+name = "markupsafe"
+version = "2.1.2"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
+ {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
+ {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
+ {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
+ {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
+ {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
+ {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
+]
+
+[[package]]
+name = "mccabe"
+version = "0.7.0"
+description = "McCabe checker, plugin for flake8"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
+ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
+]
+
+[[package]]
+name = "mypy-extensions"
+version = "0.4.3"
+description = "Experimental type system extensions for programs checked with the mypy typechecker."
+optional = false
+python-versions = "*"
+files = [
+ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
+ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
+]
+
+[[package]]
+name = "packaging"
+version = "23.0"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"},
+ {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"},
+]
+
+[[package]]
+name = "pathspec"
+version = "0.11.0"
+description = "Utility library for gitignore style pattern matching of file paths."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pathspec-0.11.0-py3-none-any.whl", hash = "sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229"},
+ {file = "pathspec-0.11.0.tar.gz", hash = "sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc"},
+]
+
+[[package]]
+name = "pillow"
+version = "9.4.0"
+description = "Python Imaging Library (Fork)"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "Pillow-9.4.0-1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b4b4e9dda4f4e4c4e6896f93e84a8f0bcca3b059de9ddf67dac3c334b1195e1"},
+ {file = "Pillow-9.4.0-1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:fb5c1ad6bad98c57482236a21bf985ab0ef42bd51f7ad4e4538e89a997624e12"},
+ {file = "Pillow-9.4.0-1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:f0caf4a5dcf610d96c3bd32932bfac8aee61c96e60481c2a0ea58da435e25acd"},
+ {file = "Pillow-9.4.0-1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:3f4cc516e0b264c8d4ccd6b6cbc69a07c6d582d8337df79be1e15a5056b258c9"},
+ {file = "Pillow-9.4.0-1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b8c2f6eb0df979ee99433d8b3f6d193d9590f735cf12274c108bd954e30ca858"},
+ {file = "Pillow-9.4.0-1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b70756ec9417c34e097f987b4d8c510975216ad26ba6e57ccb53bc758f490dab"},
+ {file = "Pillow-9.4.0-1-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:43521ce2c4b865d385e78579a082b6ad1166ebed2b1a2293c3be1d68dd7ca3b9"},
+ {file = "Pillow-9.4.0-2-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:9d9a62576b68cd90f7075876f4e8444487db5eeea0e4df3ba298ee38a8d067b0"},
+ {file = "Pillow-9.4.0-2-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:87708d78a14d56a990fbf4f9cb350b7d89ee8988705e58e39bdf4d82c149210f"},
+ {file = "Pillow-9.4.0-2-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8a2b5874d17e72dfb80d917213abd55d7e1ed2479f38f001f264f7ce7bae757c"},
+ {file = "Pillow-9.4.0-2-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:83125753a60cfc8c412de5896d10a0a405e0bd88d0470ad82e0869ddf0cb3848"},
+ {file = "Pillow-9.4.0-2-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9e5f94742033898bfe84c93c831a6f552bb629448d4072dd312306bab3bd96f1"},
+ {file = "Pillow-9.4.0-2-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:013016af6b3a12a2f40b704677f8b51f72cb007dac785a9933d5c86a72a7fe33"},
+ {file = "Pillow-9.4.0-2-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:99d92d148dd03fd19d16175b6d355cc1b01faf80dae93c6c3eb4163709edc0a9"},
+ {file = "Pillow-9.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:2968c58feca624bb6c8502f9564dd187d0e1389964898f5e9e1fbc8533169157"},
+ {file = "Pillow-9.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c5c1362c14aee73f50143d74389b2c158707b4abce2cb055b7ad37ce60738d47"},
+ {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd752c5ff1b4a870b7661234694f24b1d2b9076b8bf337321a814c612665f343"},
+ {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3049a10261d7f2b6514d35bbb7a4dfc3ece4c4de14ef5876c4b7a23a0e566d"},
+ {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16a8df99701f9095bea8a6c4b3197da105df6f74e6176c5b410bc2df2fd29a57"},
+ {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:94cdff45173b1919350601f82d61365e792895e3c3a3443cf99819e6fbf717a5"},
+ {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ed3e4b4e1e6de75fdc16d3259098de7c6571b1a6cc863b1a49e7d3d53e036070"},
+ {file = "Pillow-9.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5b2f8a31bd43e0f18172d8ac82347c8f37ef3e0b414431157718aa234991b28"},
+ {file = "Pillow-9.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:09b89ddc95c248ee788328528e6a2996e09eaccddeeb82a5356e92645733be35"},
+ {file = "Pillow-9.4.0-cp310-cp310-win32.whl", hash = "sha256:f09598b416ba39a8f489c124447b007fe865f786a89dbfa48bb5cf395693132a"},
+ {file = "Pillow-9.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6e78171be3fb7941f9910ea15b4b14ec27725865a73c15277bc39f5ca4f8391"},
+ {file = "Pillow-9.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:3fa1284762aacca6dc97474ee9c16f83990b8eeb6697f2ba17140d54b453e133"},
+ {file = "Pillow-9.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eaef5d2de3c7e9b21f1e762f289d17b726c2239a42b11e25446abf82b26ac132"},
+ {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4dfdae195335abb4e89cc9762b2edc524f3c6e80d647a9a81bf81e17e3fb6f0"},
+ {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6abfb51a82e919e3933eb137e17c4ae9c0475a25508ea88993bb59faf82f3b35"},
+ {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451f10ef963918e65b8869e17d67db5e2f4ab40e716ee6ce7129b0cde2876eab"},
+ {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:6663977496d616b618b6cfa43ec86e479ee62b942e1da76a2c3daa1c75933ef4"},
+ {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:60e7da3a3ad1812c128750fc1bc14a7ceeb8d29f77e0a2356a8fb2aa8925287d"},
+ {file = "Pillow-9.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:19005a8e58b7c1796bc0167862b1f54a64d3b44ee5d48152b06bb861458bc0f8"},
+ {file = "Pillow-9.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f715c32e774a60a337b2bb8ad9839b4abf75b267a0f18806f6f4f5f1688c4b5a"},
+ {file = "Pillow-9.4.0-cp311-cp311-win32.whl", hash = "sha256:b222090c455d6d1a64e6b7bb5f4035c4dff479e22455c9eaa1bdd4c75b52c80c"},
+ {file = "Pillow-9.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba6612b6548220ff5e9df85261bddc811a057b0b465a1226b39bfb8550616aee"},
+ {file = "Pillow-9.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5f532a2ad4d174eb73494e7397988e22bf427f91acc8e6ebf5bb10597b49c493"},
+ {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dd5a9c3091a0f414a963d427f920368e2b6a4c2f7527fdd82cde8ef0bc7a327"},
+ {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef21af928e807f10bf4141cad4746eee692a0dd3ff56cfb25fce076ec3cc8abe"},
+ {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:847b114580c5cc9ebaf216dd8c8dbc6b00a3b7ab0131e173d7120e6deade1f57"},
+ {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:653d7fb2df65efefbcbf81ef5fe5e5be931f1ee4332c2893ca638c9b11a409c4"},
+ {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:46f39cab8bbf4a384ba7cb0bc8bae7b7062b6a11cfac1ca4bc144dea90d4a9f5"},
+ {file = "Pillow-9.4.0-cp37-cp37m-win32.whl", hash = "sha256:7ac7594397698f77bce84382929747130765f66406dc2cd8b4ab4da68ade4c6e"},
+ {file = "Pillow-9.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:46c259e87199041583658457372a183636ae8cd56dbf3f0755e0f376a7f9d0e6"},
+ {file = "Pillow-9.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:0e51f608da093e5d9038c592b5b575cadc12fd748af1479b5e858045fff955a9"},
+ {file = "Pillow-9.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:765cb54c0b8724a7c12c55146ae4647e0274a839fb6de7bcba841e04298e1011"},
+ {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:519e14e2c49fcf7616d6d2cfc5c70adae95682ae20f0395e9280db85e8d6c4df"},
+ {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d197df5489004db87d90b918033edbeee0bd6df3848a204bca3ff0a903bef837"},
+ {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0845adc64fe9886db00f5ab68c4a8cd933ab749a87747555cec1c95acea64b0b"},
+ {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:e1339790c083c5a4de48f688b4841f18df839eb3c9584a770cbd818b33e26d5d"},
+ {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:a96e6e23f2b79433390273eaf8cc94fec9c6370842e577ab10dabdcc7ea0a66b"},
+ {file = "Pillow-9.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7cfc287da09f9d2a7ec146ee4d72d6ea1342e770d975e49a8621bf54eaa8f30f"},
+ {file = "Pillow-9.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d7081c084ceb58278dd3cf81f836bc818978c0ccc770cbbb202125ddabec6628"},
+ {file = "Pillow-9.4.0-cp38-cp38-win32.whl", hash = "sha256:df41112ccce5d47770a0c13651479fbcd8793f34232a2dd9faeccb75eb5d0d0d"},
+ {file = "Pillow-9.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7a21222644ab69ddd9967cfe6f2bb420b460dae4289c9d40ff9a4896e7c35c9a"},
+ {file = "Pillow-9.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0f3269304c1a7ce82f1759c12ce731ef9b6e95b6df829dccd9fe42912cc48569"},
+ {file = "Pillow-9.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cb362e3b0976dc994857391b776ddaa8c13c28a16f80ac6522c23d5257156bed"},
+ {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2e0f87144fcbbe54297cae708c5e7f9da21a4646523456b00cc956bd4c65815"},
+ {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28676836c7796805914b76b1837a40f76827ee0d5398f72f7dcc634bae7c6264"},
+ {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0884ba7b515163a1a05440a138adeb722b8a6ae2c2b33aea93ea3118dd3a899e"},
+ {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:53dcb50fbdc3fb2c55431a9b30caeb2f7027fcd2aeb501459464f0214200a503"},
+ {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:e8c5cf126889a4de385c02a2c3d3aba4b00f70234bfddae82a5eaa3ee6d5e3e6"},
+ {file = "Pillow-9.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6c6b1389ed66cdd174d040105123a5a1bc91d0aa7059c7261d20e583b6d8cbd2"},
+ {file = "Pillow-9.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0dd4c681b82214b36273c18ca7ee87065a50e013112eea7d78c7a1b89a739153"},
+ {file = "Pillow-9.4.0-cp39-cp39-win32.whl", hash = "sha256:6d9dfb9959a3b0039ee06c1a1a90dc23bac3b430842dcb97908ddde05870601c"},
+ {file = "Pillow-9.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:54614444887e0d3043557d9dbc697dbb16cfb5a35d672b7a0fcc1ed0cf1c600b"},
+ {file = "Pillow-9.4.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b9b752ab91e78234941e44abdecc07f1f0d8f51fb62941d32995b8161f68cfe5"},
+ {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3b56206244dc8711f7e8b7d6cad4663917cd5b2d950799425076681e8766286"},
+ {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aabdab8ec1e7ca7f1434d042bf8b1e92056245fb179790dc97ed040361f16bfd"},
+ {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db74f5562c09953b2c5f8ec4b7dfd3f5421f31811e97d1dbc0a7c93d6e3a24df"},
+ {file = "Pillow-9.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e9d7747847c53a16a729b6ee5e737cf170f7a16611c143d95aa60a109a59c336"},
+ {file = "Pillow-9.4.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b52ff4f4e002f828ea6483faf4c4e8deea8d743cf801b74910243c58acc6eda3"},
+ {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:575d8912dca808edd9acd6f7795199332696d3469665ef26163cd090fa1f8bfa"},
+ {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c4ed2ff6760e98d262e0cc9c9a7f7b8a9f61aa4d47c58835cdaf7b0b8811bb"},
+ {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e621b0246192d3b9cb1dc62c78cfa4c6f6d2ddc0ec207d43c0dedecb914f152a"},
+ {file = "Pillow-9.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8f127e7b028900421cad64f51f75c051b628db17fb00e099eb148761eed598c9"},
+ {file = "Pillow-9.4.0.tar.gz", hash = "sha256:a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e"},
+]
+
+[package.extras]
+docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"]
+tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
+
+[[package]]
+name = "platformdirs"
+version = "2.6.2"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"},
+ {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"},
+]
+
+[package.extras]
+docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
+
+[[package]]
+name = "playwright"
+version = "1.41.2"
+description = "A high-level API to automate web browsers"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "playwright-1.41.2-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:cf68335a5dfa4038fa797a4ba0105faee0094ebbb372547d7a27feec5b23c672"},
+ {file = "playwright-1.41.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:431e3a05f8c99147995e2b3e8475d07818745294fd99f1510b61756e73bdcf68"},
+ {file = "playwright-1.41.2-py3-none-macosx_11_0_universal2.whl", hash = "sha256:0608717cbf291a625ba6f751061af0fc0cc9bdace217e69d87b1eb1383b03406"},
+ {file = "playwright-1.41.2-py3-none-manylinux1_x86_64.whl", hash = "sha256:4bf214d812092cf5b9b9648ba84611aa35e28685519911342a7da3a3031f9ed6"},
+ {file = "playwright-1.41.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaa17ab44622c447de26ed8f7d99912719568d8dbc3a9db0e07f0ae1487709d9"},
+ {file = "playwright-1.41.2-py3-none-win32.whl", hash = "sha256:edb210a015e70bb0d328bf1c9b65fa3a08361f33e4d7c4ddd1ad2adb6d9b4479"},
+ {file = "playwright-1.41.2-py3-none-win_amd64.whl", hash = "sha256:71ead0f33e00f5a8533c037c647938b99f219436a1b27d4ba4de4e6bf0567278"},
+]
+
+[package.dependencies]
+greenlet = "3.0.3"
+pyee = "11.0.1"
+
+[[package]]
+name = "pluggy"
+version = "1.0.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "psycopg2-binary"
+version = "2.9.5"
+description = "psycopg2 - Python-PostgreSQL Database Adapter"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "psycopg2-binary-2.9.5.tar.gz", hash = "sha256:33e632d0885b95a8b97165899006c40e9ecdc634a529dca7b991eb7de4ece41c"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-macosx_10_15_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:0775d6252ccb22b15da3b5d7adbbf8cfe284916b14b6dc0ff503a23edb01ee85"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ec46ed947801652c9643e0b1dc334cfb2781232e375ba97312c2fc256597632"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3520d7af1ebc838cc6084a3281145d5cd5bdd43fdef139e6db5af01b92596cb7"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cbc554ba47ecca8cd3396ddaca85e1ecfe3e48dd57dc5e415e59551affe568e"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:5d28ecdf191db558d0c07d0f16524ee9d67896edf2b7990eea800abeb23ebd61"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:b9c33d4aef08dfecbd1736ceab8b7b3c4358bf10a0121483e5cd60d3d308cc64"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:05b3d479425e047c848b9782cd7aac9c6727ce23181eb9647baf64ffdfc3da41"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1e491e6489a6cb1d079df8eaa15957c277fdedb102b6a68cfbf40c4994412fd0"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:9e32cedc389bcb76d9f24ea8a012b3cb8385ee362ea437e1d012ffaed106c17d"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46850a640df62ae940e34a163f72e26aca1f88e2da79148e1862faaac985c302"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-win32.whl", hash = "sha256:3d790f84201c3698d1bfb404c917f36e40531577a6dda02e45ba29b64d539867"},
+ {file = "psycopg2_binary-2.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:1764546ffeaed4f9428707be61d68972eb5ede81239b46a45843e0071104d0dd"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-macosx_10_9_universal2.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:426c2ae999135d64e6a18849a7d1ad0e1bd007277e4a8f4752eaa40a96b550ff"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7cf1d44e710ca3a9ce952bda2855830fe9f9017ed6259e01fcd71ea6287565f5"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:024030b13bdcbd53d8a93891a2cf07719715724fc9fee40243f3bd78b4264b8f"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcda1c84a1c533c528356da5490d464a139b6e84eb77cc0b432e38c5c6dd7882"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:2ef892cabdccefe577088a79580301f09f2a713eb239f4f9f62b2b29cafb0577"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-manylinux_2_24_ppc64le.whl", hash = "sha256:af0516e1711995cb08dc19bbd05bec7dbdebf4185f68870595156718d237df3e"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e72c91bda9880f097c8aa3601a2c0de6c708763ba8128006151f496ca9065935"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e67b3c26e9b6d37b370c83aa790bbc121775c57bfb096c2e77eacca25fd0233b"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5fc447058d083b8c6ac076fc26b446d44f0145308465d745fba93a28c14c9e32"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d892bfa1d023c3781a3cab8dd5af76b626c483484d782e8bd047c180db590e4c"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-win32.whl", hash = "sha256:2abccab84d057723d2ca8f99ff7b619285d40da6814d50366f61f0fc385c3903"},
+ {file = "psycopg2_binary-2.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:bef7e3f9dc6f0c13afdd671008534be5744e0e682fb851584c8c3a025ec09720"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:6e63814ec71db9bdb42905c925639f319c80e7909fb76c3b84edc79dadef8d60"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:212757ffcecb3e1a5338d4e6761bf9c04f750e7d027117e74aa3cd8a75bb6fbd"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f8a9bcab7b6db2e3dbf65b214dfc795b4c6b3bb3af922901b6a67f7cb47d5f8"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:56b2957a145f816726b109ee3d4e6822c23f919a7d91af5a94593723ed667835"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:f95b8aca2703d6a30249f83f4fe6a9abf2e627aa892a5caaab2267d56be7ab69"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:70831e03bd53702c941da1a1ad36c17d825a24fbb26857b40913d58df82ec18b"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:dbc332beaf8492b5731229a881807cd7b91b50dbbbaf7fe2faf46942eda64a24"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:2d964eb24c8b021623df1c93c626671420c6efadbdb8655cb2bd5e0c6fa422ba"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:95076399ec3b27a8f7fa1cc9a83417b1c920d55cf7a97f718a94efbb96c7f503"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-win32.whl", hash = "sha256:3fc33295cfccad697a97a76dec3f1e94ad848b7b163c3228c1636977966b51e2"},
+ {file = "psycopg2_binary-2.9.5-cp36-cp36m-win_amd64.whl", hash = "sha256:02551647542f2bf89073d129c73c05a25c372fc0a49aa50e0de65c3c143d8bd0"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-macosx_10_15_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:63e318dbe52709ed10d516a356f22a635e07a2e34c68145484ed96a19b0c4c68"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7e518a0911c50f60313cb9e74a169a65b5d293770db4770ebf004245f24b5c5"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9d38a4656e4e715d637abdf7296e98d6267df0cc0a8e9a016f8ba07e4aa3eeb"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:68d81a2fe184030aa0c5c11e518292e15d342a667184d91e30644c9d533e53e1"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:7ee3095d02d6f38bd7d9a5358fcc9ea78fcdb7176921528dd709cc63f40184f5"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:46512486be6fbceef51d7660dec017394ba3e170299d1dc30928cbedebbf103a"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b911dfb727e247340d36ae20c4b9259e4a64013ab9888ccb3cbba69b77fd9636"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:422e3d43b47ac20141bc84b3d342eead8d8099a62881a501e97d15f6addabfe9"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c5682a45df7d9642eff590abc73157c887a68f016df0a8ad722dcc0f888f56d7"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-win32.whl", hash = "sha256:b8104f709590fff72af801e916817560dbe1698028cd0afe5a52d75ceb1fce5f"},
+ {file = "psycopg2_binary-2.9.5-cp37-cp37m-win_amd64.whl", hash = "sha256:7b3751857da3e224f5629400736a7b11e940b5da5f95fa631d86219a1beaafec"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-macosx_10_15_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:043a9fd45a03858ff72364b4b75090679bd875ee44df9c0613dc862ca6b98460"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9ffdc51001136b699f9563b1c74cc1f8c07f66ef7219beb6417a4c8aaa896c28"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c15ba5982c177bc4b23a7940c7e4394197e2d6a424a2d282e7c236b66da6d896"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc85b3777068ed30aff8242be2813038a929f2084f69e43ef869daddae50f6ee"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:215d6bf7e66732a514f47614f828d8c0aaac9a648c46a831955cb103473c7147"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:7d07f552d1e412f4b4e64ce386d4c777a41da3b33f7098b6219012ba534fb2c2"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a0adef094c49f242122bb145c3c8af442070dc0e4312db17e49058c1702606d4"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:00475004e5ed3e3bf5e056d66e5dcdf41a0dc62efcd57997acd9135c40a08a50"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:7d88db096fa19d94f433420eaaf9f3c45382da2dd014b93e4bf3215639047c16"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:902844f9c4fb19b17dfa84d9e2ca053d4a4ba265723d62ea5c9c26b38e0aa1e6"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-win32.whl", hash = "sha256:4e7904d1920c0c89105c0517dc7e3f5c20fb4e56ba9cdef13048db76947f1d79"},
+ {file = "psycopg2_binary-2.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:a36a0e791805aa136e9cbd0ffa040d09adec8610453ee8a753f23481a0057af5"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-macosx_10_15_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:25382c7d174c679ce6927c16b6fbb68b10e56ee44b1acb40671e02d29f2fce7c"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9c38d3869238e9d3409239bc05bc27d6b7c99c2a460ea337d2814b35fb4fea1b"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5c6527c8efa5226a9e787507652dd5ba97b62d29b53c371a85cd13f957fe4d42"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e59137cdb970249ae60be2a49774c6dfb015bd0403f05af1fe61862e9626642d"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:d4c7b3a31502184e856df1f7bbb2c3735a05a8ce0ade34c5277e1577738a5c91"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:b9a794cef1d9c1772b94a72eec6da144c18e18041d294a9ab47669bc77a80c1d"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5254cbd4f4855e11cebf678c1a848a3042d455a22a4ce61349c36aafd4c2267"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c5e65c6ac0ae4bf5bef1667029f81010b6017795dcb817ba5c7b8a8d61fab76f"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:74eddec4537ab1f701a1647214734bc52cee2794df748f6ae5908e00771f180a"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:01ad49d68dd8c5362e4bfb4158f2896dc6e0c02e87b8a3770fc003459f1a4425"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-win32.whl", hash = "sha256:937880290775033a743f4836aa253087b85e62784b63fd099ee725d567a48aa1"},
+ {file = "psycopg2_binary-2.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:484405b883630f3e74ed32041a87456c5e0e63a8e3429aa93e8714c366d62bd1"},
+]
+
+[[package]]
+name = "pycodestyle"
+version = "2.9.1"
+description = "Python style guide checker"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"},
+ {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"},
+]
+
+[[package]]
+name = "pycparser"
+version = "2.21"
+description = "C parser in Python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
+ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
+]
+
+[[package]]
+name = "pyee"
+version = "11.0.1"
+description = "A rough port of Node.js's EventEmitter to Python with a few tricks of its own"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pyee-11.0.1-py3-none-any.whl", hash = "sha256:9bcc9647822234f42c228d88de63d0f9ffa881e87a87f9d36ddf5211f6ac977d"},
+ {file = "pyee-11.0.1.tar.gz", hash = "sha256:a642c51e3885a33ead087286e35212783a4e9b8d6514a10a5db4e57ac57b2b29"},
+]
+
+[package.dependencies]
+typing-extensions = "*"
+
+[package.extras]
+dev = ["black", "flake8", "flake8-black", "isort", "jupyter-console", "mkdocs", "mkdocs-include-markdown-plugin", "mkdocstrings[python]", "pytest", "pytest-asyncio", "pytest-trio", "toml", "tox", "trio", "trio", "trio-typing", "twine", "twisted", "validate-pyproject[all]"]
+
+[[package]]
+name = "pyflakes"
+version = "2.5.0"
+description = "passive checker of Python programs"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"},
+ {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"},
+]
+
+[[package]]
+name = "pygments"
+version = "2.14.0"
+description = "Pygments is a syntax highlighting package written in Python."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"},
+ {file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"},
+]
+
+[package.extras]
+plugins = ["importlib-metadata"]
+
+[[package]]
+name = "pymarker"
+version = "0.3.2"
+description = "A python package to generate AR markers and patterns based on input images"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "pymarker-0.3.2-py3-none-any.whl", hash = "sha256:2bb82f8db6340b78e636ea7e38e5ad0d8857259c1eeca7f51da9e7a7fb03179f"},
+ {file = "pymarker-0.3.2.tar.gz", hash = "sha256:750f236dfeb718a163a6b5a03665f75a55e7f4b4e1f5547433e97ddad72743f4"},
+]
+
+[package.dependencies]
+click = ">=7.1.1"
+pillow = ">=7.1.0"
+
+[[package]]
+name = "pytest"
+version = "7.2.1"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-7.2.1-py3-none-any.whl", hash = "sha256:c7c6ca206e93355074ae32f7403e8ea12163b1163c976fee7d4d84027c162be5"},
+ {file = "pytest-7.2.1.tar.gz", hash = "sha256:d45e0952f3727241918b8fd0f376f5ff6b301cc0777c6f9a556935c92d8a7d42"},
+]
+
+[package.dependencies]
+attrs = ">=19.2.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+
+[[package]]
+name = "pytest-base-url"
+version = "2.1.0"
+description = "pytest plugin for URL based testing"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest_base_url-2.1.0-py3-none-any.whl", hash = "sha256:3ad15611778764d451927b2a53240c1a7a591b521ea44cebfe45849d2d2812e6"},
+ {file = "pytest_base_url-2.1.0.tar.gz", hash = "sha256:02748589a54f9e63fcbe62301d6b0496da0d10231b753e950c63e03aee745d45"},
+]
+
+[package.dependencies]
+pytest = ">=7.0.0"
+requests = ">=2.9"
+
+[package.extras]
+test = ["black (>=22.1.0)", "flake8 (>=4.0.1)", "pre-commit (>=2.17.0)", "pytest-localserver (>=0.7.1)", "tox (>=3.24.5)"]
+
+[[package]]
+name = "pytest-django"
+version = "4.5.2"
+description = "A Django plugin for pytest."
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "pytest-django-4.5.2.tar.gz", hash = "sha256:d9076f759bb7c36939dbdd5ae6633c18edfc2902d1a69fdbefd2426b970ce6c2"},
+ {file = "pytest_django-4.5.2-py3-none-any.whl", hash = "sha256:c60834861933773109334fe5a53e83d1ef4828f2203a1d6a0fa9972f4f75ab3e"},
+]
+
+[package.dependencies]
+pytest = ">=5.4.0"
+
+[package.extras]
+docs = ["sphinx", "sphinx-rtd-theme"]
+testing = ["Django", "django-configurations (>=2.0)"]
+
+[[package]]
+name = "pytest-playwright"
+version = "0.4.4"
+description = "A pytest wrapper with fixtures for Playwright to automate web browsers"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest-playwright-0.4.4.tar.gz", hash = "sha256:5488db4cc49028491c5130af0a2bb6b1d0b222a202217f6d14491d4c9aa67ff9"},
+ {file = "pytest_playwright-0.4.4-py3-none-any.whl", hash = "sha256:df306f3a60a8631a3cfde1b95a2ed5a89203a3408dfa1154de049ca7de87c90b"},
+]
+
+[package.dependencies]
+playwright = ">=1.18"
+pytest = ">=6.2.4,<9.0.0"
+pytest-base-url = ">=1.0.0,<3.0.0"
+python-slugify = ">=6.0.0,<9.0.0"
+
+[[package]]
+name = "pytest-xdist"
+version = "3.1.0"
+description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-xdist-3.1.0.tar.gz", hash = "sha256:40fdb8f3544921c5dfcd486ac080ce22870e71d82ced6d2e78fa97c2addd480c"},
+ {file = "pytest_xdist-3.1.0-py3-none-any.whl", hash = "sha256:70a76f191d8a1d2d6be69fc440cdf85f3e4c03c08b520fd5dc5d338d6cf07d89"},
+]
+
+[package.dependencies]
+execnet = ">=1.1"
+pytest = ">=6.2.0"
+
+[package.extras]
+psutil = ["psutil (>=3.0)"]
+setproctitle = ["setproctitle"]
+testing = ["filelock"]
+
+[[package]]
+name = "python-dateutil"
+version = "2.8.2"
+description = "Extensions to the standard Python datetime module"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+files = [
+ {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
+ {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
+]
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+name = "python-slugify"
+version = "8.0.4"
+description = "A Python slugify application that also handles Unicode"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"},
+ {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"},
+]
+
+[package.dependencies]
+text-unidecode = ">=1.3"
+
+[package.extras]
+unidecode = ["Unidecode (>=1.1.1)"]
+
+[[package]]
+name = "pytz"
+version = "2022.7.1"
+description = "World timezone definitions, modern and historical"
+optional = false
+python-versions = "*"
+files = [
+ {file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"},
+ {file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"},
+]
+
+[[package]]
+name = "requests"
+version = "2.28.2"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.7, <4"
+files = [
+ {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"},
+ {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset-normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<1.27"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "s3transfer"
+version = "0.6.0"
+description = "An Amazon S3 Transfer Manager"
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"},
+ {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"},
+]
+
+[package.dependencies]
+botocore = ">=1.12.36,<2.0a.0"
+
+[package.extras]
+crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"]
+
+[[package]]
+name = "sentry-sdk"
+version = "1.14.0"
+description = "Python client for Sentry (https://sentry.io)"
+optional = false
+python-versions = "*"
+files = [
+ {file = "sentry-sdk-1.14.0.tar.gz", hash = "sha256:273fe05adf052b40fd19f6d4b9a5556316807246bd817e5e3482930730726bb0"},
+ {file = "sentry_sdk-1.14.0-py2.py3-none-any.whl", hash = "sha256:72c00322217d813cf493fe76590b23a757e063ff62fec59299f4af7201dd4448"},
+]
+
+[package.dependencies]
+certifi = "*"
+urllib3 = {version = ">=1.26.11", markers = "python_version >= \"3.6\""}
+
+[package.extras]
+aiohttp = ["aiohttp (>=3.5)"]
+beam = ["apache-beam (>=2.12)"]
+bottle = ["bottle (>=0.12.13)"]
+celery = ["celery (>=3)"]
+chalice = ["chalice (>=1.16.0)"]
+django = ["django (>=1.8)"]
+falcon = ["falcon (>=1.4)"]
+fastapi = ["fastapi (>=0.79.0)"]
+flask = ["blinker (>=1.1)", "flask (>=0.11)"]
+httpx = ["httpx (>=0.16.0)"]
+opentelemetry = ["opentelemetry-distro (>=0.35b0)"]
+pure-eval = ["asttokens", "executing", "pure-eval"]
+pymongo = ["pymongo (>=3.1)"]
+pyspark = ["pyspark (>=2.4.4)"]
+quart = ["blinker (>=1.1)", "quart (>=0.16.1)"]
+rq = ["rq (>=0.6)"]
+sanic = ["sanic (>=0.8)"]
+sqlalchemy = ["sqlalchemy (>=1.2)"]
+starlette = ["starlette (>=0.19.1)"]
+starlite = ["starlite (>=1.48)"]
+tornado = ["tornado (>=5)"]
+
+[[package]]
+name = "setuptools"
+version = "67.0.0"
+description = "Easily download, build, install, upgrade, and uninstall Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "setuptools-67.0.0-py3-none-any.whl", hash = "sha256:9d790961ba6219e9ff7d9557622d2fe136816a264dd01d5997cfc057d804853d"},
+ {file = "setuptools-67.0.0.tar.gz", hash = "sha256:883131c5b6efa70b9101c7ef30b2b7b780a4283d5fc1616383cdf22c83cbefe6"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
+
+[[package]]
+name = "sidekick"
+version = "0.5.2"
+description = "The companion that gives you functional superpowers"
+optional = false
+python-versions = "*"
+files = [
+ {file = "sidekick-0.5.2.tar.gz", hash = "sha256:3f1b2c65f2d9cadc4ad06ba57010d7aae0ef3eeff92a94ac3aadb9863b692a6a"},
+]
+
+[package.dependencies]
+toolz = ">=0.9,<1.0"
+
+[package.extras]
+dev = ["flake8 (>=3.7,<4.0)", "invoke (>=1.0)", "manuel (>=1.10,<2.0)", "pytest (>=4.2,<5.0)", "pytest-cov (>=2.6,<3.0)"]
+docs = ["sphinx"]
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
+
+[[package]]
+name = "snowballstemmer"
+version = "2.2.0"
+description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
+optional = false
+python-versions = "*"
+files = [
+ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
+ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
+]
+
+[[package]]
+name = "sphinx"
+version = "5.3.0"
+description = "Python documentation generator"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"},
+ {file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"},
+]
+
+[package.dependencies]
+alabaster = ">=0.7,<0.8"
+babel = ">=2.9"
+colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
+docutils = ">=0.14,<0.20"
+imagesize = ">=1.3"
+Jinja2 = ">=3.0"
+packaging = ">=21.0"
+Pygments = ">=2.12"
+requests = ">=2.5.0"
+snowballstemmer = ">=2.0"
+sphinxcontrib-applehelp = "*"
+sphinxcontrib-devhelp = "*"
+sphinxcontrib-htmlhelp = ">=2.0.0"
+sphinxcontrib-jsmath = "*"
+sphinxcontrib-qthelp = "*"
+sphinxcontrib-serializinghtml = ">=1.1.5"
+
+[package.extras]
+docs = ["sphinxcontrib-websupport"]
+lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"]
+test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"]
+
+[[package]]
+name = "sphinxcontrib-applehelp"
+version = "1.0.4"
+description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"},
+ {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"},
+]
+
+[package.extras]
+lint = ["docutils-stubs", "flake8", "mypy"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-devhelp"
+version = "1.0.2"
+description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document."
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"},
+ {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"},
+]
+
+[package.extras]
+lint = ["docutils-stubs", "flake8", "mypy"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-htmlhelp"
+version = "2.0.1"
+description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"},
+ {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"},
+]
+
+[package.extras]
+lint = ["docutils-stubs", "flake8", "mypy"]
+test = ["html5lib", "pytest"]
+
+[[package]]
+name = "sphinxcontrib-jsmath"
+version = "1.0.1"
+description = "A sphinx extension which renders display math in HTML via JavaScript"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"},
+ {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"},
+]
+
+[package.extras]
+test = ["flake8", "mypy", "pytest"]
+
+[[package]]
+name = "sphinxcontrib-qthelp"
+version = "1.0.3"
+description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document."
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"},
+ {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"},
+]
+
+[package.extras]
+lint = ["docutils-stubs", "flake8", "mypy"]
+test = ["pytest"]
+
+[[package]]
+name = "sphinxcontrib-serializinghtml"
+version = "1.1.5"
+description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"},
+ {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"},
+]
+
+[package.extras]
+lint = ["docutils-stubs", "flake8", "mypy"]
+test = ["pytest"]
+
+[[package]]
+name = "sqlparse"
+version = "0.4.4"
+description = "A non-validating SQL parser."
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"},
+ {file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"},
+]
+
+[package.extras]
+dev = ["build", "flake8"]
+doc = ["sphinx"]
+test = ["pytest", "pytest-cov"]
+
+[[package]]
+name = "text-unidecode"
+version = "1.3"
+description = "The most basic Text::Unidecode port"
+optional = false
+python-versions = "*"
+files = [
+ {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"},
+ {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"},
+]
+
+[[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 = "toolz"
+version = "0.12.0"
+description = "List processing tools and functional utilities"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "toolz-0.12.0-py3-none-any.whl", hash = "sha256:2059bd4148deb1884bb0eb770a3cde70e7f954cfbbdc2285f1f2de01fd21eb6f"},
+ {file = "toolz-0.12.0.tar.gz", hash = "sha256:88c570861c440ee3f2f6037c4654613228ff40c93a6c25e0eba70d17282c6194"},
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.9.0"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"},
+ {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"},
+]
+
+[[package]]
+name = "tzdata"
+version = "2022.7"
+description = "Provider of IANA time zone data"
+optional = false
+python-versions = ">=2"
+files = [
+ {file = "tzdata-2022.7-py2.py3-none-any.whl", hash = "sha256:2b88858b0e3120792a3c0635c23daf36a7d7eeeca657c323da299d2094402a0d"},
+ {file = "tzdata-2022.7.tar.gz", hash = "sha256:fe5f866eddd8b96e9fcba978f8e503c909b19ea7efda11e52e39494bad3a7bfa"},
+]
+
+[[package]]
+name = "urllib3"
+version = "1.26.14"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+files = [
+ {file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"},
+ {file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
+secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+
+[[package]]
+name = "zope-event"
+version = "4.6"
+description = "Very basic event publishing system"
+optional = false
+python-versions = "*"
+files = [
+ {file = "zope.event-4.6-py2.py3-none-any.whl", hash = "sha256:73d9e3ef750cca14816a9c322c7250b0d7c9dbc337df5d1b807ff8d3d0b9e97c"},
+ {file = "zope.event-4.6.tar.gz", hash = "sha256:81d98813046fc86cc4136e3698fee628a3282f9c320db18658c21749235fce80"},
+]
+
+[package.dependencies]
+setuptools = "*"
+
+[package.extras]
+docs = ["Sphinx"]
+test = ["zope.testrunner"]
+
+[[package]]
+name = "zope-interface"
+version = "5.5.2"
+description = "Interfaces for Python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "zope.interface-5.5.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:a2ad597c8c9e038a5912ac3cf166f82926feff2f6e0dabdab956768de0a258f5"},
+ {file = "zope.interface-5.5.2-cp27-cp27m-win_amd64.whl", hash = "sha256:65c3c06afee96c654e590e046c4a24559e65b0a87dbff256cd4bd6f77e1a33f9"},
+ {file = "zope.interface-5.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d514c269d1f9f5cd05ddfed15298d6c418129f3f064765295659798349c43e6f"},
+ {file = "zope.interface-5.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5334e2ef60d3d9439c08baedaf8b84dc9bb9522d0dacbc10572ef5609ef8db6d"},
+ {file = "zope.interface-5.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc26c8d44472e035d59d6f1177eb712888447f5799743da9c398b0339ed90b1b"},
+ {file = "zope.interface-5.5.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:17ebf6e0b1d07ed009738016abf0d0a0f80388e009d0ac6e0ead26fc162b3b9c"},
+ {file = "zope.interface-5.5.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f98d4bd7bbb15ca701d19b93263cc5edfd480c3475d163f137385f49e5b3a3a7"},
+ {file = "zope.interface-5.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:696f3d5493eae7359887da55c2afa05acc3db5fc625c49529e84bd9992313296"},
+ {file = "zope.interface-5.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7579960be23d1fddecb53898035a0d112ac858c3554018ce615cefc03024e46d"},
+ {file = "zope.interface-5.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:765d703096ca47aa5d93044bf701b00bbce4d903a95b41fff7c3796e747b1f1d"},
+ {file = "zope.interface-5.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e945de62917acbf853ab968d8916290548df18dd62c739d862f359ecd25842a6"},
+ {file = "zope.interface-5.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:655796a906fa3ca67273011c9805c1e1baa047781fca80feeb710328cdbed87f"},
+ {file = "zope.interface-5.5.2-cp35-cp35m-win_amd64.whl", hash = "sha256:0fb497c6b088818e3395e302e426850f8236d8d9f4ef5b2836feae812a8f699c"},
+ {file = "zope.interface-5.5.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:008b0b65c05993bb08912f644d140530e775cf1c62a072bf9340c2249e613c32"},
+ {file = "zope.interface-5.5.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:404d1e284eda9e233c90128697c71acffd55e183d70628aa0bbb0e7a3084ed8b"},
+ {file = "zope.interface-5.5.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3218ab1a7748327e08ef83cca63eea7cf20ea7e2ebcb2522072896e5e2fceedf"},
+ {file = "zope.interface-5.5.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d169ccd0756c15bbb2f1acc012f5aab279dffc334d733ca0d9362c5beaebe88e"},
+ {file = "zope.interface-5.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:e1574980b48c8c74f83578d1e77e701f8439a5d93f36a5a0af31337467c08fcf"},
+ {file = "zope.interface-5.5.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:0217a9615531c83aeedb12e126611b1b1a3175013bbafe57c702ce40000eb9a0"},
+ {file = "zope.interface-5.5.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:311196634bb9333aa06f00fc94f59d3a9fddd2305c2c425d86e406ddc6f2260d"},
+ {file = "zope.interface-5.5.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6373d7eb813a143cb7795d3e42bd8ed857c82a90571567e681e1b3841a390d16"},
+ {file = "zope.interface-5.5.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:959697ef2757406bff71467a09d940ca364e724c534efbf3786e86eee8591452"},
+ {file = "zope.interface-5.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:dbaeb9cf0ea0b3bc4b36fae54a016933d64c6d52a94810a63c00f440ecb37dd7"},
+ {file = "zope.interface-5.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:604cdba8f1983d0ab78edc29aa71c8df0ada06fb147cea436dc37093a0100a4e"},
+ {file = "zope.interface-5.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e74a578172525c20d7223eac5f8ad187f10940dac06e40113d62f14f3adb1e8f"},
+ {file = "zope.interface-5.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0980d44b8aded808bec5059018d64692f0127f10510eca71f2f0ace8fb11188"},
+ {file = "zope.interface-5.5.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6e972493cdfe4ad0411fd9abfab7d4d800a7317a93928217f1a5de2bb0f0d87a"},
+ {file = "zope.interface-5.5.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9d783213fab61832dbb10d385a319cb0e45451088abd45f95b5bb88ed0acca1a"},
+ {file = "zope.interface-5.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:a16025df73d24795a0bde05504911d306307c24a64187752685ff6ea23897cb0"},
+ {file = "zope.interface-5.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:40f4065745e2c2fa0dff0e7ccd7c166a8ac9748974f960cd39f63d2c19f9231f"},
+ {file = "zope.interface-5.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8a2ffadefd0e7206adc86e492ccc60395f7edb5680adedf17a7ee4205c530df4"},
+ {file = "zope.interface-5.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d692374b578360d36568dd05efb8a5a67ab6d1878c29c582e37ddba80e66c396"},
+ {file = "zope.interface-5.5.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4087e253bd3bbbc3e615ecd0b6dd03c4e6a1e46d152d3be6d2ad08fbad742dcc"},
+ {file = "zope.interface-5.5.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fb68d212efd057596dee9e6582daded9f8ef776538afdf5feceb3059df2d2e7b"},
+ {file = "zope.interface-5.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:7e66f60b0067a10dd289b29dceabd3d0e6d68be1504fc9d0bc209cf07f56d189"},
+ {file = "zope.interface-5.5.2.tar.gz", hash = "sha256:bfee1f3ff62143819499e348f5b8a7f3aa0259f9aca5e0ddae7391d059dce671"},
+]
+
+[package.dependencies]
+setuptools = "*"
+
+[package.extras]
+docs = ["Sphinx", "repoze.sphinx.autointerface"]
+test = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
+testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.10"
+content-hash = "84bba7d5ee3576bad6107eb6dd0cbdf63b28e7ca290353eca27a4a1798a38043"
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 00000000..15fde249
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,64 @@
+[tool.poetry]
+name = "Jandig"
+version = "2.0.0"
+description = ""
+authors = ["Your Name "]
+
+[tool.poetry.dependencies]
+python = "^3.10"
+MarkupSafe = "^2.1.1"
+Django = "^4.0.8"
+Jinja2 = "^3.1.2"
+gunicorn = "^20.1.0"
+Pillow = "^9.2.0"
+django-cors-headers = "^3.13.0"
+invoke = "^1.7.1"
+django-environ = "^0.9.0"
+psycopg2-binary = "^2.9.3"
+django-boogie = "^0.13.3"
+Sphinx = "^5.0.2"
+Babel = "^2.10.3"
+django-debug-toolbar = "^3.5.0"
+gevent = "^23.9.1"
+pymarker = "^0.3.1"
+django-extensions = "^3.1.5"
+factory-boy = "^3.2.1"
+boto3 = "^1.24.27"
+django-storages = "^1.12.3"
+sentry-sdk = "^1.7.0"
+djangorestframework = "^3.13.1"
+drf-nested-routers = "^0.93.4"
+django-htmx = "^1.18.0"
+
+[tool.poetry.dev-dependencies]
+playwright = "^1.41.2"
+pytest = "^7.2.0"
+pytest-xdist = "^3.0.2"
+flake8 = "^5.0.4"
+black = "^22.10.0"
+isort = "^5.10.1"
+pytest-django = "^4.5.2"
+dj-inmemorystorage = "^2.1.0"
+pytest-playwright = "^0.4.4"
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.pytest.ini_options]
+DJANGO_SETTINGS_MODULE = "config.test_settings"
+python_files = ["tests.py", "test_*.py", "*_tests.py"]
+pythonpath = "src"
+addopts="-n4"
+
+[tool.black]
+exclude = '''
+/(
+ \.git
+ | migrations
+)/
+'''
+[tool.isort]
+profile = "black"
+src_paths = ["src"]
+skip_glob = "*/migrations/*.py"
\ No newline at end of file
diff --git a/run.sh b/run.sh
index 3a953847..13bb0be0 100755
--- a/run.sh
+++ b/run.sh
@@ -1,3 +1,3 @@
#!/bin/bash
-pip list
-inv i18n --compile docs run -p -g
+poetry show
+poetry run inv collect db i18n --compile docs run -g
diff --git a/src/.envs/.example b/src/.envs/.example
deleted file mode 100644
index 1aef234d..00000000
--- a/src/.envs/.example
+++ /dev/null
@@ -1,29 +0,0 @@
-# Use this file to create a .env with filled variables
-# Django Variables
-DJANGO_DEBUG=True
-DJANGO_SETTINGS_MODULE=config.settings
-DJANGO_ADMIN_URL=admin/
-DEV_DB=False
-DEV_STATIC=False
-DEBUG_TOOLBAR=True
-DJANGO_SECRET_KEY=
-
-## Amazon AWS Variables
-AWS_ACCESS_KEY_ID=
-AWS_SECRET_ACCESS_KEY=
-AWS_STORAGE_BUCKET_NAME=
-AWS_S3_REGION_NAME=
-USE_S3=
-
-## Postgres variables
-POSTGRES_HOST=postgres
-POSTGRES_PORT=5432
-POSTGRES_DB=goldpenny
-POSTGRES_USER=goldpenny
-POSTGRES_PASSWORD=goldpenny123
-
-# Email server variables
-SMTP_SERVER=smtp.gmail.com
-SMTP_PORT=587
-JANDIG_EMAIL=local_jandig@memelab.com.br
-JANDIG_EMAIL_PASSWORD=local_password
\ No newline at end of file
diff --git a/src/ARte/config/settings.py b/src/ARte/config/settings.py
deleted file mode 100644
index d69e88a8..00000000
--- a/src/ARte/config/settings.py
+++ /dev/null
@@ -1,228 +0,0 @@
-import os
-import environ
-from .wait_db import start_services
-from django.utils.translation import ugettext_lazy as _
-
-from socket import gethostbyname, gethostname
-
-ROOT_DIR = environ.Path(__file__) - 2 # (ARte/config/settings.py - 2 = ARte/)
-APPS_DIR = ROOT_DIR.path('ARte')
-
-# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
-BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-env = environ.Env()
-
-READ_DOT_ENV_FILE = env.bool('DJANGO_READ_DOT_ENV_FILE', default=False)
-if READ_DOT_ENV_FILE:
- # OS environment variables take precedence over variables from .env
- env.read_env(str(ROOT_DIR.path('.env')))
-
-DEBUG = env.bool('DJANGO_DEBUG', False)
-
-
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = env('DJANGO_SECRET_KEY', default='gw)48fp(ct67v4+0_tpxl=$vw=-x&y9(&0n6!n4mpw5m!4gaor')
-
-ALLOWED_HOSTS = [
- "localhost",
- "0.0.0.0",
- "127.0.0.1",
- gethostname(),
- gethostbyname(gethostname()),
-]
-CUSTOM_ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS', default=['*'])
-ALLOWED_HOSTS += CUSTOM_ALLOWED_HOSTS
-print(f"ALLOWED_HOSTS:{ALLOWED_HOSTS}")
-# Application definition
-
-import sentry_sdk
-from sentry_sdk.integrations.django import DjangoIntegration
-
-sentry_sdk.init(
- dsn="https://081a2c3476b24a9f9a51d74bde539b62@o968990.ingest.sentry.io/5920229",
- integrations=[DjangoIntegration()],
-
- # Set traces_sample_rate to 1.0 to capture 100%
- # of transactions for performance monitoring.
- # We recommend adjusting this value in production.
- traces_sample_rate=1.0,
-
- # If you wish to associate users to errors (assuming you are using
- # django.contrib.auth) you may enable sending PII data.
- send_default_pii=True
-)
-
-INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'debug_toolbar',
- 'corsheaders',
- 'users',
- 'core',
- 'docs',
- #'django_extensions',
-]
-
-MIDDLEWARE = [
- 'debug_toolbar.middleware.DebugToolbarMiddleware',
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.locale.LocaleMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
-]
-DEBUG_TOOLBAR_CONFIG = {
- 'SHOW_TOOLBAR_CALLBACK': 'config.settings.debug'
-}
-
-def debug(request):
- return env.bool('DEBUG_TOOLBAR', False)
-
-## Let whitenoise serve static files -- DON'T USE IN PRODUCTION --
-if env.bool('DEV_STATIC', False):
- MIDDLEWARE.insert(1, 'whitenoise.middleware.WhiteNoiseMiddleware')
- STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
- print('\n ------- SERVING STATIC FILES USING WHITENOISE! -------\n')
-
-ROOT_URLCONF = 'config.urls'
-
-TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.jinja2.Jinja2',
- 'DIRS': [],
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'environment': 'config.jinja2.environment',
- },
- },
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [],
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- ],
- },
- },
-]
-
-WSGI_APPLICATION = 'config.wsgi.application'
-
-
-if env.bool('DEV_DB', False):
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
- }
- }
-else:
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.postgresql_psycopg2',
- 'HOST': env('POSTGRES_HOST'),
- 'NAME': env('POSTGRES_DB'),
- 'USER': env('POSTGRES_USER'),
- 'PASSWORD': env('POSTGRES_PASSWORD'),
- },
- }
-
- # STARTS SERVICES THAT DJANGO DEPENDS E.G. postgres
- start_services()
-
-
-AUTH_PASSWORD_VALIDATORS = [
- {
- 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
- },
-]
-
-
-# Internationalization
-# https://docs.djangoproject.com/en/2.1/topics/i18n/
-
-LOCALE_PATHS = (
- # os.path.join(str(ROOT_DIR), 'locale'),
- '/ARte/locale',
-)
-
-LANGUAGE_CODE = 'en'
-
-LANGUAGES = (
- ('en-us', _('English')),
- ('pt-br', _('Brazilian Portuguese')),
-)
-
-TIME_ZONE = 'UTC'
-
-USE_I18N = True
-
-USE_L10N = True
-
-USE_TZ = True
-
-
-# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/2.1/howto/static-files/
-
-COLLECT_DIR = os.path.dirname(os.path.dirname(BASE_DIR))
-USE_S3 = os.getenv("USE_S3", "False").lower() == "true"
-STATICFILES_DIRS = [
- os.path.join(BASE_DIR, 'core', 'static'),
- os.path.join(BASE_DIR, 'users', 'static')
-]
-if USE_S3:
- # AWS credentials
- AWS_S3_OBJECT_PARAMETERS = {
- "CacheControl": "max-age=86400",
- }
- AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID", "")
- AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY", "")
- AWS_STORAGE_BUCKET_NAME = os.getenv("AWS_STORAGE_BUCKET_NAME", "")
- AWS_S3_REGION_NAME = os.getenv("AWS_S3_REGION_NAME", "us-east-2")
- AWS_S3_CUSTOM_DOMAIN = f"{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com"
- AWS_DEFAULT_ACL = os.getenv("AWS_DEFAULT_ACL", None)
- AWS_STATIC_LOCATION = os.getenv("AWS_STATIC_LOCATION", "static")
-
- # Static configuration
- STATIC_URL = f"https://{AWS_S3_CUSTOM_DOMAIN}/{AWS_STATIC_LOCATION}/"
- STATICFILES_STORAGE = "config.storage_backends.StaticStorage"
-
- AWS_PUBLIC_MEDIA_LOCATION = "media/public"
- DEFAULT_FILE_STORAGE = "config.storage_backends.PublicMediaStorage"
-else:
- STATIC_URL = '/static/'
- STATIC_ROOT = os.path.join(COLLECT_DIR, 'collect')
-
-
-MEDIA_URL = '/media/'
-MEDIA_ROOT = os.path.join(BASE_DIR, 'users', 'media')
-
-# LOGIN / LOGOUT
-LOGIN_URL = 'login'
-LOGIN_REDIRECT_URL = 'home'
-LOGOUT_REDIRECT_URL = 'home'
-
-# Sphinx docs
-DOCS_ROOT = os.path.join(BASE_DIR, '../../build/')
\ No newline at end of file
diff --git a/src/ARte/config/urls.py b/src/ARte/config/urls.py
deleted file mode 100644
index 537d4e3c..00000000
--- a/src/ARte/config/urls.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from django.conf import settings
-from django.conf.urls.static import static
-from django.contrib import admin
-from django.urls import path, include
-import debug_toolbar
-import os
-
-urlpatterns = [
- path(os.getenv('DJANGO_ADMIN_URL', 'admin/'), admin.site.urls),
- path('', include('core.urls')),
- path('', include('core.routes')),
- path('users/', include('users.urls')),
- path('docs/', include('docs.urls'), name='docs'),
-]
-
-urlpatterns += [path('__debug__/', include(debug_toolbar.urls)),]
-
-urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
\ No newline at end of file
diff --git a/src/ARte/config/wait_db.py b/src/ARte/config/wait_db.py
deleted file mode 100644
index fd090b6e..00000000
--- a/src/ARte/config/wait_db.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import importlib
-import os
-import time
-
-import logging
-
-SERVICES_STARTED = False
-
-log = logging.getLogger('ej')
-
-
-def start_services():
- global SERVICES_STARTED
-
- if SERVICES_STARTED:
- return
-
- start_postgres()
-
- SERVICES_STARTED = True
-
-
-
-log = logging.getLogger('ej')
-
-
-def start_postgres():
- settings_path = os.environ['DJANGO_SETTINGS_MODULE']
- settings = importlib.import_module(settings_path)
-
- db = settings.DATABASES['default']
- dbname = db['NAME']
- user = db['USER']
- password = db['PASSWORD']
- host = db['HOST']
-
- for _ in range(100):
- if can_connect(dbname, user, password, host):
- log.info("Postgres is available. Continuing...")
- return
- log.warning('Postgres is unavailable. Retrying in 0.5 seconds')
- time.sleep(0.5)
-
- log.critical('Maximum number of attempts connecting to postgres database')
- raise RuntimeError('could not connect to database')
-
-
-def can_connect(dbname, user, password, host):
- import psycopg2
-
- try:
- psycopg2.connect(
- dbname=dbname,
- user=user,
- password=password,
- host=host
- )
- except psycopg2.OperationalError:
- return False
- return True
diff --git a/src/ARte/core/helpers.py b/src/ARte/core/helpers.py
deleted file mode 100644
index 2dea8181..00000000
--- a/src/ARte/core/helpers.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from django.contrib.staticfiles.templatetags.staticfiles import static
-
-def handle_upload_image(image):
- path = "core" + static(f"images/{image.name}")
- with open(path, 'wb+') as destination:
- for chunk in image.chunks():
- destination.write(chunk)
diff --git a/src/ARte/core/jinja2/core/collection.jinja2 b/src/ARte/core/jinja2/core/collection.jinja2
deleted file mode 100644
index 5d148f83..00000000
--- a/src/ARte/core/jinja2/core/collection.jinja2
+++ /dev/null
@@ -1,58 +0,0 @@
-{% extends '/core/home.jinja2' %}
-
-{% block content %}
- {% block subcontent %}
- {% endblock %}
-
-
-
- {# FIXME: maybe this can be improved #}
-
-
- {% if exhibits %}
-
- {% with repository_list = objects, element_type="object" %}
- {% include "users/components/item-list.jinja2" %}
- {% endwith%}
- {% if seeall == False %}
- {{_("All Objects")}}
- {% endif %}
- {% endif %}
-
- {% if not exhibits and not artworks and not markers and not objects %}
-
{{_("We found no content on your Collection, try uploading an object.")}}
- {% endif %}
- {% include "users/components/elements-modal.jinja2" %}
-
+{% endblock %}
\ No newline at end of file
diff --git a/src/blog/jinja2/blog/post_preview.jinja2 b/src/blog/jinja2/blog/post_preview.jinja2
new file mode 100644
index 00000000..5d0db089
--- /dev/null
+++ b/src/blog/jinja2/blog/post_preview.jinja2
@@ -0,0 +1,9 @@
+{% for post in posts %}
+
{{ _('Edit Jandig Artwork') if selected_marker else _('Create Jandig Artwork')}}
@@ -37,7 +37,7 @@
-
-
+
{{ _('Next') }}
@@ -72,119 +72,94 @@
{{ form.visible_fields()[7] }}
{{ form.visible_fields()[7].errors }}
-
+
{% endblock %}
\ No newline at end of file
diff --git a/src/ARte/users/jinja2/users/components/artworks-list.jinja2 b/src/users/jinja2/users/components/artworks-list.jinja2
similarity index 56%
rename from src/ARte/users/jinja2/users/components/artworks-list.jinja2
rename to src/users/jinja2/users/components/artworks-list.jinja2
index 35dcdfb4..594e0b1a 100644
--- a/src/ARte/users/jinja2/users/components/artworks-list.jinja2
+++ b/src/users/jinja2/users/components/artworks-list.jinja2
@@ -8,7 +8,6 @@
{% endblock %}
\ No newline at end of file
diff --git a/src/ARte/users/jinja2/users/components/createbox.jinja2 b/src/users/jinja2/users/components/createbox.jinja2
similarity index 100%
rename from src/ARte/users/jinja2/users/components/createbox.jinja2
rename to src/users/jinja2/users/components/createbox.jinja2
diff --git a/src/ARte/users/jinja2/users/components/elements-modal.jinja2 b/src/users/jinja2/users/components/elements-modal.jinja2
similarity index 93%
rename from src/ARte/users/jinja2/users/components/elements-modal.jinja2
rename to src/users/jinja2/users/components/elements-modal.jinja2
index 0d271352..d06d1d9e 100644
--- a/src/ARte/users/jinja2/users/components/elements-modal.jinja2
+++ b/src/users/jinja2/users/components/elements-modal.jinja2
@@ -7,15 +7,16 @@
{% endblock %}
{% block content %}
-
+
Download file:
+
+ {% if form_type == 'marker' and edit == False %}
+
{{ _('Upload Marker') }}
+ {% endif %}
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/users/jinja2/users/upload-object.jinja2 b/src/users/jinja2/users/upload-object.jinja2
new file mode 100644
index 00000000..a01fa45e
--- /dev/null
+++ b/src/users/jinja2/users/upload-object.jinja2
@@ -0,0 +1,184 @@
+
+{% extends '/core/home.jinja2' %}
+
+{% block content %}
+
+ {# FIXME: maybe this can be improved #}
+
+
+ {% if form_type == 'object' and edit == False %}
+
{{ _('Upload Object') }}
+ {% else %}
+
{{_('Edit_object')}}
+ {% endif %}
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/ARte/users/jinja2/users/upload.jinja2 b/src/users/jinja2/users/upload.jinja2
similarity index 91%
rename from src/ARte/users/jinja2/users/upload.jinja2
rename to src/users/jinja2/users/upload.jinja2
index 80756ebc..6899cd61 100644
--- a/src/ARte/users/jinja2/users/upload.jinja2
+++ b/src/users/jinja2/users/upload.jinja2
@@ -55,9 +55,9 @@