diff --git a/.circleci/config.yml b/.circleci/config.yml index 250ff65ec..9695095da 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,6 +38,9 @@ jobs: docker compose -f docker-compose.yml -f docker-compose.selenium.yml exec django python manage.py collectstatic --noinput - run: docker-compose exec django flake8 src/ + - run: docker pull codalab/codalab-legacy:py37 # not available without "not e2e" tests as they pull ahead of time + - run: docker pull codalab/codalab-legacy:py3 # not available without "not e2e" tests as they pull ahead of time + - run: docker pull vergilgxw/autotable:v2 # not available without "not e2e" tests as they pull ahead of time - run: name: pytest @@ -48,6 +51,13 @@ jobs: command: docker compose -f docker-compose.yml -f docker-compose.selenium.yml exec django py.test src/tests/functional/ -m e2e no_output_timeout: 60m + # Example to run specific set of tests (for debugging individual tests from a batch of tests) + # - run: + # name: e2e tests - competitions + # command: docker compose -f docker-compose.yml -f docker-compose.selenium.yml exec django py.test src/tests/functional/test_competitions.py -m e2e + # no_output_timeout: 60m + + - store_artifacts: path: artifacts/ diff --git a/.github/workflows/ghPages-dev.yml b/.github/workflows/ghPages-dev.yml new file mode 100644 index 000000000..9616e1fb5 --- /dev/null +++ b/.github/workflows/ghPages-dev.yml @@ -0,0 +1,25 @@ +name: github-pages-dev +on: + push: + branches: + - develop +permissions: + contents: write +jobs: + deploy-dev: + runs-on: ubuntu-latest + defaults: + run: + working-directory: documentation/ + steps: + - uses: actions/checkout@v4 + - name: Configure Git Credentials + run: | + git config user.name github-actions[bot] + git config user.email 41898282+github-actions[bot]@users.noreply.github.com + - uses: actions/setup-python@v5 + with: + python-version: 3.x + - run: curl -LsSf https://astral.sh/uv/install.sh | sh + - run: /home/runner/.local/bin/uv sync + - run: git fetch origin gh-pages --depth=1 && PDF=1 /home/runner/.local/bin/uv run mike deploy -u dev --push \ No newline at end of file diff --git a/.github/workflows/ghPages-prod.yml b/.github/workflows/ghPages-prod.yml new file mode 100644 index 000000000..b12be4cd6 --- /dev/null +++ b/.github/workflows/ghPages-prod.yml @@ -0,0 +1,25 @@ +name: github-pages-prod +on: + push: + tags: + - '*' +permissions: + contents: write +jobs: + deploy-prod: + runs-on: ubuntu-latest + defaults: + run: + working-directory: documentation/ + steps: + - uses: actions/checkout@v4 + - name: Configure Git Credentials + run: | + git config user.name github-actions[bot] + git config user.email 41898282+github-actions[bot]@users.noreply.github.com + - uses: actions/setup-python@v5 + with: + python-version: 3.x + - run: curl -LsSf https://astral.sh/uv/install.sh | sh + - run: /home/runner/.local/bin/uv sync + - run: git fetch origin gh-pages --depth=1 && PDF=1 /home/runner/.local/bin/uv run mike deploy -u ${{ github.ref_name }} latest --push \ No newline at end of file diff --git a/Dockerfile.compute_worker b/Dockerfile.compute_worker index 6e6b626bf..ca70672d3 100644 --- a/Dockerfile.compute_worker +++ b/Dockerfile.compute_worker @@ -1,13 +1,19 @@ -FROM --platform=linux/amd64 python:3.9 +FROM --platform=linux/amd64 fedora:42 # This makes output not buffer and return immediately, nice for seeing results in stdout ENV PYTHONUNBUFFERED 1 # Install Docker -RUN apt-get update && curl -fsSL https://get.docker.com | sh +RUN dnf -y install dnf-plugins-core && \ + dnf-3 config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo && \ + dnf -y update && \ + dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin && \ + dnf install -y python3.9 && \ + dnf clean all && \ + rm -rf /var/cache /var/log/dnf* /var/log/yum.* -RUN curl -sSL https://install.python-poetry.org | python3 - --version 1.8.3 +RUN curl -sSL https://install.python-poetry.org | python3.9 - --version 1.8.3 # Poetry location so future commands (below) work ENV PATH $PATH:/root/.local/bin # Want poetry to use system python of docker container @@ -15,7 +21,8 @@ RUN poetry config virtualenvs.create false RUN poetry config virtualenvs.in-project false COPY ./compute_worker/pyproject.toml ./ COPY ./compute_worker/poetry.lock ./ -RUN poetry install +# To use python3.9 instead of system python +RUN poetry config virtualenvs.prefer-active-python true && poetry install ADD compute_worker . diff --git a/Dockerfile.compute_worker_gpu b/Dockerfile.compute_worker_gpu index 6bf96f3c5..ba6d42680 100644 --- a/Dockerfile.compute_worker_gpu +++ b/Dockerfile.compute_worker_gpu @@ -1,38 +1,12 @@ -FROM --platform=linux/amd64 python:3.9 - -# This makes output not buffer and return immediately, nice for seeing results in stdout -ENV PYTHONUNBUFFERED 1 - -# Install Docker -RUN apt-get update && curl -fsSL https://get.docker.com | sh - - +FROM --platform=linux/amd64 codalab/competitions-v2-compute-worker:latest # Nvidia Container Toolkit for cuda use with docker # [source](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) -RUN curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ - && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ - sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ - tee /etc/apt/sources.list.d/nvidia-container-toolkit.list -RUN apt-get update -y; -RUN apt-get install -y nvidia-container-toolkit +# Include deps +RUN dnf -y config-manager addrepo --from-repofile=https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo && \ + dnf -y update && \ + dnf -y install nvidia-container-runtime nvidia-container-toolkit --exclude container-selinux && \ + dnf clean all && \ + rm -rf /var/cache /var/log/dnf* /var/log/yum.* # Make it explicit that we're using GPUs # BB - not convinced we need this ENV USE_GPU 1 - -RUN curl -sSL https://install.python-poetry.org | python3 - --version 1.8.3 -# Poetry location so future commands (below) work -ENV PATH $PATH:/root/.local/bin -# Want poetry to use system python of docker container -RUN poetry config virtualenvs.create false -RUN poetry config virtualenvs.in-project false -COPY ./compute_worker/pyproject.toml ./ -COPY ./compute_worker/poetry.lock ./ -RUN poetry install - -ADD compute_worker . - -CMD celery -A compute_worker worker \ - -l info \ - -Q compute-worker \ - -n compute-worker@%n \ - --concurrency=1 diff --git a/compute_worker/compute_worker.py b/compute_worker/compute_worker.py index 85a2cbe06..364714d6b 100644 --- a/compute_worker/compute_worker.py +++ b/compute_worker/compute_worker.py @@ -302,7 +302,9 @@ def get_detailed_results_file_path(self): async def send_detailed_results(self, file_path): logger.info(f"Updating detailed results {file_path} - {self.detailed_results_url}") self._put_file(self.detailed_results_url, file=file_path, content_type='text/html') - async with websockets.connect(self.websocket_url) as websocket: + websocket_url = f"{self.websocket_url}?kind=detailed_results" + logger.info(f"Connecting to {websocket_url} for detailed results") + async with websockets.connect(websocket_url) as websocket: await websocket.send(json.dumps({ "kind": 'detailed_result_update', })) @@ -390,10 +392,14 @@ async def _send_data_through_socket(self, error_message): - Docker image pull failure logs - Execution time limit exceeded logs """ - logger.info(f"Connecting to {self.websocket_url} to send docker image pull error") + # Create a unique websocket URL for error messages + websocket_url = f"{self.websocket_url}?kind=error_logs" + logger.info(f"Connecting to {websocket_url} to send error message") + + logger.info(f"Connecting to {websocket_url} to send docker image pull error") # connect to web socket - websocket = await websockets.connect(self.websocket_url) + websocket = await websockets.connect(websocket_url) # define websocket errors websocket_errors = (socket.gaierror, websockets.WebSocketException, websockets.ConnectionClosedError, ConnectionRefusedError) @@ -416,7 +422,7 @@ async def _send_data_through_socket(self, error_message): # no error in websocket message sending logger.info(f"Error sent successfully through websocket") - logger.info(f"Disconnecting from websocket {self.websocket_url}") + logger.info(f"Disconnecting from websocket {websocket_url}") # close websocket await websocket.close() @@ -500,8 +506,11 @@ async def _run_container_engine_cmd(self, engine_cmd, kind): } # Start websocket, it will reconnect in the stdout/stderr listener loop below - logger.info(f"Connecting to {self.websocket_url}") - websocket = await websockets.connect(self.websocket_url) + # This ensures each task has its own independent WebSocket connection + websocket_url = f"{self.websocket_url}?kind={kind}" + logger.debug(f"WORKER_MARKER: Connecting to {websocket_url}") + websocket = await websockets.connect(websocket_url) + # websocket = await websockets.connect(self.websocket_url) # old BB websocket_errors = (socket.gaierror, websockets.WebSocketException, websockets.ConnectionClosedError, ConnectionRefusedError) # Function to read a line, if the line is larger than the buffer size we will @@ -522,7 +531,7 @@ async def _readline_or_chunk(stream): logs = [self.logs[kind][key] for key in ('stdout', 'stderr')] for value in logs: try: - out = await asyncio.wait_for(_readline_or_chunk(value["stream"]), timeout=.1) + out = await asyncio.wait_for(_readline_or_chunk(value["stream"]), timeout=0.1) if out: value["data"] += out print("WS: " + str(out)) @@ -535,12 +544,12 @@ async def _readline_or_chunk(stream): except asyncio.TimeoutError: continue except websocket_errors: + logger.debug("\n\nWebsocket error (line 538)\n\n") try: # do we need to await websocket.close() on the old socket? before making a new one probably not? await websocket.close() except Exception as e: logger.error(e) - logger.info(e) # TODO: catch proper exceptions here..! What can go wrong failing to close? pass @@ -548,19 +557,23 @@ async def _readline_or_chunk(stream): tries = 0 while tries < 3 and not websocket.open: try: - websocket = await websockets.connect(self.websocket_url) + logger.debug(f"\n\nAttempting to reconnect in 2 seconds (attempt {tries+1}/3)") + websocket = await websockets.connect(websocket_url) + logger.debug(f"\n\nSuccessfully reconnected to {websocket_url}") except websocket_errors: + logger.error(f"\n\nReconnection attempt {tries+1} failed: {websocket_errors}") await asyncio.sleep(2) tries += 1 self.logs[kind]["end"] = time.time() - logger.info(f"Process exited with {proc.returncode}") - logger.info(f"Disconnecting from websocket {self.websocket_url}") + logger.debug(f"Process exited with {proc.returncode}") + logger.debug(f"Disconnecting from websocket {websocket_url}") # Communicate that the program is closing self.completed_program_counter += 1 + logger.debug(f"WORKER_MARKER: Disconnecting from {websocket_url}, program counter = {self.completed_program_counter}") await websocket.close() def _get_host_path(self, *paths): @@ -609,6 +622,9 @@ async def _run_program_directory(self, program_dir, kind): logger.info( "Program directory missing metadata, assuming it's going to be handled by ingestion" ) + # Copy submission files into prediction output + # This is useful for results submissions but wrongly uses storage + shutil.copytree(program_dir, self.output_dir) return else: raise SubmissionException("Program directory missing 'metadata.yaml/metadata'") diff --git a/docker-compose.selenium.yml b/docker-compose.selenium.yml index 450f2c3e4..d1c62894d 100644 --- a/docker-compose.selenium.yml +++ b/docker-compose.selenium.yml @@ -4,11 +4,12 @@ services: environment: - SELENIUM_HOSTNAME=selenium - SUBMISSIONS_API_URL=http://django:36475/api + - WEBSOCKET_ALLOWED_ORIGINS=* ports: - 36475:36475 selenium: - image: selenium/standalone-firefox:124.0 + image: selenium/standalone-firefox:120.0 volumes: - ./src/tests/functional/test_files:/test_files/ - ./artifacts:/artifacts/:z diff --git a/docker-compose.yml b/docker-compose.yml index 09165a9d9..2d1c05001 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -53,7 +53,7 @@ services: # Minio local storage helper #----------------------------------------------- minio: - image: minio/minio:RELEASE.2020-10-03T02-19-42Z + image: minio/minio:RELEASE.2025-04-22T22-12-26Z command: server /export volumes: - ./var/minio:/export @@ -62,11 +62,11 @@ services: - $MINIO_PORT:9000 env_file: .env healthcheck: - test: ["CMD", "nc", "-z", "minio", "9000"] + test: ["CMD", "curl", "-I", "http://minio:9000/minio/health/live"] interval: 5s retries: 5 createbuckets: - image: minio/mc + image: minio/mc:RELEASE.2025-07-21T05-28-08Z depends_on: minio: condition: service_healthy @@ -78,7 +78,7 @@ services: /bin/sh -c " set -x; if [ -n \"$MINIO_ACCESS_KEY\" ] && [ -n \"$MINIO_SECRET_KEY\" ] && [ -n \"$MINIO_PORT\" ]; then - until /usr/bin/mc config host add minio_docker http://minio:$MINIO_PORT $MINIO_ACCESS_KEY $MINIO_SECRET_KEY && break; do + until /usr/bin/mc alias set minio_docker http://minio:$MINIO_PORT $MINIO_ACCESS_KEY $MINIO_SECRET_KEY && break; do echo '...waiting...' && sleep 5; done; /usr/bin/mc mb minio_docker/$AWS_STORAGE_BUCKET_NAME || echo 'Bucket $AWS_STORAGE_BUCKET_NAME already exists.'; diff --git a/documentation/.gitignore b/documentation/.gitignore new file mode 100644 index 000000000..af3887b1b --- /dev/null +++ b/documentation/.gitignore @@ -0,0 +1,14 @@ +# Python-generated files +__pycache__/ +*.py[oc] +build/ +dist/ +wheels/ +*.egg-info +.cache/ +# Virtual environments +.venv + +uv.lock + +site/* diff --git a/documentation/.python-version b/documentation/.python-version new file mode 100644 index 000000000..e4fba2183 --- /dev/null +++ b/documentation/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/documentation/README.md b/documentation/README.md new file mode 100644 index 000000000..efd3cdad7 --- /dev/null +++ b/documentation/README.md @@ -0,0 +1,39 @@ +## Codabench Documentation +Welcome to the Codabench Documentation. + +You can access the documentation generated from this folder [here](https://codalab.org/codabench/latest/) + +If you want to contribute to the wiki, you can create a Pull Request modifying the files you want (located in `docs/`) while adding a quick explanation on what you have changed and why. + + +When creating a Pull Request to modify the core code of Codabench, you can also include the wiki modification by modifying the relevant files. Once the Pull Request is merged, the wiki will automatically be updated with your changes (`dev` tag when it's merged into develop, and the `latest` version of the wiki once it's merged in master) + +## How to build +To build the wiki locally, you will have to first install [uv](https://github.com/astral-sh/uv) + +Once that is done, you can run the following commands (while inside this folder): + +```bash +uv sync # You only need to run this once, it will download all the necessary python packages +PDF=1 uv run mkdocs serve -a localhost:8888 # This will build the site and serve it on localhost:8888 +``` + +Open [localhost:8888](http://localhost:8888/) in your browser and you will see the wiki. Every changes you make will rebuild the documentation. +You can remove the `PDF=1` environement variable if you want to speed up the build process, but you will not generate the related PDF. + + +### Versioning +We use the [mike](https://github.com/jimporter/mike) plugin to preserve multiple version of the wiki. + +To use it, you can run the following command: +```bash +PDF=1 uv run mike deploy -u dev # This will create the site and push the changes in the gh-pages branch +uv run mike serve -a localhost:8888 # Serve the site on localhost:8888 +``` +Check the official Github page of the plugin for more information on how it works. + +## Images and Assets +Images and assets are saved in the `_attachments` folder closest to the documentation file that calls for the image. If an image is used in multiple different places, then it should be put in `_attachements` folder in the `docs/` root directory. + +## Github workflow +We have Github workflows set up to automatically rebuild the wiki when the `develop` branch receives changes, and when a new tag is created for the `master` branch. \ No newline at end of file diff --git a/documentation/assets/favicon.ico b/documentation/assets/favicon.ico new file mode 100644 index 000000000..434eb01de Binary files /dev/null and b/documentation/assets/favicon.ico differ diff --git a/documentation/docs/Contribute/contributing.md b/documentation/docs/Contribute/contributing.md new file mode 100644 index 000000000..d88ed4695 --- /dev/null +++ b/documentation/docs/Contribute/contributing.md @@ -0,0 +1,21 @@ +## Being a Codabench user + +- Create a user account on [Codabench](https://codabench.org) +- Register on [Codabench](https://codabench.org) to this existing competition [IRIS-tuto](https://www.codabench.org/competitions/1115/) and make a submission (you can find the necessary files [here](https://github.com/codalab/competition-examples/tree/master/codabench/iris)): `sample_result_submission` and `sample_code_submission`. See [this page](../Participants/User_Participating-in-a-Competition.md) for more information. +- Create your own private competition (you can find the necessary files [here](https://github.com/codalab/competition-examples/tree/master/codabench/) ). See [this page](../Organizers/Benchmark_Creation/Getting-started-with-Codabench.md) for more information. + +## Setting up a local instance of Codabench + +- Follow the tutorial in codabench [wiki](../Developers_and_Administrators/Codabench-Installation.md). According to your hosting OS, you might have to tune your environment file a bit. Try without enabling the SSL protocol (doing so, you don't need a domain name for the server). Try using the embedded Minio storage solution instead of a private cloud storage. +- If needed, you can also look into [How to deploy Codabench on your server](../Developers_and_Administrators/How-to-deploy-Codabench-on-your-server.md) + +### Using your local instance + +- Create your own competition and play with it. You can look at the output logs of each different docker container. +- Setting you as an [admin](../Developers_and_Administrators/Administrator-procedures.md#give-superuser-privileges-to-a-user) of your platform and visit the Django Admin menu. + +## Setting up an autonomous Compute Worker on a machine + +- Configure and launch a [compute worker](../Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md) docker container. +- Create a private [Queue](../Organizers/Running_a_benchmark/Queue-Management.md#create-queue) on your new own competition on the production server codabench.org +- Assign your own compute-worker to this private queue instead of the default queue. diff --git a/documentation/docs/Contribute/index.md b/documentation/docs/Contribute/index.md new file mode 100644 index 000000000..24cf6ee3a --- /dev/null +++ b/documentation/docs/Contribute/index.md @@ -0,0 +1,6 @@ +- Use [Codabench](https://codabench.org/) by either participating in a competition or hosting a new competition. +- Find a bug? Got a feature request? Submit a [GitHub issue](https://github.com/codalab/codalab/issues?state=open). +- [P1 issues](https://github.com/codalab/codabench/issues?q=is%3Aissue+is%3Aopen+label%3AP1) are the most important ones. +- Submit pull requests on GitHub to implement new features or fix bugs (see [the contributing section](contributing.md)). +- Improve this documentation. +- Let others know about Codabench! \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Administrator-procedures.md b/documentation/docs/Developers_and_Administrators/Administrator-procedures.md new file mode 100644 index 000000000..a8b0c1083 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Administrator-procedures.md @@ -0,0 +1,249 @@ +## Maintenance Mode +You can turn on maintenance mode by creating a `maintenance.on` file in the `maintenance_mode` folder. This will change the front page of the website, showing a customizable page (the `maintenance.html` file in the same folder). + +Simply remove the `maintenance_mode/maintenance.on` file to end maintenance mode. + +--- +During testing, if you want to update or restart some services (e.g : Django), you should follow the following steps: + +```bash +docker compose stop django +docker compose rm django ## remove old django container +docker compose create django ## create new django container with the changes from your development +docker compose start django +``` + +This procedure helps you update changes of your development on Django without having to restart every Codabench container. + +## Give superuser privileges to a user + +With superuser privileges, the user can edit any benchmark and can access the Django admin interface. + +```python +docker compose exec django ./manage.py shell_plus +u = User.objects.get(username='') ## can also use email +u.is_staff = True +u.is_superuser = True +u.save() +``` + +## Migration + +```bash +docker compose exec django ./manage.py makemigrations +docker compose exec django ./manage.py migrate +``` + +## Collect static files + +```bash +docker compose exec django ./manage.py collectstatic --noinput +``` + +## Delete POSTGRESDB and MINIO : +!!! warning + This will delete all your data ! + +```bash +## Begin in codabench root directory +cd codabench +``` + +#### Purge data + +```bash +sudo rm -r var/postgres/* +sudo rm -r var/minio/* +``` + + +#### See data we are going to purge +```bash +ls var +``` + + +#### Restart services and recreate database tables + +```bash +docker compose down +docker compose up -d +docker compose exec django ./manage.py migrate +``` + +## Feature competitions in home page + +There are two ways of setting a competition as featured: +1. Use Django admin (see below) -> click the competition -> scroll down to is featured filed -> Check/Uncheck it +2. Use competition ID in the django bash to feature or unfeature a competition +```python +docker compose exec django ./manage.py shell_plus +comp = Competition.objects.get(id=) ## replace with competition id +comp.is_featured = True ## set to False if you want to unfeature a competition +comp.save() +``` + +## Shell Based Admin Features +If you're running your own Codabench instance, there are different ways to interact with the application. Inside the `django` container (`#!bash docker compose exec django bash`) you can use `#!bash python manage.py help` to display all available commands and a brief description. By far the most useful are `createsuperuser` and `shell/shell_plus`. + + +## Django Admin interface + +Once you log in an account with superuser privileges, you have access to the "Django Admin" interface: + +![interface access](_attachments/214587579-53b8f79c-dc51-4323-b48d-360dd7b5774f_1753436642870153.png) + +From this interface, you can change a user's quota, change their staff and superuser status, change the featured competitions displayed on the homepage, manage user accounts and more. + +#### Edit announcement and news + +In the Django admin interface, click on `Announcements` or `New posts`: + +![](_attachments/de2a053f-c804-4c2a-a7ff-0df189c1d79c_17534366434691174.jpg) + +For announcement, only the first announcement is read by the front page. For news, all objects are read as separate news. +You can create and edit objects using the interface. Write the announcement and news using HTML to format the text, add links, and more: + +![](_attachments/38c0d1ce-9b27-44bb-804b-c4eed55613df_17534366434285173.jpg) + + +#### Delete a user + +Go to `Users`: + +![](_attachments/47b45c3e-13ed-4870-a83d-a25338aeaa39_17534366434936385.jpg) + +Select it, select the `Delete selected users` action and click on `Go`: + +![](_attachments/c0fdd7ff-0c46-4bae-b9e2-7d4e0b774ec2_17534366434447145.jpg) + + + +## RabbitMQ Management +The RabbitMQ management tool allows you to see the status of various queues, virtual hosts, and jobs. By default, you can access it at: `http://:15672/`. The username/password is your RabbitMQ `.env` settings for username and password. The port is hard-set in `docker-compose.yml` to 15672, but you can always change this if needed. For more information, see: +https://www.rabbitmq.com/management.html + +## Flower Management +Flower is a web based tool for monitoring and administrating Celery clusters. By default, you can access the Flower web portal at `http://:5555/`. The username/password is your Flower `.env` settings for username and password. 5555 is the default port, and cannot be changed without editing the `docker-compose.yml` file. + +For more information on flower, please visit: +[https://flower.readthedocs.io/en/latest/](https://flower.readthedocs.io/en/latest/) + +## Storage analytics +#### The interface +The storage analytics page is accessible at [codabench-url/analytics/](https://www.codabench.org/analytics/) under the storage tab. + +![image](../_attachments/5107b308-b445-45a3-91d9-b1fbfb5a1ed9_17528513107704363.jpg) + +From this interface, you will have access to various analytics data: + +- A Storage usage history chart +- A Competitions focused storage evolution, distribution and table +- A Users focused storage evolution, distribution and table + +All of those data can be filtered by date range and resolution, and exported as CSVs. + +The data displayed in those charts are only calculated from a background analytics task that takes place every Sunday at 02:00 UTC time (value editable in the `src/settings/base.py`). + +#### The background task + +The analytics task is a celery tasked named `analytics.tasks.create_storage_analytics_snapshot`. +What it does: + +- It scans the database looking for file sizes that are not set or flagged in error +- Actually measures their size and saves it in the database +- Aggregate the storage space used by day and by Competition/User (for example every day for the last year for each competition) by looking at the database file size fields +- For data related to the _Platform Administration_ it measures as well the database backup folder directly from the storage instance. +- Everything is saved as multiple snapshot in time in each Category table (i.g.: `UserStorageDataPoint`) +- This tasks also runs a database <-> storage inconsistency check and saves the results in a log file located in the `var/logs/` folder + +To manually start the task, you can do the following: + +- Start codabench `docker compose up -d` +- Bash into the django container and start a python console: +```sh +docker compose exec django ./manage.py shell_plus +``` +- Manually start the task: +```python +from analytics.tasks import create_storage_analytics_snapshot +eager_results = create_storage_analytics_snapshot.apply_async() +``` +- If you check the logs (`docker compose logs -f`) of the app you should see "Task create_storage_analytics_snapshot started" coming from the site_worker container +- If you have to restart the task, don't worry, it will only compute the size of the files that hasn't been computed yet. +- Once the task is over you should be able to see the results on the web page + + +## Homepage counters + +There is also a daily background task counting users, competitions and submissions, in order to display it on the homepage. + +You can manually run it: + +```bash +docker compose exec django ./manage.py shell_plus +``` + +```python +from analytics.tasks import update_home_page_counters +eager_results = update_home_page_counters.apply_async() +``` + + +## User Quota management + +#### Increase user quota + +###### Using the Django Shell + +```python +docker-compose exec django ./manage.py shell_plus +``` + +```python +u = User.objects.get(username='') ## can also use email +u.quota = u.quota * 3 # We multiply the quota by 3 in this example +u.save() +``` + +###### Using the Django Admin Interface +- Go to the Django admin page +- Click user table +- Select the user for whom you want to increase/decrease quota +- Update the quota field with new quota (in GB e.g. 15) +![](_attachments/5c8aae99-0cbb-4ffa-87aa-0e9d3f6fd018_17534366434342587.jpg) + +## Codabench Statistics +You can create two types of codabench statistics: + +- Overall platform statistics for a specified year +- Overall published competitions statistics + +Follow the steps below to create the statistics + +#### Start codabench +```bash +docker compose up -d +``` +#### Bash into the django container and start a python console: +```bash +docker compose exec django ./manage.py shell_plus +``` + +#### For overall platform statistics +```python +from competitions.statistics import create_codabench_statistics +create_codabench_statistics(year=2024) +``` +!!! note + - If `year` is not specified, the current year is used by default + - A CSV file named `codabench_statistics_2024.csv` is generated in `statistics` folder (for year=2024) + +#### For overall published competitions statistics +```python +from competitions.statistics import create_codabench_statistics_published_comps +create_codabench_statistics_published_comps() +``` +!!! note + A csv file named `codabench_statistics_published_comps.csv` is generated in `statistics folder` + diff --git a/documentation/docs/Developers_and_Administrators/Automating-with-Selenium.md b/documentation/docs/Developers_and_Administrators/Automating-with-Selenium.md new file mode 100644 index 000000000..76482641d --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Automating-with-Selenium.md @@ -0,0 +1,73 @@ + +## What and Why +It's useful to test various parts of the system with lots of data or many intricate actions. The selenium tests do this generally and are used as a guide for this tutorial. One problem is that Selenium needs to launch an instance of a browser to control. Our tests do this inside a docker container and uses a test database that doesn't persist as it cleans up after itself. We need to be able to control a live codabench session that is running. To do that we install a driver locally which is normally only inside the selenium docker container during tests. It is specific to your browser so keep that in mind. + +## Virtualenv +You'll need a python virtual env as you don't want to be inside Django or you won't be able to launch a browser. + +### Virtualenv +I used 3.8. +```bash +python3 -m venv codabench +source ./codabench/bin/activate +``` + +### Pyenv +```bash +pyenv install 3.8 +pyenv virtualenv 3.8 codabench +pyenv activate codabench +``` + +## Requirements +We have a couple extra things like `webdriver-manager` for getting a driver programmatically and `selenium` needs to be upgraded to use modern client interface. +```bash +pip install -r requitements.txt +pip install -r requitements.dev.txt +pip install webdriver-manager +pip install --upgrade selenium +``` + +## Automate competition creation +[Main Selenium Docs](https://selenium-python.readthedocs.io/) +[Install](https://selenium-python.readthedocs.io/installation.html) +[Getting Started](https://selenium-python.readthedocs.io/getting-started.html) + +```python +import os, time +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.chrome.service import Service +from webdriver_manager.chrome import ChromeDriverManager + +# Use `ChromeDriverManager` to ensure the `chromedriver` is installed and in PATH +service = Service(ChromeDriverManager().install()) +driver = webdriver.Chrome(service=service) + +# ... now use `driver` to control the local Chrome instance +driver.get("http://localhost/accounts/login") + +# Use CSS selectors to find the input fields and button +username_input = driver.find_element(By.CSS_SELECTOR, 'input[name="username"]') +password_input = driver.find_element(By.CSS_SELECTOR, 'input[name="password"]') +submit_button = driver.find_element(By.CSS_SELECTOR, '.submit.button') + +# Type the credentials into the fields +username_input.send_keys('bbearce') +password_input.send_keys('testtest') + +# Click the submit button +submit_button.click() + +comp_path = "/home/bbearce/Documents/codabench/src/tests/functional/test_files/competition_v2_multi_task.zip" +def upload_competition(competition_zip_path): + driver.get("http://localhost/competitions/upload") + file_input = driver.find_element(By.CSS_SELECTOR, 'input[ref="file_input"]') + file_input.send_keys(os.path.join(competition_zip_path)) + + +for i in range(30): + upload_competition(comp_path) + time.sleep(5) # tune for your system + +``` \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Codabench-Architecture.md b/documentation/docs/Developers_and_Administrators/Codabench-Architecture.md new file mode 100644 index 000000000..74ead2ca2 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Codabench-Architecture.md @@ -0,0 +1,68 @@ + +![image](../_attachments/71679668-f6324a00-2d3c-11ea-816a-70e22e14e583_17528513131865652.png) + +[Source](https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ3JhcGggVERcbkEoKFVzZXIpKVxuQltDYWRkeV1cbkN7e0RqYW5nb319XG5EW1Bvc3RncmVzXVxuRnt7UmFiYml0fX1cbkdbTWluaW9dXG5IW0NyZWF0ZSBCdWNrZXRzXVxuSXt7QnVpbGRlcn19XG5LW0Zsb3dlcl1cbkxbQ29tcHV0ZSBXb3JrZXJdXG5NW1NpdGUgV29ya2VyXVxuQSAtLT4gQlxuQiAtLT4gQ1xuQyAtLT4gRFxuQyAtLT4gRlxuRiAtLT4gTFxuRiAtLT4gTVxuQyAtLT58U3RvcmFnZXxHXG5HIC0tPnxJbml0aWFsaXphdGlvbiBIZWxwZXJ8IEhcbkYgLS0-IEtcbkMgLS0-fEpTIEFzc2V0IEhlbHBlcnwgSVxuIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0): +```mermaid +graph TD +A((User)) +B[Caddy] +C{{Django}} +D[Postgres] +F{{Rabbit}} +G[Minio] +H[Create Buckets] +I{{Builder}} +K[Flower] +L[Compute Worker] +M[Site Worker] +A --> B +B --> C +C --> D +C --> F +F --> L +F --> M +C -->|Storage|G +G -->|Initialization Helper| H +F --> K +C -->|JS Asset Helper| I +``` + + +Codabench consists of many docker containers that are connected and organized through docker compose. Below is an overview of each container and their function: + +## Django +The main container that runs and contains the python code (A Django project). This is the container that is mainly used for utility functions like creating admins, creating backups, and manually making changes through the python django shell. It has a gunicorn webserver that serves internally on port 8000. + +## Caddy +The HTTP/HTTPs web server. It acts as a reverse proxy for the Django container. This container controls SSL/HTTPs functionality and other web server configuration options. Serves on port 80/443. + +## Postgres (Labeled DB in docker-compose) +The default database container. It will contain the default Postgres database used by codabench. (Name/user/pass,etc determined by .env.) If you need to make manual DB changes, this is the container to look into. + +Here is the DB schema ![codabench_db](../_attachments/7d8caf1d-cfdb-46cb-af48-2a2bcdc979eb_17528513157974837.jpg) + +## Compute Worker +The container(s) (can be external) that runs submissions for the codabench instance on their associated queues. The default workers are tied to the default queue. +Commands to re-build the compute worker Docker image can be found [here](../Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md#building-compute-worker). + +## Site Worker +The container that runs various tasks for the Django container such as unpacking and processing a competition bundle. + +## Minio +The default storage solution container. Runs a MinIO instance that serves on the port defined by settings in your .env. + +## Create Buckets +A helper container for the Minio container that initially creates the buckets defined by settings in your .env if they don't already exist. Usually this container exits after that. + +## Builder +A container to build RiotJS tags into a single unified tag that can then be mounted. Uses NPM. + +## Rabbit +Task/Message management container. Organizes queues for Celery Tasks and compute workers. Any queues that get created are accessible through rabbit's own command line interface. + +## Flower +Administrative utility container for Celery tasks and queues. + +## Competition docker image + +The services of Codabench run inside Docker environments. This should not be confused with the Docker environment used to run the submissions, which may vary for each benchmark. The docker running submissions is discussed [here](Submission-Docker-Container-Layout.md) \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Codabench-Installation.md b/documentation/docs/Developers_and_Administrators/Codabench-Installation.md new file mode 100644 index 000000000..c0a23f418 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Codabench-Installation.md @@ -0,0 +1,150 @@ +Compared to Codalab, installing Codabench should be relatively easy since you no longer have to worry about special ways to set up SSL or storage. We include default solutions that should handle that for most basic uses. + +## Pre-requisites + +### Install Docker and Docker Compose +- [Docker](https://docs.docker.com/install/) +- [Docker Compose](https://docs.docker.com/compose/install/) + +## Clone Repository +Download the Codabench repository: + +```bash +git clone https://github.com/codalab/codabench +``` + +## Edit the settings (.env) + +The `.env` file contains the settings of your instance. +On a fresh installation, you will need to use the following command to get your `.env` file: + +```bash +cd codabench +cp .env_sample .env +``` + +Then edit the necessary settings inside. The most important are the database, storage, and Caddy/SSL settings. For a quick **local** setup, you should not need to edit this file. For a [public server deployment](How-to-deploy-Codabench-on-your-server.md), you will have to modify some settings. + +!!! warning "It is important to change the default passwords if you intend for the instance to be public" + +If you are using `AWS_S3_ENDPOINT_URL=http://minio:9000/` in your `.env`, edit your `/etc/hosts` file by adding this line `127.0.0.1 minio` + + +#### For MacOS + +In `.env`, replace: +```ini +AWS_S3_ENDPOINT_URL=http://minio:9000/ +``` + +by + +```ini +AWS_S3_ENDPOINT_URL=http://docker.for.mac.localhost:9000/ +``` +!!! note "If needed, some troubleshooting of this step is provided at [the end of this page](#troubleshooting-storage-endpoint-url) or [in this page](How-to-deploy-Codabench-on-your-server.md#frequently-asked-questions-faqs)" + +## Start the service + +To deploy the platform, run: + +```bash +docker compose up -d +``` + +## Run the following commands + +Create the required tables in the database: + +```bash +docker compose exec django ./manage.py migrate +``` + +Generate the required static resource files: + +```bash +docker compose exec django ./manage.py collectstatic --noinput +``` + +You should be able to verify it is running correctly by looking at the logs with `docker compose logs -f` and by visiting `localhost:80` (Depending on your configuration). + + +## Advanced Configuration + +### Testing + +To run automated tests for your local instance, get inside the Django container with `docker compose exec django bash` then run `py.test` to start the automated tests. + + +### SSL +To enable SSL: + +- If you already have a DNS for your server that is appropriate, in the `.env` simply set `DOMAIN_NAME` to your DNS. Remove any port designation like `:80`. This will have Caddy serve both HTTP and HTTPS. + +!!! warning "For a public instance, HTTPS is strongly recomended" + +### Validate user account on local instance + +When deploying a local instance, the email server is not configured by default, so you won't receive the confirmation email during signup. + +To manually confirm your account: + +1. Find the confirmation link in the Django logs using `docker compose logs -f django` +2. Replace `example.com` by `localhost`on the URL and open it in your browser. + +Another way is to go inside the Django containers and use commands like in [administrative procedures](Administrator-procedures.md). + +### Troubleshooting storage endpoint URL + +You may have to manually change the endpoint URL to have your local instance working. This may be an OS related issue. +Here is a possible fix: + +1. `docker compose logs -f minio` +2. Grab the first one of these IP addresses: +```bash +minio_1 | Browser Access: +minio_1 | http://172.27.0.5:9000 http://127.0.0.1:9000 +``` +3. Set `AWS_S3_ENDPOINT_URL=http://172.27.0.5:9000`in your `.env` file. + +--- + +If static files are not loaded correctly, adding `DEBUG=True` to the `.env` file can help. + + +### For Apple CPU (M1, M2 chips) + +In `docker-compose.yml`, replace in the `compute_worker` service: + +```yaml title="docker-compose.yml" +command: bash -c "watchmedo auto-restart -p '*.py' --recursive -- celery -A compute_worker worker -l info -Q compute-worker -n compute-worker@%n" +``` + +by + +```yaml title="docker-compose.yml" +command: bash -c "celery -A compute_worker worker -l info -Q compute-worker -n compute-worker@%n" +``` + + +### Storage +By default, Codabench uses a built-in MinIO container. Some users may want a different solution, such as S3 or Azure. The configuration will vary slightly for each different type of storage. + +For all possible supported storage solutions, see: +https://django-storages.readthedocs.io/en/latest/ + +### Remote Compute Workers +To set up remote compute workers, you can follow the steps described in our +[Compute Worker Management](../Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md) page. + +## Troubleshooting + +Read the following guide for troubleshooting: [How to deploy Codabench](How-to-deploy-Codabench-on-your-server.md#frequently-asked-questions-faqs). + +Also, adding `DEBUG=True` to the `.env` file can help with troubleshooting the deployment. + +Open a [Github issue](https://github.com/codalab/codabench/issues) to find help with your installation + +## Online Deployement + +For information about online deployment of Codabench, go to the [following page](How-to-deploy-Codabench-on-your-server.md) \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Creating-and-Restoring-from-Backup.md b/documentation/docs/Developers_and_Administrators/Creating-and-Restoring-from-Backup.md new file mode 100644 index 000000000..e8c1193e9 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Creating-and-Restoring-from-Backup.md @@ -0,0 +1,55 @@ + +Codabench has a custom command that uploads a database backup, and copies it to the storage you are using under `/backups`. We'll see how to execute and automate that command, and how to restore from one of these backups in the event of a failure. + +## Creating Backups +### Create +```bash +DB_NAME= +DB_USERNAME= +DB_PASSWORD= +DUMP_NAME= +docker exec codabench-db-1 bash -c "PGPASSWORD=$DB_PASSWORD pg_dump -Fc -U $DB_USERNAME $DB_NAME > /app/backups/$DUMP_NAME.dump" +``` + +### Upload +There's a custom command on codabench that we use to upload database backups to storage. It should be accessible from inside the Django container (`docker compose exec django bash`) with `python manage.py upload_backup `. It takes an argument `backup_path` which is the path relative to your backup folder, `codabench/backups` and storage bucket, `/backups`. For instance if I pass it as `2022/$DUMP_NAME.dump`, the backup should happen in `codabench/backups/2022/$DUMP_NAME.dump` and will be uploaded to `/backups/2022/$DUMP_NAME.dump` in your storage bucket. + +## Scheduling Automatic Backups +To schedule automatic backups, we're going to schedule a daily cronjob. To start, open the cron editor in a shell with `crontab -e`. + +Add a new entry like so, with the correct path to `pg_dump.py`: + +```bash +@daily /home/ubuntu/codabench/bin/pg_dump.py +``` + +You should confirm this backup process works by setting some known cronjob time a few minutes in the future and see the dump in storage. + +Once done, save and quit the crontab editor, and verify your changes held by listing out cronjobs with `crontab -l`. You should see your new crontab entry. + +## Restoring From Backup + +Re-install Codabench according to the documentation here: [Codabench Installation](Codabench-Installation.md). + +Once Codabench is re-installed and working, we're ready to restore our database backup. Upload the database backup to the webserver. It should go under the `codabench` install folder in the `/backups` directory. For example your path might look like: +`/home/users/ubuntu/codabench/backups` + +Once the backup is located in the `/backups` folder, you'll want to get into the postgres container (`docker compose exec db bash`). Make sure you know your `DB_NAME`, `DB_USERNAME`, and `DB_PASSWORD` variables from your .env. + +You can restore two ways. The first would be manually dropping the db, re-creating it, then using pg_restore to restore the data: +```bash title="Inside the database container" +dropdb $DB_NAME -U $DB_USERNAME +createdb $DB_NAME -U $DB_USERNAME +pg_restore -U $DB_USERNAME -d $DB_NAME -1 /app/backups/.dump +``` + +Or, you can let `pg_restore` do that for you with a couple of flags/arguments: +```bash title="Inside the database container" +pg_restore --verbose --clean --no-acl --no-owner -h $DB_HOST -U $DB_USERNAME -d $DB_NAME /app/backups/.dump +``` + +The arguments `--no-acl` & `--no-owner` may be useful if you're restoring as a non-root user. The owner argument is used for: ```Do not output commands to set ownership of objects to match the original database.``` + +The ACL argument is for: ```Prevent dumping of access privileges (grant/revoke commands).``` + +After running `pg_restore` successfully without errors, you should find everything has been restored. \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/How-to-deploy-Codabench-on-your-server.md b/documentation/docs/Developers_and_Administrators/How-to-deploy-Codabench-on-your-server.md new file mode 100644 index 000000000..7825ad297 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/How-to-deploy-Codabench-on-your-server.md @@ -0,0 +1,441 @@ +## Overview +This document focuses on how to deploy the current project to the local machine or server you are on. + +## Preliminary steps + +As for the [minimal local installation](Codabench-Installation.md), you first need to: + +1. Install docker and docker-compose (see [instructions](Codabench-Installation.md#pre-requisites)) + +2. Clone Codabench repository: + +```sh +git clone https://github.com/codalab/codabench +``` + + +## Modify .env file configuration + +Then you need to modify the `.env` file with the relevant settings. This step is critical to have a working and secure deployment. + +- Go to the folder where codabench is located (`cd codabench`) +```bash +cp .env_sample .env +``` + + +Then edit the variables inside the `.env` file. + +### Submissions endpoint +For an online deployment, you'll need to fill in the IP address or domain name in some environment variables. + +#### Using an IP address + +b) For an online deployment using IP address: +!!! note + To get the IP address of the machine. You can use one of the following commands: + + - `ifconfig -a` + - `ip addr` + - `ip a` + - `hostname -I | awk '{print $1}'` + - `nmcli -p device show` + +Replace the value of IP address in the following environment variables according to your infrastructure configuration: + +```ini title=".env" +SUBMISSIONS_API_URL=https:///api +DOMAIN_NAME=:80 +AWS_S3_ENDPOINT_URL=http:/// +``` + +#### Using a domain name (DNS) + +```ini title=".env" +SUBMISSIONS_API_URL=https://yourdomain.com/api +DOMAIN_NAME=yourdomain.com +AWS_S3_ENDPOINT_URL=https://yourdomain.com +``` + +!!! tip "If you are deploying on an azure machine, then AWS_S3_ENDPOINT_URL needs to be set to an IP address that is accessible on the external network" + + +### Change default usernames and passwords + +Set up new usernames and passwords: + +``` +DB_USERNAME=postgres +DB_PASSWORD=postgres +[...] +RABBITMQ_DEFAULT_USER=rabbit-username +RABBITMQ_DEFAULT_PASS=rabbit-password-you-should-change +[...] +FLOWER_BASIC_AUTH=root:password-you-should-change +[...] +#EMAIL_HOST_USER=user +#EMAIL_HOST_PASSWORD=pass +[...] +MINIO_ACCESS_KEY=testkey +MINIO_SECRET_KEY=testsecret +# or +AWS_ACCESS_KEY_ID=testkey +AWS_SECRET_ACCESS_KEY=testsecret +``` +!!! warning "It is very important to set up an SSL certificate for Public deployement" + +## Open Access Permissions for following port number + +If you are deploying on a Linux server, which usually has a firewall, you need to open access permissions to the following port numbers + +- `5672`: rabbit mq port +- `8000`: django port +- `9000`: minio port + +## Modify django-related configuration + +- Go to the folder where codabench is located +- Go to the settings directory and modify `base.py` file + - `cd src/settings/` + - `nano base.py` +- Change the value of `DEBUG` to `True` + - `DEBUG = os.environ.get("DEBUG", True)` +!!! note "If DEBUG is not set to true, then you will not be able to load to the static resource file" +- Comment out the following code +```py +# ============================================================================= +# Debug +# ============================================================================= +#if DEBUG: +# INSTALLED_APPS += ('debug_toolbar',) +# MIDDLEWARE = ('debug_toolbar.middleware.DebugToolbarMiddleware', +# 'querycount.middleware.QueryCountMiddleware', +# ) + MIDDLEWARE # we want Debug Middleware at the top +# # tricks to have debug toolbar when developing with docker +# +# INTERNAL_IPS = ['127.0.0.1'] +# +# import socket +# +# try: +# INTERNAL_IPS.append(socket.gethostbyname(socket.gethostname())[:-1]) +# except socket.gaierror: +# pass +# +# QUERYCOUNT = { +# 'IGNORE_REQUEST_PATTERNS': [ +# r'^/admin/', +# r'^/static/', +# ] +# } +# +# DEBUG_TOOLBAR_CONFIG = { +# "SHOW_TOOLBAR_CALLBACK": lambda request: True +# } +``` +## Start service + +- Execute command `docker compose up -d` +- Check if the service is started properly `docker compose ps` + +```bash +codabench_compute_worker_1 "bash -c 'watchmedo …" running +codabench_caddy_1 "/bin/parent caddy -…" running 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp, 2015/tcp +codabench_site_worker_1 "bash -c 'watchmedo …" running +codabench_django_1 "bash -c 'cd /app/sr…" running 0.0.0.0:8000->8000/tcp, :::8000->8000/tcp +codabench_flower_1 "flower" restarting +codabench_rabbit_1 "docker-entrypoint.s…" running 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, :::5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp, :::15672->15672/tcp +codabench_minio_1 "/usr/bin/docker-ent…" running 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp +codabench_db_1 "docker-entrypoint.s…" running 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp +codabench_builder_1 "docker-entrypoint.s…" running +codabench_redis_1 "docker-entrypoint.s…" running 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp + +``` + +- Create the required tables in the database: `docker compose exec django ./manage.py migrate` +- Generate the required static resource files: `docker compose exec django ./manage.py collectstatic --noinput` + +!!! tip + You can generate mock data with `docker compose exec django ./manage.py generate_data` if you want to test the website. However, it is not recomended to do that on an installation that you intend to use for Production + +## Set public bucket policy to read/write + +This can easily be done via the minio web console (local URL: minio:9000) +![minio-9000-bucketPolicy](../_attachments/224348279-65fd619a-28ce-4b65-bdb1-c791508c9d21_17528513111161823.png) + +## Checkout the log of the specified container + +!!! tip "The following commands can help you debug" + - `docker compose logs -f django` : checkout django container logs in the docker-compose service + - `docker compose logs -f site_worker` : checkout site-worker container logs in the docker-compose service + - `docker compose logs -f compute_worker` : checkout compute-worker container logs in the docker-compose service + - `docker compose logs -f minio` : checkout minio container logs in the docker-compose service + + You can also use `docker compose logs -f` to get the logs of all the containers. + +## Stop service + +- Execute command `docker compose down --volumes` + +## Disabling docker containers on production + +To override settings on your production server, create a `docker-compose.override.yml` in the `codabench` root directory. +If on your production server, you are using remote MinIO or another cloud storage provider then you don't need **minio** container. +If you have already buckets available for your s3 storage, you don't need **createbuckets** container. +Therefore, you should disable minio and createbuckets containers. You may also want to disable the compute worker that is contained in the main server compute, to keep only remote compute workers. + +Add this to your `docker-compose.override.yml`: + +```yaml title="docker-compose.override.yml" +version: '3.4' +services: + compute_worker: + command: "/bin/true" + minio: + restart: "no" + command: "/bin/true" + createbuckets: + entrypoint: "/bin/true" + restart: "no" + depends_on: + minio: + condition: service_started +``` + +!!! warning + This will force the following container from exiting on start: + + - Compute Worker + - MinIO + - CreateBuckets + + If you need one of these then remove the corresponding lines from the file before launching + + + +## Link compute workers to default queue + +The default queue of the platform runs all jobs, except when a custom queue is specified by the competition or benchmark. +By default, the compute worker of the default queue is a docker container run by the main VM. If your server is used by many users and receives several submissions per day, it is recommended to use separate compute workers and to link them to the default queue. + +To set up a compute worker, follow this [guide](../Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md) + +In the `.env` file of the compute worker, the `BROKER_URL` should reflect settings of the `.env` file of the platform: + +```bash title=".env" +BROKER_URL=pyamqp://:@:/ +HOST_DIRECTORY=/codabench +BROKER_USE_SSL=True +``` + + +## Personalize Main Banner +The main banner on the Codabench home page shows 3 organization logos + +- [LISN](https://www.lisn.upsaclay.fr/) +- [Université Paris-Saclay](https://www.universite-paris-saclay.fr/) +- [CNRS](https://www.cnrs.fr/) +![](_attachments/6ec1780d-227f-472e-84fd-1d08847a24b8_1753436644389027.jpg) + +You can update these by: + +1. Replacing the logos in `src/static/img/` folder +2. Updating the code in `src/templates/pages/home.html` to point to the right websites of your organizations + + +## Frequently asked questions (FAQs) + +### Invalid HTTP method + +Exception detail (by using `docker logs -f codabench_django_1`) + +```java +Traceback (most recent call last): + File "/usr/local/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 165, in data_received + self.parser.feed_data(data) + File "httptools/parser/parser.pyx", line 193, in httptools.parser.parser.HttpParser.feed_data +httptools.parser.errors.HttpParserInvalidMethodError: invalid HTTP method +[2021-02-09 06:58:58 +0000] [14] [WARNING] Invalid HTTP request received. +Traceback (most recent call last): + File "/usr/local/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 165, in data_received + self.parser.feed_data(data) + File "httptools/parser/parser.pyx", line 193, in httptools.parser.parser.HttpParser.feed_data +httptools.parser.errors.HttpParserInvalidMethodError: invalid HTTP method +``` + +![image](../_attachments/113236785-28cc4900-92d8-11eb-8b2d-bbec05090788_17528513112217138.png) + +Solution + +- First, modify the `.env` file and set `DJANGO_SETTINGS_MODULE=settings.develop` + +- Then, restart services by using following docker-compose command + +```bash +docker compose down --volumes +docker compose up -d +``` + +### Missing static resources (css/js) + +Solution: Change the value of the `DEBUG` parameter to `True` + +- `nano competitions-v2/src/settings/base.py` +- `DEBUG = os.environ.get("DEBUG", True)` + +![image](../_attachments/113236839-44375400-92d8-11eb-9c12-9d8654423662_17528513112593784.png) + +- Also comment out the following code in `base.py` + +![image](../_attachments/113236871-544f3380-92d8-11eb-86bf-05ffb9fac5d2_17528513120945034.png) + +### CORS Error (could not upload bundle) + +Exception detail (by checkout google develop tools) + +```java +botocore.exceptions.EndpointConnectionError: Could not connect to the endpoint URL: "[http://docker.for.mac.localhost:9000/private/dataset/2021-02-18-1613624215/24533cfc523e/competition.zip](http://docker.for.mac.localhost:9000/private/dataset/2021-02-18-1613624215/24533cfc523e/competition.zip)" +``` + +Solution: Set AWS_S3_ENDPOINT_URL to an address that is accessible to the external network + +- `nano codabench/.env` + +![image](../_attachments/113236903-66c96d00-92d8-11eb-9186-2fac1b0a6918_17528513113931694.png) + +Make sure the IP address and port number is accessible by external network, You can check this by : + +- `telnet {ip-address-filling-in AWS_S3_ENDPOINT_URL} {port-filling-in AWS_S3_ENDPOINT_URL}` +- Make sure the firewall is closed on port 9000 + +!!! note "This problem may also be caused by a bug in MinIO, in which case you will need to follow these steps" + + - Upgrade the minio docker image to the latest version + - Delete the previous minio directory folder in your codabench folder under `/var/minio` directory + - Stop the current minio container + - Delete the current minio container and the corresponding image + - Re-execute `docker compose up -d` + + +### Display logos error: logos don't upload from minio: + + +Check bucket policy of public minio bucket: read/write access should be allowed. + +This can easily be done via the minio web console (local URL: minio:9000) + + +![minio-9000-bucketPolicy](../_attachments/224348279-65fd619a-28ce-4b65-bdb1-c791508c9d21_17528513111161823.png) + + +### Compute worker execution with insufficient privileges + +This issue may be encountered when starting a docker container in a compute worker, the problem is caused by the installation of snap docker (if you are using Ubuntu). + +Solution + +- Uninstall snap docker +- Install the official version of docker + +## Securing Codabench and Minio +Codabench uses [Caddy](https://caddyserver.com/) to manage HTTPS and to secure Codabench. What you need is a valid DNS pointed towards the IP address of your instance. + +### Secure Minio with a reverse proxy +To secure MinIO, you should install a reverse-proxy, e.g: Nginx, and have a valid SSL certificate. Here is a tutorial sample: + +[Secure MinIO with Certbot and Letsencrypt](https://blog.min.io/minio-nginx-letsencrypt-certbot/) + +**Don't forget to update your AWS_S3_ENDPOINT_URL parameter** + +Update it to `AWS_S3_ENDPOINT_URL=https://` + +### Secure Minio on the same server as codabench (simpler) +Summary: + +* Use same SSL certs from letsencrypt (certbot) but change fullchain.pem -> public.crt and privkey.pem -> private.key. I copied from ./certs/caddy (for django/caddy) to ./certs/minio/certs. +* You need to change the command for minio to "server /export --certs-dir /root/.minio/certs" and not just "server /export" +* Mount in certs: + - Add "- ./certs/minio:/root/.minio" under the minio service's "volumes" section +* Certs must be in /${HOME}/.minio and for dockers ends up being /root/.minio +* Edit the .env with minio cert location: +```bash +MINIO_CERT_FILE=/root/.minio/certs/public.crt +MINIO_KEY_FILE=/root/.minio/certs/private.key +# MINIO_CERTS_DIR=/certs/caddy # was told .pem files could work but for now separating +MINIO_CERTS_DIR=/root/.minio/certs # either this or the CERT\KEY above is redundant...but it works for now. +# NOTE! if you change this port, change it in AWS_S3_ENDPOINT_URL as well +MINIO_PORT=9000 + +``` +* Here is an example docker-compose.yml change for this: +```bash + #----------------------------------------------- + # Minio local storage helper + #----------------------------------------------- + minio: + image: minio/minio:RELEASE.2020-10-03T02-19-42Z + command: server /export --certs-dir /root/.minio/certs + volumes: + - ./var/minio:/export + - ./certs/minio:/root/.minio + restart: unless-stopped + ports: + - $MINIO_PORT:9000 + env_file: .env + healthcheck: + test: ["CMD", "nc", "-z", "minio", "9000"] + interval: 5s + retries: 5 + createbuckets: + image: minio/mc + depends_on: + minio: + condition: service_healthy + env_file: .env + # volumes: + # This volume is shared with `minio`, so `z` to share it + # - ./var/minio:/export + entrypoint: > + /bin/sh -c " + set -x; + if [ -n \"$MINIO_ACCESS_KEY\" ] && [ -n \"$MINIO_SECRET_KEY\" ] && [ -n \"$MINIO_PORT\" ]; then + until /usr/bin/mc config host add minio_docker https://minio:$MINIO_PORT $MINIO_ACCESS_KEY $MINIO_SECRET_KEY && break; do + echo '...waiting...' && sleep 5; + done; + /usr/bin/mc mb minio_docker/$AWS_STORAGE_BUCKET_NAME || echo 'Bucket $AWS_STORAGE_BUCKET_NAME already exists.'; + /usr/bin/mc mb minio_docker/$AWS_STORAGE_PRIVATE_BUCKET_NAME || echo 'Bucket $AWS_STORAGE_PRIVATE_BUCKET_NAME already exists.'; + /usr/bin/mc anonymous set download minio_docker/$AWS_STORAGE_BUCKET_NAME; + else + echo 'MINIO_ACCESS_KEY, MINIO_SECRET_KEY, or MINIO_PORT are not defined. Skipping buckets creation.'; + fi; + exit 0; + " +``` +![image](../_attachments/893b1d55-3d6e-45ed-887b-3df882c7e127_17528513131864328.jpg) + +!!! Note + Don't forget to change the entrypoint to run **https** and not **http**. + + +## Workaround: MinIO and Django on the same machine with only the port 443 opened to the external network. + +The S3 API signature calculation algorithm does not support proxy schemes where you host the MinIO Server API such as example.net/s3/. + +However, we can set the same URL for minio and django site and configure a proxy for each bucket in the Caddyfile : +```ini +DOMAIN_NAME=https://mysite.com +AWS_S3_ENDPOINT_URL=https://mysite.com +``` + +Caddyfile : +``` + @dynamic { + not path /static/* /media/* /{$AWS_STORAGE_BUCKET_NAME}* /{$AWS_STORAGE_PRIVATE_BUCKET_NAME}* /minio* + } + reverse_proxy @dynamic django:8000 + + @min_bucket { + path /{$AWS_STORAGE_BUCKET_NAME}* /{$AWS_STORAGE_PRIVATE_BUCKET_NAME}* + } + reverse_proxy @min_bucket minio:{$MINIO_PORT} +``` \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Manual-validation.md b/documentation/docs/Developers_and_Administrators/Manual-validation.md new file mode 100644 index 000000000..b5d9b3c27 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Manual-validation.md @@ -0,0 +1,15 @@ +This is a checklist to follow in order to perform a manual validation of the platform's proper functioning. +This is especially useful when validating a "bump" pull request made by the dependabot, a fresh installation or any change in the code base. + +1. Create a user account and login +2. Create a competition +3. Create a queue +4. Upload a submission +5. Check that the submission was processed (results, visualization tab, leaderboard) +6. Change/recover password +7. Delete user +8. Delete submission +9. Delete queue +10. Delete competition +11. Admin page +12. Look at the logs for any problematic messages (`docker compose logs -f`) \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Robot-submissions.md b/documentation/docs/Developers_and_Administrators/Robot-submissions.md new file mode 100644 index 000000000..efa029389 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Robot-submissions.md @@ -0,0 +1,257 @@ +This script is designed to test the Robot Submissions feature. Robot users should be able to submit to bot-enabled competitions without being admitted as a participant. + +This article will explain how to make a robot submission on your local computer, and how to present the results on the Leaderboard. + +## Pre-requisite +- Python 3 +- Demo bundle: autowsl +- Github download [URL](https://github.com/codalab/competitions-v2/tree/codabench/sample_bundle/src/tests/functional/test_files/AutoWSL_sample) + +![demo bundle](../_attachments/102425038-7d102d80-4047-11eb-9d67-4590426e91f0_17528513079491048.png) + +- Robot submission sample script here: [link](https://github.com/codalab/competitions-v2/tree/develop/docs/example_scripts) + +Brief description for demo bundle: + +- `code_submission`: It contains the sample bundle for the code submission and the code solution for the submission. + - `auto_wsl_code_submission.zip`:This bundle is used for making submission. + - `new_v18_code_mul_mul.zip`: The bundle is multiple phases, each phase has multiple tasks, and between these tasks, they share the same scoring program, that is, there is no need to copy multiple scoring program for hardcode. + - `new_v18_code_mul_mul_sep_scoring.zip`: This bundle is multiple phases, multiple tasks under each phase share a scoring program that is exclusive to their particular phase. + - `new_v18_code_sin_mul.zip`: This is the sample bundle of a single phase multi-task that shares the same scoring program. +![image](../_attachments/102425514-73d39080-4048-11eb-8689-c21d6d1ae4ac_1752851307966413.png) + +- `dataset_submission`: It contains the sample bundle for data submission and the corresponding dataset solution for submission. + - `AutoWSL_dataset_submission.zip`: This is the bundle used for dataset submissions. + - `new_v18_dataset_mul_mul.zip`:This is a multi-phase, each phase has multiple tasks below the sample bundle, multiple tasks, using the same scoring program, do not need to copy multiple scoring program for hardcode + - `new_v18_dataset_mul_mul_sep_scoring.zip`: This is a multi-phase, each phase has multiple tasks below the sample bundle, the task between the different phases, using a different scoring program, that is, each phase has its own independent scoring program. + - `new_v18_dataset_sin_mul.zip`: This is a sample bundle of single-phase multi-task commit datasets. +![image](../_attachments/102425665-b72dff00-4048-11eb-9b65-caa05e2f409d_17528513079724836.png) + +## Getting started + +### Upload a bundle +Use the sample bundle provided above to upload the bundle and create a competition +![image](../_attachments/102425747-e8a6ca80-4048-11eb-9d2d-09a59f63df09_1752851307954863.png) + +### Set the competition to allow robot submissions +On the created competition page, click the EDIT button + +![image](../_attachments/102425807-08d68980-4049-11eb-96ef-2220a7a70bda_17528513079972107.png) + +Then click on the Participation tab, then scroll down to the bottom and click on Allow robot submission and click SAVE button. + +![image](../_attachments/102425846-20157700-4049-11eb-93ed-e38e4db91611_17528513080323348.png) +![image](../_attachments/102425904-43d8bd00-4049-11eb-86c2-870d743baa00_17528513080195067.png) + +After the above steps are done, the Competition is allowed for making robot submission. + +### Set yourself to Is bot +Go to the backend administration page, PROFILES tab bar below the user + +![image](../_attachments/102426012-7b476980-4049-11eb-96f9-f88d716ed4ea_17528513080236058.png) +![image](../_attachments/102426040-8a2e1c00-4049-11eb-9477-3b1b128ef0ef_17528513080496614.png) + +Check the `is bot` box, click save. You can now proceed with your robot submissions. + +### Change CODALAB_URL address +Change CODALAB_URL address in following scripts:`get_competition_details.py`, `example_submission.py`, `get_submission_details.py` +CODALAB_URL = 'https://www.codabench.org/' + +> Find scripts at `docs/example_scripts` + +### Choose the competition +Run the following command on the command line: `python3 get_competition_details.py` +What you're about to see is something like this +![image](../_attachments/102426221-e5600e80-4049-11eb-95ed-3abf37ffd1d5_1752851308257055.png) + +Choose the ID of the competition you are interested in, for example 127. +![image](../_attachments/102426259-f6a91b00-4049-11eb-8e73-54bcd0514099_17528513080718298.png) + +Run the script again with the competition ID as a parameter +`python3 get_competition_details.py 127` +Then you will see the following +![image](../_attachments/102426306-0c1e4500-404a-11eb-8e0a-a056cd9ffdab_17528513080908906.png) + +You can select the phase ID you're interested in, then use it as the second argument and run the script again, this time you'll get the task information associated with that phase. +`python3 get_competition_details.py 127 215` +![image](../_attachments/102426338-1f311500-404a-11eb-9a85-42cfa7b4f34c_17528513081201243.png) + +### Making submission +Inside the `example_submission.py` script, configure these options: +![image](../_attachments/102426374-340da880-404a-11eb-8bf0-e62498560c38_17528513081279504.png) + +- `CODALAB_URL` can be changed if not testing locally. +- `USERNAME` and `PASSWORD` should correspond with the user being tested. +- `PHASE_ID` should correspond with the phase being tested on. +- `TASK_LIST` can be used to submit to specific tasks on a phase. If left blank, the submission will run on all tasks. +- `SUBMISSION_ZIP_PATH` You can fill in the absolute path of the submission directly. + +The idea here is that I'm going to test all the tasks below the competition with phase ID `215`. +Then run the script. +`python3 example_submission.py` +![image](../_attachments/102426590-91095e80-404a-11eb-9b13-3b04b6d7c05d_17528513084907422.png) + +You can see that you have successfully submitted the submission bundle. + +### View submission details +Configure the` get_submission_details.py` options before running. +![image](../_attachments/102426640-a9797900-404a-11eb-9d28-12fe9b6e9544_17528513081428964.png) + +- `CODALAB_URL` can be changed if not testing locally. +- `USERNAME` and `PASSWORD` should correspond with the user being tested. +Run the `get_submission_details`.py script with the ID of the phase containing the desired submission as the first argument. + +Since we chose `215` for our phase ID above, we'll choose `215` here. + +Then run the script. +`python3 get_submission_details.py 215` +![image](../_attachments/102426710-d29a0980-404a-11eb-9ec7-cb9c1d5cb732_17528513082572203.png) + +Find the ID of the desired submission. For example, `542`. + +Then run the script. +`python3 get_submission_details.py 215 542` +![image](../_attachments/102426762-e7769d00-404a-11eb-9f11-9df1039225a2_17528513086615834.png) + +### Finally +Finally, you can go to the competition page, add your submission, and add it to the Leaderboard! +![image](../_attachments/102426802-007f4e00-404b-11eb-88c2-305bcb789a5c_1752851308285328.png) + +On the Leaderboard, you can see the score details of each of your tasks. +![image](../_attachments/102426823-0d9c3d00-404b-11eb-8068-d8fe454dcec2_17528513087142718.png) + + +## Using the Scripts: + +### Setup: + +* Create a competition with robot submissions enabled + + [Example competition bundle](https://github.com/codalab/competitions-v2/blob/develop/src/tests/functional/test_files/competition.zip) + + +![Edit Competition Page Allow Bots Checkbox](../_attachments/87486437-3037af00-c5f0-11ea-8edf-e758c969ab84_1752851308355029.jpeg) + +* Create a user and enable the bot user flag on the Django admin page. + +![Admin Page Is Bot Checkbox](../_attachments/87486786-e9968480-c5f0-11ea-997f-b3a875f7f7d1_17528513083605943.jpeg) + +--- + +### get_competition_details.py: + +* Inside the [`get_competition_details.py`](https://github.com/codalab/competitions-v2/blob/develop/docs/example_scripts/get_competition_details.py) script, configure these options: + +![image](../_attachments/89593505-32aeb280-d804-11ea-9262-7594958f1cfe_17528513083898718.png) + +* `CODALAB_URL` can be changed if not testing locally. + +* Run the `get_competition_details` script with no arguments. + +* Find the competition you want to test on. + +* Run the `get_competition_details` script again with the competition ID as the only argument. + +* Find the phase you want to test on. + +* If you want to use the task selection feature, run the script again with the competition ID as the first argument and the phase ID as the second argument. + +* Select the task you would like to run your submission on. + +* Use the phase ID and task IDs to configure `example_submission.py`. + +--- + +### example_submission.py: + +* Inside the [`example_submission.py`](https://github.com/codalab/competitions-v2/blob/develop/docs/example_scripts/example_submission.py) script, configure these options: + +![Submission Example Options](../_attachments/89591433-03497700-d7ff-11ea-8016-517408ba4a4a_17528513083924172.png) + +* `CODALAB_URL` can be changed if not testing locally. + +* `USERNAME` and `PASSWORD` should correspond with the user being tested. + +* `PHASE_ID` should correspond with the phase being tested on. + +* `TASK_LIST` can be used to submit to specific tasks on a phase. If left blank, the submission will run on all tasks. + +* `SUBMISSION_ZIP_PATH` should be changed if testing on anything but the default "Classify Wheat Seeds" competition. An example submission can be found [here](https://github.com/codalab/competitions-v2/blob/develop/src/tests/functional/test_files/submission.zip). + +* Run this script in a python3 environment with `requests` library installed. + +--- + +### get_submission_details.py + +* Configure the [`get_submission_details.py`](https://github.com/codalab/competitions-v2/blob/develop/docs/example_scripts/get_submission_details.py) options before running. + +![Submission Details Options](../_attachments/89593680-a0f37500-d804-11ea-9bc0-88e4b7ca94e7_17528513084168103.png) + +* `CODALAB_URL` can be changed if not testing locally. + +* `USERNAME` and `PASSWORD` should correspond with the user being tested. + +* Run the `get_submission_details.py --phase ` script with the ID of the phase containing the desired submission. + +* Find the ID of the desired submission. + +* Run the `get_submission_details.py --submission ` script with the desired submission ID. + * The output of the script should be a submission object and a submission `get_details` object. This data can be used view scores, get prediction results, ect. + +* Run the `get_submission_details.py --submission -v` to save a zip containing previous info plus the original submission and logs. + * `--output ` can be used to choose where to save the zip file. Otherwise, it will be saved in the current directory. +--- + +### rerun_submission.py +Robot users have the unique permission to rerun anyone's submission on a specific task. This enables clinicians to test pre-made solutions on private datasets that exist on tasks that have no competition. + +* Configure the [`rerun_submission.py`](https://github.com/codalab/competitions-v2/blob/develop/docs/example_scripts/rerun_submission.py) options before running. + +![Rerun Submission Options](../_attachments/89593680-a0f37500-d804-11ea-9bc0-88e4b7ca94e7_17528513084168103.png) + +* `CODALAB_URL` can be changed if not testing locally. + +* `USERNAME` and `PASSWORD` should correspond with the user being tested. + +### Running the script + +1. Create a competition that allows robots, and create a user marked as a robot + user. Use that username and password below. + + +2. Get into a python3 environment with requests installed + + +3. Review this script and edit the applicable variables, like... + + ``` + CODALAB_URL + USERNAME + PASSWORD + ... + ``` + + +4. Execute the contents of this script with no additional command line arguments with + the command shown below: + + `./rerun_submission.py` + + The script is built to assist the user in the selection of the submission that will be re-run. + + +5. After selecting a submission ID from the list shown in the previous step, add that ID to + the command as a positional argument as shown below. + + `./rerun_submission.py 42` + + The script will assist the user in the selection of a task ID. + + +6. After selecting both a submission ID and a task ID, run the command again with both arguments to + see a demonstration of a robot user re-running a submission on a specific task. + + e.g. + + `./rerun_submission.py 42 a217a322-6ddf-400c-ac7d-336a42863724` diff --git a/documentation/docs/Developers_and_Administrators/Running-tests.md b/documentation/docs/Developers_and_Administrators/Running-tests.md new file mode 100644 index 000000000..a1b18e0b6 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Running-tests.md @@ -0,0 +1,39 @@ +```bash +# Without "end to end" tests +$ docker compose exec django py.test -m "not e2e" + +# "End to end tests" (a shell script to launch a selenium docker container) +$ ./run_selenium_tests.sh + +# If you are on Mac OSX it is easy to watch these tests, no need to install +# anything just do: +$ open vnc://0.0.0.0:5900 + +# And login with password "secret" +``` + +## CircleCI + +To simulate the tests run by CircleCI locally, run the following command: + +```sh +docker compose -f docker-compose.yml -f docker-compose.selenium.yml exec django py.test src/ -m "not e2e" +``` + +## Example competitions + +The repo comes with a couple examples that are used during tests: + +### v2 test data + ``` + src/tests/functional/test_files/submission.zip + src/tests/functional/test_files/competition.zip + ``` +### v1.5 legacy test data + ``` + src/tests/functional/test_files/submission15.zip + src/tests/functional/test_files/competition15.zip + ``` + +### Other Codalab Competition examples +[https://github.com/codalab/competition-examples/tree/master/v2/](https://github.com/codalab/competition-examples/tree/master/v2/) \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Submission-Docker-Container-Layout.md b/documentation/docs/Developers_and_Administrators/Submission-Docker-Container-Layout.md new file mode 100644 index 000000000..849d22375 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Submission-Docker-Container-Layout.md @@ -0,0 +1,28 @@ +When you make a submission to Codabench, the information and file are saved to the database. Afterwards, a Celery task gets sent to the compute worker (Default queue or a compute worker attached to a custom queue). From there the compute worker spins up another docker container with either the default docker image for submissions, or a custom one supplied by the organizer. + +## Site Worker +The site worker can be thought of exactly how it sounds. It's a local celery worker for the site to handle different Celery tasks and other miscellaneous functions. This is what is responsible for creating competition dumps, unpacking competitions, firing off the tasks for re-running submissions, etc. + +## Compute Worker +Is a remote and/or local celery worker that listens to the main RabbitMQ server for tasks. A compute worker can be given a special queue to listen to, or listen to the default queue. For more information on setting up a custom queue and compute worker, see: + +- [Queue Management](../Organizers/Running_a_benchmark/Queue-Management.md) +- [Compute Worker Management and Setup](../Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md) + +## Submission Container +The submission container is the container that participant's submissions get ran in. The image used to create this container is either the Codabench default if the organizer's haven't specified an image, or the custom image they specified in the competition. +The default docker image is `codalab/codalab-legacy:py37`. Organizers can specify their own image using either the [YAML file](../Organizers/Benchmark_Creation/Yaml-Structure.md) or the [editor](../Organizers/Running_a_benchmark/Competition-Management-&-List.md#edit-competition-button). + +This container is also created with some specific directories, some of which are only available at specific steps of the run. For example, generally for a submission there are 2 steps. The prediction step (If the submission needs to make predictions) and the scoring step, where the predictions are scored against the truth reference data. + +Here are the following directories: + + - `/app/input_data` Where input data will be (Only exists if input data is supplied for the task) + - `/app/output` Where all submission output should go (Should always exist) + - `/app/ingestion_program` Where the ingestion program files should exist (Only available in ingestion) + - `/app/program` Where the scoring program and/or the ingestion program should be located (Should always exist) + - `/app/input` Where any input for this step should be. (I.E: Previous predictions from ingestion for scoring. Only exists on scoring step) + - `/app/input/ref` Where the reference data should live (Not available to submissions. Only available on scoring step.) + - `/app/input/res` Where predictions/output from the prediction step should live. (Only available on scoring step) + - `/app/shared` Where any data that needs to be shared between the ingestion program and submission should exist. (Only available on scoring steps.) + - `/app/ingested_program` Where submission code should live if it is a code submission. (Only available in ingestion) \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Submission-Process-Overview.md b/documentation/docs/Developers_and_Administrators/Submission-Process-Overview.md new file mode 100644 index 000000000..5486667e5 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Submission-Process-Overview.md @@ -0,0 +1,34 @@ +![image](../_attachments/71681121-bb321580-2d40-11ea-8c0d-a1d810268ea7_17528513101128633.png) + +[Source](https://mermaidjs.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ3JhcGggVERcbkEoKFVzZXIgU3VibWlzc2lvbikpXG5Ce3tDb2RhbGFiIEZyb250IEVuZH19XG5DKENsaWVudHNpZGUgSmF2YXNjcmlwdClcbkRbQ29kYWxhYiBBUEldXG5FW0NvZGFsYWIgQmFjayBFbmRdXG5Ge3tDb21wdXRlIFdvcmtlcn19XG5cbkEtLT5CXG5CLS0-Q1xuQy0tPkJcbkMtLT5EXG5ELS0-Q1xuRC0tPkVcbkUtLT5EXG5FLS0-fFJhYmJpdE1RfEZcbkYtLT58V2ViIFNvY2tldHMgJiBSZXN1bHRzfEUiLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ): +```mermaid +graph TD +A((User Submission)) +B{{Codalab Front End}} +C(Clientside Javascript) +D[Codalab API] +E[Codalab Back End] +F{{Compute Worker}} + +A-->B +B-->C +C-->B +C-->D +D-->C +D-->E +E-->D +E-->|RabbitMQ|F +F-->|Web Sockets & Results|E +``` + + +## Overview: +- When making a submission to Codabench, the website uses a client-side javascript to send the submission file along with proper details to an API point for submissions. +- Once the API receives the new submission, Codabench's back-end fires off a Celery task through RabbitMQ. +- This task is picked up by a Codabench Compute Worker listening in on the associated RabbitMQ. The Compute Worker starts processing the data. +- The compute worker begins execution by creating the container the submission will run in using the organizer's specified docker image for the competition. +- Once the container is created, the scoring program and other necessary organizer and user supplied binaries are executed to produce results. While the submission is processing, communication back to the Codabench instance is possible through web-sockets. +- Once the submission is done processing, it moves the output to the proper folders, and the compute worker posts these scores (if found) to the Codabench API. +- From here, the submission is done processing and is marked as failed/finished. If at any part of the processing step (Scoring/Ingestion step of the submission) an exception is raised, the compute worker will halt and send all current output. + + diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Add-line-into-.env-for-default-queue-worker-duration.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Add-line-into-.env-for-default-queue-worker-duration.md new file mode 100644 index 000000000..48a1e4222 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Add-line-into-.env-for-default-queue-worker-duration.md @@ -0,0 +1,8 @@ +!!! note "This intervention is needed when upgrading from a version equal or lower than [v1.7.0](https://github.com/codalab/codabench/releases/tag/v1.7.0)" + +You will need to add the following line into your `.env` file +```ini title=".env" +MAX_EXECUTION_TIME_LIMIT=600 # time limit for the default queue (in seconds) +``` + +This will change the maximum time a job can run on the default queue of your instance, as noted [here](https://github.com/codalab/codabench/pull/1154) \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Create-new-logos-for-each-competition.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Create-new-logos-for-each-competition.md new file mode 100644 index 000000000..37570a628 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Create-new-logos-for-each-competition.md @@ -0,0 +1,31 @@ +!!! note "This intervention is needed when upgrading from a version equal or lower than [v1.4.1](https://github.com/codalab/codabench/releases/tag/v1.4.1)" + +In order to create a "logo icon" for each existing competition + +1. Shell into django +```bash +docker compose exec django bash +python manage.py shell_plus --plain +``` + +2. Get competitions that don't have logo icons +```python +import io, os +from PIL import Image +from django.core.files.base import ContentFile +comps_no_icon_logo = Competition.objects.filter(logo_icon__isnull=True) +all = Competition.objects.all() +len(Competition.objects.all()) +len(comps_no_icon_logo) +``` + +3. Then run this script +```python +for comp in comps_no_icon_logo: + try: + comp.make_logo_icon() + comp.save() + except Exception as e: + print(f"An error occurred: {e}") + print(comp) +``` diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Database-size-fixes.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Database-size-fixes.md new file mode 100644 index 000000000..ce63ac505 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Database-size-fixes.md @@ -0,0 +1,114 @@ +!!! warning + You need to stop the database from being changed while running these commands. + They might take time to complete depending on the size of your database. + + +Start maintenance mode: +```sh +touch maintenance/maintenance.on +``` + +### 1. Django migration ([1774](https://github.com/codalab/codabench/pull/1774), [1752](https://github.com/codalab/codabench/pull/1752)) + +```sh +docker compose exec django ./manage.py migrate +``` + +### 2. Reset User Quota from Bytes to GB ([1749](https://github.com/codalab/codabench/pull/1749)) + +```sh +docker compose exec django ./manage.py shell_plus +``` + +```python +from profiles.quota import reset_all_users_quota_to_gb +reset_all_users_quota_to_gb() +``` + +```python +# Convert all 16 GB quota into 15 GB +from profiles.models import User +users = User.objects.all() +for user in users: + # Reset quota to 15 if quota is between 15 and 20 + # Do not reset quota for special users like adrien + if user.quota > 15 and user.quota < 20: + user.quota = 15 + user.save() +``` + + +### 3. Important for file sizes cleanup ([1752](https://github.com/codalab/codabench/pull/1752)) + +We have some critical changes here so before deployment we should run the following 3 blocks of code to get the last ids of `Data`, `Submission` and `SubmissionDetail` + +Then, in the shell_plus: + +```python +# Get the maximum ID for Data +from datasets.models import Data +latest_id_data = Data.objects.latest('id').id +print("Data Last ID: ", latest_id_data) +``` + +```python +# Get the maximum ID for Submission +from competitions.models import Submission +latest_id_submission = Submission.objects.latest('id').id +print("Submission Last ID: ", latest_id_submission) +``` + +```python +# Get the maximum ID for Submission Detail +from competitions.models import SubmissionDetails +latest_id_submission_detail = SubmissionDetails.objects.latest('id').id +print("SubmissionDetail Last ID: ", latest_id_submission_detail) +``` + +After we have the latest ids, we should deploy and run the 3 blocks of code below to fix the sizes i.e. to convert all kib to bytes to make everything consistent. For new files uploaded after the deployment, the sizes will be saved in bytes automatically that is why we need to run the following code for older files only. + +```python +# Run the conversion only for records with id <= latest_id +from datasets.models import Data +for data in Data.objects.filter(id__lte=latest_id_data): + if data.file_size: + data.file_size = data.file_size * 1024 # Convert from KiB to bytes + data.save() +``` + +```python +# Run the conversion only for records with id <= latest_id +from competitions.models import Submission +for sub in Submission.objects.filter(id__lte=latest_id_submission): + updated = False # Track if any field is updated + + if sub.prediction_result_file_size: + sub.prediction_result_file_size = sub.prediction_result_file_size * 1024 # Convert from KiB to bytes + updated = True + + if sub.scoring_result_file_size: + sub.scoring_result_file_size = sub.scoring_result_file_size * 1024 # Convert from KiB to bytes + updated = True + + if sub.detailed_result_file_size: + sub.detailed_result_file_size = sub.detailed_result_file_size * 1024 # Convert from KiB to bytes + updated = True + + if updated: + sub.save() +``` + +```python +# Run the conversion only for records with id <= latest_id +from competitions.models import SubmissionDetails +for sub_det in SubmissionDetails.objects.filter(id__lte=latest_id_submission_detail): + if sub_det.file_size: + sub_det.file_size = sub_det.file_size * 1024 # Convert from KiB to bytes + sub_det.save() +``` + +Then, do not forget to stop maintenance mode: + +```sh +rm maintenance/maintenance.on +``` diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Homepage-counters.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Homepage-counters.md new file mode 100644 index 000000000..9d3966613 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Homepage-counters.md @@ -0,0 +1,18 @@ +!!! note "After upgrading from Codabench <1.15, you will need to follow these steps to compute the homepage counters. See [this](https://github.com/codalab/codabench/pull/1694) for more information" + +1. Re-build containers + +```bash +docker compose build && docker compose up -d +``` + +2. Update the homepage counters (to avoid waiting 1 day) + +```bash +docker compose exec django ./manage.py shell_plus +``` + +```python +from analytics.tasks import update_home_page_counters +eager_results = update_home_page_counters.apply_async() +``` \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Move-the-last-storage_inconsistency-files-from--logs-folder-to--var-logs--folder.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Move-the-last-storage_inconsistency-files-from--logs-folder-to--var-logs--folder.md new file mode 100644 index 000000000..a32d781c3 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Move-the-last-storage_inconsistency-files-from--logs-folder-to--var-logs--folder.md @@ -0,0 +1,17 @@ +!!! note "This intervention is needed when upgrading from a version equal or lower than [v1.11.0](https://github.com/codalab/codabench/releases/tag/v1.11.0)" + +You will need to move the last storage_inconsistency files from /logs folder to /var/logs/ folder. + +```bash +cd codabench +cp -r logs/* var/logs +``` + +You will also need to rebuild the celery image because of a version change that's needed. +```bash +docker compose down +docker images # Take the ID of the celery image +docker rmi *celery_image_id* +docker compose up -d +``` +More information [here](https://github.com/codalab/codabench/pull/1575) \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Rebuilding-all-docker-images.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Rebuilding-all-docker-images.md new file mode 100644 index 000000000..5466beaf6 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Rebuilding-all-docker-images.md @@ -0,0 +1,16 @@ +!!! note "This intervention is needed when upgrading from a version equal or lower than [v1.9.2](https://github.com/codalab/codabench/releases/tag/v1.9.2)" + + +Since we are now using Poetry, we need to rebuild all our docker images to include it. + +You can achieve this by running the following commands : + +!!! warning + If your machine has other images or containers that you want to keep, do not run `docker system prune -af`. Instead, manually delete all the images related to codabench + +```bash +docker compose build && docker compose up -d +docker system prune -a +``` + +More information (and alternative commands) [here](https://github.com/codalab/codabench/pull/1416) \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Submissions-and-Participants-Counts.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Submissions-and-Participants-Counts.md new file mode 100644 index 000000000..7826f32c2 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Submissions-and-Participants-Counts.md @@ -0,0 +1,41 @@ +!!! note "After upgrading from Codabench <1.14, you will need to follow these steps to compute the submissions and participants counts on the competition pages. See [this](https://github.com/codalab/codabench/pull/1669) for more information" + + +## 1. Re-build containers + +```bash +docker compose build && docker compose up -d +``` + +## 2. Migration + +```sh +docker compose exec django ./manage.py migrate +``` + +## 3. Update counts for all competitions + +Bash into django console +``` +docker compose exec django ./manage.py shell_plus +``` + +Import and call the function +```python +from competitions.submission_participant_counts import compute_submissions_participants_counts +compute_submissions_participants_counts() +``` + +## 4. Feature some competitions in home page + +There are two ways to do it: +1. Use Django admin -> click the competition -> scroll down to is featured filed -> Check/Uncheck it +2. Use competition ID in the django bash to feature / unfeature a competition +```bash +docker compose exec django ./manage.py shell_plus +``` +```python +comp = Competition.objects.get(id=) # replace with competition id +comp.is_featured = True # set to False if you want to unfeature a competition +comp.save() +``` diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Uncomment-a-line-in-your-.env-file.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Uncomment-a-line-in-your-.env-file.md new file mode 100644 index 000000000..54085ef39 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Uncomment-a-line-in-your-.env-file.md @@ -0,0 +1,8 @@ +!!! note "This intervention is needed when upgrading from a version equal or lower than [v1.8.0](https://github.com/codalab/codabench/releases/tag/v1.8.0)" + + +After the Caddy upgrade, you will need to uncomment a line in your `.env` file: +```ini title=".env" +TLS_EMAIL = "your@email.com" +``` +More information [here](https://github.com/codalab/codabench/pull/1424) \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Upgrade-RabbitMQ.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Upgrade-RabbitMQ.md new file mode 100644 index 000000000..0d519e607 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Upgrade-RabbitMQ.md @@ -0,0 +1,38 @@ +!!! note "This intervention is needed when upgrading from a version equal or lower than [v1.0.0](https://github.com/codalab/codabench/releases/tag/v1.0.0)" + +## Backup RabbitMQ settings +Go to `http://:/api/definitions` and save the response (enter login and password as configured in `.env`) + +For example: + +![image](../../_attachments/72eb2b73-768d-4ee5-b42b-280ff2b63af3_17528513095488863.jpg) + +!!! warning "Do not submit any submission and wait until all submissions are processed" + +## Stop and remove RabbitMQ's container and data + +```bash +docker compose stop rabbit && docker compose rm rabbit +sudo rm -rvf var/rabbit/* +``` + +## Switch to the latest RabbitMQ version + +Add `WORKER_CONNECTION_TIMEOUT=` into your `.env` file with your custom value. Then execute: + +```bash +git pull +docker compose build rabbit +docker compose up -d +``` + +## Restore the backup settings +Connect to the instance by ssh and upload your json file at 1st step, execute : + +```bash +curl -u : -H "Content-Type: application/json" -X POST -T .json http://localhost:/api/definitions +``` + +You can check if it succeeded by doing the 1st step. + +## Verify that your submission can be processed. \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/User-removal.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/User-removal.md new file mode 100644 index 000000000..da7d554b4 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/User-removal.md @@ -0,0 +1,5 @@ +!!! note "After upgrading from Codabench <1.17, you will need to perform a Django migration ([#1715](https://github.com/codalab/codabench/pull/1715), [#1741](https://github.com/codalab/codabench/pull/1741))" + +```bash +docker compose exec django ./manage.py migrate +``` \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Worker-Docker-Image-manual-update.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Worker-Docker-Image-manual-update.md new file mode 100644 index 000000000..8c088955f --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/Worker-Docker-Image-manual-update.md @@ -0,0 +1,19 @@ +!!! note "This intervention is needed when upgrading from a version equal or lower than [v1.3.1](https://github.com/codalab/codabench/releases/tag/v1.3.1)" + +To update your worker docker image, you can launch the following code in the terminal on the machine where your worker is located. + +```bash +docker stop compute_worker +docker rm compute_worker +docker pull codalab/competitions-v2-compute-worker:latest +docker run \ + -v /codabench:/codabench \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -d \ + --env-file .env \ + --name compute_worker \ + --restart unless-stopped \ + --log-opt max-size=50m \ + --log-opt max-file=3 \ + codalab/competitions-v2-compute-worker:latest +``` \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/index.md b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/index.md new file mode 100644 index 000000000..aa9c8a658 --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Upgrading_Codabench/index.md @@ -0,0 +1,25 @@ +## Upgrade Codabench + +```sh +cd codabench +git pull +docker compose build && docker compose up -d +docker compose exec django ./manage.py migrate +docker compose exec django ./manage.py collectstatic --noinput +``` + +## Manual interventions + +You can find here various manual intervention needed depending on which version you are upgrading from: + +- [Upgrade RabbitMQ](Upgrade-RabbitMQ.md) (version < 1.0.0) +- [Create new logos for each competition](Create-new-logos-for-each-competition.md) (version < 1.4.1) +- [Worker Docker Image manual update](Worker-Docker-Image-manual-update.md) (version < 1.3.1) +- [Add line into `.env` for default queue worker duration](Add-line-into-.env-for-default-queue-worker-duration.md) (version < 1.7.0) +- [Uncomment a line in your `.env` file](Uncomment-a-line-in-your-.env-file.md) (version < 1.8.0) +- [Rebuilding all docker images](Rebuilding-all-docker-images.md) (version < 1.9.2) +- [Move the last storage_inconsistency files from logs folder to var logs folder](Move-the-last-storage_inconsistency-files-from--logs-folder-to--var-logs--folder.md) (version < 1.12.0) +- [Submissions and Participants Counts](Submissions-and-Participants-Counts.md) (version < 1.14.0) +- [Homepage counters](Homepage-counters.md) (version < 1.15.0) +- [User removal](User-removal.md) (version < 1.17.0) +- [Database size Fix](Database-size-fixes.md) (version < 1.18.0) \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/Validation-and-deployment-of-pull-requests.md b/documentation/docs/Developers_and_Administrators/Validation-and-deployment-of-pull-requests.md new file mode 100644 index 000000000..f30418ada --- /dev/null +++ b/documentation/docs/Developers_and_Administrators/Validation-and-deployment-of-pull-requests.md @@ -0,0 +1,151 @@ +## 1. Local testing and validation of the changes + +### Setup + +Required: +- "Maintain" role on the repository +- A working local installation + +Pull the changes, checkout the branch you are testing and deploy your local instance: + +```bash +cd codabench +git pull +git checkout branch +docker compose up -d +``` + +If necessary, migrate and collect static files (see this [page](Codabench-Installation.md)). + +!!! note + If the branch with the changes is from an external repository, you can create a branch in Codabench's repository and make a first merging into this new branch. Then, you'll be able to merge the new branch into master. This way, the automatic tests will be triggered. + + _EDIT: It may be possible to trigger the tests even if the branch is external. To be confirmed._ + +### Testing + +Here is the usual checklist in order to validate the pull request: + +![](_attachments/3b003311-df9b-42bb-9c20-0d3231db328a_17534366441039398.jpg) + +The contributor may have provided guidelines for testing that you should follow. +In addition to this: + +- Testing must be thorough, really trying to break the new changes. Try as many use cases as possible. Do not trust the contributor. +- In addition to the checklist of the PR, you can follow this checklist to check that the basic functionalities of the platform are still working: [manual validation](Manual-validation.md) + +### Merging + +Once everything is validated, merge the pull request. +If there are many minor commits, use "squash and merge" to merge them into one. + +![](_attachments/eaedaeae-1690-473b-8934-dc92271917c1_1753436644337235.jpg) + +You can then safely click on `Delete branch`. It is a good practice to keep the project clean. + + +## Update the test server + +Here are the necessary steps to update the Codabench server to reflect the last changes. We prodive here general guidelines that work for both the test server and the production server. + +### Log into the server +```bash +ssh codabench-server +cd /home/codalab/codabench +``` + +Replace `codabench-server` by your own SSH host setting, or the IP address of the server. + +!!! note + Make sure to log in as the user that deployed the containers. + +### Pull the last change +!!! tip + - If you are deploying on a test server, you can use the `develop` branch. + - If you are deploying on a Production server, we strongly adivse on using the `master` branch. + +```bash +docker compose down +git status +git pull +docker compose up -d +``` + +### Restart Django +```bash +docker compose stop django +docker compose rm django +docker compose create django +docker compose start django +``` + +If `docker compose` does not exist, use `docker-compose`. + +### Database migration + +```bash +docker compose exec django ./manage.py migrate +``` + +!!! warning "Do not use `makemigrations`" + +!!! note "_Remark: [we need to solve the migration files configuration](https://github.com/codalab/codabench/issues/1109). In the meantime, `makemigrations --merge` may be needed._" + +### Collect static files +```bash +docker compose exec django ./manage.py collectstatic --noinput +``` + +### Final testing + +- Access the platform from your browser +- You may need a hard refresh (Maj + R) so the changes take effect. +- Check that everything is working fine, the new changes, and the basic functionalities of the platform + + +## Merge develop into master + +Once some pull requests (~3 - 10) were merged into `develop`, we can prepare a merge into `master`. +Simply create a new pull request from Github interface, selecting `master` as the base branch: + +![](_attachments/c1fd3ba3-f3a8-457b-a0fd-c664ae7e361d_17534366440875823.jpg) + +In the text of the PR, link all relevant PR made to develop, and indicate the URL of the test server. +Example: [https://github.com/codalab/codabench/pull/1166](https://github.com/codalab/codabench/pull/1166) + +## Update the production server + +Same procedure as [Update the test server](#update-the-test-server), but on the production server. + + +!!! tip + **Do not forget to access the platform and perform a final round of live testing after the deployment.** + +## Creating a Release +Once the develop branch has been merged into master, it is possible to use the Github interface to tag the commit of the merge and create a release containing all the changes as well as manual interventions if needed. + +For this, you will need to go to the [release page](https://github.com/codalab/codabench/releases) and click on `Draft a new release` + +![image](../_attachments/88c04254-7333-4aea-8351-95ab83e02eaa_1752851311028784.jpg) + +Afterwards, you click on `Choose a tag` and enter the tag you want to create (in this exemple, 1.17.0 which doesn't exist yet) + +![image](../_attachments/bfeb57be-c926-4da2-bb0e-7ff00193872f_17528513112279325.jpg) + +You can then choose the targeted branch to create the tag on (`master` in our case) and then click on `Generate release notes` +Github will automatically generate releases based on the new commits compared to the last tag. + +![image](../_attachments/29e74b35-7e47-4a6a-b85c-341f4bf9fa96_17528513113086753.jpg) + +You can then change the text format however you like, as well as add things like Manual Intervention if there are any. + +When you are done, you publish the release. + +![image](../_attachments/000c3096-13b4-4d25-a8e1-efcba0fb75fd_17528513114340215.jpg) + + +## TODO + +Add a note about: + +- Merging the github action PR to update the release tag \ No newline at end of file diff --git a/documentation/docs/Developers_and_Administrators/_attachments/214587579-53b8f79c-dc51-4323-b48d-360dd7b5774f_1753436642870153.png b/documentation/docs/Developers_and_Administrators/_attachments/214587579-53b8f79c-dc51-4323-b48d-360dd7b5774f_1753436642870153.png new file mode 100644 index 000000000..1dc815e8c Binary files /dev/null and b/documentation/docs/Developers_and_Administrators/_attachments/214587579-53b8f79c-dc51-4323-b48d-360dd7b5774f_1753436642870153.png differ diff --git a/documentation/docs/Developers_and_Administrators/_attachments/38c0d1ce-9b27-44bb-804b-c4eed55613df_17534366434285173.jpg b/documentation/docs/Developers_and_Administrators/_attachments/38c0d1ce-9b27-44bb-804b-c4eed55613df_17534366434285173.jpg new file mode 100644 index 000000000..f34537690 Binary files /dev/null and b/documentation/docs/Developers_and_Administrators/_attachments/38c0d1ce-9b27-44bb-804b-c4eed55613df_17534366434285173.jpg differ diff --git a/documentation/docs/Developers_and_Administrators/_attachments/3b003311-df9b-42bb-9c20-0d3231db328a_17534366441039398.jpg b/documentation/docs/Developers_and_Administrators/_attachments/3b003311-df9b-42bb-9c20-0d3231db328a_17534366441039398.jpg new file mode 100644 index 000000000..a8fad99ca Binary files /dev/null and b/documentation/docs/Developers_and_Administrators/_attachments/3b003311-df9b-42bb-9c20-0d3231db328a_17534366441039398.jpg differ diff --git a/documentation/docs/Developers_and_Administrators/_attachments/47b45c3e-13ed-4870-a83d-a25338aeaa39_17534366434936385.jpg b/documentation/docs/Developers_and_Administrators/_attachments/47b45c3e-13ed-4870-a83d-a25338aeaa39_17534366434936385.jpg new file mode 100644 index 000000000..f97216c1a Binary files /dev/null and b/documentation/docs/Developers_and_Administrators/_attachments/47b45c3e-13ed-4870-a83d-a25338aeaa39_17534366434936385.jpg differ diff --git a/documentation/docs/Developers_and_Administrators/_attachments/5c8aae99-0cbb-4ffa-87aa-0e9d3f6fd018_17534366434342587.jpg b/documentation/docs/Developers_and_Administrators/_attachments/5c8aae99-0cbb-4ffa-87aa-0e9d3f6fd018_17534366434342587.jpg new file mode 100644 index 000000000..8d349aa61 Binary files /dev/null and b/documentation/docs/Developers_and_Administrators/_attachments/5c8aae99-0cbb-4ffa-87aa-0e9d3f6fd018_17534366434342587.jpg differ diff --git a/documentation/docs/Developers_and_Administrators/_attachments/6ec1780d-227f-472e-84fd-1d08847a24b8_1753436644389027.jpg b/documentation/docs/Developers_and_Administrators/_attachments/6ec1780d-227f-472e-84fd-1d08847a24b8_1753436644389027.jpg new file mode 100644 index 000000000..fe4343626 Binary files /dev/null and b/documentation/docs/Developers_and_Administrators/_attachments/6ec1780d-227f-472e-84fd-1d08847a24b8_1753436644389027.jpg differ diff --git a/documentation/docs/Developers_and_Administrators/_attachments/c0fdd7ff-0c46-4bae-b9e2-7d4e0b774ec2_17534366434447145.jpg b/documentation/docs/Developers_and_Administrators/_attachments/c0fdd7ff-0c46-4bae-b9e2-7d4e0b774ec2_17534366434447145.jpg new file mode 100644 index 000000000..4b4479093 Binary files /dev/null and b/documentation/docs/Developers_and_Administrators/_attachments/c0fdd7ff-0c46-4bae-b9e2-7d4e0b774ec2_17534366434447145.jpg differ diff --git a/documentation/docs/Developers_and_Administrators/_attachments/c1fd3ba3-f3a8-457b-a0fd-c664ae7e361d_17534366440875823.jpg b/documentation/docs/Developers_and_Administrators/_attachments/c1fd3ba3-f3a8-457b-a0fd-c664ae7e361d_17534366440875823.jpg new file mode 100644 index 000000000..255b7a935 Binary files /dev/null and b/documentation/docs/Developers_and_Administrators/_attachments/c1fd3ba3-f3a8-457b-a0fd-c664ae7e361d_17534366440875823.jpg differ diff --git a/documentation/docs/Developers_and_Administrators/_attachments/de2a053f-c804-4c2a-a7ff-0df189c1d79c_17534366434691174.jpg b/documentation/docs/Developers_and_Administrators/_attachments/de2a053f-c804-4c2a-a7ff-0df189c1d79c_17534366434691174.jpg new file mode 100644 index 000000000..3e858903b Binary files /dev/null and b/documentation/docs/Developers_and_Administrators/_attachments/de2a053f-c804-4c2a-a7ff-0df189c1d79c_17534366434691174.jpg differ diff --git a/documentation/docs/Developers_and_Administrators/_attachments/eaedaeae-1690-473b-8934-dc92271917c1_1753436644337235.jpg b/documentation/docs/Developers_and_Administrators/_attachments/eaedaeae-1690-473b-8934-dc92271917c1_1753436644337235.jpg new file mode 100644 index 000000000..be121724e Binary files /dev/null and b/documentation/docs/Developers_and_Administrators/_attachments/eaedaeae-1690-473b-8934-dc92271917c1_1753436644337235.jpg differ diff --git a/documentation/docs/Newsletters_Archive/CodaLab-in-2024.md b/documentation/docs/Newsletters_Archive/CodaLab-in-2024.md new file mode 100644 index 000000000..353c1c2a9 --- /dev/null +++ b/documentation/docs/Newsletters_Archive/CodaLab-in-2024.md @@ -0,0 +1,95 @@ +## CodaLab in 2024 +### A Year of Breakthroughs and New Horizons with Codabench + +Welcome to the first edition of CodaLab’s newsletter! This year has been full of novelty, success, and scientific progress. The platform is breaking records of participation and number of organized competitions, and [Codabench](https://codabench.org/), the new version of [CodaLab](https://codalab.lisn.fr/), had a very promising launch. Let’s dive into more details. + +![image_2025_01_30T15_23_35_261Z](../_attachments/991c18dc-3baa-4d69-b157-6a5561e6798d_17528513106457524.jpg) + + +## Unprecedented engagement +In October, Codabench has registered its **10,000th user**! From about 100 daily submissions in January, it is now **more than 500 daily submissions** that are handled on the servers. In 2024, more than 20,000 new users have registered on CodaLab, whereas more than 12,000 on Codabench. + +**249 public competitions** have been created on CodaLab, whereas **193 on Codabench: +15%** of total competitions of both platforms compared to 2023. CodaLab continues to handle a large number of submissions, as many past competitions remain active even after they have officially ended: **240,000 submissions on CodaLab** whereas **83,000 on Codabench**. + +Contributors community is very active with **143 pull requests** this year. Since the platform is still relatively new, the primary focus has been on bug fixes, security and performance enhancements, and administrative features, accounting for approximately two-thirds of the pull requests. Nevertheless, we are keen on improving the experience for both participants and organizers. We have set a versioning and a release-notes follow-up to give more visibility to the platform evolution and maturity. + +![pie-chart](../_attachments/2b41574f-9597-47c0-b492-cf427eba7eff_17528513107025487.jpg) + + +## Introducing Codabench +[Codabench](https://codabench.org/), the modernized version of [CodaLab](https://codalab.lisn.fr/), was released in summer 2023, and [presented at JCAD days](https://www.canal-u.tv/chaines/jcad/codalab-competitions-and-codabench-open-source-platforms-to-organize-scientific) in November 2024! Codabench platform software is now concentrating all development effort of the community. In addition to CodaLab features, it offers improved performance, live logs, more transparency, data-centric benchmarks and more! + +We warmly encourage you to use [codabench.org](https://codabench.org/) for all your new competitions and benchmarks. Note that CodaLab bundles are compatible with Codabench, easing the transition, as explained in the following Wiki page: [How-to-transition-from-CodaLab-to-Codabench](https://github.com/codalab/codabench/wiki/How-to-transition-from-CodaLab-to-Codabench%3F) + +CodaLab and Codabench are hosted on servers located at [Paris-Saclay university](https://www.universite-paris-saclay.fr/), maintained by [LISN lab](http://lisn.upsaclay.fr/). + + +## Spotlight on competitions +The most popular competition this year, featuring **520 participants**, was the SemEval task [Bridging the Gap in Text-Based Emotion Detection](https://www.codabench.org/competitions/3863). The task of this competition focused on identifying the emotion that most people would associate with a speaker based on a given sentence or short text snippet. + +The competition with the highest reward, a **prize pool of $100,000**, was the [Global Artificial Intelligence Championships](https://www.codabench.org/competitions/2325/), track Maths 2024, a pioneering contest that aimed to advance the development of artificial intelligence tools for solving advanced mathematical problems across multiple levels of difficulty ([full report here](https://www.agiodyssey.org/pdf/GAIC_2024_Report.pdf)). + +Codabench featured interesting **NeurIPS 2024 challenges**: + +- The [LLM Privacy Challenge](https://llm-pc.github.io/), where participants were divided into two teams: [Red Team](https://www.codabench.org/competitions/3283/) and [Blue Team](https://www.codabench.org/competitions/3288/), each one aiming at developing attack and defense approaches for data privacy in LLMs. +- [Fair Universe - Higgs Uncertainy Challenge](https://www.codabench.org/competitions/2977/), exploring uncertainty-aware AI techniques for High Energy Physics (HEP). +- The [Concordia Challenge](https://www.codabench.org/competitions/3888/), focusing on improving the cooperative intelligence of AI systems: promise-keeping, negotiation, reciprocity, reputation, partner choice, compromise, and sanctioning. +- The [Erasing the Invisible Challenge](https://www.codabench.org/competitions/3857/), where the task is to remove invisible watermarks from images, while preserving the overall image quality. +- Codabench also hosted the [NeurIPS 2024 Checklist Assistant](https://www.codabench.org/competitions/2338/), a self-service tool for the NeurIPS 2024 checklist. This verification assistant helps authors confirm their papers’ compliance and submit improved versions based on the Assistant’s feedback. For more details check out the [blog post](https://blog.neurips.cc/2024/05/07/soliciting-participants-for-the-neurips-2024-checklist-assistant-study/) and the [experiment results](https://blog.neurips.cc/2024/12/10/results-of-the-neurips-2024-experiment-on-the-usefulness-of-llms-as-an-author-checklist-assistant-for-scientific-papers/). + +Last but not least, Codabench featured several competitions in the fields of medicine and biology, such as the [Dental CBCT Scans](https://www.codabench.org/competitions/3025/), [Panoramic X-ray Images](https://www.codabench.org/competitions/3024/), [Butterfly Hybrid Detection](https://www.codabench.org/competitions/3764/), and [Monitoring Age-related Macular Degeneration Progression In Optical Coherence Tomography](https://www.codabench.org/competitions/2852/). + +We’d like to thank the whole community for these exceptional scientific contributions. You can explore more challenges in the [public listing](https://www.codabench.org/competitions/public/?page=1). + +## What about the future? +We always develop new features to serve the state-of-the art of Machine Learning science. We plan to invest effort in **handling medical data**, improving **federated learning** use-cases, and allowing **human-in-the loop** feedback for better AI experience. + +The **platform interface will also be improved** for better visibility and facilitated re-use of datasets, tasks or solutions generated through it. + +Keep in touch and give us feedback on your experience on Codabench ! + +## Community +Reminder on our communication tools: + +- Join our [google forum](https://groups.google.com/g/codalab-competitions) to emphasize your competitions and events +- Contact us for any question: info@codalab.org +- Write an issue on [github](https://github.com/codalab/codabench) about interesting suggestions + +Please cite one of these papers when working with our platforms: + +``` +@article{codabench, + title = {Codabench: Flexible, easy-to-use, and reproducible meta-benchmark platform}, + author = {Zhen Xu and Sergio Escalera and Adrien Pavão and Magali Richard and + Wei-Wei Tu and Quanming Yao and Huan Zhao and Isabelle Guyon}, + journal = {Patterns}, + volume = {3}, + number = {7}, + pages = {100543}, + year = {2022}, + issn = {2666-3899}, + doi = {https://doi.org/10.1016/j.patter.2022.100543}, + url = {https://www.sciencedirect.com/science/article/pii/S2666389922001465} +} +``` + +``` +@article{codalab_competitions_JMLR, + author = {Adrien Pavao and Isabelle Guyon and Anne-Catherine Letournel and Dinh-Tuan Tran and Xavier Baro and Hugo Jair Escalante and Sergio Escalera and Tyler Thomas and Zhen Xu}, + title = {CodaLab Competitions: An Open Source Platform to Organize Scientific Challenges}, + journal = {Journal of Machine Learning Research}, + year = {2023}, + volume = {24}, + number = {198}, + pages = {1--6}, + url = {http://jmlr.org/papers/v24/21-1436.html} +} +``` + +## Last words +Thank you for reading the first edition of our newsletter. We look forward to sharing more exciting updates, competitions, and breakthroughs with you soon. Until then, keep exploring, keep competing, and stay inspired! + +![partners](_attachments/96bbc3a0-cb9b-479a-85c8-ba795c59d6f4_1753436671847627.jpg) + + + diff --git a/documentation/docs/Newsletters_Archive/_attachments/96bbc3a0-cb9b-479a-85c8-ba795c59d6f4_1753436671847627.jpg b/documentation/docs/Newsletters_Archive/_attachments/96bbc3a0-cb9b-479a-85c8-ba795c59d6f4_1753436671847627.jpg new file mode 100644 index 000000000..7ec23e7ce Binary files /dev/null and b/documentation/docs/Newsletters_Archive/_attachments/96bbc3a0-cb9b-479a-85c8-ba795c59d6f4_1753436671847627.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/Advanced-Tutorial.md b/documentation/docs/Organizers/Benchmark_Creation/Advanced-Tutorial.md new file mode 100644 index 000000000..4c4c1b791 --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Advanced-Tutorial.md @@ -0,0 +1,164 @@ + +Here is an advanced tutorial. If you are new to CodaBench, please refer to [get started tutorial](https://github.com/codalab/codabench/wiki/Getting-started-with-Codabench) first. +In this article, you'll learn how to use more advanced features and how to create benchmarks using either the editor or bundles. +Before proceeding to our tutorial, make sure you have registered for an account on the [Codabench](https://www.codabench.org/) website. + +The image below is an overview of the benchmark creation process +![image](../../_attachments/102429234-771d4b00-404d-11eb-9ec3-bc75d39d3194_17528513092407322.png) + +## Creating a Benchmark by Editor + +In this chapter, I'll take you step by step through the Editor's approach to creating benchmark, including algorithm type and dataset type. + +### Step 1: Click on Management in the top right corner of Codabench's home page under Competitions. +![image](../../_attachments/102429989-a9c74380-404d-11eb-8b99-9e7829fe8678_17528513092920961.png) +When you click on it, you will see the screen as shown in the screenshot below. +![image](../../_attachments/102430225-b9468c80-404d-11eb-81f1-879138afad2c_175285130932125.png) + +### Step 2: Click on the Create button in the top right corner of Competition Management. +![image](../../_attachments/102430591-d24f3d80-404d-11eb-8adf-1f562d2f9cb4_17528513093284764.png) + +### Step 3: Fill in the Details tab content. + +![image](../../_attachments/102431578-12aebb80-404e-11eb-8d07-d74e9de46280_17528513097437637.png) + +### Step 4: Fill in the Participant Tab. + +![image](../../_attachments/102431721-1d695080-404e-11eb-87a4-92a4b43b349c_1752851309399166.png) + +### Step 5: Fill in the Pages Tab. + +![image](../../_attachments/102431937-2c500300-404e-11eb-9a28-344f26d79013_17528513093988035.png) + +### Step 6: Fill in the Phases Tab. + +![image](../../_attachments/102432087-36720180-404e-11eb-9dda-a593d7a45af2_17528513094299598.png) + +![image](../../_attachments/102432234-40940000-404e-11eb-8a3d-1e72b2688267_17528513094664094.png) + +When you click on the Manage Tasks/Datasets button, you will see the screenshot shown below + +Click the Add Dataset button in the diagram to upload the resource files needed to create the competition. + +![image](../../_attachments/102432435-4d185880-404e-11eb-967f-1735f6a9f145_17528513094839308.png) + +Creating a phase will require a bundle of the following types (.zip format), I'll give you more details on how to write these bundle later. + +Now you just need to have this concept in your mind + +![image](../../_attachments/102432573-56092a00-404e-11eb-9788-512586edd693_1752851309496168.png) + +Here are the screenshots of the 5 types of bundles after they were uploaded + +![image](../../_attachments/102432684-5e616500-404e-11eb-8b82-8ea332050cdf_17528513095790792.png) + +![image](../../_attachments/102432819-67523680-404e-11eb-9032-b725058ffa3c_17528513102032712.png) + +![image](../../_attachments/102432974-71743500-404e-11eb-95ef-84d39597a412_1752851309572427.png) + +![image](../../_attachments/102433142-7b963380-404e-11eb-9ad0-035eb60d7f64_17528513096323566.png) + +### Step 7: Fill in the Leaderboard Tab. + +![image](../../_attachments/102433276-84870500-404e-11eb-8638-60eeab21fe8d_17528513096378942.png) + +![image](../../_attachments/102433391-8c46a980-404e-11eb-871c-6d443be44062_1752851309654381.png) + +### Step 8: Save and Publish the Benchmark + +![image](../../_attachments/102433537-95377b00-404e-11eb-8649-57f70a830564_1752851309686341.png) + +![image](../../_attachments/102433657-9cf71f80-404e-11eb-9aa0-d23cf595c7db_1752851309773052.png) + + + +## Creating a Benchmark by Bundle + +Creating a benchmark through bundles is a much more efficient way than using editors. + +### Simple Version Example: CLASSIFY WHEAT SEEDS + +### Step 1: Download bundle + +https://github.com/codalab/competition-examples/blob/master/codabench/wheat_seeds/code_submission_bundle.zip + +Click on the link above to download the bundle in the screenshot. + +![image](../../_attachments/102433828-aa140e80-404e-11eb-9886-3f6960eb6a5e_17528513100792131.png) + + +### Step 2: Go to the benchmark upload page + +![image](../../_attachments/102433943-b1d3b300-404e-11eb-9594-39de8566c6a0_17528513097862737.png) + +![image](../../_attachments/102433960-bbf5b180-404e-11eb-8102-26c03d5084b8_17528513098046653.png) + +![image](../../_attachments/102433974-c57f1980-404e-11eb-9b50-54b170755850_17528513098181317.png) + + +### Step 3: Upload the bundle + +After the bundle has been uploaded, you will see the screenshot shown below. + +![image](../../_attachments/102433995-ce6feb00-404e-11eb-95c9-2ed9e5d8bb54_1752851309822554.png) + + +### Step 4: View your new benchmark + +![image](../../_attachments/102434012-d6c82600-404e-11eb-85dd-88338d7aa033_17528513098401737.png) + +![image](../../_attachments/102434028-e182bb00-404e-11eb-9de8-002e4589db66_17528513099222646.png) + + + +## Benchmark Examples + +Example bundles for code & dataset competition can be found here: + +https://github.com/codalab/competition-examples/tree/master/codabench + +### Iris + +[Iris Codabench Bundle](https://github.com/codalab/competition-examples/tree/master/codabench/iris) is a simple benchmark involving two phases, code submission and results submission. + +### AutoWSL + +Two versions of the [Automated Weakly Supervised Learning Benchmark](https://github.com/codalab/competition-examples/tree/master/codabench/autowsl): +- [Code submission benchmark](https://github.com/codalab/competition-examples/tree/master/codabench/autowsl/code_submission) +- [Dataset submission benchmark](https://github.com/codalab/competition-examples/tree/master/codabench/autowsl/dataset_submission) + +### Mini-AutoML + +[Mini-AutoML Bundle](https://github.com/codalab/competition-examples/tree/master/codabench/mini-automl) is a benchmark template for Codabench, featuring code submission to multiple datasets (tasks). + + +## How do I set up submission comments for multiple submissions? + +### Steps + +#### Step 1: Click the edit button + +![image](../../_attachments/102434058-f5c6b800-404e-11eb-98e2-88ee12195d7a_17528513098936615.png) + + +#### Step 2: Enable multiple submissions on leaderboard + +![image](../../_attachments/102434073-fcedc600-404e-11eb-859c-658fdc57bb37_17528513098851938.png) + +![image](../../_attachments/102434089-04ad6a80-404f-11eb-9f70-faa80fa8b6ba_17528513099604332.png) + +#### Step 3: Set up submission comment + +![image](../../_attachments/102434105-0e36d280-404f-11eb-99b1-dae0127cb941_1752851309982288.png) + +#### Step 4: Save all changes + +![image](../../_attachments/102434120-168f0d80-404f-11eb-91e1-04f52a7dd77a_1752851309963938.png) + +#### Step 5: Leave a comment before making submission + +![image](../../_attachments/102434132-1d1d8500-404f-11eb-8370-11fe623f3d2f_17528513103749812.png) + +#### Step 6: Check out the leaderboard + +![image](../../_attachments/102434153-27d81a00-404f-11eb-9aea-86763cc0d631_17528513100395033.png) diff --git a/documentation/docs/Organizers/Benchmark_Creation/Cancer-Benchmarks.md b/documentation/docs/Organizers/Benchmark_Creation/Cancer-Benchmarks.md new file mode 100644 index 000000000..873fea44c --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Cancer-Benchmarks.md @@ -0,0 +1,95 @@ + +This is our use case of cancer benchmarks. +This document focuses on how to run the following three bundles in Codabench + +- `CODABENCH CANCER HETEROGENEITY DT#1 TRANSCRIPTOME PANCREAS` +- `CODABENCH CANCER HETEROGENEITY DT#2 METHYLOME PANCREAS` +- `CODABENCH CANCER HETEROGENEITY DT#3 IMMUNE CELL TYPES` + +## Steps +### 1. Decompressing the original bundle +![image](../../_attachments/102427038-7aafd280-404b-11eb-94a5-9df0dcac3901_17528513125646255.png) + +Unzip the bundle from its original zip file format into a folder. + +### 2. Decompressing ingestion_program_1.zip +![image](../../_attachments/102427080-8c917580-404b-11eb-8f2c-be74be778fb4_17528513126002839.png) + +### 3. Modify the sub_ingestion.R file in the ingestion_program_1 folder. +![image](../../_attachments/102427100-9a46fb00-404b-11eb-9068-1437e4f5352a_17528513126199927.png) + +Add lines 19 and 20 of code, and replace the underlined variable in line 25 with submission_program_dir + +Two new lines of code have been added to allow the v2 compute worker to find the user-submitted program (program.R). (Because the v2 compute worker does not support searching for user-submitted code in subfolders.) + +```r +child_dir <- list.files(path=submission_program) +submission_program_dir <- paste0(submission_program, .Platform$file.sep, tail(child_dir, n=1)) +``` +```r +// read code submitted by the participants : +.tempEnv <- new.env( ) +source( + file = paste0(submission_program_dir, .Platform$file.sep, "program.R") + , local = .tempEnv +) +``` +![image](../../_attachments/102427341-193c3380-404c-11eb-9a69-5a024d3a6599_17528513130877678.png) + +### 4.Save the changes and re-zip the ingestion_program_1 folder. +Open the command line and go to the ingestion_program_1 folder. + +![image](../../_attachments/102427380-2d803080-404c-11eb-9161-2c8d5fb09369_17528513126502273.png) + +Use the following command to package the modified folder as a zip file +`zip -r ingestion_program_1.zip *` + +![image](../../_attachments/102427403-3bce4c80-404c-11eb-9cc8-e241fd4e7474_17528513126719942.png) + +Replace the latest compressed ingestion_program_1.zip file with the previous ingestion_program_1.zip file, and delete the ingestion_program_1 folder. + +![image](../../_attachments/102427413-45f04b00-404c-11eb-8b4c-c6e8b64fd945_17528513131024394.png) + +### 5. Recompress the modified original bundle. +Go to the directory at the same level as `competition.yaml` and execute the following command to compress the file +`zip -r Codabench_cancer_heterogeneity_DT#2.zip *` + +![image](../../_attachments/102427457-5bfe0b80-404c-11eb-8c52-ffe5362b54e1_17528513131442835.png) + +### 6. Creating competition with compressed bundles +### 7. Modify the default execution time +The default execution time is 10 minutes, but since these three bundles are time-consuming to execute, you have to turn it up. + +![image](../../_attachments/102427495-70420880-404c-11eb-8864-443b5f3d1913_17528513127302663.png) +![image](../../_attachments/102427510-7932da00-404c-11eb-8138-63889a0664b3_17528513127678237.png) +![image](../../_attachments/102427536-818b1500-404c-11eb-9ab5-83ed190db742_17528513128221796.png) + +We recommend that you adjust the time to the maximum value of `2147483647`, so that the task will not time out and be forced to terminate by the compute worker. + + +## Summary +This paragraph summarizes the results of the execution of three bundles in codalab v2. +### CODABENCH CANCER HETEROGENEITY DT#1 TRANSCRIPTOME PANCREAS +[https://www.codabench.org/competitions/147/](https://www.codabench.org/competitions/147/) + +All three submissions were successful. + +![image](../../_attachments/102427661-ca42ce00-404c-11eb-93c8-df58812c4085_1752851312901565.png) + +### CODABENCH CANCER HETEROGENEITY DT#2 METHYLOME PANCREAS +[https://www.codabench.org/competitions/174/](https://www.codabench.org/competitions/174/) + +Two Submissions were successfully run, while the third failed due to insufficient execution time (We have now adjusted from the original 10,000 minute execution time limit to a maximum of 2,147483647.) + +![image](../../_attachments/102427705-dfb7f800-404c-11eb-87c1-c4ac69c003be_1752851312950296.png) + +### CODABENCH CANCER HETEROGENEITY DT#3 IMMUNE CELL TYPES +[https://www.codabench.org/competitions/148/](https://www.codabench.org/competitions/148/) + +2 Submissions run successfully, 1 execution fails (screenshot below) + +![image](../../_attachments/102427767-f5c5b880-404c-11eb-9caa-f0cd7a702a84_17528513130498507.png) + +Failed execution screenshot: + +![image](../../_attachments/102427791-0118e400-404d-11eb-923a-87d724ff5a54_1752851313121837.png) \ No newline at end of file diff --git a/documentation/docs/Organizers/Benchmark_Creation/Competition-Bundle-Structure.md b/documentation/docs/Organizers/Benchmark_Creation/Competition-Bundle-Structure.md new file mode 100644 index 000000000..d2fc0d029 --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Competition-Bundle-Structure.md @@ -0,0 +1,128 @@ +A competition bundle is simply a zip file containing the `competition.yaml` which defines different aspects and attributes of your competition such as the logo, the html/markdown pages documenting your competition, and the data associated with your competition. + +## What is a Competition? +A competition is composed of a phase or many phases defining the active times of the competition, along with some other settings such as execution time limit. Each phase can have one or more tasks. + +A task is the problem the submission should be solving, therefore submissions that solve a task can be thought of as a solution. A task consists of reference data, input data, scoring program, and an ingestion program. + +For starting kits in v2, they should be solutions included with the competition bundle. See the example `competiton.yaml` or the section Competition YAML below for a link with more info. For more information on the different types of data, see the lower section of this page. + +## Example Competition Bundle Layout: + +**[Some competition bundle examples!](https://github.com/codalab/competition-examples/tree/master/codabench)** + +!!! Note + Files can be under a directory, they just have to be referenced by their full path in the YAML. See the Competition YAML section below. + +``` +--\ example_competition.zip + | + |- competition.yaml + |- logo.png + |- example_reference_data.zip + |- example_scoring_program.zip + |- example_solution.zip + |- overview.md + |- evaluation.md + |- terms_and_conditions.md + |- data.md +``` + + +## Example competition.yaml: +```yaml title="competition.yaml" +title: Example Competition Submit Scores +description: An example competition where submissions should output the score they want +image: logo.jpg +terms: terms.md +pages: + - title: overview + file: overview.md + - title: evaluation + file: evaluation.md + - title: terms + file: terms_and_conditions.md + - title: data + file: data.md +phases: + - index: 0 + name: First phase + description: An example phase + start: 2018-03-01 + end: 2027-03-01 + tasks: + - 0 +tasks: + - index: 0 + name: First Phase Task + description: Task for the first phase + scoring_program: example_scoring_program.zip + reference_data: example_reference_data.zip +solutions: + - index: 0 + path: example_solution.zip + tasks: + - 0 +leaderboard: + - title: Results + key: main + columns: + - title: score + key: score + index: 0 + sorting: desc +``` + + +## Competition YAML +The `competition.yaml` file is the most important file in the bundle. It's what Codabench looks for to figure out the structure and layout of your competition, along with additional details. For more information on setting up a `competition.yaml` see the wiki page here: +[Competition YAML](https://github.com/codalab/competitions-v2/wiki/Yaml-Structure) + + +## Data Types And Their Role: + +### Reference Data: +Reference data is typically the truth data that your participant's predictions are compared against. + +### Scoring Program +The scoring program is the file that gets ran to determine the scores of the submission, typically either based on the submission's prediction outputs, or the results from the submission itself when compared with the reference data. Usually this should be a script like a python file, but it can generally be anything. + +This is also paired with a `metadata.yaml` file with a key `command` that correlates to the command used to run your scoring program. There are also special directories available for use. + +Example: +Here's what a `metadata.yaml` might look like: +```yaml title="metadata.yaml" +command: python3 /app/program/scoring.py /app/input/ /app/output/ +``` + +This specifies that python3 is going to run the scoring program (which is going to be located in /app/program/scoring.py). +It also gives, as `args`: +- The input folder, which contains either the user's own results or predictions from ingestion +- The output folder where the score is placed. + +The arguments are optional, but passing them may be more convenient. + +The scoring program outputs a `scores.json` file containing the results for each column of the leaderboard. After computing a submission, this file should look like something like this: + +```json title="scores.json" +{"accuracy": 0.886, "duration": 42.4} +``` + +The keys should match the leaderboard columns keys defined in [the `competition.yaml` file](https://github.com/codalab/codabench/wiki/Yaml-Structure#leaderboards). + +The scoring program can also output detailed results as an HTML file for each submission. [Click here for more information](https://github.com/codalab/codabench/wiki/Detailed-Results-and-Visualizations). + +### Ingestion Program +The ingestion program is a file that gets ran to generate the predictions from the submissions if necessary. This is usually a python script or a script in another language, but it can generally be anything. + +The ingestion program is also paired with a `metadata.yaml` that specifies how to run it. It should have a key `command` that is the command used to run your ingestion program. The same special directories should be available to your ingestion program. + +Example: Here's what an ingestion `metdata.yaml` might look like this: +```yaml title="metadata.yaml" +command: python3 /app/program/ingestion.py /app/input_data/ /app/output/ /app/program /app/ingested_program +``` + +Just like the example above, this specifies we're using python to run our ingestion program. Please note that it is not necessary to pass these directories as arguments to the programs, but it can be convenient. More information about the folder layout [here](https://github.com/codalab/codabench/wiki/Submission-Docker-Container-Layout#submission-container). + +### Input Data +This is usually the test data used to generate predictions from a user's code submission when paired with an ingestion program. diff --git a/documentation/docs/Organizers/Benchmark_Creation/Competition-Creation.md b/documentation/docs/Organizers/Benchmark_Creation/Competition-Creation.md new file mode 100644 index 000000000..cc1a4d977 --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Competition-Creation.md @@ -0,0 +1,15 @@ +Competition creation can be done two ways. Through the online form on Codalab, or by uploading a competition bundle to Codalab. + +## Bundle Upload +For more information on Bundle Upload see here: + +[Competition Creation: Bundle](https://github.com/codalab/competitions-v2/wiki/Competition-Creation:-Bundle) + +For more information on Competition Bundle Structure, see here: + +[Competition Bundle Structure](https://github.com/codalab/competitions-v2/wiki/Competition-Bundle-Structure) + +## GUI creation +For more information on GUI creation see here: + +[Competition Creation: Form](https://github.com/codalab/competitions-v2/wiki/Competition-Creation:-Form) \ No newline at end of file diff --git a/documentation/docs/Organizers/Benchmark_Creation/Competition-Creation:-Bundle.md b/documentation/docs/Organizers/Benchmark_Creation/Competition-Creation:-Bundle.md new file mode 100644 index 000000000..95f2fc6fa --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Competition-Creation:-Bundle.md @@ -0,0 +1,11 @@ +This page is relatively simple. It's where you submit a completed competition bundle to Codabench, in order for it to be processed into a competition instance. For more information on competition bundles, see this link here: [Competition Bundle Structure](https://github.com/codalab/competitions-v2/wiki/Competition-Bundle-Structure). + +![image](../../_attachments/71213494-82863c80-2268-11ea-8efc-27c51795a23e_17528513091588552.png) + +To begin, just click the paper clip icon, or the bar next to it. It should open a file select dialogue. From here, you select your competition bundle, and click upload. Once Codabench is done processing and unpacking your competition, you should be greeted with a success message and a link to your new competition. + +![image (8)](../../_attachments/71214435-27ede000-226a-11ea-8dde-6bf4bf470677_17528513092595706.png) + +## Backward compatibility + +If you previously used [CodaLab Competitions](https://github.com/codalab/codalab-competitions), note that Codabench is compatible with CodaLab bundles. \ No newline at end of file diff --git a/documentation/docs/Organizers/Benchmark_Creation/Competition-Creation:-Form.md b/documentation/docs/Organizers/Benchmark_Creation/Competition-Creation:-Form.md new file mode 100644 index 000000000..6043cb814 --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Competition-Creation:-Form.md @@ -0,0 +1,84 @@ + +Competitions can now be created through a wizard/form. This page will cover each different tab of the competition form correlating to a section, and the fields for each section. + +## Details +The details tab covers all basic competition info, such as title, logo, description, and the queue used. + +![image](../../_attachments/70936146-962a6c80-1ff6-11ea-9725-815d8bf04870_17528513124953895.png) + +- Title: The title of your competition. +- Logo: The logo corresponding to your competition +- Description: The description of your competition +- Queue: If you've previously created a queue through queue management, you can assign it to your competition here. + + +## Participation +The participation tab covers your terms and conditions for the competition, and settings for auto-approval of participants. + +![image](../../_attachments/70936536-57e17d00-1ff7-11ea-893b-c056fa225223_1752851312147678.png) + +- Terms: Your terms and conditions for the competition. +- Auto Approve Registration: If checked, the organizer is not required to approve new participants. + + +## Pages +In the pages section, you can add any additional content you would like to display to competition participants as `pages`. (Tabs on the competition detail page). + +![image](../../_attachments/70936678-a8f17100-1ff7-11ea-8753-fb93dcb6fa7e_17528513121920757.png) + +Clicking `Add page` should present you a modal with the following layout: +![image](../../_attachments/70936761-d76f4c00-1ff7-11ea-86e7-ffa0d8b48a08_17528513122337482.png) + +- Title: The title of the page you are adding +- Content: The content of your page formatted as Markdown. + +## Phases +The phases section allows you to define your phases and their attached tasks. + +![image](../../_attachments/70937064-8ca20400-1ff8-11ea-8820-460c9cd88d5e_17528513122757797.png) + +By clicking `Add phase`, you should be presented with a modal for phase creation: +![image](../../_attachments/70937347-f91d0300-1ff8-11ea-850a-a1d92609ea40_175285131232458.png) + +- Name: The name of your phase +- Start: The start day of your phase +- End: The end day of your phase +- Tasks: Here you can assign one or multiple task objects to your phase. Tasks are problems that the submission should be solving. For more information, see the explanation on competition structure [here](https://github.com/codalab/codabench/wiki/Competition-Bundle-Structure#what-is-a-competition): If you don't have any tasks created yet, click the green button at the bottom of the new phase modal titled `Manage Tasks/Datasets` +- Description: The description of your phase + +*Advanced* + +- Execution Time Limit: The time limit for submission execution time measured in seconds (Currently the label says this is measured in MS, but this seems to be false) +- Max submissions per day: The max submissions allowed for the phase. The time period is from midnight UTC to midnight the next day UTC. +- Max submissions per person: The absolute max amount of submissions a participant can make on this phase. + +## Leaderboards +The leaderboards section allows you to define leaderboards which determine how submissions are scored. + +![image](../../_attachments/70949998-304cdd80-2014-11ea-9ecf-c21af198125b_1752851312365067.png) + +Clicking add leaderboard should bring up this modal: + +![image](../../_attachments/70950344-1eb80580-2015-11ea-9439-10e0e1b23d9b_17528513124041011.png) + +- Title: The title of your leaderboard +- Key: A unique name to refer to this leaderboard by (Preferably lowercase) + +Adding a column will add some fields for the values of the column: + +![image](../../_attachments/70950466-7fdfd900-2015-11ea-8173-b81fee776adb_17528513124599934.png) + +- Title (Unlabeled top input): The title of your column +- Primary Column: Whether this is the main column in the leaderboard (I.E: Is the sum/average of other columns) +- Computation (None/Average): If average is selected, this column should not have a score submitted to it, and will be a computation of the average of all the other columns. +- Sorting: Determine which way scores are sorted for this column. +- Column Key: A unique key to refer to this column by. + +## Collaborators +Here you can add other users to your competition as administrators. + +![image](../../_attachments/70950678-2af09280-2016-11ea-9c82-e21b821441c9_17528513125402734.png) + +As per the other pages, clicking `Add collaborator` should bring up a modal. The search text can be the user's email if you know it, or their username. + +![image](../../_attachments/70950762-54112300-2016-11ea-8ce7-73736dd01f18_17528513125245275.png) diff --git a/documentation/docs/Organizers/Benchmark_Creation/Competition-docker-image.md b/documentation/docs/Organizers/Benchmark_Creation/Competition-docker-image.md new file mode 100644 index 000000000..a33dd244e --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Competition-docker-image.md @@ -0,0 +1,36 @@ +The competition docker image defines the docker environment in which the submissions of the competitions or benchmarks are run. Each competition can have a different docker environment, referred by its [DockerHub](https://hub.docker.com/) name and tag. + +## Default competition docker image + +The default competition docker image is `codalab/codalab-legacy:py37`. +More information here: https://github.com/codalab/codalab-dockers + + +## Set up another image + +You can select another docker image: + +- In the `competition.yaml` file, using `docker_image: username/image:tag` +- In the editor field "Competition Docker image" as shown in the following screenshot: +![](_attachments/b8124291-92ea-4d1d-b743-00fd7a35c313_17534366792118.jpg) + +## Building an image + +If the default image does not suit your needs (missing libraries, etc.), you can either: + +- Select an existing image from DockerHub +- Create your own image from scratch +- Create a custom image based on the Codalab image. (more information below) + +If you wish to create a custom image based on the Codalab image, you can follow the steps below: + +1) Install Docker +2) Sign up to DockerHub +3) `docker run -itd -u root codalab/codalab-legacy:py39 /bin/bash` +4) Use `docker ps` to find running container id +5) Now run `docker exec -it -u root bash` +6) Install anything you want at the docker container shell (`apt-get install`, `pip install`, etc.) +7) Exit the shell with `exit` +8) `docker commit username/image:tag` +9) `docker login` +10) `docker push username/image:tag` \ No newline at end of file diff --git a/documentation/docs/Organizers/Benchmark_Creation/Dataset-competition-creation-and-participate-instruction.md b/documentation/docs/Organizers/Benchmark_Creation/Dataset-competition-creation-and-participate-instruction.md new file mode 100644 index 000000000..2446d71d1 --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Dataset-competition-creation-and-participate-instruction.md @@ -0,0 +1,39 @@ + +This page focuses on how to create a dataset contest via bundle and make submission for dataset competition + +## Overall process +The brief process can be summarized in the following diagram![](../../_attachments/0_17528513120435548.png) + +There are two main parts: +- the contest organizer creates the dataset competition by uploading a bundle (For more information on how to create a contest via bundle, and the definition of bundle, you can refer to this link [Competition-Creation:-Bundle](https://github.com/codalab/competitions-v2/wiki/Competition-Creation:-Bundle)) + +- Competition participant submission dataset + +## Differences from the code submission competition +### For the competition creator +The main difference is the definition of the bundle, which differs from the code commit bundle in 2 ways + +#### Input data +![](../../_attachments/1_17528513120437856.jpg) +- In the code submission, input data folder is filled with the dataset files + +- In the dataset submission, input data folder is filled with the sample code submission files(NB: the sample code submission file is the algorithm file to be submitted by the participants in the code submission.) + +#### Ingestion program +![](../../_attachments/6_1752851312043884.jpg) +![](../../_attachments/2_17528513126088269.jpg) +- Unlike the code submission, we need to switch the position of the variables $input and $submission_program +- In a dataset submission competition, the contents of $submission_program is the dataset submitted by the participant, and the contents of $input is the competition creator's built-in sample code submission. + +## For the competition participant +![](../../_attachments/4_17528513126157694.jpg) +- The left-hand side of the image above shows the contents of the documents that competition participants need to prepare for the code submission competition + +- the right-hand side of the image above shows the contents of the documents that competition participants need to prepare for the dataset submission competition + +- The competition creator needs to define the bundle by specifying the content of the dataset file to be uploaded + +- For example, the right-hand side of the picture shows the contents of the dataset file required for the HADACA competition to run. + +- Therefore, when competition participants upload their dataset submission, the zip file must contain all the files shown on the right side of the picture above. + diff --git a/documentation/docs/Organizers/Benchmark_Creation/Detailed-Results-and-Visualizations.md b/documentation/docs/Organizers/Benchmark_Creation/Detailed-Results-and-Visualizations.md new file mode 100644 index 000000000..cb48be6af --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Detailed-Results-and-Visualizations.md @@ -0,0 +1,75 @@ +Detailed results is a means of passing extra information from the scoring program to the frontend. + +This is done via writing to a `detailed_results.html` file (OR any `.html` -- first by alphabetical order -- in the output folder), and setting `enable_detailed_results` to `True` in competition settings (via yaml or editor). + +This file is watched for changes and updated on the frontend every time the file is updated, so users can get a live feed from the compute worker. + +There is no limitation to the contents of this HTML file, and can thus be used to relay any information desired. +Use case ideas: + +- Plot data using a python plot library like matplotlib or seaborn. + - plot the learning curve over time of a reinforcement learning challenge + - plot the slope of a linear regression model + - plot the location of clusters in a classification challenge + - plot anything you can conceive of +- Run a profiler that outputs a network of method calls. +- Display any additional data about the submission file that can not be distilled down in to a score of some kind + +## How to include figures + +Figures can be included directly inside the HTML code, by converting them in bytes format. An example is given in the [scoring program of the Mini-AutoML bundle](https://github.com/codalab/competition-examples/blob/master/codabench/mini-automl/bundle/scoring_program/scoring.py). + +```python title="scoring.py" +[...] + +# Path +input_dir = '/app/input' # Input from ingestion program +output_dir = '/app/output/' # To write the scores +reference_dir = os.path.join(input_dir, 'ref') # Ground truth data +prediction_dir = os.path.join(input_dir, 'res') # Prediction made by the model +score_file = os.path.join(output_dir, 'scores.json') # Scores +html_file = os.path.join(output_dir, 'detailed_results.html') # Detailed feedback + +def write_file(file, content): + """ Write content in file. + """ + with open(file, 'a', encoding="utf-8") as f: + f.write(content) + +def make_figure(scores): + x = get_dataset_names() + y = [scores[dataset] for dataset in x] + fig, ax = plt.subplots() + ax.plot(x, y, 'bo') + ax.set_ylabel('accuracy') + ax.set_title('Submission results') + return fig + +def fig_to_b64(fig): + buf = io.BytesIO() + fig.savefig(buf, format='png') + buf.seek(0) + fig_b64 = base64.b64encode(buf.getvalue()).decode('ascii') + return fig_b64 + +def main(): + # Initialized detailed results + write_file(html_file, '

Detailed results

') # Create the file to give real-time feedback + + [...] # compute the scores + + # Create a figure for detailed results + figure = fig_to_b64(make_figure(scores)) + write_file(html_file, f'') +``` + +## Example + +When the visualization is enabled, a link to the detailed results can be found on the leaderboard for each submission: + +![](_attachments/3510a61b-c67b-4919-a897-59a0bf2b807d_17534366812283037.jpg) + +The `detailed_results.html`, generated by the scoring program, is then shown: + +![](_attachments/4ae6bd79-bd3d-486e-a2cb-ec546b293515_17534366812272964.jpg) + diff --git a/documentation/docs/Organizers/Benchmark_Creation/Getting-started-with-Codabench.md b/documentation/docs/Organizers/Benchmark_Creation/Getting-started-with-Codabench.md new file mode 100644 index 000000000..d30d2ad34 --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Getting-started-with-Codabench.md @@ -0,0 +1,37 @@ +[Codabench](https://codabench.org) is an upgraded version of the [CodaLab Competitions](https://codalab.lisn.fr/) platform, allowing you to create either **competitions** or **benchmarks**. A benchmark is essentially an **ever-lasting competition** with **multiple tasks**, for which a participant can make **multiple entries** in the result table. + +This getting started tutorial shows a **simple example** of how to create a competition. Advanced users should check [fancier examples](https://github.com/codalab/competition-examples/tree/master/codabench) and [the full documentation](https://github.com/codalab/codabench/wiki). If you simply wish to participate in a benchmark or competition, go to [Participating in a benchmark](../../Participants/User_Participating-in-a-Competition.md). + +## Getting ready + +- Create a [Codabench](https://codabench.org) account (if not done yet) +- Download the [sample competition bundle](https://github.com/codalab/competition-examples/blob/master/codabench/wheat_seeds/code_submission_bundle.zip) and the [sample submission](https://github.com/codalab/competition-examples/blob/master/codabench/wheat_seeds/sample_code_submission.zip). +- Do not unzip them. + +## Create a competition +- From the front page of [Codabench](https://codabench.org), in the top menu, go to the **Benchmark > Management** +- Click the green **Upload** button at the top right. +- Upload the (zipped) sample competition bundle => this will create your competition. + +## Make changes +- Click on the **Edit** gray button at the top to enter the editor. +- Make small changes + - Change the logo in the **Details** tab to another png of jpg file. + - Change the end date in the **Phases** tab: if the competition is terminated, you will not be able to make submissions. +- Save your changes and verify that they have become effective. + +## Make a submission +- In your competition page, go to the tab **My submissions** +- Submit the (zipped) sample submission bundle you downloaded. +- When your submission finishes, go to the **Result tab** to check if it shows up on the leaderboard. +!!! warning "In some competitions, submissions successfully processed do not automatically get pushed to the leaderboard" + +## Publish your competition +- If you want to make your competition visible to all, you must publish it by checking the **Publish** box at the very bottom of the editor **Details** page. +- After you publish your competition, it should now be visible when you are not logged in, at the URL of your competition page. + + +You are done with this simple tutorial. +Next, check the more [advanced tutorial](Advanced-Tutorial.md). + +You can also check out this blog post: [How to create your first benchmark on Codabench](https://medium.com/@adrienpavao/how-to-create-your-first-benchmark-on-codabench-910e2aee130c). \ No newline at end of file diff --git a/documentation/docs/Organizers/Benchmark_Creation/How-to-transition-from-CodaLab-to-Codabench?.md b/documentation/docs/Organizers/Benchmark_Creation/How-to-transition-from-CodaLab-to-Codabench?.md new file mode 100644 index 000000000..92f3bbfbc --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/How-to-transition-from-CodaLab-to-Codabench?.md @@ -0,0 +1,60 @@ +[Codabench](https://codabench.org/) serves as a modern, faster, and more reliable upgrade to [CodaLab](https://codalab.lisn.fr/), designed to supersede it. This quick guide is meant for CodaLab users wondering how to successfully adopt this new challenge platform. + +![transition](../../_attachments/0af8f0c0-1311-4777-9bdc-7daa123868d2_17528513091693199.jpg) + +## What’s new in Codabench? + +[Codabench](https://codabench.org/) includes all features from [CodaLab Competitions](https://codalab.lisn.fr/), and proposes a faster and more intuitive interface. It also has new features such as: + +- Live logs during submission processes +- Storage quotas +- [Computation servers management](https://github.com/codalab/codabench/wiki/Server-status-page) for all users. + +It also emphasizes on benchmarking, allowing dataset submissions and multiple leaderboard rows per user. Finally, future project development and maintenance will be focused on Codabench. + +## Do I need to create a new account? + +Yes, even if you previously had a CodaLab account, you need to [create a new account](https://www.codabench.org/accounts/signup) on Codabench. Sign up is quick and free. From there, as a competition participant, you are all set. + +The next questions concern competition organizers. + +## Can I upload my old competition bundles to Codabench? + +Yes! That is the good news: competition bundles are back-compatible. This means that you can upload your CodaLab competition bundles into Codabench without any modifications and have them working just fine. + +Simply go to “_Benchmarks > Management_”, then click on “_Upload_” and select your competition bundle. + +![tuto1](../../_attachments/3cd0a725-a9f7-4288-b59d-0d31ea910ed7_17528513093736768.jpg) + + +_Go to “Benchmarks > Management”._ + +![tuto2](../../_attachments/aeeedf6b-8703-47a9-8f71-1916f547cf29_1752851309283848.jpg) + +_Click on “Upload” and select your competition bundle._ + +That’s it! Your competition is ready to receive submissions. + + +## How to move a competition from CodaLab to Codabench? + +If you competitition is already live on CodaLab, that is fine too. You simply need to create a dump, download it and re-upload it on Codabench. + +![](_attachments/947b149d-ebc7-4f78-bed7-d0a16b195065_17534366794768937.jpg) + +_Go to “Dumps” organizer interface._ + +![](_attachments/8f5c7953-1bb1-488b-b1aa-babf723160f2_17534366794457016.jpg) + +_Click on “Create Dump” then “Download”. You’ll obtain a competition bundle that you’ll be able to re-upload on Codabench, following the instructions of the previous section._ + +!!! note "Leaderboard results won’t be transferred. For that, you’ll need to re-submit the submissions." + +## How to create a competition from scratch on Codabench? + +If you don’t have any previous competition, and want to learn how to create one from scratch, please refer to the [Getting started guide](Getting-started-with-Codabench.md). + +## Concluding remarks + +Codabench, the new version of the competition and benchmark platform CodaLab, was launched on August 2023 and is already receiving great attention. For users accustomed to CodaLab, the transition to Codabench is quick and easy. Indeed, competition bundles are back-compatible, and all that is required is to create an account on Codabench. To go further, you can refer to [Codabench’s Wiki](https://github.com/codalab/codabench/wiki/). + diff --git a/documentation/docs/Organizers/Benchmark_Creation/Leaderboard-Functionality.md b/documentation/docs/Organizers/Benchmark_Creation/Leaderboard-Functionality.md new file mode 100644 index 000000000..ded5fffa4 --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Leaderboard-Functionality.md @@ -0,0 +1,90 @@ +For specific information on leaderboard and column fields, see the explanations in the [YAML structure](Yaml-Structure.md#leaderboards). + +## Writing scores +A leaderboard and column are written to via their keys. +A leaderboard declaration like so +```yaml +leaderboard: + - title: Results + key: main + submission_rule: "Force_Last" + columns: + - title: Accuracy Score 1 + key: accuracy_1 + index: 0 + sorting: desc + - title: Accuracy Score 2 + key: accuracy_2 + index: 1 + sorting: desc + - title: Max Accuracy + key: max_accuracy + index: 2 + sorting: desc + computation: max + computation_indexes: + - 0 + - 1 + - title: Duration + key: duration + index: 3 + sorting: asc +``` +would require, via the scoring program, the following `scores.json` file +```json title="scores.json" +{"accuracy_1": 0.5, "accuracy_2": 0.75, "duration": 123.45} +``` +This is the end result shown on the leaderboard: +``` +| Accuracy Score 1 | Accuracy Score 2 | Max Accuracy | Duration | +|:----------------:|:----------------:|:------------:|:--------:| +| 0.5 | 0.75 | 0.75 | 123.45 | +``` + +## Computation +Scores should not be written to computation columns, instead they will be calculated by the platform at the time scores are read from `scores.json`. + +Computation options are: + - sum + - avg + - min + - max + +These are applied across the columns specified as `computation_indexes`. + +So in the example above, the computation option specified is `max` and the indexes are 0 and 1, meaning we will take the max score of columns at index 0 and 1 (i.e: .5 and .75) so .75 is returned in the computation. + +## Primary columns +**Ranking is determined first by the primary column of the leaderboard**. In the `competition.yaml`, this is the column at index 0. This option can be changed in the competition editor. +After sorting scores by the primary column (asc or desc as specified on the column) sorting then continues from left to right. Final sorting is done by the `submitted_at` timestamp, so that if submissions have identical scores (as in the case of baselines), the earlier submissions will be ranked higher. + +Example (with Max Accuracy set as the primary column): +``` +| Rank | Accuracy Score 1 | Accuracy Score 2 | Max Accuracy | Duration | +|------|:----------------:|:----------------:|:------------:|:--------:| +| 1 | 0.5 | 0.75 | 0.75 | 123.45 | +| 2 | 0.43 | 0.75 | 0.75 | 123.45 | +| 3 | 0.6 | 0.6 | 0.6 | 100 | # submitted at Jan 1, 2020 +| 4 | 0.6 | 0.6 | 0.6 | 100 | # submitted at Jan 2, 2020 +``` +So we sort the submissions by the primary column, (Max Accuracy) and then by columns from left to right, so accuracy 1, then accuracy 2, then duration, then by submission_at. + +## Submission rules + +The submission rule set the behavior of the leaderboard regarding new submissions. Submissions can be forced to the leaderboard or manually selected, can be unique or multiple on the leaderboard, etc. + +- **Add**: Only allow adding one submission +- **Add And Delete**: Allow users to add a single submission and remove that submission +- **Add And Delete Multiple**: Allow users to add multiple submissions and remove those submissions +- **Force Last**: Force only the last submission +- **Force Latest Multiple**: Force latest submission to be added to leaderboard (multiple) +- **Force Best**: Force only the best submission to the leaderboard + +Here are the corresponding values for the YAML field `submission_rule`: "Add", "Add_And_Delete", "Add_And_Delete_Multiple", "Force_Last", "Force_Latest_Multiple" or "Force_Best". + +## Hidden Leaderboard +If a leaderboard is marked as hidden, it will not be visible to participants in the competition. It will only be visible to platform administrators, competition administrators, and competition collaborators. + +## Downloading Leaderboard Data +If an administrator, competition administrator, and competition collaborator would like to download the current leaderboard data, they will have access to a button labeled "CSV" on the leaderboard page. This creates a downloadable ZIP file. Each CSV file inside will be titled with the name of the leaderboard. The first row of the CSV is the title for each column, followed by all the submissions on the leaderboard. +This can be access directly through the API by sending a GET request to `[HOSTNAME]/api/competitions/'ID'/get_csv` where 'ID' is the competition ID. \ No newline at end of file diff --git a/documentation/docs/Organizers/Benchmark_Creation/Public-Tasks-and-Tasks-Sharing.md b/documentation/docs/Organizers/Benchmark_Creation/Public-Tasks-and-Tasks-Sharing.md new file mode 100644 index 000000000..eb9442185 --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Public-Tasks-and-Tasks-Sharing.md @@ -0,0 +1,48 @@ +Codabench tasks are a combination of datasets and programs: + +- Scoring program +- Ingestion program +- Input data +- Reference data + +A scoring program is required while others are optional in a task. + +In the [Codabench Resources Interface](https://www.codabench.org/tasks/) you can upload datasets and programs in the `Datasets & Programs` tab and then create a task in the `Tasks` tab. + +**Example of uploaded datasets and programs:** +![](_attachments/198a75a1-cd72-436a-bf36-8e15fd35addc_17534366796278713.jpg) + +**Example of a task created using the above datasets and programs:** +![](_attachments/b0da8ed1-3d64-40e8-b471-f81ea14c8388_17534366795575287.jpg) + + + + +## Make a Task Public + +You can make a task public that you have created by clicking on the task name to show task details and then click the button `Make Public` + +### Example of task details: +![](_attachments/3357ae4a-5fe4-4462-bb93-eb4385b0c615_17534366802654817.jpg) + + +## Search Public Tasks + +To search public tasks, you can check the `Show Public Tasks` to view public tasks from other users +![](_attachments/d7b29b9a-daa4-4e10-b39b-d1c3c3097342_1753436680340381.jpg) + + +## Use Public Tasks in Competitions + +You can use public tasks created by other people in your competitions, to do this follow the steps below: + +1. Open your competition and click `Edit` button +![](_attachments/9ac648b0-c477-402a-8f0d-33f7045ce001_175343668059375.jpg) + +2. Click the `Phases` tab and click the edit button in front of the phase where you want to use a public task +![](_attachments/e0611606-46a7-40b9-be68-c737f88d8a2c_1753436680368063.jpg) + + +3. Start writing the task name in the Tasks field and the matching task will show up. Click the task in the list to select it +![](_attachments/8a1d3799-e40b-4b4d-a420-10b3107b27f6_1753436680434018.jpg) + diff --git a/documentation/docs/Organizers/Benchmark_Creation/Yaml-Structure.md b/documentation/docs/Organizers/Benchmark_Creation/Yaml-Structure.md new file mode 100644 index 000000000..16bf7b0e3 --- /dev/null +++ b/documentation/docs/Organizers/Benchmark_Creation/Yaml-Structure.md @@ -0,0 +1,301 @@ +This page describes all the attributes in the Codabench competition definition language, using [YAML](https://yaml.org). This is used to create configuration files in Codabench competition bundles. + +[Iris competition YAML file example!](https://github.com/codalab/competition-examples/blob/master/codabench/iris/competition.yaml) + +## Versioning + +A version for the YAML is required as this platform can support multiple versions of a `competition.yaml` file. For examples of v1.5 bundles, look [here](https://github.com/codalab/codalab-competitions/wiki/Organizer_Codalab-competition-YAML-definition-language). + +For all v2 style competition bundles, be sure to add `version: 2` to the top of the competition.yml file. + +**Note:** Not all features of v1.5 competitions are currently supported in v2. + +## Competition Properties +### Required +- **title:** Title of the competition +- **image:** File path of competition logo, relative to `competition.yaml` +- **terms:** File path to a markdown or HTML page containing the terms of participation participants must agree to before joining a competition + +### Optional +- **description:** A brief description of the competition. +- **registration_auto_approve:** True/False. If True, participation requests will not require manual approval by competition administrators. Defaults to False +- **docker_image:** Can specify a specific docker image for the competition to use. Defaults to `codalab/codalab-legacy:py3`. [More information here](Competition-docker-image.md). +- **make_programs_available:** Can specify whether to share the ingestion and scoring program with participants or not. Always available to competition organizer. +- **make_input_data_available:** Can specify whether to share the input data with participants or not. Always available to competition organizer. +- **queue:** Queue submissions are sent to. Can be used to specify competition specific compute workers. Defaults to the standard queue shared by all competitions. The queue should be referenced by its **Vhost**, not by its name. You can find the Vhost in `Queue Management` by clicking the eye button `View Queue Detail`. +- **enable_detailed_results:** True/False. If True, competition will watch for a `detailed_results.html` file and send its contents to storage. [More information here](Detailed-Results-and-Visualizations.md). +- **show_detailed_results_in_submission_panel:** a boolean (default: `True`) If set to `True`, participants can see detailed results in the submission panel +- **show_detailed_results_in_leaderboard:** a boolean (default: `True`) If set to `True`, participants can see detailed results in the leaderboard +- **contact_email:** a valid contact email to reach the organizers. +- **reward:** a string to show the reward of the competition e.g. "$1000" for competition. +- **auto_run_submissions:** a boolean (default: `True`) if set to `False`, organizers have to manually run the submissions of each participant +- **can_participants_make_submissions_public:** a boolean (default: `True`) if set to `False`, participants cannot make their submissions public from submissions panel. +- **forum_enabled:** a boolean (default: `True`) if set to `False`, organizers and participants cannot see or interact with competition forum. + + + + +```yaml +# Required +version: 2 +title: Compute Pi +image: images/pi.png +terms: pages/terms.md + +# Optional +description: Calculate pi to as many digits as possible, as quick as you can. +registration_auto_approve: True +docker_image: codalab/codalab-legacy:py37 # default docker image +make_programs_available: True +make_input_data_available: False +enable_detailed_results: True +show_detailed_results_in_submission_panel: True +show_detailed_results_in_leaderboard: True +contact_email: organizer_email@example.com +reward: $1000 prize pool +auto_run_submissions: True +can_participants_make_submissions_public: False +forum_enabled: True +``` + +## Pages +### Required +- **title:** String that will be displayed in the competition detail page as the title of the page +- **file:** File path to a markdown or HTML page relative to competition.yaml containing the desired content of the page. + +```yaml +pages: + - title: Welcome + file: welcome.md + - title: Getting started + file: pages/getting_started.html +``` + +## Phases +### Required +- **name:** Name of the phase +- **start:** Datetime string for the start of the competition. ISO format strings are recommended. Use `YYYY-MM-DD HH:MM:SS` date-time format. (Example date-time: 2024-12-31 14:30:00) +- **end:** Datetime string for the end of the phase (optional for _last phase only._ If not supplied for the final phase, that phase continues indefinitely). Use `YYYY-MM-DD HH:MM:SS` date-time format. (Example date-time: 2024-12-31 14:30:00) +- **tasks:** An array of numbers pointing to the index of any defined tasks relevant to this phase (see tasks for more information) + + +### Optional +- **index:** Integer for noting the order of phases, Phases _must_ be sequential, without any overlap. If indexes are not supplied, ordering will be assumed by declaration order. +- **max_submissions:** Total submissions allowed per participant for the entire phase +- **max_submissions_per_day:** Submission limit for each participant for a given day +- **auto_migrate_to_this_phase:** Cannot be set on the first phase of the competition. This will re-submit all successful submissions from the previous phase to this phase at the time the phase starts. +- **execution_time_limit:** Execution time limit for submissions, given in seconds. Default is 600. +- **hide_output:** True/False. If True, stdout/stderr for all submissions to this phase will be hidden from users who are not competition administrators or collaborators. +- **hide_prediction_output:** True/False. If True, participants won't be able to download the "Output from prediction step". +- **hide_score_output:** True/False. If True, participants won't be able to download the "Output from scoring step" containing the `scores.txt` file. +- **starting_kit:** path to the starting kit, a folder that participants will be able to download. Put there any useful files to help participants (example submissions, notebooks, documentation). +- **public_data:** path to public data, that participants will be able to download. +- **accepts_only_result_submissions**(default=False): When set to True, the phase is expected to accept only result submissions. + +```yaml +phases: + - index: 0 + name: Development Phase + description: Tune your models + start: 2019-12-12 13:30:00 # Time in UTC+0 and 24-hour format + end: 2020-02-01 00:00:00 # Time in UTC+0 and 24-hour format + execution_time_limit: 1200 + starting_kit: starting_kit + public_data: public_data + accepts_only_result_submissions: True + tasks: + - 0 + - index: 1 + name: Final Phase + description: Final testing of your models + start: 2020-02-02 00:00:00 # Time in UTC+0 and 24-hour format + auto_migrate_to_this_phase: True + accepts_only_result_submissions: False + tasks: + - 1 +``` + +## Tasks +### Required +- **index:** Number used for internal reference of the task, pointed to by solutions (below) and phases (above) +- **name:** Name of the Task +- **scoring_program:** File path relative to `competition.yaml` pointing to a `.zip` file or an unzipped directory, containing the scoring program + +OR + +- **key:** UUID of a task already in the database. **If key is provided, all fields other than index will be ignored** + +### Optional +- **description:** Brief description of the task +- **input_data:** File path to the data to be provided during the prediction step +- **reference_data:** File path to the data to be provided to the scoring program +- **ingestion_program:** File path to the ingestion program files +- **ingestion_only_during_scoring:** True/False. If true, the ingestion program will be run in parallel with the scoring program, and can communicate w/ the scoring program via a shared directory + +```yaml +tasks: + - index: 0 + name: Compute Pi Developement Task + description: Compute Pi, focusing on accuracy + input_data: dev_phase/input_data/ + reference_data: dev_phase/reference_data/ + ingestion_program: ingestion_program.zip + scoring_program: scoring_program.zip + - index: 1 + name: Compute Pi Final Task + description: Compute Pi, speed and accuracy matter + input_data: final_phase/input_data/ + reference_data: final_phase/reference_data/ + ingestion_program: ingestion_program.zip + scoring_program: scoring_program.zip +``` + +## Solutions +### Required +- **index:** Index number of solution +- **tasks:** Array of the tasks (referenced internally) for which this solution applies. +- **path:** File path to `.zip` or directory containing the solution data. + +```yaml +solutions: + - index: 0 + path: solutions/solution1.zip + tasks: + - 0 + - 1 + - index: 1 + path: solutions/solution2/ + tasks: + - 0 +``` + +## Fact Sheet +### Optional +JSON for asking metadata questions about each submission when they are submitted +- **KEY:** Programmatic name for a response. Should not contain any whitespace. +- **QUESTION TYPE:** + - **"checkbox":** Prompts the user with a checkbox for a yes/no or true/false type question + - **_Required_ SELECTION**: [true, false] + - **"text":**: Prompts the user with a text box to write a response. + - **_Required_ SELECTION**: "" + - `"is_required": "false"` will allow the user not to submit a response. Otherwise, the user will have to type something. + - **"select":** Gives the user a dropdown to select a value from. + - **SELECTION**: Give an array of comma separated values that the user can select from: ["Value1","Value2","Value3",...,"ValueN"] + - TIP: If you want this selection to be optional you can add "" as an option. ex. ["", "Value1", ...] and set `"is_required": "false"` +- `is_on_leaderboard:` setting this to "true" will show this response on the leaderboard along with their submission. + +### Structure +```yaml +fact_sheet: { + "[KEY]": { + "key": "[KEY]", + "type": "[QUESTION TYPE]", + "title": "[DISPLAY NAME]", + "selection": [SELECTION], + "is_required": ["true" OR "false"], + "is_on_leaderboard": ["true" OR "false"] +} +``` + +```yaml +fact_sheet: { + "bool_question": { + "key": "bool_question", + "type": "checkbox", + "title": "boolean", + "selection": [True, False], + "is_required": "false", + "is_on_leaderboard": "false" + }, + "text_question": { + "key": "text_question", + "type": "text", + "title": "text", + "selection": "", + "is_required": "false", + "is_on_leaderboard": "false" + }, + "text_required": { + "key": "text_required", + "type": "text", + "title": "text", + "selection": "", + "is_required": "true", + "is_on_leaderboard": "false" + }, + "selection": { + "key": "selection", + "type": "select", + "title": "selection", + "selection": ["", "v1", "v2", "v3"], + "is_required": "false", + "is_on_leaderboard": "true" + } +} +``` + + +## Leaderboards +### Leaderboard Details + +### Required +- **title:** Title of leaderboard +- **key:** Key for scoring program to write to +- **columns:** An array of columns (see column layout below) + +### Optional +- **submission_rule:** "Add", "Add_And_Delete", "Add_And_Delete_Multiple", "Force_Last", "Force_Latest_Multiple" or "Force_Best". It sets the behavior of the leaderboard regarding new submissions. See [Leaderboard Functionality](Leaderboard-Functionality.md) for more details. +- **hidden:** True/False. If True, the contents of this leaderboard will be hidden to all users who are not competition administrators or collaborators. + +## Column Details + +### Required +- **title:** Title of the column +- **key:** Key for the scoring program to write to. The keys must match the keys of the `scores.json` file returned by the scoring program, as explained with more details [here](Competition-Bundle-Structure.md#scoring-program). +- **index:** Number specifying the order the column should show up on the leaderboard + +### Optional +- **sorting:** sorting order for the column: Descending (desc) or Ascending (asc) + - Ascending: smaller scores are better + - Descending: larger scores are better +- **computation:** computation to be applied *must be accompanied by computation indexes* + - computation options: sum, avg, min, max +- **computation_indexes:** an array of indexes of the columns the computation should be applied to +- **precision:** (*integer, default=2*) to round the score to *precision* number of digits +- **hidden:** (*boolean, default=False*) to hide/unhide a column on leaderboard + +```yaml +leaderboards: + - title: Results + key: main + submission_rule: "Force_Last" + columns: + - title: Accuracy Score 1 + key: accuracy_1 + index: 0 + sorting: desc + precision: 2 + hidden: False + - title: Accuracy Score 2 + key: accuracy_2 + index: 1 + sorting: desc + precision: 3 + hidden: False + - title: Max Accuracy + key: max_accuracy + index: 2 + sorting: desc + computation: max + precision: 3 + hidden: False + computation_indexes: + - 0 + - 1 + - title: Duration + key: duration + index: 3 + sorting: asc + precision: 2 + hidden: False +``` \ No newline at end of file diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/198a75a1-cd72-436a-bf36-8e15fd35addc_17534366796278713.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/198a75a1-cd72-436a-bf36-8e15fd35addc_17534366796278713.jpg new file mode 100644 index 000000000..348cd7410 Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/198a75a1-cd72-436a-bf36-8e15fd35addc_17534366796278713.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/3357ae4a-5fe4-4462-bb93-eb4385b0c615_17534366802654817.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/3357ae4a-5fe4-4462-bb93-eb4385b0c615_17534366802654817.jpg new file mode 100644 index 000000000..d5ad6e6e1 Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/3357ae4a-5fe4-4462-bb93-eb4385b0c615_17534366802654817.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/3510a61b-c67b-4919-a897-59a0bf2b807d_17534366812283037.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/3510a61b-c67b-4919-a897-59a0bf2b807d_17534366812283037.jpg new file mode 100644 index 000000000..4d97558ec Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/3510a61b-c67b-4919-a897-59a0bf2b807d_17534366812283037.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/4ae6bd79-bd3d-486e-a2cb-ec546b293515_17534366812272964.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/4ae6bd79-bd3d-486e-a2cb-ec546b293515_17534366812272964.jpg new file mode 100644 index 000000000..9eba7b420 Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/4ae6bd79-bd3d-486e-a2cb-ec546b293515_17534366812272964.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/8a1d3799-e40b-4b4d-a420-10b3107b27f6_1753436680434018.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/8a1d3799-e40b-4b4d-a420-10b3107b27f6_1753436680434018.jpg new file mode 100644 index 000000000..e3f1a7e8d Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/8a1d3799-e40b-4b4d-a420-10b3107b27f6_1753436680434018.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/8f5c7953-1bb1-488b-b1aa-babf723160f2_17534366794457016.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/8f5c7953-1bb1-488b-b1aa-babf723160f2_17534366794457016.jpg new file mode 100644 index 000000000..239468c54 Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/8f5c7953-1bb1-488b-b1aa-babf723160f2_17534366794457016.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/947b149d-ebc7-4f78-bed7-d0a16b195065_17534366794768937.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/947b149d-ebc7-4f78-bed7-d0a16b195065_17534366794768937.jpg new file mode 100644 index 000000000..239468c54 Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/947b149d-ebc7-4f78-bed7-d0a16b195065_17534366794768937.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/9ac648b0-c477-402a-8f0d-33f7045ce001_175343668059375.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/9ac648b0-c477-402a-8f0d-33f7045ce001_175343668059375.jpg new file mode 100644 index 000000000..a0b0fb57d Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/9ac648b0-c477-402a-8f0d-33f7045ce001_175343668059375.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/b0da8ed1-3d64-40e8-b471-f81ea14c8388_17534366795575287.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/b0da8ed1-3d64-40e8-b471-f81ea14c8388_17534366795575287.jpg new file mode 100644 index 000000000..d7ea2f320 Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/b0da8ed1-3d64-40e8-b471-f81ea14c8388_17534366795575287.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/b8124291-92ea-4d1d-b743-00fd7a35c313_17534366792118.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/b8124291-92ea-4d1d-b743-00fd7a35c313_17534366792118.jpg new file mode 100644 index 000000000..8bbce51e9 Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/b8124291-92ea-4d1d-b743-00fd7a35c313_17534366792118.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/d7b29b9a-daa4-4e10-b39b-d1c3c3097342_1753436680340381.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/d7b29b9a-daa4-4e10-b39b-d1c3c3097342_1753436680340381.jpg new file mode 100644 index 000000000..914c8a182 Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/d7b29b9a-daa4-4e10-b39b-d1c3c3097342_1753436680340381.jpg differ diff --git a/documentation/docs/Organizers/Benchmark_Creation/_attachments/e0611606-46a7-40b9-be68-c737f88d8a2c_1753436680368063.jpg b/documentation/docs/Organizers/Benchmark_Creation/_attachments/e0611606-46a7-40b9-be68-c737f88d8a2c_1753436680368063.jpg new file mode 100644 index 000000000..7ff5cf5ee Binary files /dev/null and b/documentation/docs/Organizers/Benchmark_Creation/_attachments/e0611606-46a7-40b9-be68-c737f88d8a2c_1753436680368063.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/Competition-Detail-Page.md b/documentation/docs/Organizers/Running_a_benchmark/Competition-Detail-Page.md new file mode 100644 index 000000000..7a94bd69b --- /dev/null +++ b/documentation/docs/Organizers/Running_a_benchmark/Competition-Detail-Page.md @@ -0,0 +1,99 @@ +The competition detail page is the main way to interact with competitions. This is where your participants (Or if you are a participant) will read the pages you uploaded, register, make submissions, and check results. + +![](_attachments/f6816bd8-af4e-4ab0-99b3-61a69d7e1278_17534367048086147.jpg) + +1) Editor (organizer feature) +2) Copy competition secret URL (Document icon, secret URL covered) +3) Competition Detail Tab Navigation + + - Get Started + - Phases + - My Submissions + - Results + - Forum (if enabled) + +4) Competition Detail Tab Pane Navigation + + +## Competition organizer features + +These features are only for competition organizers. + +![](_attachments/49ca5f21-a10f-4453-a04e-4ac30bfa27b2_17534367047245183.jpg) + +- Editor +- Manage participants +- Manage submissions +- Manage dumps (save the current state of the competition as a bundle) +- Migration + + + +### Submissions + +From here, you can: + - Delete submissions + - Re-run submissions + - Set a submissions score + - Force a submission to leaderboard + +You can also view the logs, and all output associated with a submission. + +![](_attachments/e42ea472-4f52-4f0e-8dfb-a39cba8b3838_1753436704639189.jpg) + +- Download CSV: Download a CSV file with all submission info +- Re-run all submissions per phase: Re-runs all submissions in a phase. +- Search: Used to search for a submission by file name +- Phase: Used to filter submissions by phase +- Status: Used to filter submissions by status +- Action Buttons: + - Blue Circular Arrow: Re-runs the submission + - Yellow Cross: Cancels the current submission if it is running + - Red Trash Can: Deletes the submission + - Green arrow: Puts this submission on the leaderboard + +### Participants + +From here, you should be able to: + - Email all participants + - Approve/Deny participants + - Revoke participants + +![](_attachments/4f331c80-7d24-47f7-ba4f-71d4bd9dc003_17534367045066261.jpg) + + +- Search: Search for a participant by username or email address. +- Status: Filter participants by status +- Email Participants: Opens a modal to email all participants: + - Subject: The email subject + - Content: The email content + +![](_attachments/d369cbf6-a129-4599-ae39-defe99b8aaac_1753436704381793.jpg) + + +### Copy competition secret URL +Clicking the document icon copies the competition secret URL to your clipboard. + + +# Competition Detail Tab Navigation +Used to navigate between the different sections of the competition detail page. + +### Get Started +Contains all the organizer made pages, and some defaults. + +![image](../../_attachments/71232172-b5025a80-22a5-11ea-8b9f-0a5a85499382_1752851309000107.png) + +### Phases +Contains a diagram list with details on each phase in the order in which they're active. + +![image](../../_attachments/71232052-3c030300-22a5-11ea-9718-76cd7f6d5a37_1752851309061598.png) + +### My Submissions +This view contains a table with all your submissions, and allows you to upload new ones. + +![image](../../_attachments/71232079-54731d80-22a5-11ea-9190-17dc7505535e_1752851309115967.png) + +### Results +This view contains the leaderboard results. + +![](_attachments/ebf6b2b9-41f0-419f-9c95-cf0f4d8a5ffc_17534367052880635.jpg) diff --git a/documentation/docs/Organizers/Running_a_benchmark/Competition-Management-&-List.md b/documentation/docs/Organizers/Running_a_benchmark/Competition-Management-&-List.md new file mode 100644 index 000000000..9d6b1e752 --- /dev/null +++ b/documentation/docs/Organizers/Running_a_benchmark/Competition-Management-&-List.md @@ -0,0 +1,30 @@ +This page will show you how to create, manage, edit and delete your competitions. + +It will also show you how to track the competitions you are currently in. + +![v2_labeled_comp_list](../../_attachments/70932628-08974e80-1fef-11ea-9303-734d098df784_17528513089370105.png) + +## Competition create button (Form) +This button will take you to the wizard/form for creating competitions. This will allow you to walk through each step of creating a competition using our creation/edit form. For more information on this form/wizard, please see the following link: [Competition Creation: Form](../Benchmark_Creation/Competition-Creation:-Form.md) + + +## Competition create button (Upload) +This button will take you to the upload page for competition bundles. Here you will be able to upload a competition bundle, and if it is validated and processed successfully, you should see a link to your new competition. For more information on this page, please see the following link: [Competition Creation: Bundle](../Benchmark_Creation/Competition-Creation:-Bundle.md) + +## Competitions I'm running tab +This should be the default selection for the tab navigation at the top. Having this selected will show you all the competitions you currently run/manage, and the available actions for them. + +## Competitions I'm in tab +Clicking on this tab will change the main view of the page. You should now see a list of competitions you're competing in (Without any competition administrator options). Clicking any of these titles should bring you to the competition detail page of that competition. + +## Publish competition button +This button will publish your competition in order to make it publicly available. If your competition is already published, this button will appear green and be used to remove your competition from public availability (It will not be deleted). By default, if your competition is un-published, it appears grey. + +## Edit competition button +This button will take you to the wizard/form for editing competitions. For more information on the competition edit form, please see the link [here](../Benchmark_Creation/Competition-Creation:-Form.md) + +## Delete competition button +Deletes your competition. There will be a confirmation dialogue before deletion. We cannot recover deleted competitions. + +## Competition link +A link to the competition's detail page where users can register, make submissions, view the leaderboard and terms, etc. For more information about the competition detail page, see the link [here](Competition-Detail-Page.md) diff --git a/documentation/docs/Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md b/documentation/docs/Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md new file mode 100644 index 000000000..3c01367ba --- /dev/null +++ b/documentation/docs/Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md @@ -0,0 +1,317 @@ +Compute workers are simply machines that are able to accept/send celery messages on the port used by the broker URL you wish to connect to that have a compute worker image, or other software to receive submissions. This means that you can add computing power to your competitions or benchmarks if needed! Any computer, from your own physical machines to virtual machines on cloud computing services can be used for this purpose. You can add multiple workers to a queue to process several submissions simultaneously. + +!!! note "To use Podman, go to the [Podman documentation](Compute-worker-installation-with-Podman.md)." + +**To use Docker, follow these instructions below:** + +Steps: + + - Have a machine (_either physical or virtual, 100 GB storage recommended_) + - Install Docker + - Pull Compute Worker Image + - Run the compute worker via Docker + + +## Install Docker +Either: + +a) Install docker via the installation script: https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-using-the-convenience-script + +```bash +curl https://get.docker.com | sudo sh +sudo usermod -aG docker $USER +``` + +b) Install manually, following the steps at: https://docs.docker.com/install/ + +## Pull Compute Worker Image +On the compute worker machine, run the following command in a shell: +```bash +docker pull codalab/competitions-v2-compute-worker +``` + +That will pull the latest image for the v2 worker. For specific versions, see the docker hub page at: +https://hub.docker.com/r/codalab/competitions-v2-compute-worker/tags + + +## Start CPU worker + +Make a file `.env` and put this in it: +```ini title=".env" +# Queue URL +BROKER_URL= + +# Location to store submissions/cache -- absolute path! +HOST_DIRECTORY=/codabench + +# If SSL isn't enabled, then comment or remove the following line +BROKER_USE_SSL=True +``` + +!!! note + - The broker URL is a unique identifier of the job queue that the worker should listen to. To create a queue or obtain the broker URL of an existing queue, you can refer to [Queue Management](Queue-Management.md) wiki page. + + - `/codabench` -- this path needs to be volumed into `/codabench` on the worker, as you can see below. You can select another location if convenient. + +Create a `docker-compose.yml` file and paste the following content in it: +```yaml title="docker-compose.yml" +# Codabench Worker +services: + worker: + image: codalab/competitions-v2-compute-worker:latest + container_name: compute_worker + volumes: + - /codabench:/codabench + - /var/run/docker.sock:/var/run/docker.sock + env_file: + - .env + restart: unless-stopped + #hostname: ${HOSTNAME} + logging: + options: + max-size: 50m + max-file: 3 + +``` +!!! note + `hostname: ${HOSTNAME}` allows you to set the hostname of the compute worker container, which will then be shown in the [server status](Server-status-page.md) page on Codabench. This can be set to anything you want, by setting the `HOSTNAME` environment variable on the machine hosting the Compute Worker, then uncommenting the line the `docker-compose.yml` before launching the compute worker. + + +You can then launch the worker by running this command in the terminal where the `docker-compose.yml` file is located: +```bash +docker compose up -d +``` + +### Deprecated method (one liner) +Alternately, you can use the docker run below: +```bash +docker run \ + -v /codabench:/codabench \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -d \ + --env-file .env \ + --name compute_worker \ + --restart unless-stopped \ + --log-opt max-size=50m \ + --log-opt max-file=3 \ + codalab/competitions-v2-compute-worker:latest +``` + + +## Start GPU worker + +Make a `.env` file, as explained in CPU worker instructions. + +Then, install the NVIDIA toolkit: +[Nvidia toolkit installation instructions](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/index.html) + +Once you install and configure the NVIDIA container toolkit, you can create a `docker-compose.yml` file with the following content: +```yaml title="docker-compose.yml" +# Codabench GPU worker (NVIDIA) +services: + worker: + image: codalab/competitions-v2-compute-worker:gpu1.3 + container_name: compute_worker + volumes: + - /codabench:/codabench + - /var/run/docker.sock:/var/run/docker.sock + env_file: + - .env + restart: unless-stopped + #hostname: ${HOSTNAME} + logging: + options: + max-size: 50m + max-file: 3 + runtime: nvidia + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: all + capabilities: + - gpu +``` +!!! note + `hostname: ${HOSTNAME}` allows you to set the hostname of the compute worker container, which will then be shown in the [server status](Server-status-page.md) page on Codabench. This can be set to anything you want, by setting the `HOSTNAME` environment variable on the machine hosting the Compute Worker, then uncommenting the line the `docker-compose.yml` before launching the compute worker. + + +You can then launch the worker by running this command in the terminal where the `docker-compose.yml` file is located: +```bash +docker compose up -d +``` + + +### NVIDIA-docker Wrapper (deprecated method) +[Nvidia installation instructions](https://github.com/NVIDIA/nvidia-docker#quickstart) +```bash +nvidia-docker run \ + -v /codabench:/codabench \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v /var/lib/nvidia-docker/nvidia-docker.sock:/var/lib/nvidia-docker/nvidia-docker.sock \ + -d \ + --env-file .env \ + --name compute_worker \ + --restart unless-stopped \ + --log-opt max-size=50m \ + --log-opt max-file=3 \ + codalab/competitions-v2-compute-worker:gpu +``` + +Note that a competition docker image including CUDA and other GPU libraries, such as `codalab/codalab-legacy:gpu`, is then required. + +## Check logs + +Use the following command to check logs and ensure everything is working fine: + +```bash +docker logs -f compute_worker +``` + +## Cleaning up periodically + +It is recommended to clean up docker images and containers regularly to avoid filling up the storage. + +1. Run the following command: + +```bash +sudo crontab -e +``` + +2. Add the following line: + +```bash +@daily docker system prune -af +``` + +## Keep track of the worker + +It is recommended to store the docker container hostname to identify the worker. This way, it is easier to troubleshoot issues when having multiple workers in one queue. To get the hostname, simply run `docker ps` and look at the key `CONTAINER ID` at the beginning of the output: + +```sh +$ docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +1a2b3d4e5f67 codalab/competitions-v2-compute-worker:latest "/bin/sh -c 'celery …" 3 days ago Up 3 days compute_worker +``` + +For each submission made to your queue, you can know what worker computed the ingestion and the scoring jobs in the [server status page](Server-status-page.md). + +--- + +## Optional: put data directly inside the compute worker + +The folder `$HOST_DIRECTORY/data`, usually `/codabench/data`, is shared between the host (the compute worker) and the container running the submission (a new container is created for each submission). It is mounted inside the container as `/app/data`. This means that you can put data in your worker, in `$HOST_DIRECTORY/data`, so it can be read-only accessed during the job's process. You'll need to modify the scoring and/or ingestion programs accordingly, to points to `/app/data`. This is especially useful if you work with confidential data, or with a heavy dataset. + +!!! note "If you have several workers in your queue, remember to have the data accessible for each one." + +![](_attachments/4259c2e5-d119-4ca2-8fc8-b69196f1528c_17534367097493236.jpg) + + + +!!! tip "If you simply wish to set up some compute workers to increase the computing power of your benchmark, you don't need to scroll this page any further." + +--- + +## Building compute worker + +This is helpful only if you want to build the compute worker image. It is not needed if you simply want to set up compute workers to run submissions. + +To build the normal image: + +```bash +docker build -t codalab/competitions-v2-compute-worker:latest -f Dockerfile.compute_worker . +``` + +To build the GPU version: +```bash +docker build -t codalab/competitions-v2-compute-worker:gpu -f Dockerfile.compute_worker_gpu . +``` + +To update the image (add tag `:latest`, `:gpu` or else if needed) + +```bash +docker push codalab/competitions-v2-compute-worker +``` + +!!! note "If you have running compute workers, you'll need to pull again the image and to restart the workers to take into account the changes." + + +## Worker management + +Outside of docker containers install [Fabric](http://fabfile.org/) like so: + +```bash +pip install fab-classic==1.17.0 +``` + +Create a `server_config.yaml` in the root of this repository using: +``` +cp server_config_sample.yaml server_config.yaml +``` + +Below is an example `server_config.yaml` that defines 2 roles `comp-gpu` and `comp-cpu`, +one with GPU style workers (`is_gpu` and the GPU `docker_image`) and one with CPU style workers + +```yaml title="server_config.yaml" +comp-gpu: + hosts: + - ubuntu@12.34.56.78 + - ubuntu@12.34.56.79 + broker_url: pyamqp://user:pass@host:port/vhost-gpu + is_gpu: true + docker_image: codalab/competitions-v2-compute-worker:gpu + +comp-cpu: + hosts: + - ubuntu@12.34.56.80 + broker_url: pyamqp://user:pass@host:port/vhost-cpu + is_gpu: false + docker_image: codalab/competitions-v2-compute-worker:latest +``` + +You can of course create your own `docker_image` and specify it here. + +You can execute commands against a role: + +```bash +fab -R comp-gpu status +.. +[ubuntu@12.34.56.78] out: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +[ubuntu@12.34.56.78] out: 1d318268bee1 codalab/competitions-v2-compute-worker:gpu "/bin/sh -c 'celery …" 2 hours ago Up 2 hours hardcore_greider +.. + +fab -R comp-gpu update +.. +(updates workers) +``` + +See available commands with `fab -l` + +## Update docker image + +If the compute worker docker image was updated, you can reflect the changes using the following commands. + +Check no job is running: + +```sh +docker ps +``` + +Update the worker: + +```sh +docker stop compute_worker +docker rm compute_worker +docker pull codalab/competitions-v2-compute-worker:latest # or other relevant docker image +docker run \ # or docker compose up -d + -v /codabench:/codabench \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -d \ + --env-file .env \ + --name compute_worker \ + --restart unless-stopped \ + --log-opt max-size=50m \ + --log-opt max-file=3 \ + codalab/competitions-v2-compute-worker:latest # or other relevant docker image +``` \ No newline at end of file diff --git a/documentation/docs/Organizers/Running_a_benchmark/Compute-worker-installation-with-Podman.md b/documentation/docs/Organizers/Running_a_benchmark/Compute-worker-installation-with-Podman.md new file mode 100644 index 000000000..52455d667 --- /dev/null +++ b/documentation/docs/Organizers/Running_a_benchmark/Compute-worker-installation-with-Podman.md @@ -0,0 +1,140 @@ +Here is the specification for compute worker installation by using Podman. +## Requirements for host machine + +We need to install Podman on the VM. We use Debian based OS, like Ubuntu. Ubuntu is recommended, because it has better Nvidia driver support. + +`sudo apt install podman ` + +Then, configure where Podman will download the images: Podman will use Dockerhub by adding this line into `/etc/containers/registries.conf `: + +`unqualified-search-registries = ["docker.io"] ` + +Create the `.env` file in order to add the compute worker into a queue (here, the default queue is used. If you use a particular queue, then, fill in your BROKER_URL generated when creating this particular queue) : + +```ini title=".env" +BROKER_URL=pyamqp://:@codabench-test.lri.fr:5672 +HOST_DIRECTORY=/codabench +# If SSL isn't enabled, then comment or remove the following line +BROKER_USE_SSL=True +CONTAINER_ENGINE_EXECUTABLE=podman +``` + +**Create user for running Podman container** +```bash +useradd worker +``` + +!!! note "In order to use podman later to launch the computer worker, you need to have logged out completely first from whatever user you were using and log in as "worker". If you fail to do so, your environment will likely store environment variables tied to the original user and launching podman will not work." + +## For GPU compute worker VM + +You need to install nvidia packages supporting Podman and nvidia drivers: + +```bash +distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \ + && curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \ + && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-container.list +sudo apt update +sudo apt install nvidia-container-runtime nvidia-containe-toolkit nvidia-driver- +``` + +Edit the nvidia runtime config + +```bash +sudo sed -i 's/^#no-cgroups = false/no-cgroups = true/;' /etc/nvidia-container-runtime/config.toml +``` + +Check if nvidia driver is working, by executing: + +```bash +nvidia-smi + ++-----------------------------------------------------------------------------+ +| NVIDIA-SMI 520.61.05 Driver Version: 520.61.05 CUDA Version: 11.8 | +|-------------------------------+----------------------+----------------------+ +| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | +| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | +| | | MIG M. | +|===============================+======================+======================| +| 0 NVIDIA GeForce ... On | 00000000:01:00.0 Off | N/A | +| 27% 26C P8 20W / 250W | 1MiB / 11264MiB | 0% Default | +| | | N/A | ++-------------------------------+----------------------+----------------------+ + ++-----------------------------------------------------------------------------+ +| Processes: | +| GPU GI CI PID Type Process name GPU Memory | +| ID ID Usage | +|=============================================================================| +| No running processes found | ++-----------------------------------------------------------------------------+ + +``` + +The result should show gpu card information. + +We need to configure the OCI hook (entry point to inject code) script for nvidia. Create this file `/usr/share/containers/oci/hooks.d/oci-nvidia-hook.json` if not exists: + +```json title="oci-nvidia-hook.json" +{ + "version": "1.0.0", + "hook": { + "path": "/usr/bin/nvidia-container-toolkit", + "args": ["nvidia-container-toolkit", "prestart"], + "env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ] + }, + "when": { + "always": true, + "commands": [".*"] + }, + "stages": ["prestart"] +} +``` + +Validating if all are working by running a test container: + +```bash +podman run --rm -it \ + --security-opt="label=disable" \ + --hooks-dir=/usr/share/containers/oci/hooks.d/ \ + nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi +``` +The result should show as same as the command `nvidia-smi` above. + + +## Compute worker installation + +### For CPU container + +Run the compute worker container : + +```bash +podman run -d \ + --env-file .env \ + --name compute_worker \ + --security-opt="label=disable" \ + --device /dev/fuse --user worker \ + --restart unless-stopped \ + --log-opt max-size=50m \ + --log-opt max-file=3 \ + codalab/codabench_worker_podman:0.1 +``` + +### For GPU container + +Run the GPU compute worker container + +```bash +podman run -d \ + --env-file .env \ + --privileged \ + --name gpu_compute_worker \ + --device /dev/fuse --user worker \ + --security-opt="label=disable" \ + --restart unless-stopped \ + --log-opt max-size=50m \ + --log-opt max-file=3 \ + codalab/codabench_worker_podman_gpu:0.2 +``` \ No newline at end of file diff --git a/documentation/docs/Organizers/Running_a_benchmark/Queue-Management.md b/documentation/docs/Organizers/Running_a_benchmark/Queue-Management.md new file mode 100644 index 000000000..5934ac51f --- /dev/null +++ b/documentation/docs/Organizers/Running_a_benchmark/Queue-Management.md @@ -0,0 +1,57 @@ +The queue management page lists all queues you have access to, and optionally all current public queues. + +For queues you've created, it will also show options for editing, deleting, copying and displaying the broker URL. + +You can also create new queues from this page. You can use the [server status page](Server-status-page.md) to have an overview of the submissions made to a queue you own. + + +![wip_codalab_v2_q_mgmt](../../_attachments/71212869-0dfece00-2267-11ea-9971-e5a13b65ea0a_17528513102591712.png) + + +1) [Show Public Queues](Queue-Management.md#show-public-queues) +2) [Create Queue](Queue-Management.md#create-queue) +3) [Action Buttons](Queue-Management.md#action-buttons) + + - Eye Icon + - Document Icon + - Edit Icon + - Trash Icon + + +## Show Public Queues +Enabling this checkbox will display public queues as well as queues you organized, or have been given access to. You will not be able to edit them, but you can view queue details and copy the broker URL. + +## Create Queue +Clicking this button will bring up a modal with the queue form. + +![image](../../_attachments/71212939-371f5e80-2267-11ea-9531-1efd4f55f229_17528513102900565.png) + +The following fields are present: + +- Name: The name of the queue +- Make Public: If checked, this queue will be available for public use. +- Collaborators: A multi-select field that you can search for users by username or email. These will be people who have access to your queue. + +## Action Buttons + +### Eye Icon +Clicking this button will show you details about your queue such as the Broker URL and Vhost name. + +### Document Icon +The document icon is used to copy the broker URL to your clipboard with one-click. + +### Edit Icon +The edit icon brings up the queue modal/form for editing the current queue. + +### Trash Icon +The trash icon deletes the current queue. There will be a confirmation dialogue. Once this is done your queue is gone forever so be careful. + +--- + +## Compute workers setup + +See [compute worker management and setup](Compute-Worker-Management---Setup.md) for more information about workers configuration. + +Internal and external compute workers can be linked to Codabench competitions. The queues dispatch the jobs between the compute workers. Note that a queue can receive jobs (submissions) from several competitions, and can send them to several compute workers. The general architecture of queues and workers can be represented like this: + +![codalab_workers_architecture](../../_attachments/4ad333ae-4d22-49e8-82be-757ea0423642_17528513109674363.jpg) diff --git a/documentation/docs/Organizers/Running_a_benchmark/Resource-Management.md b/documentation/docs/Organizers/Running_a_benchmark/Resource-Management.md new file mode 100644 index 000000000..4fd14c77d --- /dev/null +++ b/documentation/docs/Organizers/Running_a_benchmark/Resource-Management.md @@ -0,0 +1,109 @@ +This page is where you can manage your resources e.g. Submissions, Datasets, Programs, Tasks, and Competition Bundles. You can also view and manage your quota on this page. + + +You can access this interface by clicking on "**Resources**" in the main menu: +![](_attachments/7013c755-824f-4c12-9c69-ef8ef03025eb_17534367071670744.jpg) + + +--- + +## Submissions +In this tab, you can view all your submissions either uploaded in this interface or submitted to a competition. +![](_attachments/3eb6336a-5f0c-4abc-abd2-a9c4280b0863_17534367073499072.jpg) + +By clicking the `Add Submission` button you can fill a form and attach a submission file to upload a new submission. This is useful in different cases e.g. when you want to share a sample submission with the participants of a competition you are organizing. +![](_attachments/fb6ecce8-fdc8-4fff-af33-ad68153ded86_17534367075859904.jpg) + + +## Datasets/Programs +In this tab, you can view the datasets and programs that you have uploaded. You can also view auto-created and publicly available datasets/programs by checking the relevant checkboxes. + +![](_attachments/548b326e-5e1b-4688-82c2-fed0a402af21_17534367080187995.jpg) + +By clicking the `Add Dataset/Program` button you can fill a form and attach a dataset file to upload. + +![](_attachments/b7aba5b0-1eab-4b8c-8f0e-7d463aa20c3b_1753436707984425.jpg) + +You can click on a dataset/program and make it public or private. This is useful when you want to share a dataset with participants so that hey can use it to prepare a submission for a competition. + +![](_attachments/99ec6090-86bd-4425-8f12-46115e09409d_1753436708048147.jpg) + + +For a general breakdown of the roles of different types of datasets, see this link: [Competition Bundle Structure: Data types and their role](https://github.com/codalab/competitions-v2/wiki/Competition-Bundle-Structure#data-types-and-their-role). + + + +## Tasks +In this tab, you can manage your tasks. You can create a new task, upload a task, edit a task and check task details. +![](_attachments/fe61c496-4b40-4c6e-bda1-bfa579393987_17534367082532165.jpg) + + +### Create New Task +To create a new task, you have to fill the form by entering task name and description +![](_attachments/7217bebc-0a9c-45f4-b0e6-2881c8e74a67_1753436708407207.jpg) + +You also have to select datasets and programs from the already uploaded ones in the Datasets/Programs tab +![](_attachments/b99658f9-4819-49b2-a272-69503a4361ac_17534367088250148.jpg) + + + +### Edit a Task +You can change the task name and description +![](_attachments/49fe8121-9cd5-4364-ac5f-f463396ea525_1753436708800273.jpg) + +You can also change the datasets/programs used in the task +![](_attachments/b89268e3-bbdd-483c-a595-add9eb5fee7a_17534367089431207.jpg) + +!!! note + Organizers should be careful when updating a task because some submissions may have used the task and updating the task will not allow you to rerun those submissions because the task they have used is now changed. + + + +### Upload a Task +You can create a new task by uploading a task zip that has the required files in the correct format. +![](_attachments/1ffc7805-950e-46ad-adfe-bca8a4b85c70_1753436708942981.jpg) + + +Create a zip file that consists of a `task.yaml` file and zips of datasets/programs if required. You can use already existing datasets/prograsm by using their keys in the yaml, or upload new datasets/programs or use a mix of keys and files e.g. you choose to use already existing input data and reference data but use zip files for ingestion and scoring program. In the last case, codabench will create two programs and then use them in your task and will use existing datasets in the same task. + +Check the files below for examples of task upload zips. + +- [task_with_keys_only.zip](https://github.com/user-attachments/files/17597251/task_with_keys_only.zip) +- [task_with_files_only.zip](https://github.com/user-attachments/files/17597252/task_with_files_only.zip) +- [task_with_mix_of_keys_and_files.zip](https://github.com/user-attachments/files/17597265/task_with_mix_of_keys_and_files.zip) + +For reference, here is the content of the `task.yaml` file that you can find inside the `task_with_mix_of_keys_and_files.zip` task: +```yaml title="task.yaml" +name: Iris Task +description: Iris Task for Flower classification +is_public: false +scoring_program: + zip: iris-scoring-program.zip +ingestion_program: + zip: iris-ingestion-program.zip +input_data: + key: 6c3e6dde-d0fa-4c22-af66-030187dbfd4f +reference_data: + key: c4179c3f-498c-486a-8ac5-1e194036a3ed +``` + + +### Task Details +In the task details, you can view all the task details e.g. title, description, task owner, created date, people with whom this task is shared, competitions where this task is used, the datasets/programs used in this task and option to download them, and option to make the task public/private. +![](_attachments/996bf4c7-bccf-44b3-b90d-7513f8d83c0f_17534367093325448.jpg) + + + + + +## Competition Bundles +In this tab, you can mange your competition bundles. These bundles are stored when you create your competitions using a zip. +![](_attachments/b6c7f500-f531-4b1c-9b08-86609c197126_17534367096771557.jpg) + + + +## Quota and Cleanup +This section of the resource interface shows you the usage of your quota. A free quota of 15 GB is given to all the users and this can be increased by the platform administrators in special circumstances for selected users. You can also do some quick cleanup from here by deleting unused resources e.g. submissions, datasets and tasks etc. +![](_attachments/e4bcf27a-6af1-4b1a-9802-1af259570619_1753436709645197.jpg) + + diff --git a/documentation/docs/Organizers/Running_a_benchmark/Server-status-page.md b/documentation/docs/Organizers/Running_a_benchmark/Server-status-page.md new file mode 100644 index 000000000..46fcd29f1 --- /dev/null +++ b/documentation/docs/Organizers/Running_a_benchmark/Server-status-page.md @@ -0,0 +1,13 @@ +The server status page gives information about past and current submissions, and is useful for troubleshooting. Any user can access the interface, and get information about their own submissions and the submissions made to queues they own. Administrators can see all submissions. Here is an overview of the page: + +![](_attachments/4bdc0662-ad72-4894-9611-966978652443_17534367071485858.jpg) + +Note that `*` refers to the default queue of the platform. "Hostname" refers to the docker container ID of the compute worker that computed the job. + +## How to access the interface + +You can access it either from the top right menu, or from the "[Queue management](Queue-Management.md)" page, as shown in the screenshots below. + +![](_attachments/0d87060c-b095-42eb-a69f-272d4ba94215_17534367067992313.jpg) + +![](_attachments/b69fa0c7-52aa-4083-b0ca-ea50229a637e_17534367071084306.jpg) \ No newline at end of file diff --git a/documentation/docs/Organizers/Running_a_benchmark/Update-programs-or-data.md b/documentation/docs/Organizers/Running_a_benchmark/Update-programs-or-data.md new file mode 100644 index 000000000..118cc2174 --- /dev/null +++ b/documentation/docs/Organizers/Running_a_benchmark/Update-programs-or-data.md @@ -0,0 +1,76 @@ +In this page, you'll learn how to update critical elements of your benchmark like the scoring program or the reference data, while your benchmark is already up and running. + +For a general overview of resources management, [click here](Resource-Management.md). + +If order to update your programs or data, you have two approaches: +- **A.** Edit an existing Task (simpler and straightforward) +- **B.** Create a new Task + +Let's see both approach in detail. + +## A. Edit an existing Task + +### 1. Prepare the new dataset or program + +- Make local changes to the elements you want to update: scoring program, ingestion program, input data and/or reference data. + +- Zip the new version of your program or data. **Make sure to zip the files at the root of the archive, without zipping the folder structure.** + +### 2. Upload the new dataset or program + +- Go to Resources + +![](_attachments/c3679b14-444f-4718-ae4a-ac0d5f297b76_17534367051868246.jpg) + +- Go to "Datasets and Programs" and click on "Add Dataset/Program" + +![](_attachments/879ae590-498b-49cf-9872-77c15e4b5dae_17534367054113083.jpg) + +- Fill in the form: Name the new program or dataset, select the type (scoring program, input data, etc.), and select your ZIP file + +![](_attachments/3f1dc4a3-f90d-4497-abce-ff3b8960278f_17534367055954835.jpg) + +### 3. Update the Task used by your benchmark + +Still on "Resources" page, go to the "Task" tab. Find the task you want to edit. In order to recognize it, make sure it is marked as "In Use", and click to see more information and make sure it is related to the right benchmark. + +Then click on the pencil symbol to edit it: +![](_attachments/25b506f9-dc9b-4ffc-8c2a-8c8bb95b3149_17534367056648443.jpg) + +Start typing the name of your new program or dataset in the corresponding field and select it, then save. + +![](_attachments/377c4f6b-8975-4462-91c0-e5c9926b91f6_17534367061268125.jpg) + + +**Done!** Your task is updated and its new version will be triggered by new submissions. You don't need to update the benchmark/competition for the change to take effect. + + +## B. Create a new Task + +### 1. Prepare your new dataset / program + +First, upload the new versions of your program and/or dataset. To that end, follow steps **1.** and **2.** presented above. + +### 2. Create Task + +- Go to "Resources" > "Task" > "Create Task" + +![](_attachments/78d98652-2ad6-47a2-90e1-96700325a4a4_1753436706098669.jpg) + +- Fill in all fields: Name, Description, Scoring program, (optionally: Ingestion program, Reference data, Input data) + +### Edit your benchmark + +- Once your task is created, go to the editor of your challenge + +![](_attachments/49650ec6-ce8f-440b-9245-0ff04dcfb7df_17534367060782135.jpg) + +- Go to "Phases" and edit the relevant phase + +![](_attachments/f136dce0-2be2-42d4-9d27-9743149f1a4f_1753436706408659.jpg) + +- Select your new task and save + +![](_attachments/aba614a8-06f5-4c81-b060-0afc3647e777_17534367063286426.jpg) + +**Done!** Your benchmark is now ready to run your new task for future submissions. diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/0d87060c-b095-42eb-a69f-272d4ba94215_17534367067992313.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/0d87060c-b095-42eb-a69f-272d4ba94215_17534367067992313.jpg new file mode 100644 index 000000000..e918fd9c6 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/0d87060c-b095-42eb-a69f-272d4ba94215_17534367067992313.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/1ffc7805-950e-46ad-adfe-bca8a4b85c70_1753436708942981.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/1ffc7805-950e-46ad-adfe-bca8a4b85c70_1753436708942981.jpg new file mode 100644 index 000000000..08466c567 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/1ffc7805-950e-46ad-adfe-bca8a4b85c70_1753436708942981.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/25b506f9-dc9b-4ffc-8c2a-8c8bb95b3149_17534367056648443.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/25b506f9-dc9b-4ffc-8c2a-8c8bb95b3149_17534367056648443.jpg new file mode 100644 index 000000000..2c5956396 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/25b506f9-dc9b-4ffc-8c2a-8c8bb95b3149_17534367056648443.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/377c4f6b-8975-4462-91c0-e5c9926b91f6_17534367061268125.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/377c4f6b-8975-4462-91c0-e5c9926b91f6_17534367061268125.jpg new file mode 100644 index 000000000..75988d4da Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/377c4f6b-8975-4462-91c0-e5c9926b91f6_17534367061268125.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/3eb6336a-5f0c-4abc-abd2-a9c4280b0863_17534367073499072.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/3eb6336a-5f0c-4abc-abd2-a9c4280b0863_17534367073499072.jpg new file mode 100644 index 000000000..3b981349a Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/3eb6336a-5f0c-4abc-abd2-a9c4280b0863_17534367073499072.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/3f1dc4a3-f90d-4497-abce-ff3b8960278f_17534367055954835.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/3f1dc4a3-f90d-4497-abce-ff3b8960278f_17534367055954835.jpg new file mode 100644 index 000000000..6ccbeecc6 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/3f1dc4a3-f90d-4497-abce-ff3b8960278f_17534367055954835.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/4259c2e5-d119-4ca2-8fc8-b69196f1528c_17534367097493236.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/4259c2e5-d119-4ca2-8fc8-b69196f1528c_17534367097493236.jpg new file mode 100644 index 000000000..4bf9cb90f Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/4259c2e5-d119-4ca2-8fc8-b69196f1528c_17534367097493236.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/49650ec6-ce8f-440b-9245-0ff04dcfb7df_17534367060782135.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/49650ec6-ce8f-440b-9245-0ff04dcfb7df_17534367060782135.jpg new file mode 100644 index 000000000..22016a9ea Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/49650ec6-ce8f-440b-9245-0ff04dcfb7df_17534367060782135.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/49ca5f21-a10f-4453-a04e-4ac30bfa27b2_17534367047245183.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/49ca5f21-a10f-4453-a04e-4ac30bfa27b2_17534367047245183.jpg new file mode 100644 index 000000000..11733ba90 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/49ca5f21-a10f-4453-a04e-4ac30bfa27b2_17534367047245183.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/49fe8121-9cd5-4364-ac5f-f463396ea525_1753436708800273.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/49fe8121-9cd5-4364-ac5f-f463396ea525_1753436708800273.jpg new file mode 100644 index 000000000..d1944219c Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/49fe8121-9cd5-4364-ac5f-f463396ea525_1753436708800273.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/4bdc0662-ad72-4894-9611-966978652443_17534367071485858.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/4bdc0662-ad72-4894-9611-966978652443_17534367071485858.jpg new file mode 100644 index 000000000..425e716f6 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/4bdc0662-ad72-4894-9611-966978652443_17534367071485858.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/4f331c80-7d24-47f7-ba4f-71d4bd9dc003_17534367045066261.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/4f331c80-7d24-47f7-ba4f-71d4bd9dc003_17534367045066261.jpg new file mode 100644 index 000000000..9511fe228 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/4f331c80-7d24-47f7-ba4f-71d4bd9dc003_17534367045066261.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/548b326e-5e1b-4688-82c2-fed0a402af21_17534367080187995.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/548b326e-5e1b-4688-82c2-fed0a402af21_17534367080187995.jpg new file mode 100644 index 000000000..79e045805 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/548b326e-5e1b-4688-82c2-fed0a402af21_17534367080187995.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/7013c755-824f-4c12-9c69-ef8ef03025eb_17534367071670744.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/7013c755-824f-4c12-9c69-ef8ef03025eb_17534367071670744.jpg new file mode 100644 index 000000000..bc6d7a077 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/7013c755-824f-4c12-9c69-ef8ef03025eb_17534367071670744.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/7217bebc-0a9c-45f4-b0e6-2881c8e74a67_1753436708407207.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/7217bebc-0a9c-45f4-b0e6-2881c8e74a67_1753436708407207.jpg new file mode 100644 index 000000000..c13038bc1 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/7217bebc-0a9c-45f4-b0e6-2881c8e74a67_1753436708407207.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/78d98652-2ad6-47a2-90e1-96700325a4a4_1753436706098669.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/78d98652-2ad6-47a2-90e1-96700325a4a4_1753436706098669.jpg new file mode 100644 index 000000000..de7ba6897 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/78d98652-2ad6-47a2-90e1-96700325a4a4_1753436706098669.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/879ae590-498b-49cf-9872-77c15e4b5dae_17534367054113083.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/879ae590-498b-49cf-9872-77c15e4b5dae_17534367054113083.jpg new file mode 100644 index 000000000..6387268a6 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/879ae590-498b-49cf-9872-77c15e4b5dae_17534367054113083.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/996bf4c7-bccf-44b3-b90d-7513f8d83c0f_17534367093325448.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/996bf4c7-bccf-44b3-b90d-7513f8d83c0f_17534367093325448.jpg new file mode 100644 index 000000000..8f151b3ec Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/996bf4c7-bccf-44b3-b90d-7513f8d83c0f_17534367093325448.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/99ec6090-86bd-4425-8f12-46115e09409d_1753436708048147.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/99ec6090-86bd-4425-8f12-46115e09409d_1753436708048147.jpg new file mode 100644 index 000000000..849d9197d Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/99ec6090-86bd-4425-8f12-46115e09409d_1753436708048147.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/aba614a8-06f5-4c81-b060-0afc3647e777_17534367063286426.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/aba614a8-06f5-4c81-b060-0afc3647e777_17534367063286426.jpg new file mode 100644 index 000000000..e2d328494 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/aba614a8-06f5-4c81-b060-0afc3647e777_17534367063286426.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/b69fa0c7-52aa-4083-b0ca-ea50229a637e_17534367071084306.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/b69fa0c7-52aa-4083-b0ca-ea50229a637e_17534367071084306.jpg new file mode 100644 index 000000000..ea2702f2c Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/b69fa0c7-52aa-4083-b0ca-ea50229a637e_17534367071084306.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/b6c7f500-f531-4b1c-9b08-86609c197126_17534367096771557.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/b6c7f500-f531-4b1c-9b08-86609c197126_17534367096771557.jpg new file mode 100644 index 000000000..9be411734 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/b6c7f500-f531-4b1c-9b08-86609c197126_17534367096771557.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/b7aba5b0-1eab-4b8c-8f0e-7d463aa20c3b_1753436707984425.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/b7aba5b0-1eab-4b8c-8f0e-7d463aa20c3b_1753436707984425.jpg new file mode 100644 index 000000000..3618852e9 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/b7aba5b0-1eab-4b8c-8f0e-7d463aa20c3b_1753436707984425.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/b89268e3-bbdd-483c-a595-add9eb5fee7a_17534367089431207.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/b89268e3-bbdd-483c-a595-add9eb5fee7a_17534367089431207.jpg new file mode 100644 index 000000000..410e336e6 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/b89268e3-bbdd-483c-a595-add9eb5fee7a_17534367089431207.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/b99658f9-4819-49b2-a272-69503a4361ac_17534367088250148.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/b99658f9-4819-49b2-a272-69503a4361ac_17534367088250148.jpg new file mode 100644 index 000000000..b479aa1ea Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/b99658f9-4819-49b2-a272-69503a4361ac_17534367088250148.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/c3679b14-444f-4718-ae4a-ac0d5f297b76_17534367051868246.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/c3679b14-444f-4718-ae4a-ac0d5f297b76_17534367051868246.jpg new file mode 100644 index 000000000..1efefc0d6 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/c3679b14-444f-4718-ae4a-ac0d5f297b76_17534367051868246.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/d369cbf6-a129-4599-ae39-defe99b8aaac_1753436704381793.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/d369cbf6-a129-4599-ae39-defe99b8aaac_1753436704381793.jpg new file mode 100644 index 000000000..863034c14 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/d369cbf6-a129-4599-ae39-defe99b8aaac_1753436704381793.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/e42ea472-4f52-4f0e-8dfb-a39cba8b3838_1753436704639189.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/e42ea472-4f52-4f0e-8dfb-a39cba8b3838_1753436704639189.jpg new file mode 100644 index 000000000..2892aa67e Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/e42ea472-4f52-4f0e-8dfb-a39cba8b3838_1753436704639189.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/e4bcf27a-6af1-4b1a-9802-1af259570619_1753436709645197.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/e4bcf27a-6af1-4b1a-9802-1af259570619_1753436709645197.jpg new file mode 100644 index 000000000..932c8b3c1 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/e4bcf27a-6af1-4b1a-9802-1af259570619_1753436709645197.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/ebf6b2b9-41f0-419f-9c95-cf0f4d8a5ffc_17534367052880635.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/ebf6b2b9-41f0-419f-9c95-cf0f4d8a5ffc_17534367052880635.jpg new file mode 100644 index 000000000..feb3c2e27 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/ebf6b2b9-41f0-419f-9c95-cf0f4d8a5ffc_17534367052880635.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/f136dce0-2be2-42d4-9d27-9743149f1a4f_1753436706408659.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/f136dce0-2be2-42d4-9d27-9743149f1a4f_1753436706408659.jpg new file mode 100644 index 000000000..b72225020 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/f136dce0-2be2-42d4-9d27-9743149f1a4f_1753436706408659.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/f6816bd8-af4e-4ab0-99b3-61a69d7e1278_17534367048086147.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/f6816bd8-af4e-4ab0-99b3-61a69d7e1278_17534367048086147.jpg new file mode 100644 index 000000000..2b872a94d Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/f6816bd8-af4e-4ab0-99b3-61a69d7e1278_17534367048086147.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/fb6ecce8-fdc8-4fff-af33-ad68153ded86_17534367075859904.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/fb6ecce8-fdc8-4fff-af33-ad68153ded86_17534367075859904.jpg new file mode 100644 index 000000000..2df26405b Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/fb6ecce8-fdc8-4fff-af33-ad68153ded86_17534367075859904.jpg differ diff --git a/documentation/docs/Organizers/Running_a_benchmark/_attachments/fe61c496-4b40-4c6e-bda1-bfa579393987_17534367082532165.jpg b/documentation/docs/Organizers/Running_a_benchmark/_attachments/fe61c496-4b40-4c6e-bda1-bfa579393987_17534367082532165.jpg new file mode 100644 index 000000000..66a7f2db6 Binary files /dev/null and b/documentation/docs/Organizers/Running_a_benchmark/_attachments/fe61c496-4b40-4c6e-bda1-bfa579393987_17534367082532165.jpg differ diff --git a/documentation/docs/Participants/User_Participating-in-a-Competition.md b/documentation/docs/Participants/User_Participating-in-a-Competition.md new file mode 100644 index 000000000..6c92cf3c1 --- /dev/null +++ b/documentation/docs/Participants/User_Participating-in-a-Competition.md @@ -0,0 +1,30 @@ +### Signing up and updating your settings +When you sign up, you will have to provide your name and a valid email. + +### Registering for a Benchmark +To make an entry in a benchmark click on the "My Submissions" tab, you will then be prompted to accept the rules to register to that benchmark. When registering, a request may be sent to the benchmark organizer. You will be notified when the benchmark organizer has approved your registration request. Follow the instructions of the organizers. + +![](_attachments/215463137-ee9bed00-514b-4fff-ba74-148c2f93d3b2_1753436746832619.png) + +### Making a Submission +Making a submission to a benchmark involves uploading a bundle (.zip archive) containing files with your answer, in the format that has been specified by the benchmark organizer. There are two types of submissions: +- **_Code_** submissions contain a metadata file specifying the command to execute +- **_Results_** submission contain the solution to the problem (no code executed on the platform) + +**To make a submission** + +1. [Sign in to Codabench](https://codabench.org/). If you do not have an account, you will need to create one. +1. Select the benchmark you want to work with. +1. Click the **My Submissions** tab. Here, you can access the data that has been provided by the benchmark organizer. +1. Click on the **paper clip logo** and select your zip file. + +![](_attachments/215463850-0eaefbf1-00c1-4ed3-bfad-833a0e3775bc_17534367468319316.png) + +On this page, you can make new submissions, and see previous submissions for each phase in the competition. + +You can also view all your submissions in the [Resources Interface](https://github.com/codalab/codabench/wiki/Task-&-Dataset-Management). + +### Viewing Benchmark Results +You can keep up with the progress of benchmarks you are participating in by clicking on the **Results** tab. This will display the leaderboard. + +![](_attachments/215464475-a88ce587-ea3d-4309-bd8e-011f375249b6_17534367468913481.png) diff --git a/documentation/docs/Participants/_attachments/215463137-ee9bed00-514b-4fff-ba74-148c2f93d3b2_1753436746832619.png b/documentation/docs/Participants/_attachments/215463137-ee9bed00-514b-4fff-ba74-148c2f93d3b2_1753436746832619.png new file mode 100644 index 000000000..d46155f83 Binary files /dev/null and b/documentation/docs/Participants/_attachments/215463137-ee9bed00-514b-4fff-ba74-148c2f93d3b2_1753436746832619.png differ diff --git a/documentation/docs/Participants/_attachments/215463850-0eaefbf1-00c1-4ed3-bfad-833a0e3775bc_17534367468319316.png b/documentation/docs/Participants/_attachments/215463850-0eaefbf1-00c1-4ed3-bfad-833a0e3775bc_17534367468319316.png new file mode 100644 index 000000000..026877858 Binary files /dev/null and b/documentation/docs/Participants/_attachments/215463850-0eaefbf1-00c1-4ed3-bfad-833a0e3775bc_17534367468319316.png differ diff --git a/documentation/docs/Participants/_attachments/215464475-a88ce587-ea3d-4309-bd8e-011f375249b6_17534367468913481.png b/documentation/docs/Participants/_attachments/215464475-a88ce587-ea3d-4309-bd8e-011f375249b6_17534367468913481.png new file mode 100644 index 000000000..c230d88b1 Binary files /dev/null and b/documentation/docs/Participants/_attachments/215464475-a88ce587-ea3d-4309-bd8e-011f375249b6_17534367468913481.png differ diff --git a/documentation/docs/Project_CodaBench_FAQ.md b/documentation/docs/Project_CodaBench_FAQ.md new file mode 100644 index 000000000..40f5ad780 --- /dev/null +++ b/documentation/docs/Project_CodaBench_FAQ.md @@ -0,0 +1,81 @@ + +## General questions + +### What is Codabench for? +Codabench benchmarks are aimed at researchers, scientists and other professionals who want to track algorithm performance via benchmarks or have participants participate in a competition to find the best solution to a problem. We run a free public instance at [https://www.codabench.org/](https://www.codabench.org/) and the raw code is on [Github](https://github.com/codalab/codabench). + + +### Can CodaLab competitions be privately hosted? +Yes, you can host your own CodaLab instance on a private or hosted server (e.g. Azure, GCP or AWS). For more information, see [how to deploy Codabench on your server](Developers_and_Administrators/How-to-deploy-Codabench-on-your-server.md) and [local installation](Developers_and_Administrators/Codabench-Installation.md) guide. However, most benchmark organizers do NOT need to run their own instance. If you run a computationally demanding competition, you can hook up your own [compute workers](Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md) in the backend very easily. + + +### How to change my username? +You cannot change your username BUT you can change your display name which will then be displayed instead of your username. To change your display name, follow these instructions: + + 1. Login to Codabench + 2. Click your username in the top right corner + 3. Click `Edit Profile` in the list + 4. Set a display name you want to use + 5. Click `Submit` button to save changes + +### How to make a task public or use public tasks from other users? +Follow the detailed instruction [here](Organizers/Benchmark_Creation/Public-Tasks-and-Tasks-Sharing.md) to know how you can make your task public and use other public tasks in your competitions. + +### How to delete my account? +Click on your account name on the top right of the website, then on `account` + + + +*** + +## Technical questions + +### Server Setup Issues +Many technical FAQ are already located in the [deploy your own server instructions.](Developers_and_Administrators/How-to-deploy-Codabench-on-your-server.md) + +Questions already answered there: + +- Getting `Invalid HTTP method` in django logs. +- I am missing some static resources (css/js) on front end. +- CORS error when uploading bundle. +- Logos don't upload from minio. +- Compute worker execution with insufficient privileges +- Securing Codabench and Minio + + +### A library is missing in the docker environment. What do to? + + +#### How does Codabench use dockers? +When you submit code to the Codabench platform, your code is executed inside a docker container. This environment can be exactly reproduced on your local machine by downloading the corresponding docker image. + +#### For participants + +- If you are a **competition participant**, contact the competition organizers to ask them if they can add the missing library or program. They can either accept or refuse the request. + +#### For organizers +- If you are a **competition organizer**, you can select a different competition docker image. If the default docker image (`codalab/codalab-legacy:py37`) does not suits your needs, you can either: + - Select another image from DockerHub + - Create a new image from scratch + - Edit the default image and push it to your own DockerHub account + +[More information here](Organizers/Benchmark_Creation/Competition-docker-image.md). + +### Emails are not showing up in my inbox for registration +When deploying a local instance, the email server is not configured by default, so you won't receive the confirmation email during signup. In `.env` towards the bottom you will find: +```ini title=".env" +# Uncomment to enable email settings +#EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend +#EMAIL_HOST=smtp.sendgrid.net +#EMAIL_HOST_USER=user +#EMAIL_HOST_PASSWORD=pass +#EMAIL_PORT=587 +#EMAIL_USE_TLS=True +``` + +Uncomment and fill in SMPT server credentials. A good suggestion if you've never done this is to use [sendgrid](https://sendgrid.com/). + +### Robots and automated submissions? +What about robot policy, reckless, or malicious behavior? +Codabench does not forbid the use of [robots](Developers_and_Administrators/Robot-submissions.md) (bots) to access the website, provided that it is not done with malicious intentions to disturb the normal use and jam the system. A user who abuses their rights by knowingly, maliciously, or recklessly jamming the system, causing the system to crash, causing loss of data, or gaining access to unauthorized data, will be banned from accessing all Codabench services. + diff --git a/documentation/docs/_attachments/000c3096-13b4-4d25-a8e1-efcba0fb75fd_17528513114340215.jpg b/documentation/docs/_attachments/000c3096-13b4-4d25-a8e1-efcba0fb75fd_17528513114340215.jpg new file mode 100644 index 000000000..e062b3f50 Binary files /dev/null and b/documentation/docs/_attachments/000c3096-13b4-4d25-a8e1-efcba0fb75fd_17528513114340215.jpg differ diff --git a/documentation/docs/_attachments/0_17528513120435548.png b/documentation/docs/_attachments/0_17528513120435548.png new file mode 100644 index 000000000..6c2a926ef Binary files /dev/null and b/documentation/docs/_attachments/0_17528513120435548.png differ diff --git a/documentation/docs/_attachments/0af8f0c0-1311-4777-9bdc-7daa123868d2_17528513091693199.jpg b/documentation/docs/_attachments/0af8f0c0-1311-4777-9bdc-7daa123868d2_17528513091693199.jpg new file mode 100644 index 000000000..0ca28449f Binary files /dev/null and b/documentation/docs/_attachments/0af8f0c0-1311-4777-9bdc-7daa123868d2_17528513091693199.jpg differ diff --git a/documentation/docs/_attachments/102425038-7d102d80-4047-11eb-9d67-4590426e91f0_17528513079491048.png b/documentation/docs/_attachments/102425038-7d102d80-4047-11eb-9d67-4590426e91f0_17528513079491048.png new file mode 100644 index 000000000..1dc79a259 Binary files /dev/null and b/documentation/docs/_attachments/102425038-7d102d80-4047-11eb-9d67-4590426e91f0_17528513079491048.png differ diff --git a/documentation/docs/_attachments/102425514-73d39080-4048-11eb-8689-c21d6d1ae4ac_1752851307966413.png b/documentation/docs/_attachments/102425514-73d39080-4048-11eb-8689-c21d6d1ae4ac_1752851307966413.png new file mode 100644 index 000000000..18ae9dd29 Binary files /dev/null and b/documentation/docs/_attachments/102425514-73d39080-4048-11eb-8689-c21d6d1ae4ac_1752851307966413.png differ diff --git a/documentation/docs/_attachments/102425665-b72dff00-4048-11eb-9b65-caa05e2f409d_17528513079724836.png b/documentation/docs/_attachments/102425665-b72dff00-4048-11eb-9b65-caa05e2f409d_17528513079724836.png new file mode 100644 index 000000000..a58c8923e Binary files /dev/null and b/documentation/docs/_attachments/102425665-b72dff00-4048-11eb-9b65-caa05e2f409d_17528513079724836.png differ diff --git a/documentation/docs/_attachments/102425747-e8a6ca80-4048-11eb-9d2d-09a59f63df09_1752851307954863.png b/documentation/docs/_attachments/102425747-e8a6ca80-4048-11eb-9d2d-09a59f63df09_1752851307954863.png new file mode 100644 index 000000000..b7737c56d Binary files /dev/null and b/documentation/docs/_attachments/102425747-e8a6ca80-4048-11eb-9d2d-09a59f63df09_1752851307954863.png differ diff --git a/documentation/docs/_attachments/102425807-08d68980-4049-11eb-96ef-2220a7a70bda_17528513079972107.png b/documentation/docs/_attachments/102425807-08d68980-4049-11eb-96ef-2220a7a70bda_17528513079972107.png new file mode 100644 index 000000000..2a9abe2c8 Binary files /dev/null and b/documentation/docs/_attachments/102425807-08d68980-4049-11eb-96ef-2220a7a70bda_17528513079972107.png differ diff --git a/documentation/docs/_attachments/102425846-20157700-4049-11eb-93ed-e38e4db91611_17528513080323348.png b/documentation/docs/_attachments/102425846-20157700-4049-11eb-93ed-e38e4db91611_17528513080323348.png new file mode 100644 index 000000000..0855adbb5 Binary files /dev/null and b/documentation/docs/_attachments/102425846-20157700-4049-11eb-93ed-e38e4db91611_17528513080323348.png differ diff --git a/documentation/docs/_attachments/102425904-43d8bd00-4049-11eb-86c2-870d743baa00_17528513080195067.png b/documentation/docs/_attachments/102425904-43d8bd00-4049-11eb-86c2-870d743baa00_17528513080195067.png new file mode 100644 index 000000000..73e18c84f Binary files /dev/null and b/documentation/docs/_attachments/102425904-43d8bd00-4049-11eb-86c2-870d743baa00_17528513080195067.png differ diff --git a/documentation/docs/_attachments/102426012-7b476980-4049-11eb-96f9-f88d716ed4ea_17528513080236058.png b/documentation/docs/_attachments/102426012-7b476980-4049-11eb-96f9-f88d716ed4ea_17528513080236058.png new file mode 100644 index 000000000..7231a4601 Binary files /dev/null and b/documentation/docs/_attachments/102426012-7b476980-4049-11eb-96f9-f88d716ed4ea_17528513080236058.png differ diff --git a/documentation/docs/_attachments/102426040-8a2e1c00-4049-11eb-9477-3b1b128ef0ef_17528513080496614.png b/documentation/docs/_attachments/102426040-8a2e1c00-4049-11eb-9477-3b1b128ef0ef_17528513080496614.png new file mode 100644 index 000000000..66d8b3614 Binary files /dev/null and b/documentation/docs/_attachments/102426040-8a2e1c00-4049-11eb-9477-3b1b128ef0ef_17528513080496614.png differ diff --git a/documentation/docs/_attachments/102426221-e5600e80-4049-11eb-95ed-3abf37ffd1d5_1752851308257055.png b/documentation/docs/_attachments/102426221-e5600e80-4049-11eb-95ed-3abf37ffd1d5_1752851308257055.png new file mode 100644 index 000000000..fbb2552b9 Binary files /dev/null and b/documentation/docs/_attachments/102426221-e5600e80-4049-11eb-95ed-3abf37ffd1d5_1752851308257055.png differ diff --git a/documentation/docs/_attachments/102426259-f6a91b00-4049-11eb-8e73-54bcd0514099_17528513080718298.png b/documentation/docs/_attachments/102426259-f6a91b00-4049-11eb-8e73-54bcd0514099_17528513080718298.png new file mode 100644 index 000000000..e014fe3c4 Binary files /dev/null and b/documentation/docs/_attachments/102426259-f6a91b00-4049-11eb-8e73-54bcd0514099_17528513080718298.png differ diff --git a/documentation/docs/_attachments/102426306-0c1e4500-404a-11eb-8e0a-a056cd9ffdab_17528513080908906.png b/documentation/docs/_attachments/102426306-0c1e4500-404a-11eb-8e0a-a056cd9ffdab_17528513080908906.png new file mode 100644 index 000000000..68da4fb04 Binary files /dev/null and b/documentation/docs/_attachments/102426306-0c1e4500-404a-11eb-8e0a-a056cd9ffdab_17528513080908906.png differ diff --git a/documentation/docs/_attachments/102426338-1f311500-404a-11eb-9a85-42cfa7b4f34c_17528513081201243.png b/documentation/docs/_attachments/102426338-1f311500-404a-11eb-9a85-42cfa7b4f34c_17528513081201243.png new file mode 100644 index 000000000..15349d3ab Binary files /dev/null and b/documentation/docs/_attachments/102426338-1f311500-404a-11eb-9a85-42cfa7b4f34c_17528513081201243.png differ diff --git a/documentation/docs/_attachments/102426374-340da880-404a-11eb-8bf0-e62498560c38_17528513081279504.png b/documentation/docs/_attachments/102426374-340da880-404a-11eb-8bf0-e62498560c38_17528513081279504.png new file mode 100644 index 000000000..255d6992d Binary files /dev/null and b/documentation/docs/_attachments/102426374-340da880-404a-11eb-8bf0-e62498560c38_17528513081279504.png differ diff --git a/documentation/docs/_attachments/102426590-91095e80-404a-11eb-9b13-3b04b6d7c05d_17528513084907422.png b/documentation/docs/_attachments/102426590-91095e80-404a-11eb-9b13-3b04b6d7c05d_17528513084907422.png new file mode 100644 index 000000000..509d4058d Binary files /dev/null and b/documentation/docs/_attachments/102426590-91095e80-404a-11eb-9b13-3b04b6d7c05d_17528513084907422.png differ diff --git a/documentation/docs/_attachments/102426640-a9797900-404a-11eb-9d28-12fe9b6e9544_17528513081428964.png b/documentation/docs/_attachments/102426640-a9797900-404a-11eb-9d28-12fe9b6e9544_17528513081428964.png new file mode 100644 index 000000000..7b2bd2ee5 Binary files /dev/null and b/documentation/docs/_attachments/102426640-a9797900-404a-11eb-9d28-12fe9b6e9544_17528513081428964.png differ diff --git a/documentation/docs/_attachments/102426710-d29a0980-404a-11eb-9ec7-cb9c1d5cb732_17528513082572203.png b/documentation/docs/_attachments/102426710-d29a0980-404a-11eb-9ec7-cb9c1d5cb732_17528513082572203.png new file mode 100644 index 000000000..9cd82ffe9 Binary files /dev/null and b/documentation/docs/_attachments/102426710-d29a0980-404a-11eb-9ec7-cb9c1d5cb732_17528513082572203.png differ diff --git a/documentation/docs/_attachments/102426762-e7769d00-404a-11eb-9f11-9df1039225a2_17528513086615834.png b/documentation/docs/_attachments/102426762-e7769d00-404a-11eb-9f11-9df1039225a2_17528513086615834.png new file mode 100644 index 000000000..b8b5ab812 Binary files /dev/null and b/documentation/docs/_attachments/102426762-e7769d00-404a-11eb-9f11-9df1039225a2_17528513086615834.png differ diff --git a/documentation/docs/_attachments/102426802-007f4e00-404b-11eb-88c2-305bcb789a5c_1752851308285328.png b/documentation/docs/_attachments/102426802-007f4e00-404b-11eb-88c2-305bcb789a5c_1752851308285328.png new file mode 100644 index 000000000..68e671b18 Binary files /dev/null and b/documentation/docs/_attachments/102426802-007f4e00-404b-11eb-88c2-305bcb789a5c_1752851308285328.png differ diff --git a/documentation/docs/_attachments/102426823-0d9c3d00-404b-11eb-8068-d8fe454dcec2_17528513087142718.png b/documentation/docs/_attachments/102426823-0d9c3d00-404b-11eb-8068-d8fe454dcec2_17528513087142718.png new file mode 100644 index 000000000..c3b24ac25 Binary files /dev/null and b/documentation/docs/_attachments/102426823-0d9c3d00-404b-11eb-8068-d8fe454dcec2_17528513087142718.png differ diff --git a/documentation/docs/_attachments/102427038-7aafd280-404b-11eb-94a5-9df0dcac3901_17528513125646255.png b/documentation/docs/_attachments/102427038-7aafd280-404b-11eb-94a5-9df0dcac3901_17528513125646255.png new file mode 100644 index 000000000..fc992d3ea Binary files /dev/null and b/documentation/docs/_attachments/102427038-7aafd280-404b-11eb-94a5-9df0dcac3901_17528513125646255.png differ diff --git a/documentation/docs/_attachments/102427080-8c917580-404b-11eb-8f2c-be74be778fb4_17528513126002839.png b/documentation/docs/_attachments/102427080-8c917580-404b-11eb-8f2c-be74be778fb4_17528513126002839.png new file mode 100644 index 000000000..a76001063 Binary files /dev/null and b/documentation/docs/_attachments/102427080-8c917580-404b-11eb-8f2c-be74be778fb4_17528513126002839.png differ diff --git a/documentation/docs/_attachments/102427100-9a46fb00-404b-11eb-9068-1437e4f5352a_17528513126199927.png b/documentation/docs/_attachments/102427100-9a46fb00-404b-11eb-9068-1437e4f5352a_17528513126199927.png new file mode 100644 index 000000000..ec0b528b1 Binary files /dev/null and b/documentation/docs/_attachments/102427100-9a46fb00-404b-11eb-9068-1437e4f5352a_17528513126199927.png differ diff --git a/documentation/docs/_attachments/102427341-193c3380-404c-11eb-9a69-5a024d3a6599_17528513130877678.png b/documentation/docs/_attachments/102427341-193c3380-404c-11eb-9a69-5a024d3a6599_17528513130877678.png new file mode 100644 index 000000000..8eb35d69d Binary files /dev/null and b/documentation/docs/_attachments/102427341-193c3380-404c-11eb-9a69-5a024d3a6599_17528513130877678.png differ diff --git a/documentation/docs/_attachments/102427380-2d803080-404c-11eb-9161-2c8d5fb09369_17528513126502273.png b/documentation/docs/_attachments/102427380-2d803080-404c-11eb-9161-2c8d5fb09369_17528513126502273.png new file mode 100644 index 000000000..f2b5866d3 Binary files /dev/null and b/documentation/docs/_attachments/102427380-2d803080-404c-11eb-9161-2c8d5fb09369_17528513126502273.png differ diff --git a/documentation/docs/_attachments/102427403-3bce4c80-404c-11eb-9cc8-e241fd4e7474_17528513126719942.png b/documentation/docs/_attachments/102427403-3bce4c80-404c-11eb-9cc8-e241fd4e7474_17528513126719942.png new file mode 100644 index 000000000..386b72af4 Binary files /dev/null and b/documentation/docs/_attachments/102427403-3bce4c80-404c-11eb-9cc8-e241fd4e7474_17528513126719942.png differ diff --git a/documentation/docs/_attachments/102427413-45f04b00-404c-11eb-8b4c-c6e8b64fd945_17528513131024394.png b/documentation/docs/_attachments/102427413-45f04b00-404c-11eb-8b4c-c6e8b64fd945_17528513131024394.png new file mode 100644 index 000000000..928796f63 Binary files /dev/null and b/documentation/docs/_attachments/102427413-45f04b00-404c-11eb-8b4c-c6e8b64fd945_17528513131024394.png differ diff --git a/documentation/docs/_attachments/102427457-5bfe0b80-404c-11eb-8c52-ffe5362b54e1_17528513131442835.png b/documentation/docs/_attachments/102427457-5bfe0b80-404c-11eb-8c52-ffe5362b54e1_17528513131442835.png new file mode 100644 index 000000000..44bfe7221 Binary files /dev/null and b/documentation/docs/_attachments/102427457-5bfe0b80-404c-11eb-8c52-ffe5362b54e1_17528513131442835.png differ diff --git a/documentation/docs/_attachments/102427495-70420880-404c-11eb-8864-443b5f3d1913_17528513127302663.png b/documentation/docs/_attachments/102427495-70420880-404c-11eb-8864-443b5f3d1913_17528513127302663.png new file mode 100644 index 000000000..2f1d0ae26 Binary files /dev/null and b/documentation/docs/_attachments/102427495-70420880-404c-11eb-8864-443b5f3d1913_17528513127302663.png differ diff --git a/documentation/docs/_attachments/102427510-7932da00-404c-11eb-8138-63889a0664b3_17528513127678237.png b/documentation/docs/_attachments/102427510-7932da00-404c-11eb-8138-63889a0664b3_17528513127678237.png new file mode 100644 index 000000000..4eacae2eb Binary files /dev/null and b/documentation/docs/_attachments/102427510-7932da00-404c-11eb-8138-63889a0664b3_17528513127678237.png differ diff --git a/documentation/docs/_attachments/102427536-818b1500-404c-11eb-9ab5-83ed190db742_17528513128221796.png b/documentation/docs/_attachments/102427536-818b1500-404c-11eb-9ab5-83ed190db742_17528513128221796.png new file mode 100644 index 000000000..8d6378bc8 Binary files /dev/null and b/documentation/docs/_attachments/102427536-818b1500-404c-11eb-9ab5-83ed190db742_17528513128221796.png differ diff --git a/documentation/docs/_attachments/102427661-ca42ce00-404c-11eb-93c8-df58812c4085_1752851312901565.png b/documentation/docs/_attachments/102427661-ca42ce00-404c-11eb-93c8-df58812c4085_1752851312901565.png new file mode 100644 index 000000000..2539cdfe0 Binary files /dev/null and b/documentation/docs/_attachments/102427661-ca42ce00-404c-11eb-93c8-df58812c4085_1752851312901565.png differ diff --git a/documentation/docs/_attachments/102427705-dfb7f800-404c-11eb-87c1-c4ac69c003be_1752851312950296.png b/documentation/docs/_attachments/102427705-dfb7f800-404c-11eb-87c1-c4ac69c003be_1752851312950296.png new file mode 100644 index 000000000..3d30a1c45 Binary files /dev/null and b/documentation/docs/_attachments/102427705-dfb7f800-404c-11eb-87c1-c4ac69c003be_1752851312950296.png differ diff --git a/documentation/docs/_attachments/102427767-f5c5b880-404c-11eb-9caa-f0cd7a702a84_17528513130498507.png b/documentation/docs/_attachments/102427767-f5c5b880-404c-11eb-9caa-f0cd7a702a84_17528513130498507.png new file mode 100644 index 000000000..1c91988eb Binary files /dev/null and b/documentation/docs/_attachments/102427767-f5c5b880-404c-11eb-9caa-f0cd7a702a84_17528513130498507.png differ diff --git a/documentation/docs/_attachments/102427791-0118e400-404d-11eb-923a-87d724ff5a54_1752851313121837.png b/documentation/docs/_attachments/102427791-0118e400-404d-11eb-923a-87d724ff5a54_1752851313121837.png new file mode 100644 index 000000000..c32e522cd Binary files /dev/null and b/documentation/docs/_attachments/102427791-0118e400-404d-11eb-923a-87d724ff5a54_1752851313121837.png differ diff --git a/documentation/docs/_attachments/102429234-771d4b00-404d-11eb-9ec3-bc75d39d3194_17528513092407322.png b/documentation/docs/_attachments/102429234-771d4b00-404d-11eb-9ec3-bc75d39d3194_17528513092407322.png new file mode 100644 index 000000000..a627913b1 Binary files /dev/null and b/documentation/docs/_attachments/102429234-771d4b00-404d-11eb-9ec3-bc75d39d3194_17528513092407322.png differ diff --git a/documentation/docs/_attachments/102429989-a9c74380-404d-11eb-8b99-9e7829fe8678_17528513092920961.png b/documentation/docs/_attachments/102429989-a9c74380-404d-11eb-8b99-9e7829fe8678_17528513092920961.png new file mode 100644 index 000000000..1aa95552f Binary files /dev/null and b/documentation/docs/_attachments/102429989-a9c74380-404d-11eb-8b99-9e7829fe8678_17528513092920961.png differ diff --git a/documentation/docs/_attachments/102430225-b9468c80-404d-11eb-81f1-879138afad2c_175285130932125.png b/documentation/docs/_attachments/102430225-b9468c80-404d-11eb-81f1-879138afad2c_175285130932125.png new file mode 100644 index 000000000..40ede341d Binary files /dev/null and b/documentation/docs/_attachments/102430225-b9468c80-404d-11eb-81f1-879138afad2c_175285130932125.png differ diff --git a/documentation/docs/_attachments/102430591-d24f3d80-404d-11eb-8adf-1f562d2f9cb4_17528513093284764.png b/documentation/docs/_attachments/102430591-d24f3d80-404d-11eb-8adf-1f562d2f9cb4_17528513093284764.png new file mode 100644 index 000000000..0527c29fa Binary files /dev/null and b/documentation/docs/_attachments/102430591-d24f3d80-404d-11eb-8adf-1f562d2f9cb4_17528513093284764.png differ diff --git a/documentation/docs/_attachments/102431578-12aebb80-404e-11eb-8d07-d74e9de46280_17528513097437637.png b/documentation/docs/_attachments/102431578-12aebb80-404e-11eb-8d07-d74e9de46280_17528513097437637.png new file mode 100644 index 000000000..a6f93043d Binary files /dev/null and b/documentation/docs/_attachments/102431578-12aebb80-404e-11eb-8d07-d74e9de46280_17528513097437637.png differ diff --git a/documentation/docs/_attachments/102431721-1d695080-404e-11eb-87a4-92a4b43b349c_1752851309399166.png b/documentation/docs/_attachments/102431721-1d695080-404e-11eb-87a4-92a4b43b349c_1752851309399166.png new file mode 100644 index 000000000..b5e7fc35a Binary files /dev/null and b/documentation/docs/_attachments/102431721-1d695080-404e-11eb-87a4-92a4b43b349c_1752851309399166.png differ diff --git a/documentation/docs/_attachments/102431937-2c500300-404e-11eb-9a28-344f26d79013_17528513093988035.png b/documentation/docs/_attachments/102431937-2c500300-404e-11eb-9a28-344f26d79013_17528513093988035.png new file mode 100644 index 000000000..991c34354 Binary files /dev/null and b/documentation/docs/_attachments/102431937-2c500300-404e-11eb-9a28-344f26d79013_17528513093988035.png differ diff --git a/documentation/docs/_attachments/102432087-36720180-404e-11eb-9dda-a593d7a45af2_17528513094299598.png b/documentation/docs/_attachments/102432087-36720180-404e-11eb-9dda-a593d7a45af2_17528513094299598.png new file mode 100644 index 000000000..8fdc027fd Binary files /dev/null and b/documentation/docs/_attachments/102432087-36720180-404e-11eb-9dda-a593d7a45af2_17528513094299598.png differ diff --git a/documentation/docs/_attachments/102432234-40940000-404e-11eb-8a3d-1e72b2688267_17528513094664094.png b/documentation/docs/_attachments/102432234-40940000-404e-11eb-8a3d-1e72b2688267_17528513094664094.png new file mode 100644 index 000000000..4ac83733c Binary files /dev/null and b/documentation/docs/_attachments/102432234-40940000-404e-11eb-8a3d-1e72b2688267_17528513094664094.png differ diff --git a/documentation/docs/_attachments/102432435-4d185880-404e-11eb-967f-1735f6a9f145_17528513094839308.png b/documentation/docs/_attachments/102432435-4d185880-404e-11eb-967f-1735f6a9f145_17528513094839308.png new file mode 100644 index 000000000..164ee9493 Binary files /dev/null and b/documentation/docs/_attachments/102432435-4d185880-404e-11eb-967f-1735f6a9f145_17528513094839308.png differ diff --git a/documentation/docs/_attachments/102432573-56092a00-404e-11eb-9788-512586edd693_1752851309496168.png b/documentation/docs/_attachments/102432573-56092a00-404e-11eb-9788-512586edd693_1752851309496168.png new file mode 100644 index 000000000..27e2fa2dd Binary files /dev/null and b/documentation/docs/_attachments/102432573-56092a00-404e-11eb-9788-512586edd693_1752851309496168.png differ diff --git a/documentation/docs/_attachments/102432684-5e616500-404e-11eb-8b82-8ea332050cdf_17528513095790792.png b/documentation/docs/_attachments/102432684-5e616500-404e-11eb-8b82-8ea332050cdf_17528513095790792.png new file mode 100644 index 000000000..139f0d6ac Binary files /dev/null and b/documentation/docs/_attachments/102432684-5e616500-404e-11eb-8b82-8ea332050cdf_17528513095790792.png differ diff --git a/documentation/docs/_attachments/102432819-67523680-404e-11eb-9032-b725058ffa3c_17528513102032712.png b/documentation/docs/_attachments/102432819-67523680-404e-11eb-9032-b725058ffa3c_17528513102032712.png new file mode 100644 index 000000000..93276502d Binary files /dev/null and b/documentation/docs/_attachments/102432819-67523680-404e-11eb-9032-b725058ffa3c_17528513102032712.png differ diff --git a/documentation/docs/_attachments/102432974-71743500-404e-11eb-95ef-84d39597a412_1752851309572427.png b/documentation/docs/_attachments/102432974-71743500-404e-11eb-95ef-84d39597a412_1752851309572427.png new file mode 100644 index 000000000..4bc6d07c2 Binary files /dev/null and b/documentation/docs/_attachments/102432974-71743500-404e-11eb-95ef-84d39597a412_1752851309572427.png differ diff --git a/documentation/docs/_attachments/102433142-7b963380-404e-11eb-9ad0-035eb60d7f64_17528513096323566.png b/documentation/docs/_attachments/102433142-7b963380-404e-11eb-9ad0-035eb60d7f64_17528513096323566.png new file mode 100644 index 000000000..b6c192be6 Binary files /dev/null and b/documentation/docs/_attachments/102433142-7b963380-404e-11eb-9ad0-035eb60d7f64_17528513096323566.png differ diff --git a/documentation/docs/_attachments/102433276-84870500-404e-11eb-8638-60eeab21fe8d_17528513096378942.png b/documentation/docs/_attachments/102433276-84870500-404e-11eb-8638-60eeab21fe8d_17528513096378942.png new file mode 100644 index 000000000..0f83d4e67 Binary files /dev/null and b/documentation/docs/_attachments/102433276-84870500-404e-11eb-8638-60eeab21fe8d_17528513096378942.png differ diff --git a/documentation/docs/_attachments/102433391-8c46a980-404e-11eb-871c-6d443be44062_1752851309654381.png b/documentation/docs/_attachments/102433391-8c46a980-404e-11eb-871c-6d443be44062_1752851309654381.png new file mode 100644 index 000000000..10a7ee53b Binary files /dev/null and b/documentation/docs/_attachments/102433391-8c46a980-404e-11eb-871c-6d443be44062_1752851309654381.png differ diff --git a/documentation/docs/_attachments/102433537-95377b00-404e-11eb-8649-57f70a830564_1752851309686341.png b/documentation/docs/_attachments/102433537-95377b00-404e-11eb-8649-57f70a830564_1752851309686341.png new file mode 100644 index 000000000..85bf0e5cd Binary files /dev/null and b/documentation/docs/_attachments/102433537-95377b00-404e-11eb-8649-57f70a830564_1752851309686341.png differ diff --git a/documentation/docs/_attachments/102433657-9cf71f80-404e-11eb-9aa0-d23cf595c7db_1752851309773052.png b/documentation/docs/_attachments/102433657-9cf71f80-404e-11eb-9aa0-d23cf595c7db_1752851309773052.png new file mode 100644 index 000000000..2f6a6114f Binary files /dev/null and b/documentation/docs/_attachments/102433657-9cf71f80-404e-11eb-9aa0-d23cf595c7db_1752851309773052.png differ diff --git a/documentation/docs/_attachments/102433828-aa140e80-404e-11eb-9886-3f6960eb6a5e_17528513100792131.png b/documentation/docs/_attachments/102433828-aa140e80-404e-11eb-9886-3f6960eb6a5e_17528513100792131.png new file mode 100644 index 000000000..362c08fb7 Binary files /dev/null and b/documentation/docs/_attachments/102433828-aa140e80-404e-11eb-9886-3f6960eb6a5e_17528513100792131.png differ diff --git a/documentation/docs/_attachments/102433943-b1d3b300-404e-11eb-9594-39de8566c6a0_17528513097862737.png b/documentation/docs/_attachments/102433943-b1d3b300-404e-11eb-9594-39de8566c6a0_17528513097862737.png new file mode 100644 index 000000000..6b7cf77d9 Binary files /dev/null and b/documentation/docs/_attachments/102433943-b1d3b300-404e-11eb-9594-39de8566c6a0_17528513097862737.png differ diff --git a/documentation/docs/_attachments/102433960-bbf5b180-404e-11eb-8102-26c03d5084b8_17528513098046653.png b/documentation/docs/_attachments/102433960-bbf5b180-404e-11eb-8102-26c03d5084b8_17528513098046653.png new file mode 100644 index 000000000..ccb7745b1 Binary files /dev/null and b/documentation/docs/_attachments/102433960-bbf5b180-404e-11eb-8102-26c03d5084b8_17528513098046653.png differ diff --git a/documentation/docs/_attachments/102433974-c57f1980-404e-11eb-9b50-54b170755850_17528513098181317.png b/documentation/docs/_attachments/102433974-c57f1980-404e-11eb-9b50-54b170755850_17528513098181317.png new file mode 100644 index 000000000..4ca2e6a6e Binary files /dev/null and b/documentation/docs/_attachments/102433974-c57f1980-404e-11eb-9b50-54b170755850_17528513098181317.png differ diff --git a/documentation/docs/_attachments/102433995-ce6feb00-404e-11eb-95c9-2ed9e5d8bb54_1752851309822554.png b/documentation/docs/_attachments/102433995-ce6feb00-404e-11eb-95c9-2ed9e5d8bb54_1752851309822554.png new file mode 100644 index 000000000..3c2096c8e Binary files /dev/null and b/documentation/docs/_attachments/102433995-ce6feb00-404e-11eb-95c9-2ed9e5d8bb54_1752851309822554.png differ diff --git a/documentation/docs/_attachments/102434012-d6c82600-404e-11eb-85dd-88338d7aa033_17528513098401737.png b/documentation/docs/_attachments/102434012-d6c82600-404e-11eb-85dd-88338d7aa033_17528513098401737.png new file mode 100644 index 000000000..0f45de03b Binary files /dev/null and b/documentation/docs/_attachments/102434012-d6c82600-404e-11eb-85dd-88338d7aa033_17528513098401737.png differ diff --git a/documentation/docs/_attachments/102434028-e182bb00-404e-11eb-9de8-002e4589db66_17528513099222646.png b/documentation/docs/_attachments/102434028-e182bb00-404e-11eb-9de8-002e4589db66_17528513099222646.png new file mode 100644 index 000000000..a3d0cc988 Binary files /dev/null and b/documentation/docs/_attachments/102434028-e182bb00-404e-11eb-9de8-002e4589db66_17528513099222646.png differ diff --git a/documentation/docs/_attachments/102434058-f5c6b800-404e-11eb-98e2-88ee12195d7a_17528513098936615.png b/documentation/docs/_attachments/102434058-f5c6b800-404e-11eb-98e2-88ee12195d7a_17528513098936615.png new file mode 100644 index 000000000..672f4d006 Binary files /dev/null and b/documentation/docs/_attachments/102434058-f5c6b800-404e-11eb-98e2-88ee12195d7a_17528513098936615.png differ diff --git a/documentation/docs/_attachments/102434073-fcedc600-404e-11eb-859c-658fdc57bb37_17528513098851938.png b/documentation/docs/_attachments/102434073-fcedc600-404e-11eb-859c-658fdc57bb37_17528513098851938.png new file mode 100644 index 000000000..89fc57750 Binary files /dev/null and b/documentation/docs/_attachments/102434073-fcedc600-404e-11eb-859c-658fdc57bb37_17528513098851938.png differ diff --git a/documentation/docs/_attachments/102434089-04ad6a80-404f-11eb-9f70-faa80fa8b6ba_17528513099604332.png b/documentation/docs/_attachments/102434089-04ad6a80-404f-11eb-9f70-faa80fa8b6ba_17528513099604332.png new file mode 100644 index 000000000..f328802ed Binary files /dev/null and b/documentation/docs/_attachments/102434089-04ad6a80-404f-11eb-9f70-faa80fa8b6ba_17528513099604332.png differ diff --git a/documentation/docs/_attachments/102434105-0e36d280-404f-11eb-99b1-dae0127cb941_1752851309982288.png b/documentation/docs/_attachments/102434105-0e36d280-404f-11eb-99b1-dae0127cb941_1752851309982288.png new file mode 100644 index 000000000..aa696ef2a Binary files /dev/null and b/documentation/docs/_attachments/102434105-0e36d280-404f-11eb-99b1-dae0127cb941_1752851309982288.png differ diff --git a/documentation/docs/_attachments/102434120-168f0d80-404f-11eb-91e1-04f52a7dd77a_1752851309963938.png b/documentation/docs/_attachments/102434120-168f0d80-404f-11eb-91e1-04f52a7dd77a_1752851309963938.png new file mode 100644 index 000000000..1e08f4ead Binary files /dev/null and b/documentation/docs/_attachments/102434120-168f0d80-404f-11eb-91e1-04f52a7dd77a_1752851309963938.png differ diff --git a/documentation/docs/_attachments/102434132-1d1d8500-404f-11eb-8370-11fe623f3d2f_17528513103749812.png b/documentation/docs/_attachments/102434132-1d1d8500-404f-11eb-8370-11fe623f3d2f_17528513103749812.png new file mode 100644 index 000000000..e7e998853 Binary files /dev/null and b/documentation/docs/_attachments/102434132-1d1d8500-404f-11eb-8370-11fe623f3d2f_17528513103749812.png differ diff --git a/documentation/docs/_attachments/102434153-27d81a00-404f-11eb-9aea-86763cc0d631_17528513100395033.png b/documentation/docs/_attachments/102434153-27d81a00-404f-11eb-9aea-86763cc0d631_17528513100395033.png new file mode 100644 index 000000000..222bc5bdf Binary files /dev/null and b/documentation/docs/_attachments/102434153-27d81a00-404f-11eb-9aea-86763cc0d631_17528513100395033.png differ diff --git a/documentation/docs/_attachments/113236785-28cc4900-92d8-11eb-8b2d-bbec05090788_17528513112217138.png b/documentation/docs/_attachments/113236785-28cc4900-92d8-11eb-8b2d-bbec05090788_17528513112217138.png new file mode 100644 index 000000000..718242039 Binary files /dev/null and b/documentation/docs/_attachments/113236785-28cc4900-92d8-11eb-8b2d-bbec05090788_17528513112217138.png differ diff --git a/documentation/docs/_attachments/113236839-44375400-92d8-11eb-9c12-9d8654423662_17528513112593784.png b/documentation/docs/_attachments/113236839-44375400-92d8-11eb-9c12-9d8654423662_17528513112593784.png new file mode 100644 index 000000000..f503896e5 Binary files /dev/null and b/documentation/docs/_attachments/113236839-44375400-92d8-11eb-9c12-9d8654423662_17528513112593784.png differ diff --git a/documentation/docs/_attachments/113236871-544f3380-92d8-11eb-86bf-05ffb9fac5d2_17528513120945034.png b/documentation/docs/_attachments/113236871-544f3380-92d8-11eb-86bf-05ffb9fac5d2_17528513120945034.png new file mode 100644 index 000000000..0daaae1d2 Binary files /dev/null and b/documentation/docs/_attachments/113236871-544f3380-92d8-11eb-86bf-05ffb9fac5d2_17528513120945034.png differ diff --git a/documentation/docs/_attachments/113236903-66c96d00-92d8-11eb-9186-2fac1b0a6918_17528513113931694.png b/documentation/docs/_attachments/113236903-66c96d00-92d8-11eb-9186-2fac1b0a6918_17528513113931694.png new file mode 100644 index 000000000..e23c3b2ef Binary files /dev/null and b/documentation/docs/_attachments/113236903-66c96d00-92d8-11eb-9186-2fac1b0a6918_17528513113931694.png differ diff --git a/documentation/docs/_attachments/1_17528513120437856.jpg b/documentation/docs/_attachments/1_17528513120437856.jpg new file mode 100644 index 000000000..4ec1aec60 Binary files /dev/null and b/documentation/docs/_attachments/1_17528513120437856.jpg differ diff --git a/documentation/docs/_attachments/224348279-65fd619a-28ce-4b65-bdb1-c791508c9d21_17528513111161823.png b/documentation/docs/_attachments/224348279-65fd619a-28ce-4b65-bdb1-c791508c9d21_17528513111161823.png new file mode 100644 index 000000000..c6d37ebff Binary files /dev/null and b/documentation/docs/_attachments/224348279-65fd619a-28ce-4b65-bdb1-c791508c9d21_17528513111161823.png differ diff --git a/documentation/docs/_attachments/224348279-65fd619a-28ce-4b65-bdb1-c791508c9d21_1752851311327783.png b/documentation/docs/_attachments/224348279-65fd619a-28ce-4b65-bdb1-c791508c9d21_1752851311327783.png new file mode 100644 index 000000000..c6d37ebff Binary files /dev/null and b/documentation/docs/_attachments/224348279-65fd619a-28ce-4b65-bdb1-c791508c9d21_1752851311327783.png differ diff --git a/documentation/docs/_attachments/29e74b35-7e47-4a6a-b85c-341f4bf9fa96_17528513113086753.jpg b/documentation/docs/_attachments/29e74b35-7e47-4a6a-b85c-341f4bf9fa96_17528513113086753.jpg new file mode 100644 index 000000000..863ab9636 Binary files /dev/null and b/documentation/docs/_attachments/29e74b35-7e47-4a6a-b85c-341f4bf9fa96_17528513113086753.jpg differ diff --git a/documentation/docs/_attachments/2_17528513126088269.jpg b/documentation/docs/_attachments/2_17528513126088269.jpg new file mode 100644 index 000000000..68c60eb83 Binary files /dev/null and b/documentation/docs/_attachments/2_17528513126088269.jpg differ diff --git a/documentation/docs/_attachments/2b41574f-9597-47c0-b492-cf427eba7eff_17528513107025487.jpg b/documentation/docs/_attachments/2b41574f-9597-47c0-b492-cf427eba7eff_17528513107025487.jpg new file mode 100644 index 000000000..f9d9b4751 Binary files /dev/null and b/documentation/docs/_attachments/2b41574f-9597-47c0-b492-cf427eba7eff_17528513107025487.jpg differ diff --git a/documentation/docs/_attachments/3cd0a725-a9f7-4288-b59d-0d31ea910ed7_17528513093736768.jpg b/documentation/docs/_attachments/3cd0a725-a9f7-4288-b59d-0d31ea910ed7_17528513093736768.jpg new file mode 100644 index 000000000..f3ad2398e Binary files /dev/null and b/documentation/docs/_attachments/3cd0a725-a9f7-4288-b59d-0d31ea910ed7_17528513093736768.jpg differ diff --git a/documentation/docs/_attachments/4_17528513126157694.jpg b/documentation/docs/_attachments/4_17528513126157694.jpg new file mode 100644 index 000000000..d29c249bc Binary files /dev/null and b/documentation/docs/_attachments/4_17528513126157694.jpg differ diff --git a/documentation/docs/_attachments/4ad333ae-4d22-49e8-82be-757ea0423642_17528513109674363.jpg b/documentation/docs/_attachments/4ad333ae-4d22-49e8-82be-757ea0423642_17528513109674363.jpg new file mode 100644 index 000000000..ec81d5889 Binary files /dev/null and b/documentation/docs/_attachments/4ad333ae-4d22-49e8-82be-757ea0423642_17528513109674363.jpg differ diff --git a/documentation/docs/_attachments/5107b308-b445-45a3-91d9-b1fbfb5a1ed9_17528513107704363.jpg b/documentation/docs/_attachments/5107b308-b445-45a3-91d9-b1fbfb5a1ed9_17528513107704363.jpg new file mode 100644 index 000000000..7085557e5 Binary files /dev/null and b/documentation/docs/_attachments/5107b308-b445-45a3-91d9-b1fbfb5a1ed9_17528513107704363.jpg differ diff --git a/documentation/docs/_attachments/6_1752851312043884.jpg b/documentation/docs/_attachments/6_1752851312043884.jpg new file mode 100644 index 000000000..ba72d2937 Binary files /dev/null and b/documentation/docs/_attachments/6_1752851312043884.jpg differ diff --git a/documentation/docs/_attachments/70932628-08974e80-1fef-11ea-9303-734d098df784_17528513089370105.png b/documentation/docs/_attachments/70932628-08974e80-1fef-11ea-9303-734d098df784_17528513089370105.png new file mode 100644 index 000000000..4949675f5 Binary files /dev/null and b/documentation/docs/_attachments/70932628-08974e80-1fef-11ea-9303-734d098df784_17528513089370105.png differ diff --git a/documentation/docs/_attachments/70936146-962a6c80-1ff6-11ea-9725-815d8bf04870_17528513124953895.png b/documentation/docs/_attachments/70936146-962a6c80-1ff6-11ea-9725-815d8bf04870_17528513124953895.png new file mode 100644 index 000000000..b28f911f8 Binary files /dev/null and b/documentation/docs/_attachments/70936146-962a6c80-1ff6-11ea-9725-815d8bf04870_17528513124953895.png differ diff --git a/documentation/docs/_attachments/70936536-57e17d00-1ff7-11ea-893b-c056fa225223_1752851312147678.png b/documentation/docs/_attachments/70936536-57e17d00-1ff7-11ea-893b-c056fa225223_1752851312147678.png new file mode 100644 index 000000000..8c6312f6e Binary files /dev/null and b/documentation/docs/_attachments/70936536-57e17d00-1ff7-11ea-893b-c056fa225223_1752851312147678.png differ diff --git a/documentation/docs/_attachments/70936678-a8f17100-1ff7-11ea-8753-fb93dcb6fa7e_17528513121920757.png b/documentation/docs/_attachments/70936678-a8f17100-1ff7-11ea-8753-fb93dcb6fa7e_17528513121920757.png new file mode 100644 index 000000000..5836f6cf5 Binary files /dev/null and b/documentation/docs/_attachments/70936678-a8f17100-1ff7-11ea-8753-fb93dcb6fa7e_17528513121920757.png differ diff --git a/documentation/docs/_attachments/70936761-d76f4c00-1ff7-11ea-86e7-ffa0d8b48a08_17528513122337482.png b/documentation/docs/_attachments/70936761-d76f4c00-1ff7-11ea-86e7-ffa0d8b48a08_17528513122337482.png new file mode 100644 index 000000000..3c59da225 Binary files /dev/null and b/documentation/docs/_attachments/70936761-d76f4c00-1ff7-11ea-86e7-ffa0d8b48a08_17528513122337482.png differ diff --git a/documentation/docs/_attachments/70937064-8ca20400-1ff8-11ea-8820-460c9cd88d5e_17528513122757797.png b/documentation/docs/_attachments/70937064-8ca20400-1ff8-11ea-8820-460c9cd88d5e_17528513122757797.png new file mode 100644 index 000000000..7b87647da Binary files /dev/null and b/documentation/docs/_attachments/70937064-8ca20400-1ff8-11ea-8820-460c9cd88d5e_17528513122757797.png differ diff --git a/documentation/docs/_attachments/70937347-f91d0300-1ff8-11ea-850a-a1d92609ea40_175285131232458.png b/documentation/docs/_attachments/70937347-f91d0300-1ff8-11ea-850a-a1d92609ea40_175285131232458.png new file mode 100644 index 000000000..9e969acb4 Binary files /dev/null and b/documentation/docs/_attachments/70937347-f91d0300-1ff8-11ea-850a-a1d92609ea40_175285131232458.png differ diff --git a/documentation/docs/_attachments/70949998-304cdd80-2014-11ea-9ecf-c21af198125b_1752851312365067.png b/documentation/docs/_attachments/70949998-304cdd80-2014-11ea-9ecf-c21af198125b_1752851312365067.png new file mode 100644 index 000000000..b9ee5c108 Binary files /dev/null and b/documentation/docs/_attachments/70949998-304cdd80-2014-11ea-9ecf-c21af198125b_1752851312365067.png differ diff --git a/documentation/docs/_attachments/70950344-1eb80580-2015-11ea-9439-10e0e1b23d9b_17528513124041011.png b/documentation/docs/_attachments/70950344-1eb80580-2015-11ea-9439-10e0e1b23d9b_17528513124041011.png new file mode 100644 index 000000000..6c98838b0 Binary files /dev/null and b/documentation/docs/_attachments/70950344-1eb80580-2015-11ea-9439-10e0e1b23d9b_17528513124041011.png differ diff --git a/documentation/docs/_attachments/70950466-7fdfd900-2015-11ea-8173-b81fee776adb_17528513124599934.png b/documentation/docs/_attachments/70950466-7fdfd900-2015-11ea-8173-b81fee776adb_17528513124599934.png new file mode 100644 index 000000000..ac3d1586e Binary files /dev/null and b/documentation/docs/_attachments/70950466-7fdfd900-2015-11ea-8173-b81fee776adb_17528513124599934.png differ diff --git a/documentation/docs/_attachments/70950678-2af09280-2016-11ea-9c82-e21b821441c9_17528513125402734.png b/documentation/docs/_attachments/70950678-2af09280-2016-11ea-9c82-e21b821441c9_17528513125402734.png new file mode 100644 index 000000000..33dc31475 Binary files /dev/null and b/documentation/docs/_attachments/70950678-2af09280-2016-11ea-9c82-e21b821441c9_17528513125402734.png differ diff --git a/documentation/docs/_attachments/70950762-54112300-2016-11ea-8ce7-73736dd01f18_17528513125245275.png b/documentation/docs/_attachments/70950762-54112300-2016-11ea-8ce7-73736dd01f18_17528513125245275.png new file mode 100644 index 000000000..8136dd051 Binary files /dev/null and b/documentation/docs/_attachments/70950762-54112300-2016-11ea-8ce7-73736dd01f18_17528513125245275.png differ diff --git a/documentation/docs/_attachments/71212869-0dfece00-2267-11ea-9971-e5a13b65ea0a_17528513102591712.png b/documentation/docs/_attachments/71212869-0dfece00-2267-11ea-9971-e5a13b65ea0a_17528513102591712.png new file mode 100644 index 000000000..fb3553d66 Binary files /dev/null and b/documentation/docs/_attachments/71212869-0dfece00-2267-11ea-9971-e5a13b65ea0a_17528513102591712.png differ diff --git a/documentation/docs/_attachments/71212939-371f5e80-2267-11ea-9531-1efd4f55f229_17528513102900565.png b/documentation/docs/_attachments/71212939-371f5e80-2267-11ea-9531-1efd4f55f229_17528513102900565.png new file mode 100644 index 000000000..d75b603f0 Binary files /dev/null and b/documentation/docs/_attachments/71212939-371f5e80-2267-11ea-9531-1efd4f55f229_17528513102900565.png differ diff --git a/documentation/docs/_attachments/71213494-82863c80-2268-11ea-8efc-27c51795a23e_17528513091588552.png b/documentation/docs/_attachments/71213494-82863c80-2268-11ea-8efc-27c51795a23e_17528513091588552.png new file mode 100644 index 000000000..2b365191a Binary files /dev/null and b/documentation/docs/_attachments/71213494-82863c80-2268-11ea-8efc-27c51795a23e_17528513091588552.png differ diff --git a/documentation/docs/_attachments/71214435-27ede000-226a-11ea-8dde-6bf4bf470677_17528513092595706.png b/documentation/docs/_attachments/71214435-27ede000-226a-11ea-8dde-6bf4bf470677_17528513092595706.png new file mode 100644 index 000000000..1b8f5c583 Binary files /dev/null and b/documentation/docs/_attachments/71214435-27ede000-226a-11ea-8dde-6bf4bf470677_17528513092595706.png differ diff --git a/documentation/docs/_attachments/71232052-3c030300-22a5-11ea-9718-76cd7f6d5a37_1752851309061598.png b/documentation/docs/_attachments/71232052-3c030300-22a5-11ea-9718-76cd7f6d5a37_1752851309061598.png new file mode 100644 index 000000000..54afce0d4 Binary files /dev/null and b/documentation/docs/_attachments/71232052-3c030300-22a5-11ea-9718-76cd7f6d5a37_1752851309061598.png differ diff --git a/documentation/docs/_attachments/71232079-54731d80-22a5-11ea-9190-17dc7505535e_1752851309115967.png b/documentation/docs/_attachments/71232079-54731d80-22a5-11ea-9190-17dc7505535e_1752851309115967.png new file mode 100644 index 000000000..9ff033700 Binary files /dev/null and b/documentation/docs/_attachments/71232079-54731d80-22a5-11ea-9190-17dc7505535e_1752851309115967.png differ diff --git a/documentation/docs/_attachments/71232172-b5025a80-22a5-11ea-8b9f-0a5a85499382_1752851309000107.png b/documentation/docs/_attachments/71232172-b5025a80-22a5-11ea-8b9f-0a5a85499382_1752851309000107.png new file mode 100644 index 000000000..73c2e5d6e Binary files /dev/null and b/documentation/docs/_attachments/71232172-b5025a80-22a5-11ea-8b9f-0a5a85499382_1752851309000107.png differ diff --git a/documentation/docs/_attachments/71679668-f6324a00-2d3c-11ea-816a-70e22e14e583_17528513131865652.png b/documentation/docs/_attachments/71679668-f6324a00-2d3c-11ea-816a-70e22e14e583_17528513131865652.png new file mode 100644 index 000000000..4d2c32388 Binary files /dev/null and b/documentation/docs/_attachments/71679668-f6324a00-2d3c-11ea-816a-70e22e14e583_17528513131865652.png differ diff --git a/documentation/docs/_attachments/71681121-bb321580-2d40-11ea-8c0d-a1d810268ea7_17528513101128633.png b/documentation/docs/_attachments/71681121-bb321580-2d40-11ea-8c0d-a1d810268ea7_17528513101128633.png new file mode 100644 index 000000000..3fb670926 Binary files /dev/null and b/documentation/docs/_attachments/71681121-bb321580-2d40-11ea-8c0d-a1d810268ea7_17528513101128633.png differ diff --git a/documentation/docs/_attachments/72eb2b73-768d-4ee5-b42b-280ff2b63af3_17528513095488863.jpg b/documentation/docs/_attachments/72eb2b73-768d-4ee5-b42b-280ff2b63af3_17528513095488863.jpg new file mode 100644 index 000000000..6e3ad042f Binary files /dev/null and b/documentation/docs/_attachments/72eb2b73-768d-4ee5-b42b-280ff2b63af3_17528513095488863.jpg differ diff --git a/documentation/docs/_attachments/7d8caf1d-cfdb-46cb-af48-2a2bcdc979eb_17528513157974837.jpg b/documentation/docs/_attachments/7d8caf1d-cfdb-46cb-af48-2a2bcdc979eb_17528513157974837.jpg new file mode 100644 index 000000000..694f271b4 Binary files /dev/null and b/documentation/docs/_attachments/7d8caf1d-cfdb-46cb-af48-2a2bcdc979eb_17528513157974837.jpg differ diff --git a/documentation/docs/_attachments/87486437-3037af00-c5f0-11ea-8edf-e758c969ab84_1752851308355029.jpeg b/documentation/docs/_attachments/87486437-3037af00-c5f0-11ea-8edf-e758c969ab84_1752851308355029.jpeg new file mode 100644 index 000000000..b6b43681a Binary files /dev/null and b/documentation/docs/_attachments/87486437-3037af00-c5f0-11ea-8edf-e758c969ab84_1752851308355029.jpeg differ diff --git a/documentation/docs/_attachments/87486786-e9968480-c5f0-11ea-997f-b3a875f7f7d1_17528513083605943.jpeg b/documentation/docs/_attachments/87486786-e9968480-c5f0-11ea-997f-b3a875f7f7d1_17528513083605943.jpeg new file mode 100644 index 000000000..a154439ce Binary files /dev/null and b/documentation/docs/_attachments/87486786-e9968480-c5f0-11ea-997f-b3a875f7f7d1_17528513083605943.jpeg differ diff --git a/documentation/docs/_attachments/88c04254-7333-4aea-8351-95ab83e02eaa_1752851311028784.jpg b/documentation/docs/_attachments/88c04254-7333-4aea-8351-95ab83e02eaa_1752851311028784.jpg new file mode 100644 index 000000000..dba2e0ffb Binary files /dev/null and b/documentation/docs/_attachments/88c04254-7333-4aea-8351-95ab83e02eaa_1752851311028784.jpg differ diff --git a/documentation/docs/_attachments/893b1d55-3d6e-45ed-887b-3df882c7e127_17528513131864328.jpg b/documentation/docs/_attachments/893b1d55-3d6e-45ed-887b-3df882c7e127_17528513131864328.jpg new file mode 100644 index 000000000..b614e8040 Binary files /dev/null and b/documentation/docs/_attachments/893b1d55-3d6e-45ed-887b-3df882c7e127_17528513131864328.jpg differ diff --git a/documentation/docs/_attachments/89591433-03497700-d7ff-11ea-8016-517408ba4a4a_17528513083924172.png b/documentation/docs/_attachments/89591433-03497700-d7ff-11ea-8016-517408ba4a4a_17528513083924172.png new file mode 100644 index 000000000..5d5836ec4 Binary files /dev/null and b/documentation/docs/_attachments/89591433-03497700-d7ff-11ea-8016-517408ba4a4a_17528513083924172.png differ diff --git a/documentation/docs/_attachments/89593505-32aeb280-d804-11ea-9262-7594958f1cfe_17528513083898718.png b/documentation/docs/_attachments/89593505-32aeb280-d804-11ea-9262-7594958f1cfe_17528513083898718.png new file mode 100644 index 000000000..cf00b8e81 Binary files /dev/null and b/documentation/docs/_attachments/89593505-32aeb280-d804-11ea-9262-7594958f1cfe_17528513083898718.png differ diff --git a/documentation/docs/_attachments/89593680-a0f37500-d804-11ea-9bc0-88e4b7ca94e7_17528513084168103.png b/documentation/docs/_attachments/89593680-a0f37500-d804-11ea-9bc0-88e4b7ca94e7_17528513084168103.png new file mode 100644 index 000000000..2e6be8c75 Binary files /dev/null and b/documentation/docs/_attachments/89593680-a0f37500-d804-11ea-9bc0-88e4b7ca94e7_17528513084168103.png differ diff --git a/documentation/docs/_attachments/89593680-a0f37500-d804-11ea-9bc0-88e4b7ca94e7_17528513084201488.png b/documentation/docs/_attachments/89593680-a0f37500-d804-11ea-9bc0-88e4b7ca94e7_17528513084201488.png new file mode 100644 index 000000000..2e6be8c75 Binary files /dev/null and b/documentation/docs/_attachments/89593680-a0f37500-d804-11ea-9bc0-88e4b7ca94e7_17528513084201488.png differ diff --git a/documentation/docs/_attachments/991c18dc-3baa-4d69-b157-6a5561e6798d_17528513106457524.jpg b/documentation/docs/_attachments/991c18dc-3baa-4d69-b157-6a5561e6798d_17528513106457524.jpg new file mode 100644 index 000000000..25b21c873 Binary files /dev/null and b/documentation/docs/_attachments/991c18dc-3baa-4d69-b157-6a5561e6798d_17528513106457524.jpg differ diff --git a/documentation/docs/_attachments/aeeedf6b-8703-47a9-8f71-1916f547cf29_1752851309283848.jpg b/documentation/docs/_attachments/aeeedf6b-8703-47a9-8f71-1916f547cf29_1752851309283848.jpg new file mode 100644 index 000000000..56e1f29f7 Binary files /dev/null and b/documentation/docs/_attachments/aeeedf6b-8703-47a9-8f71-1916f547cf29_1752851309283848.jpg differ diff --git a/documentation/docs/_attachments/bfeb57be-c926-4da2-bb0e-7ff00193872f_17528513112279325.jpg b/documentation/docs/_attachments/bfeb57be-c926-4da2-bb0e-7ff00193872f_17528513112279325.jpg new file mode 100644 index 000000000..4c8d1b185 Binary files /dev/null and b/documentation/docs/_attachments/bfeb57be-c926-4da2-bb0e-7ff00193872f_17528513112279325.jpg differ diff --git a/documentation/docs/contact-us.md b/documentation/docs/contact-us.md new file mode 100644 index 000000000..9ec47acae --- /dev/null +++ b/documentation/docs/contact-us.md @@ -0,0 +1,5 @@ +- The preferred way is via posting a [GitHub issue](https://github.com/codalab/codabench/issues?state=open). +- If you wish to get in touch with the community, you can use the [Google Groups](https://groups.google.com/g/codalab-competitions). +- In case of emergency + +[Send us an email :e-mail:](mailto:info@codalab.org){ .md-button .md-button--primary} \ No newline at end of file diff --git a/documentation/docs/index.md b/documentation/docs/index.md new file mode 100644 index 000000000..d94107544 --- /dev/null +++ b/documentation/docs/index.md @@ -0,0 +1,13 @@ +## Documentation + +Welcome to the Codabench wiki! + +Codabench is a platform allowing you to flexibly specify a benchmark. First you define tasks, e.g. datasets and metrics of success, then you specify the API for submissions of code (algorithms), add some documentation pages, and "CLICK!" your benchmark is created, ready to accept submissions of new algorithms. Participant results get appended to an ever-growing leaderboard. + +You may also create inverted benchmarks in which the role of datasets and algorithms are swapped. You specify reference algorithms and your participants submit datasets. + + +## Useful links +[Governance Document](https://github.com/codalab/codalab-competitions/wiki/Community-Governance) +[Privacy and Terms of Use](https://github.com/codalab/codalab-competitions/wiki/Privacy) +[About](https://github.com/codalab/codalab-competitions/wiki/Project_About_CodaLab) \ No newline at end of file diff --git a/documentation/main.py b/documentation/main.py new file mode 100644 index 000000000..04325bc6b --- /dev/null +++ b/documentation/main.py @@ -0,0 +1,6 @@ +def main(): + print("Hello from mkdocs!") + + +if __name__ == "__main__": + main() diff --git a/documentation/mkdocs.yml b/documentation/mkdocs.yml new file mode 100644 index 000000000..c8ddc0cd6 --- /dev/null +++ b/documentation/mkdocs.yml @@ -0,0 +1,170 @@ +site_name: Codabench Wiki +repo_url: https://github.com/codalab/codabench +copyright: Apache-2.0 +edit_uri: documentation/docs + +theme: + name: material + #logo: assets/favicon.ico + #favicon: assets/favicon.ico + custom_dir: overrides + features: + - content.code.copy + - navigation.tabs + - navigation.tabs.sticky + - navigation.indexes + - search.share + - navigation.footer + - navigation.top + - content.action.edit + - content.action.view + - navigation.expand + palette: + # Palette toggle for light mode + - scheme: slate + toggle: + icon: material/brightness-7 + name: Switch to dark mode + primary: indigo + accent: orange + + # Palette toggle for dark mode + - scheme: default + toggle: + icon: material/brightness-4 + name: Switch to light mode + + icon: + repo: fontawesome/brands/github + +markdown_extensions: + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - tables + - attr_list + - abbr + - toc: + permalink: true + - admonition + - pymdownx.details + - pymdownx.tabbed: + alternate_style: true + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + +plugins: + - search + - to-pdf: + enabled_if_env: PDF + download_link: header + author: Codabench Team + copyright: Apache-2.0 + cover_subtitle: Codabench Wiki PDF + output_path: codabench-wiki.pdf + toc_level: 3 + + # Version docs (with git) + - mike: + # These fields are all optional; the defaults are as below... + alias_type: symlink + redirect_template: null + deploy_prefix: "" + canonical_version: null + version_selector: true + css_dir: css + javascript_dir: js + + - open-in-new-tab: + add_icon: true + + # Image zoom + - glightbox + + - privacy + +extra: + version: + provider: mike + alias: true + footer_links: + - text: "Governance Document" + href: "https://github.com/codalab/codalab-competitions/wiki/Community-Governance" + - text: "Privacy Policy" + href: "https://github.com/codalab/codalab-competitions/wiki/Privacy" + - text: "About" + href: "https://github.com/codalab/codalab-competitions/wiki/Project_About_CodaLab" + +nav: + - Home: index.md + - Participants: + - Participating in a Competition: Participants/User_Participating-in-a-Competition.md + - List of Current Benchmarks and Competitions: https://www.codabench.org/competitions/public/?page=1 + - Organizers: + - Benchmark Creation: + - Getting Started Tutorial: Organizers/Benchmark_Creation/Getting-started-with-Codabench.md + - Advanced Tutorial: Organizers/Benchmark_Creation/Advanced-Tutorial.md + - How to Transition from Codalab to Codabench?: Organizers/Benchmark_Creation/How-to-transition-from-CodaLab-to-Codabench?.md + - Competition Creation: Organizers/Benchmark_Creation/Competition-Creation.md + - Competition Creation Form: Organizers/Benchmark_Creation/Competition-Creation:-Form.md + - Competition Creation Bundle: Organizers/Benchmark_Creation/Competition-Creation:-Bundle.md + - Competition YAML Structure: Organizers/Benchmark_Creation/Competition-Bundle-Structure.md + - YAML Structure: Organizers/Benchmark_Creation/Yaml-Structure.md + - Competition Docker Image: Organizers/Benchmark_Creation/Competition-docker-image.md + - Dataset Competition Creation and participate instruction: Organizers/Benchmark_Creation/Dataset-competition-creation-and-participate-instruction.md + - Leaderboard Features: Organizers/Benchmark_Creation/Leaderboard-Functionality.md + - Competition Examples: https://github.com/codalab/competition-examples/tree/master/codabench + - Example Cancer Benchmarks: Organizers/Benchmark_Creation/Cancer-Benchmarks.md + - Public Tasks and Tasks Sharing: Organizers/Benchmark_Creation/Public-Tasks-and-Tasks-Sharing.md + - Detailed Results and Visualization: Organizers/Benchmark_Creation/Detailed-Results-and-Visualizations.md + - Running a Benchmarks: + - Benchmark Management & List Page: Organizers/Running_a_benchmark/Competition-Management-&-List.md + - Benchmark Detail Page: Organizers/Running_a_benchmark/Competition-Detail-Page.md + - Ressource Management Submissions, Datasets/Programs, Tasks and Competition Bundles: Organizers/Running_a_benchmark/Resource-Management.md + - Update programs or data: Organizers/Running_a_benchmark/Update-programs-or-data.md + - Queue Management: Organizers/Running_a_benchmark/Queue-Management.md + - Compute Worker Management & Setup: Organizers/Running_a_benchmark/Compute-Worker-Management---Setup.md + - Compute Worker Management with Podman: Organizers/Running_a_benchmark/Compute-worker-installation-with-Podman.md + - Server Status: Organizers/Running_a_benchmark/Server-status-page.md + - Developers and Administrators: + - Codabench Basic Installtion Guide: Developers_and_Administrators/Codabench-Installation.md + - How to Deploy a Server: Developers_and_Administrators/How-to-deploy-Codabench-on-your-server.md + - Administrative Procedures: Developers_and_Administrators/Administrator-procedures.md + - Codabench Docker Architecture: Developers_and_Administrators/Codabench-Architecture.md + - Submission Docker Container Layout: Developers_and_Administrators/Submission-Docker-Container-Layout.md + - Backups - Automating Creation and Restoring: Developers_and_Administrators/Creating-and-Restoring-from-Backup.md + - Submission Process Overview: Developers_and_Administrators/Submission-Process-Overview.md + - Robot Submissions: Developers_and_Administrators/Robot-submissions.md + - Running Tests: Developers_and_Administrators/Running-tests.md + - Automation: Developers_and_Administrators/Automating-with-Selenium.md + - Manual Validation: Developers_and_Administrators/Manual-validation.md + - Validation and deplyement of pull requests: Developers_and_Administrators/Validation-and-deployment-of-pull-requests.md + - Upgrading Codabench: + - Developers_and_Administrators/Upgrading_Codabench/index.md + - Upgrade RabbitMQ (version < 1.0.0): Developers_and_Administrators/Upgrading_Codabench/Upgrade-RabbitMQ.md + - Create new logos for each competitions (version < 1.4.1): Developers_and_Administrators/Upgrading_Codabench/Create-new-logos-for-each-competition.md + - Worker docker image manual update (version < 1.3.1): Developers_and_Administrators/Upgrading_Codabench/Worker-Docker-Image-manual-update.md + - Add line in .env file for default worker queue duration (version < 1.7.0): Developers_and_Administrators/Upgrading_Codabench/Add-line-into-.env-for-default-queue-worker-duration.md + - Uncomment a line in your .env file (version < 1.8.0): Developers_and_Administrators/Upgrading_Codabench/Uncomment-a-line-in-your-.env-file.md + - Rebuilding all docker images (version < 1.9.2): Developers_and_Administrators/Upgrading_Codabench/Rebuilding-all-docker-images.md + - Move the latest storage_inconsistency files from the logs folder to var/logs (version < 1.12.0): Developers_and_Administrators/Upgrading_Codabench/Move-the-last-storage_inconsistency-files-from--logs-folder-to--var-logs--folder.md + - Submissions and Participants count (version < 1.14.0): Developers_and_Administrators/Upgrading_Codabench/Submissions-and-Participants-Counts.md + - Homepage Counters (version < 1.15.0): Developers_and_Administrators/Upgrading_Codabench/Homepage-counters.md + - User Removal (version < 1.17.0): Developers_and_Administrators/Upgrading_Codabench/User-removal.md + - Database size fix (version < 1.18.0): Developers_and_Administrators/Upgrading_Codabench/Database-size-fixes.md + - Newsletters Archive: + - 2024: Newsletters_Archive/CodaLab-in-2024.md + - How you can contribue: + - Contribute/index.md + - Contribute/contributing.md + - FAQ: Project_CodaBench_FAQ.md + - Contact Us: contact-us.md diff --git a/documentation/overrides/partials/base.html b/documentation/overrides/partials/base.html new file mode 100644 index 000000000..8d9f50509 --- /dev/null +++ b/documentation/overrides/partials/base.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% block outdated %} + You're not viewing the latest version. + + Click here to go to latest. + +{% endblock %} diff --git a/documentation/overrides/partials/copyright.html b/documentation/overrides/partials/copyright.html new file mode 100644 index 000000000..5016d64ef --- /dev/null +++ b/documentation/overrides/partials/copyright.html @@ -0,0 +1,19 @@ +{# base partial from: +github.com/squidfunk/mkdocs-material/material/templates/partials/copyright.html +#} + \ No newline at end of file diff --git a/documentation/pyproject.toml b/documentation/pyproject.toml new file mode 100644 index 000000000..ad15b5223 --- /dev/null +++ b/documentation/pyproject.toml @@ -0,0 +1,13 @@ +[project] +name = "codabench-mkdocs" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "mike>=2.1.3", + "mkdocs-glightbox>=0.4.0", + "mkdocs-material>=9.6.15", + "mkdocs-open-in-new-tab>=1.0.8", + "mkdocs-to-pdf>=0.10.1", +] diff --git a/poetry.lock b/poetry.lock index 2a8fa6429..cf29f4d44 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiofiles" @@ -60,20 +60,20 @@ files = [ [[package]] name = "asgiref" -version = "3.8.1" +version = "3.9.1" description = "ASGI specs, helper code, and adapters" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, - {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, + {file = "asgiref-3.9.1-py3-none-any.whl", hash = "sha256:f3bba7092a48005b5f5bacd747d36ee4a5a61f4a269a6df590b43144355ebd2c"}, + {file = "asgiref-3.9.1.tar.gz", hash = "sha256:a5ab6582236218e5ef1648f242fd9f10626cfd4de8dc377db215d5d5098e3142"}, ] [package.dependencies] -typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} +typing_extensions = {version = ">=4", markers = "python_version < \"3.11\""} [package.extras] -tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] +tests = ["mypy (>=1.14.0)", "pytest", "pytest-asyncio"] [[package]] name = "asttokens" @@ -113,20 +113,20 @@ files = [ [[package]] name = "attrs" -version = "24.2.0" +version = "25.3.0" description = "Classes Without Boilerplate" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, - {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, + {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, + {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, ] [package.extras] benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] @@ -161,17 +161,17 @@ xbr = ["base58 (>=2.1.0)", "bitarray (>=2.7.5)", "cbor2 (>=5.2.0)", "click (>=8. [[package]] name = "automat" -version = "24.8.1" +version = "25.4.16" description = "Self-service finite-state machines for the programmer on the go." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "Automat-24.8.1-py3-none-any.whl", hash = "sha256:bf029a7bc3da1e2c24da2343e7598affaa9f10bf0ab63ff808566ce90551e02a"}, - {file = "automat-24.8.1.tar.gz", hash = "sha256:b34227cf63f6325b8ad2399ede780675083e439b20c323d376373d8ee6306d88"}, + {file = "automat-25.4.16-py3-none-any.whl", hash = "sha256:04e9bce696a8d5671ee698005af6e5a9fa15354140a87f4870744604dcdd3ba1"}, + {file = "automat-25.4.16.tar.gz", hash = "sha256:0017591a5477066e90d26b0e696ddc143baafd87b588cfac8100bc6be9634de0"}, ] [package.dependencies] -typing-extensions = {version = "*", markers = "python_version < \"3.10\""} +typing_extensions = {version = "*", markers = "python_version < \"3.10\""} [package.extras] visualize = ["Twisted (>=16.1.1)", "graphviz (>0.5.1)"] @@ -284,18 +284,17 @@ webencodings = "*" [[package]] name = "blessed" -version = "1.20.0" +version = "1.22.0" description = "Easy, practical library for making terminal apps, by providing an elegant, well-documented interface to Colors, Keyboard input, and screen Positioning capabilities." optional = false python-versions = ">=2.7" files = [ - {file = "blessed-1.20.0-py2.py3-none-any.whl", hash = "sha256:0c542922586a265e699188e52d5f5ac5ec0dd517e5a1041d90d2bbf23f906058"}, - {file = "blessed-1.20.0.tar.gz", hash = "sha256:2cdd67f8746e048f00df47a2880f4d6acbcdb399031b604e34ba8f71d5787680"}, + {file = "blessed-1.22.0-py2.py3-none-any.whl", hash = "sha256:a1fed52d708a1aa26dfb8d3eaecf6f4714bff590e728baeefcb44f2c16c8de82"}, + {file = "blessed-1.22.0.tar.gz", hash = "sha256:1818efb7c10015478286f21a412fcdd31a3d8b94a18f6d926e733827da7a844b"}, ] [package.dependencies] jinxed = {version = ">=1.1.0", markers = "platform_system == \"Windows\""} -six = ">=1.9.0" wcwidth = ">=0.1.4" [[package]] @@ -370,17 +369,6 @@ jedi = ["jedi (>=0.16)"] urwid = ["urwid"] watch = ["watchdog"] -[[package]] -name = "cachetools" -version = "5.5.0" -description = "Extensible memoizing collections and decorators" -optional = false -python-versions = ">=3.7" -files = [ - {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, - {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, -] - [[package]] name = "celery" version = "4.4.7" @@ -434,112 +422,129 @@ zstd = ["zstandard"] [[package]] name = "certifi" -version = "2024.8.30" +version = "2025.8.3" description = "Python package for providing Mozilla's CA Bundle." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, - {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, + {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, + {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, ] [[package]] name = "cffi" -version = "1.17.1" +version = "2.0.0" description = "Foreign Function Interface for Python calling C code." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" + {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, + {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453"}, + {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495"}, + {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5"}, + {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb"}, + {file = "cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a"}, + {file = "cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739"}, + {file = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"}, + {file = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"}, + {file = "cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"}, + {file = "cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"}, + {file = "cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"}, + {file = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"}, + {file = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"}, + {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"}, + {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"}, + {file = "cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"}, + {file = "cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"}, + {file = "cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"}, + {file = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"}, + {file = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"}, + {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"}, + {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"}, + {file = "cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"}, + {file = "cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"}, + {file = "cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"}, + {file = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"}, + {file = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"}, + {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"}, + {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"}, + {file = "cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"}, + {file = "cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"}, + {file = "cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"}, + {file = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"}, + {file = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"}, + {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"}, + {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"}, + {file = "cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"}, + {file = "cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"}, + {file = "cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"}, + {file = "cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf"}, + {file = "cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63"}, + {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2"}, + {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65"}, + {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322"}, + {file = "cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a"}, + {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, + {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, +] + +[package.dependencies] +pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} [[package]] name = "channels" -version = "2.4.0" +version = "3.0.0" description = "Brings async, event-driven capabilities to Django. Django 2.2 and up only." optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "channels-2.4.0-py2.py3-none-any.whl", hash = "sha256:80a5ad1962ae039a3dcc0a5cb5212413e66e2f11ad9e9db8004834436daf3400"}, - {file = "channels-2.4.0.tar.gz", hash = "sha256:08e756406d7165cb32f6fc3090c0643f41ca9f7e0f7fada0b31194662f20f414"}, + {file = "channels-3.0.0-py3-none-any.whl", hash = "sha256:fd3596f252e8415523e2b33bf76363127326c18fb338a7b1191a6ff52e7d3f0f"}, + {file = "channels-3.0.0.tar.gz", hash = "sha256:af2206de0b76b3209fe8cc71b4a7c2975fee97ed975313d7c098414af060c1da"}, ] [package.dependencies] -asgiref = ">=3.2,<4.0" -daphne = ">=2.3,<3.0" +asgiref = ">=3.2.10,<4" +daphne = ">=3.0,<4" Django = ">=2.2" [package.extras] -tests = ["async-generator (>=1.10,<2.0)", "async-timeout (>=3.0,<4.0)", "coverage (>=4.5,<5.0)", "pytest (>=4.4,<5.0)", "pytest-asyncio (>=0.10,<1.0)", "pytest-django (>=3.4,<4.0)"] +tests = ["async-generator", "async-timeout", "coverage (>=4.5,<5.0)", "pytest", "pytest-asyncio", "pytest-django"] [[package]] name = "channels-redis" @@ -564,116 +569,90 @@ tests = ["async-timeout", "cryptography (>=1.3.0)", "pytest", "pytest-asyncio"] [[package]] name = "charset-normalizer" -version = "3.4.0" +version = "3.4.3" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, - {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, - {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, +python-versions = ">=3.7" +files = [ + {file = "charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca"}, + {file = "charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a"}, + {file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"}, ] [[package]] @@ -742,53 +721,79 @@ jinja2 = "*" [[package]] name = "cryptography" -version = "44.0.0" +version = "46.0.1" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.7" -files = [ - {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, - {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, - {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, - {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, - {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, - {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, - {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] +python-versions = "!=3.9.0,!=3.9.1,>=3.8" +files = [ + {file = "cryptography-46.0.1-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:1cd6d50c1a8b79af1a6f703709d8973845f677c8e97b1268f5ff323d38ce8475"}, + {file = "cryptography-46.0.1-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0ff483716be32690c14636e54a1f6e2e1b7bf8e22ca50b989f88fa1b2d287080"}, + {file = "cryptography-46.0.1-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9873bf7c1f2a6330bdfe8621e7ce64b725784f9f0c3a6a55c3047af5849f920e"}, + {file = "cryptography-46.0.1-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0dfb7c88d4462a0cfdd0d87a3c245a7bc3feb59de101f6ff88194f740f72eda6"}, + {file = "cryptography-46.0.1-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e22801b61613ebdebf7deb18b507919e107547a1d39a3b57f5f855032dd7cfb8"}, + {file = "cryptography-46.0.1-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:757af4f6341ce7a1e47c326ca2a81f41d236070217e5fbbad61bbfe299d55d28"}, + {file = "cryptography-46.0.1-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f7a24ea78de345cfa7f6a8d3bde8b242c7fac27f2bd78fa23474ca38dfaeeab9"}, + {file = "cryptography-46.0.1-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e8776dac9e660c22241b6587fae51a67b4b0147daa4d176b172c3ff768ad736"}, + {file = "cryptography-46.0.1-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9f40642a140c0c8649987027867242b801486865277cbabc8c6059ddef16dc8b"}, + {file = "cryptography-46.0.1-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:449ef2b321bec7d97ef2c944173275ebdab78f3abdd005400cc409e27cd159ab"}, + {file = "cryptography-46.0.1-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2dd339ba3345b908fa3141ddba4025568fa6fd398eabce3ef72a29ac2d73ad75"}, + {file = "cryptography-46.0.1-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7411c910fb2a412053cf33cfad0153ee20d27e256c6c3f14d7d7d1d9fec59fd5"}, + {file = "cryptography-46.0.1-cp311-abi3-win32.whl", hash = "sha256:cbb8e769d4cac884bb28e3ff620ef1001b75588a5c83c9c9f1fdc9afbe7f29b0"}, + {file = "cryptography-46.0.1-cp311-abi3-win_amd64.whl", hash = "sha256:92e8cfe8bd7dd86eac0a677499894862cd5cc2fd74de917daa881d00871ac8e7"}, + {file = "cryptography-46.0.1-cp311-abi3-win_arm64.whl", hash = "sha256:db5597a4c7353b2e5fb05a8e6cb74b56a4658a2b7bf3cb6b1821ae7e7fd6eaa0"}, + {file = "cryptography-46.0.1-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:4c49eda9a23019e11d32a0eb51a27b3e7ddedde91e099c0ac6373e3aacc0d2ee"}, + {file = "cryptography-46.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9babb7818fdd71394e576cf26c5452df77a355eac1a27ddfa24096665a27f8fd"}, + {file = "cryptography-46.0.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9f2c4cc63be3ef43c0221861177cee5d14b505cd4d4599a89e2cd273c4d3542a"}, + {file = "cryptography-46.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:41c281a74df173876da1dc9a9b6953d387f06e3d3ed9284e3baae3ab3f40883a"}, + {file = "cryptography-46.0.1-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0a17377fa52563d730248ba1f68185461fff36e8bc75d8787a7dd2e20a802b7a"}, + {file = "cryptography-46.0.1-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:0d1922d9280e08cde90b518a10cd66831f632960a8d08cb3418922d83fce6f12"}, + {file = "cryptography-46.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:af84e8e99f1a82cea149e253014ea9dc89f75b82c87bb6c7242203186f465129"}, + {file = "cryptography-46.0.1-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ef648d2c690703501714588b2ba640facd50fd16548133b11b2859e8655a69da"}, + {file = "cryptography-46.0.1-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:e94eb5fa32a8a9f9bf991f424f002913e3dd7c699ef552db9b14ba6a76a6313b"}, + {file = "cryptography-46.0.1-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:534b96c0831855e29fc3b069b085fd185aa5353033631a585d5cd4dd5d40d657"}, + {file = "cryptography-46.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f9b55038b5c6c47559aa33626d8ecd092f354e23de3c6975e4bb205df128a2a0"}, + {file = "cryptography-46.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ec13b7105117dbc9afd023300fb9954d72ca855c274fe563e72428ece10191c0"}, + {file = "cryptography-46.0.1-cp314-cp314t-win32.whl", hash = "sha256:504e464944f2c003a0785b81668fe23c06f3b037e9cb9f68a7c672246319f277"}, + {file = "cryptography-46.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c52fded6383f7e20eaf70a60aeddd796b3677c3ad2922c801be330db62778e05"}, + {file = "cryptography-46.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:9495d78f52c804b5ec8878b5b8c7873aa8e63db9cd9ee387ff2db3fffe4df784"}, + {file = "cryptography-46.0.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:d84c40bdb8674c29fa192373498b6cb1e84f882889d21a471b45d1f868d8d44b"}, + {file = "cryptography-46.0.1-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9ed64e5083fa806709e74fc5ea067dfef9090e5b7a2320a49be3c9df3583a2d8"}, + {file = "cryptography-46.0.1-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:341fb7a26bc9d6093c1b124b9f13acc283d2d51da440b98b55ab3f79f2522ead"}, + {file = "cryptography-46.0.1-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6ef1488967e729948d424d09c94753d0167ce59afba8d0f6c07a22b629c557b2"}, + {file = "cryptography-46.0.1-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7823bc7cdf0b747ecfb096d004cc41573c2f5c7e3a29861603a2871b43d3ef32"}, + {file = "cryptography-46.0.1-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:f736ab8036796f5a119ff8211deda416f8c15ce03776db704a7a4e17381cb2ef"}, + {file = "cryptography-46.0.1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:e46710a240a41d594953012213ea8ca398cd2448fbc5d0f1be8160b5511104a0"}, + {file = "cryptography-46.0.1-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:84ef1f145de5aee82ea2447224dc23f065ff4cc5791bb3b506615957a6ba8128"}, + {file = "cryptography-46.0.1-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9394c7d5a7565ac5f7d9ba38b2617448eba384d7b107b262d63890079fad77ca"}, + {file = "cryptography-46.0.1-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:ed957044e368ed295257ae3d212b95456bd9756df490e1ac4538857f67531fcc"}, + {file = "cryptography-46.0.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f7de12fa0eee6234de9a9ce0ffcfa6ce97361db7a50b09b65c63ac58e5f22fc7"}, + {file = "cryptography-46.0.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7fab1187b6c6b2f11a326f33b036f7168f5b996aedd0c059f9738915e4e8f53a"}, + {file = "cryptography-46.0.1-cp38-abi3-win32.whl", hash = "sha256:45f790934ac1018adeba46a0f7289b2b8fe76ba774a88c7f1922213a56c98bc1"}, + {file = "cryptography-46.0.1-cp38-abi3-win_amd64.whl", hash = "sha256:7176a5ab56fac98d706921f6416a05e5aff7df0e4b91516f450f8627cda22af3"}, + {file = "cryptography-46.0.1-cp38-abi3-win_arm64.whl", hash = "sha256:efc9e51c3e595267ff84adf56e9b357db89ab2279d7e375ffcaf8f678606f3d9"}, + {file = "cryptography-46.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd4b5e2ee4e60425711ec65c33add4e7a626adef79d66f62ba0acfd493af282d"}, + {file = "cryptography-46.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:48948940d0ae00483e85e9154bb42997d0b77c21e43a77b7773c8c80de532ac5"}, + {file = "cryptography-46.0.1-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b9c79af2c3058430d911ff1a5b2b96bbfe8da47d5ed961639ce4681886614e70"}, + {file = "cryptography-46.0.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0ca4be2af48c24df689a150d9cd37404f689e2968e247b6b8ff09bff5bcd786f"}, + {file = "cryptography-46.0.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:13e67c4d3fb8b6bc4ef778a7ccdd8df4cd15b4bcc18f4239c8440891a11245cc"}, + {file = "cryptography-46.0.1-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:15b5fd9358803b0d1cc42505a18d8bca81dabb35b5cfbfea1505092e13a9d96d"}, + {file = "cryptography-46.0.1-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:e34da95e29daf8a71cb2841fd55df0511539a6cdf33e6f77c1e95e44006b9b46"}, + {file = "cryptography-46.0.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:34f04b7311174469ab3ac2647469743720f8b6c8b046f238e5cb27905695eb2a"}, + {file = "cryptography-46.0.1.tar.gz", hash = "sha256:ed570874e88f213437f5cf758f9ef26cbfc3f336d889b1e592ee11283bb8d1c7"}, +] + +[package.dependencies] +cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9\" and platform_python_implementation != \"PyPy\""} +typing-extensions = {version = ">=4.13.2", markers = "python_full_version < \"3.11\""} + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"] docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +nox = ["nox[uv] (>=2024.4.15)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.14)", "ruff (>=0.11.11)"] sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] +test = ["certifi (>=2024)", "cryptography-vectors (==46.0.1)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] test-randomorder = ["pytest-randomly"] [[package]] @@ -808,62 +813,62 @@ cwcwidth = "*" [[package]] name = "cwcwidth" -version = "0.1.9" +version = "0.1.10" description = "Python bindings for wc(s)width" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "cwcwidth-0.1.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:704f0d6888aa5e81e76d9f76709385f9f55aca8c450ee82cc722054814a7791f"}, - {file = "cwcwidth-0.1.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0633158205b50f253ad04e301156807e309a9fb9479a520418e010da6df13604"}, - {file = "cwcwidth-0.1.9-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a5407d0933c3aab8ee92cffd9e4f09010f25af10ebdfa19776748402bba9261"}, - {file = "cwcwidth-0.1.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:72490e07dfbc599fdf6efe26a13cfbf725f0513b181c3386d65bfd84f6175924"}, - {file = "cwcwidth-0.1.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf71151ae06e95f266bef91392c1562539b2eed847fd1f00f7b5b4ca3fd41a67"}, - {file = "cwcwidth-0.1.9-cp310-cp310-win32.whl", hash = "sha256:3e3c186b5c171d85f2b7f093e7efb33fd9b6e55b791ff75a0f101b18ec0433cd"}, - {file = "cwcwidth-0.1.9-cp310-cp310-win_amd64.whl", hash = "sha256:ae17e493ffc18497c2602f8f42a0d8e490ea42ab3ccfbe5e4a6069a6d24f3b36"}, - {file = "cwcwidth-0.1.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b1c3eb0a8c1b25c4a17b6b9bbf7d25ce9df3ea43b6f87903c51bc12434a2cc29"}, - {file = "cwcwidth-0.1.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c8752815ce4e40e7b34b7fe039276a5fbfb1b077131614381b13ef3b7bb21ff"}, - {file = "cwcwidth-0.1.9-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:368ace13080dbaacdc247370d8a965a749b124aa50d0b1b6eb87601826db870f"}, - {file = "cwcwidth-0.1.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ca9a653661e152a426bdb51a272f36bc79f9830e6a7169abe8110ec367c3518c"}, - {file = "cwcwidth-0.1.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f96386cc29e6eef8ef066d7dd3c767c5119d66506dabea20dd344dabb3f2d225"}, - {file = "cwcwidth-0.1.9-cp311-cp311-win32.whl", hash = "sha256:f6ba88970ec12fdbed5554beb1b9a25d8271fc3d0d9e60639db700a79bed1863"}, - {file = "cwcwidth-0.1.9-cp311-cp311-win_amd64.whl", hash = "sha256:aa6725e7b3571fdf6ce7c02d1dd2d69e00d166bb6df44e46ab215067028b3a03"}, - {file = "cwcwidth-0.1.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:42de102d5191fc68ef3ff6530f60c4895148ddc21aa0acaaf4612e5f7f0c38c4"}, - {file = "cwcwidth-0.1.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:877e48c615b3fec88b7e640f9cf9d96704497657fb5aad2b7c0b0c59ecabff69"}, - {file = "cwcwidth-0.1.9-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdbaf0a8dad20eb685df11a195a2449fe230b08a5b356d036c8d7e59d4128a88"}, - {file = "cwcwidth-0.1.9-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f6e0e023c4b127c47fd4c44cf537be209b9a28d8725f4f576f4d63744a23aa38"}, - {file = "cwcwidth-0.1.9-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b4f7d24236ce3c9d3b5e07fd75d232452f19bdddb6ae8bbfdcb97b6cb02835e8"}, - {file = "cwcwidth-0.1.9-cp312-cp312-win32.whl", hash = "sha256:ba9da6c911bf108334426890bc9f57b839a38e1afc4383a41bd70adbce470db3"}, - {file = "cwcwidth-0.1.9-cp312-cp312-win_amd64.whl", hash = "sha256:40466f16e85c338e8fc3eee87a8c9ca23416cc68b3049f68cb4cead5fb8b71b3"}, - {file = "cwcwidth-0.1.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:167f59c3c1e1d8e231a1abd666af4e73dd8a94917efb6522e9b610ac4587903a"}, - {file = "cwcwidth-0.1.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afc745f18c9e3c38851a931c0c0a7e479d6494911ba1353f998d707f95a895b4"}, - {file = "cwcwidth-0.1.9-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8d55c47cbec4796e89cfedc89c52e6c4c2faeb77489a763415b9f76d8fc14db"}, - {file = "cwcwidth-0.1.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c858842849ce2cfdf207095253da83831d9407771c8073f6b75f24d3faf1a1eb"}, - {file = "cwcwidth-0.1.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cc049ce273f32b632f5ead649b2120f8b2b78035d7b069fdc460c4be9affddb5"}, - {file = "cwcwidth-0.1.9-cp38-cp38-win32.whl", hash = "sha256:1bafe978a5b7915848244a952829e3f8757c0cebef581c8250da6064c906c38c"}, - {file = "cwcwidth-0.1.9-cp38-cp38-win_amd64.whl", hash = "sha256:024d1b21e6123bf30a849e60eea3482f556bbd00d39215f86c904e5bd81fc1b6"}, - {file = "cwcwidth-0.1.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7d367da5e6fb538388817bf5b2d6dd4db90e5e631d99c34055589d007b5c94bc"}, - {file = "cwcwidth-0.1.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad721d9dbc14eafd06176e4f5594942336b1e813de2a5ab7bd64254393c5713f"}, - {file = "cwcwidth-0.1.9-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:711ace9796cb6767ff29095ff5b0ec4619e7297854eb4b91ba99154590eddcc9"}, - {file = "cwcwidth-0.1.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:945615a7b8cdcbcd8e06d399f96a2b09440c3a4c5cb3c2d0109f00d80da27a12"}, - {file = "cwcwidth-0.1.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ffaf706abe400282f299463594d8887566e2a280cd0255110bd4397cc7be2910"}, - {file = "cwcwidth-0.1.9-cp39-cp39-win32.whl", hash = "sha256:03093cac6f8e4326b1c30169e024fe2894f76c6ffddf6464e489bb33cb3a2897"}, - {file = "cwcwidth-0.1.9-cp39-cp39-win_amd64.whl", hash = "sha256:0ddef2c504e6f4fd6122b46d55061f487add1ebb86596ae70ffc2a8b8955c8bc"}, - {file = "cwcwidth-0.1.9.tar.gz", hash = "sha256:f19d11a0148d4a8cacd064c96e93bca8ce3415a186ae8204038f45e108db76b8"}, + {file = "cwcwidth-0.1.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:71932aaee8cba8be9365b3e4a96fd3cb4f02b3c54085cd18df26d5b90505af19"}, + {file = "cwcwidth-0.1.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2bcc437fb407850e7b8d700d08215e1f285456774802be072f80715a3054a9ad"}, + {file = "cwcwidth-0.1.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1af5edb0854442cf156497a0f7adf51ea1403a8a93404655d96769fc16307f4"}, + {file = "cwcwidth-0.1.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a36396389a4172a89a76a7768519de33873de53b81604a80f57224574a6664e5"}, + {file = "cwcwidth-0.1.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:01393cd955ca9de61d845a438cadf02bd689d6c04201b7b06cf9bae57b54c7e0"}, + {file = "cwcwidth-0.1.10-cp310-cp310-win32.whl", hash = "sha256:14823e85163160028cc9f122a0448ddadd7f65d494602b2604211e8f3d0a1e10"}, + {file = "cwcwidth-0.1.10-cp310-cp310-win_amd64.whl", hash = "sha256:8e6b20572c6d17605a69c73e1aee86db051f3ebc90e99f2d99e8751c56553d53"}, + {file = "cwcwidth-0.1.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:849091bb6845a9ddb74497b9345eb2610fb4dff4f12263fb393dd62142163046"}, + {file = "cwcwidth-0.1.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74a1ede59f73733860e775459ba07c723898cece905dd27bd536d0c99d8b42f1"}, + {file = "cwcwidth-0.1.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d15a42557a4ad2614b0281ee3dc27fb6ff9b83437f61cce44dc551926189080"}, + {file = "cwcwidth-0.1.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bf2a8e081fa882d2f97ad86443a5e3bac23c841961669d610944b7e81b2966cc"}, + {file = "cwcwidth-0.1.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79e6f708f1b00f102252b43c3e9ab90d25eaab87d9f2b5649897fb07866b6252"}, + {file = "cwcwidth-0.1.10-cp311-cp311-win32.whl", hash = "sha256:33bf671f76932af133e66f0741619e9c3a8cebbca0a1f151be65e16cf4cf3e6d"}, + {file = "cwcwidth-0.1.10-cp311-cp311-win_amd64.whl", hash = "sha256:619def845e26598a6651620f2ef50bf3adb05979efb622415f0222c6447f1a62"}, + {file = "cwcwidth-0.1.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d2b21ff2eb60c6793349b7fb161c40a8583a57ec32e61f47aab7938177bfdec"}, + {file = "cwcwidth-0.1.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0316488349c3e5ca4b20de7daa1cb8e96a05d1d14d040d46e87a495da655f4a"}, + {file = "cwcwidth-0.1.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:848b6ffca1e32e28d2ccbb2cd395ccd3c38a7c4ec110728cd9d828eaf609b09e"}, + {file = "cwcwidth-0.1.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c3a7bfe1da478c0c27c549f68c6e28a583413da3ee451854ec2d983497bd18b8"}, + {file = "cwcwidth-0.1.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cff03100f49170bc50fc399d05a31b8fcb7b0cef26df1a8068fa943387107f6c"}, + {file = "cwcwidth-0.1.10-cp312-cp312-win32.whl", hash = "sha256:2dd9a92fdfbc53fc79f0953f39708dcf743fd27450c374985f419e3d47eb89d4"}, + {file = "cwcwidth-0.1.10-cp312-cp312-win_amd64.whl", hash = "sha256:734d764281e3d87c40d0265543f00a653409145fa9f48a93bc0fbf9a8e7932ca"}, + {file = "cwcwidth-0.1.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2391073280d774ab5d9af1d3aaa26ec456956d04daa1134fb71c31cd72ba5bba"}, + {file = "cwcwidth-0.1.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6bfbdc2943631ec770ee781b35b8876fa7e283ff2273f944e2a9ae1f3df4ecdf"}, + {file = "cwcwidth-0.1.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb0103c7db8d86e260e016ff89f8f00ef5eb75c481abc346bfaa756da9f976b4"}, + {file = "cwcwidth-0.1.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3b7d38c552edf663bf13f32310f9fd6661070409807b1b5bf89917e2de804ab1"}, + {file = "cwcwidth-0.1.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1132be818498163a9208b9f4a28d759e08d3efeb885dfd10364434ccc7fa6a17"}, + {file = "cwcwidth-0.1.10-cp313-cp313-win32.whl", hash = "sha256:dcead1b7b60c99f8cda249feb8059e4da38587c34d0b5f3aa130f13c62c0ce35"}, + {file = "cwcwidth-0.1.10-cp313-cp313-win_amd64.whl", hash = "sha256:b6eafd16d3edfec9acfc3d7b8856313bc252e0eccd56fb088f51ceed14c1bbdd"}, + {file = "cwcwidth-0.1.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d8bd02fb0bc375479f1af8ff4715d0d9593095c2c72cd7f2a18841cd3657541"}, + {file = "cwcwidth-0.1.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c98ce6ddb32d7162695827ea96d9580866005eb3ed57c5cdbe83293690327a1"}, + {file = "cwcwidth-0.1.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9005da09777c769871d9c5f54f948585cf10bf49b0d176db3e22d922a3a3d77e"}, + {file = "cwcwidth-0.1.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a64a460e045108a7b9e93a6f06983d56435b2a091f3a7384848d7c32c23bcae0"}, + {file = "cwcwidth-0.1.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b0eeaed08aa37843724d5bc5ce63fc71b6341b48dddee6c2aca5500058e57be2"}, + {file = "cwcwidth-0.1.10-cp39-cp39-win32.whl", hash = "sha256:37cef6a2c1e201b4654079980e93d8849b11198a12898612818d63ab1f818d7e"}, + {file = "cwcwidth-0.1.10-cp39-cp39-win_amd64.whl", hash = "sha256:00fc0b477057b4af431632fbd6b16690add9aed435dbf89ccca9672173540763"}, + {file = "cwcwidth-0.1.10.tar.gz", hash = "sha256:7468760f72c1f4107be1b2b2854bc000401ea36a69daed36fb966a1e19a7a124"}, ] [[package]] name = "daphne" -version = "2.5.0" +version = "3.0.2" description = "Django ASGI (HTTP/WebSocket) server" optional = false -python-versions = "*" +python-versions = ">=3.6" files = [ - {file = "daphne-2.5.0-py2.py3-none-any.whl", hash = "sha256:aa64840015709bbc9daa3c4464a4a4d437937d6cda10a9b51e913eb319272553"}, - {file = "daphne-2.5.0.tar.gz", hash = "sha256:1ca46d7419103958bbc9576fb7ba3b25b053006e22058bc97084ee1a7d44f4ba"}, + {file = "daphne-3.0.2-py3-none-any.whl", hash = "sha256:a9af943c79717bc52fe64a3c236ae5d3adccc8b5be19c881b442d2c3db233393"}, + {file = "daphne-3.0.2.tar.gz", hash = "sha256:76ffae916ba3aa66b46996c14fa713e46004788167a4873d647544e750e0e99f"}, ] [package.dependencies] -asgiref = ">=3.2,<4.0" +asgiref = ">=3.2.10,<4" autobahn = ">=0.18" twisted = {version = ">=18.7", extras = ["tls"]} @@ -872,13 +877,13 @@ tests = ["hypothesis (==4.23)", "pytest (>=3.10,<4.0)", "pytest-asyncio (>=0.8,< [[package]] name = "decorator" -version = "5.1.1" +version = "5.2.1" description = "Decorators for Humans" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, - {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, + {file = "decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"}, + {file = "decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"}, ] [[package]] @@ -905,21 +910,22 @@ files = [ [[package]] name = "django" -version = "2.2.28" +version = "3.2" description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "Django-2.2.28-py3-none-any.whl", hash = "sha256:365429d07c1336eb42ba15aa79f45e1c13a0b04d5c21569e7d596696418a6a45"}, - {file = "Django-2.2.28.tar.gz", hash = "sha256:0200b657afbf1bc08003845ddda053c7641b9b24951e52acd51f6abda33a7413"}, + {file = "Django-3.2-py3-none-any.whl", hash = "sha256:0604e84c4fb698a5e53e5857b5aea945b2f19a18f25f10b8748dbdf935788927"}, + {file = "Django-3.2.tar.gz", hash = "sha256:21f0f9643722675976004eb683c55d33c05486f94506672df3d6a141546f389d"}, ] [package.dependencies] +asgiref = ">=3.3.2,<4" pytz = "*" sqlparse = ">=0.2.2" [package.extras] -argon2 = ["argon2-cffi (>=16.1.0)"] +argon2 = ["argon2-cffi (>=19.1.0)"] bcrypt = ["bcrypt"] [[package]] @@ -1008,17 +1014,17 @@ Django = ">=2.2" [[package]] name = "django-oauth-toolkit" -version = "1.0.0" +version = "1.2.0" description = "OAuth2 Provider for Django" optional = false python-versions = "*" files = [ - {file = "django_oauth_toolkit-1.0.0-py2.py3-none-any.whl", hash = "sha256:23ca6ffc06167cf9a1e94f98e7662b5b4724e2b9acc607373b8811ba62adbb23"}, + {file = "django_oauth_toolkit-1.2.0-py2.py3-none-any.whl", hash = "sha256:ad1b76275950ebbff708222cec57bbdb879f89bac7df6b9dee0f4b9db485c264"}, ] [package.dependencies] -django = ">=1.10" -oauthlib = ">=2.0.1" +django = ">=2.0" +oauthlib = ">=2.0.3" requests = ">=2.13.0" [[package]] @@ -1048,26 +1054,23 @@ redis = ">=3.0.0" [[package]] name = "django-storages" -version = "1.7.2" +version = "1.9.1" description = "Support for many storage backends in Django" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "django-storages-1.7.2.tar.gz", hash = "sha256:f3b3def96493d3ccde37b864cea376472baf6e8a596504b209278801c510b807"}, - {file = "django_storages-1.7.2-py2.py3-none-any.whl", hash = "sha256:87287b7ad2e789cd603373439994e1ac6f94d9dc2e5f8173d2a87aa3ed458bd9"}, + {file = "django-storages-1.9.1.tar.gz", hash = "sha256:a59e9923cbce7068792f75344ed7727021ee4ac20f227cf17297d0d03d141e91"}, + {file = "django_storages-1.9.1-py2.py3-none-any.whl", hash = "sha256:3103991c2ee8cef8a2ff096709973ffe7106183d211a79f22cf855f33533d924"}, ] [package.dependencies] -azure-storage-blob = {version = ">=1.3.1", optional = true, markers = "extra == \"azure\""} Django = ">=1.11" -google-cloud-storage = {version = ">=0.22.0", optional = true, markers = "extra == \"google\""} [package.extras] -azure = ["azure-storage-blob (>=1.3.1)"] -boto = ["boto (>=2.32.0)"] +azure = ["azure-storage-blob (>=1.3.1,<12.0.0)"] boto3 = ["boto3 (>=1.4.4)"] dropbox = ["dropbox (>=7.2.1)"] -google = ["google-cloud-storage (>=0.22.0)"] +google = ["google-cloud-storage (>=1.15.0)"] libcloud = ["apache-libcloud"] sftp = ["paramiko"] @@ -1087,29 +1090,31 @@ django = ">=1.11" [[package]] name = "djangorestframework" -version = "3.9.1" +version = "3.12.0" description = "Web APIs for Django, made easy." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.5" files = [ - {file = "djangorestframework-3.9.1-py2.py3-none-any.whl", hash = "sha256:a4138613b67e3a223be6c97f53b13d759c5b90d2b433bad670b8ebf95402075f"}, - {file = "djangorestframework-3.9.1.tar.gz", hash = "sha256:79c6efbb2514bc50cf25906d7c0a5cfead714c7af667ff4bd110312cd380ae66"}, + {file = "djangorestframework-3.12.0-py3-none-any.whl", hash = "sha256:7fb1c91a8f9aa5ccb39d1568925a6433659dacfc1af7ac757b293d6451ddb9e1"}, + {file = "djangorestframework-3.12.0.tar.gz", hash = "sha256:9d5b07a2dd29b4fb18da2e6a888051f34b286b3bfc1c3fe885a17e16e389c569"}, ] +[package.dependencies] +django = ">=2.2" + [[package]] name = "djangorestframework-csv" -version = "2.1.0" +version = "3.0.1" description = "CSV Tools for Django REST Framework" optional = false python-versions = "*" files = [ - {file = "djangorestframework-csv-2.1.0.tar.gz", hash = "sha256:2f008b20a44f2d3c37835ea5b5ddfe19f54394f07b9cb267c616a917a7f7e27c"}, + {file = "djangorestframework-csv-3.0.1.tar.gz", hash = "sha256:76ca3530c362e90ed46316002ea0b17e7e4e14c78240c787125d2c8f7c6c0174"}, + {file = "djangorestframework_csv-3.0.1-py3-none-any.whl", hash = "sha256:91484439b3eb555eb6496dcf25c9f8d12746533feb9eb35360f5cccee42dfd15"}, ] [package.dependencies] djangorestframework = "*" -six = "*" -unicodecsv = "*" [[package]] name = "docutils" @@ -1137,51 +1142,73 @@ files = [ [package.dependencies] djangorestframework = ">=3.8.1" +[[package]] +name = "drf-extra-fields" +version = "3.0.2" +description = "Additional fields for Django Rest Framework." +optional = false +python-versions = ">=3.5" +files = [ + {file = "drf-extra-fields-3.0.2.tar.gz", hash = "sha256:835a95a83dedb4806c13f65f2ea7df2482d4ec821ba2bf80cc8007376a71b6d1"}, +] + +[package.dependencies] +Django = ">=2.2" +djangorestframework = ">=3.9.1" + +[package.extras] +base64imagefield = ["Pillow (>=6.2.1)"] + [[package]] name = "drf-writable-nested" -version = "0.5.4" +version = "0.6.2" description = "Writable nested helpers for django-rest-framework's serializers" optional = false -python-versions = "*" +python-versions = ">=3.5" files = [ - {file = "drf-writable-nested-0.5.4.tar.gz", hash = "sha256:79839ac42a7bf393dcc03fbe4a8c51966c28f423aee8e2de1b27124fd2c4f94a"}, + {file = "drf_writable_nested-0.6.2-py3-none-any.whl", hash = "sha256:bb413286bd5ebf943460ba7c2dc177d572d6447d5287228cc763062c5a12e3d6"}, ] [[package]] -name = "drf-yasg" -version = "1.11.0" -description = "Automated generation of real Swagger/OpenAPI 2.0 schemas from Django Rest Framework code." +name = "drf-yasg2" +version = "1.19.4" +description = "Automated generation of real Swagger/OpenAPI 2.0 schemas from Django Rest Framework code" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = "*" files = [ - {file = "drf-yasg-1.11.0.tar.gz", hash = "sha256:24a02bbf56361ae0e304744f9c4aa96544270decd9d79b37d10dfd6dd04e5f22"}, - {file = "drf_yasg-1.11.0-py2.py3-none-any.whl", hash = "sha256:b07192a6697ced6da49c5b016f1805960b0a7a1682fb21e86045a6bb572ffa99"}, + {file = "drf_yasg2-1.19.4-py3-none-any.whl", hash = "sha256:75e661ca5cf15eb44fcfab408c7b864f87c20794f564aa08b3a31817a857f19d"}, + {file = "drf_yasg2-1.19.4.tar.gz", hash = "sha256:7037a8041eb5d1073fa504a284fc889685f93d0bfd008a963db1b366db786734"}, ] [package.dependencies] coreapi = ">=2.3.3" coreschema = ">=0.0.4" -Django = ">=1.11.7" -djangorestframework = ">=3.7.7" -flex = {version = ">=6.11.1", optional = true, markers = "extra == \"validation\""} +django = ">=2.2.0" +djangorestframework = ">=3.8.0" inflection = ">=0.3.1" -"ruamel.yaml" = ">=0.15.34" -six = ">=1.10.0" -swagger-spec-validator = {version = ">=2.1.0", optional = true, markers = "extra == \"validation\""} -uritemplate = ">=3.0.0" +packaging = ">=18.0" +"ruamel.yaml" = ">=0.16.12" +six = ">=1.15.0" +uritemplate = ">=3.0.1" [package.extras] -validation = ["flex (>=6.11.1)", "swagger-spec-validator (>=2.1.0)"] +dist = ["bump2version", "wheel"] +docs = ["Pillow (>=4.3.0)", "Sphinx (>=1.7.0)", "djangorestframework-camel-case (>=0.2.0)", "readme-renderer[md] (>=24.0)", "sphinx-rtd-theme (>=0.2.4)", "twine (>=1.12.1)"] +format = ["autoflake (>=1.4.0)", "black (>=20.8.0)", "isort (>=4.2.0)"] +heroku = ["dj-database-url (>=0.4.2)", "gunicorn (>=19.7.1)", "psycopg2 (>=2.7.3)", "whitenoise (>=3.3.1)"] +lint = ["flake8 (>=3.5.0)"] +tests = ["Pillow (>=4.3.0)", "dj-database-url (>=0.4.2)", "django-cors-headers (>=3.0.2)", "django-filter (>=1.1.0)", "django-oauth-toolkit (>=1.3.2)", "djangorestframework-camel-case (>=1.0.3)", "djangorestframework-recursive (>=0.1.2)", "pytest (>=4.6.11)", "pytest-django (>=3.10.0)", "tox (>=3.3.0)", "user-agents (>=1.1.0)"] +validation = ["swagger-spec-validator (>=2.1.0)"] [[package]] name = "executing" -version = "2.1.0" +version = "2.2.1" description = "Get the currently executing AST node of a frame, and other information" optional = false python-versions = ">=3.8" files = [ - {file = "executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf"}, - {file = "executing-2.1.0.tar.gz", hash = "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab"}, + {file = "executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017"}, + {file = "executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4"}, ] [package.extras] @@ -1203,18 +1230,17 @@ Faker = ">=0.7.0" [[package]] name = "faker" -version = "33.1.0" +version = "37.8.0" description = "Faker is a Python package that generates fake data for you." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "Faker-33.1.0-py3-none-any.whl", hash = "sha256:d30c5f0e2796b8970de68978365247657486eb0311c5abe88d0b895b68dff05d"}, - {file = "faker-33.1.0.tar.gz", hash = "sha256:1c925fc0e86a51fc46648b504078c88d0cd48da1da2595c4e712841cab43a1e4"}, + {file = "faker-37.8.0-py3-none-any.whl", hash = "sha256:b08233118824423b5fc239f7dd51f145e7018082b4164f8da6a9994e1f1ae793"}, + {file = "faker-37.8.0.tar.gz", hash = "sha256:090bb5abbec2b30949a95ce1ba6b20d1d0ed222883d63483a0d4be4a970d6fb8"}, ] [package.dependencies] -python-dateutil = ">=2.4" -typing-extensions = "*" +tzdata = "*" [[package]] name = "flake8" @@ -1253,253 +1279,72 @@ six = ">=1.7.3" strict-rfc3339 = ">=0.7" validate-email = ">=1.2" -[[package]] -name = "google-api-core" -version = "2.23.0" -description = "Google API client core library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google_api_core-2.23.0-py3-none-any.whl", hash = "sha256:c20100d4c4c41070cf365f1d8ddf5365915291b5eb11b83829fbd1c999b5122f"}, - {file = "google_api_core-2.23.0.tar.gz", hash = "sha256:2ceb087315e6af43f256704b871d99326b1f12a9d6ce99beaedec99ba26a0ace"}, -] - -[package.dependencies] -google-auth = ">=2.14.1,<3.0.dev0" -googleapis-common-protos = ">=1.56.2,<2.0.dev0" -proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" -requests = ">=2.18.0,<3.0.0.dev0" - -[package.extras] -async-rest = ["google-auth[aiohttp] (>=2.35.0,<3.0.dev0)"] -grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] -grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] -grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] - -[[package]] -name = "google-auth" -version = "2.36.0" -description = "Google Authentication Library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google_auth-2.36.0-py2.py3-none-any.whl", hash = "sha256:51a15d47028b66fd36e5c64a82d2d57480075bccc7da37cde257fc94177a61fb"}, - {file = "google_auth-2.36.0.tar.gz", hash = "sha256:545e9618f2df0bcbb7dcbc45a546485b1212624716975a1ea5ae8149ce769ab1"}, -] - -[package.dependencies] -cachetools = ">=2.0.0,<6.0" -pyasn1-modules = ">=0.2.1" -rsa = ">=3.1.4,<5" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] -enterprise-cert = ["cryptography", "pyopenssl"] -pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] -reauth = ["pyu2f (>=0.1.5)"] -requests = ["requests (>=2.20.0,<3.0.0.dev0)"] - -[[package]] -name = "google-cloud-core" -version = "2.4.1" -description = "Google Cloud API client core library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google-cloud-core-2.4.1.tar.gz", hash = "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073"}, - {file = "google_cloud_core-2.4.1-py2.py3-none-any.whl", hash = "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61"}, -] - -[package.dependencies] -google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.25.0,<3.0dev" - -[package.extras] -grpc = ["grpcio (>=1.38.0,<2.0dev)", "grpcio-status (>=1.38.0,<2.0.dev0)"] - -[[package]] -name = "google-cloud-storage" -version = "2.18.2" -description = "Google Cloud Storage API client library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google_cloud_storage-2.18.2-py2.py3-none-any.whl", hash = "sha256:97a4d45c368b7d401ed48c4fdfe86e1e1cb96401c9e199e419d289e2c0370166"}, - {file = "google_cloud_storage-2.18.2.tar.gz", hash = "sha256:aaf7acd70cdad9f274d29332673fcab98708d0e1f4dceb5a5356aaef06af4d99"}, -] - -[package.dependencies] -google-api-core = ">=2.15.0,<3.0.0dev" -google-auth = ">=2.26.1,<3.0dev" -google-cloud-core = ">=2.3.0,<3.0dev" -google-crc32c = ">=1.0,<2.0dev" -google-resumable-media = ">=2.7.2" -requests = ">=2.18.0,<3.0.0dev" - -[package.extras] -protobuf = ["protobuf (<6.0.0dev)"] -tracing = ["opentelemetry-api (>=1.1.0)"] - -[[package]] -name = "google-crc32c" -version = "1.6.0" -description = "A python wrapper of the C library 'Google CRC32C'" -optional = false -python-versions = ">=3.9" -files = [ - {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5bcc90b34df28a4b38653c36bb5ada35671ad105c99cfe915fb5bed7ad6924aa"}, - {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d9e9913f7bd69e093b81da4535ce27af842e7bf371cde42d1ae9e9bd382dc0e9"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a184243544811e4a50d345838a883733461e67578959ac59964e43cca2c791e7"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:236c87a46cdf06384f614e9092b82c05f81bd34b80248021f729396a78e55d7e"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebab974b1687509e5c973b5c4b8b146683e101e102e17a86bd196ecaa4d099fc"}, - {file = "google_crc32c-1.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:50cf2a96da226dcbff8671233ecf37bf6e95de98b2a2ebadbfdf455e6d05df42"}, - {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f7a1fc29803712f80879b0806cb83ab24ce62fc8daf0569f2204a0cfd7f68ed4"}, - {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:40b05ab32a5067525670880eb5d169529089a26fe35dce8891127aeddc1950e8"}, - {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e4b426c3702f3cd23b933436487eb34e01e00327fac20c9aebb68ccf34117d"}, - {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51c4f54dd8c6dfeb58d1df5e4f7f97df8abf17a36626a217f169893d1d7f3e9f"}, - {file = "google_crc32c-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:bb8b3c75bd157010459b15222c3fd30577042a7060e29d42dabce449c087f2b3"}, - {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ed767bf4ba90104c1216b68111613f0d5926fb3780660ea1198fc469af410e9d"}, - {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:62f6d4a29fea082ac4a3c9be5e415218255cf11684ac6ef5488eea0c9132689b"}, - {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c87d98c7c4a69066fd31701c4e10d178a648c2cac3452e62c6b24dc51f9fcc00"}, - {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd5e7d2445d1a958c266bfa5d04c39932dc54093fa391736dbfdb0f1929c1fb3"}, - {file = "google_crc32c-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:7aec8e88a3583515f9e0957fe4f5f6d8d4997e36d0f61624e70469771584c760"}, - {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:e2806553238cd076f0a55bddab37a532b53580e699ed8e5606d0de1f856b5205"}, - {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:bb0966e1c50d0ef5bc743312cc730b533491d60585a9a08f897274e57c3f70e0"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:386122eeaaa76951a8196310432c5b0ef3b53590ef4c317ec7588ec554fec5d2"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2952396dc604544ea7476b33fe87faedc24d666fb0c2d5ac971a2b9576ab871"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35834855408429cecf495cac67ccbab802de269e948e27478b1e47dfb6465e57"}, - {file = "google_crc32c-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:d8797406499f28b5ef791f339594b0b5fdedf54e203b5066675c406ba69d705c"}, - {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48abd62ca76a2cbe034542ed1b6aee851b6f28aaca4e6551b5599b6f3ef175cc"}, - {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18e311c64008f1f1379158158bb3f0c8d72635b9eb4f9545f8cf990c5668e59d"}, - {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05e2d8c9a2f853ff116db9706b4a27350587f341eda835f46db3c0a8c8ce2f24"}, - {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ca8145b060679ec9176e6de4f89b07363d6805bd4760631ef254905503598d"}, - {file = "google_crc32c-1.6.0.tar.gz", hash = "sha256:6eceb6ad197656a1ff49ebfbbfa870678c75be4344feb35ac1edf694309413dc"}, -] - -[package.extras] -testing = ["pytest"] - -[[package]] -name = "google-resumable-media" -version = "2.7.2" -description = "Utilities for Google Media Downloads and Resumable Uploads" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa"}, - {file = "google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0"}, -] - -[package.dependencies] -google-crc32c = ">=1.0,<2.0dev" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "google-auth (>=1.22.0,<2.0dev)"] -requests = ["requests (>=2.18.0,<3.0.0dev)"] - -[[package]] -name = "googleapis-common-protos" -version = "1.66.0" -description = "Common protobufs used in Google APIs" -optional = false -python-versions = ">=3.7" -files = [ - {file = "googleapis_common_protos-1.66.0-py2.py3-none-any.whl", hash = "sha256:d7abcd75fabb2e0ec9f74466401f6c119a0b498e27370e9be4c94cb7e382b8ed"}, - {file = "googleapis_common_protos-1.66.0.tar.gz", hash = "sha256:c3e7b33d15fdca5374cc0a7346dd92ffa847425cc4ea941d970f13680052ec8c"}, -] - -[package.dependencies] -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] - [[package]] name = "greenlet" -version = "3.1.1" +version = "3.2.4" description = "Lightweight in-process concurrent programming" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617"}, - {file = "greenlet-3.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7"}, - {file = "greenlet-3.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6"}, - {file = "greenlet-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80"}, - {file = "greenlet-3.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a"}, - {file = "greenlet-3.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511"}, - {file = "greenlet-3.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395"}, - {file = "greenlet-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39"}, - {file = "greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9"}, - {file = "greenlet-3.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0"}, - {file = "greenlet-3.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942"}, - {file = "greenlet-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01"}, - {file = "greenlet-3.1.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e"}, - {file = "greenlet-3.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1"}, - {file = "greenlet-3.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c"}, - {file = "greenlet-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822"}, - {file = "greenlet-3.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01"}, - {file = "greenlet-3.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de"}, - {file = "greenlet-3.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa"}, - {file = "greenlet-3.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af"}, - {file = "greenlet-3.1.1-cp37-cp37m-win32.whl", hash = "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798"}, - {file = "greenlet-3.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef"}, - {file = "greenlet-3.1.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1"}, - {file = "greenlet-3.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd"}, - {file = "greenlet-3.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7"}, - {file = "greenlet-3.1.1-cp38-cp38-win32.whl", hash = "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef"}, - {file = "greenlet-3.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d"}, - {file = "greenlet-3.1.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c"}, - {file = "greenlet-3.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e"}, - {file = "greenlet-3.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e"}, - {file = "greenlet-3.1.1-cp39-cp39-win32.whl", hash = "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c"}, - {file = "greenlet-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22"}, - {file = "greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467"}, + {file = "greenlet-3.2.4-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:8c68325b0d0acf8d91dde4e6f930967dd52a5302cd4062932a6b2e7c2969f47c"}, + {file = "greenlet-3.2.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:94385f101946790ae13da500603491f04a76b6e4c059dab271b3ce2e283b2590"}, + {file = "greenlet-3.2.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f10fd42b5ee276335863712fa3da6608e93f70629c631bf77145021600abc23c"}, + {file = "greenlet-3.2.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c8c9e331e58180d0d83c5b7999255721b725913ff6bc6cf39fa2a45841a4fd4b"}, + {file = "greenlet-3.2.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58b97143c9cc7b86fc458f215bd0932f1757ce649e05b640fea2e79b54cedb31"}, + {file = "greenlet-3.2.4-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2ca18a03a8cfb5b25bc1cbe20f3d9a4c80d8c3b13ba3df49ac3961af0b1018d"}, + {file = "greenlet-3.2.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9fe0a28a7b952a21e2c062cd5756d34354117796c6d9215a87f55e38d15402c5"}, + {file = "greenlet-3.2.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8854167e06950ca75b898b104b63cc646573aa5fef1353d4508ecdd1ee76254f"}, + {file = "greenlet-3.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:73f49b5368b5359d04e18d15828eecc1806033db5233397748f4ca813ff1056c"}, + {file = "greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2"}, + {file = "greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246"}, + {file = "greenlet-3.2.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94abf90142c2a18151632371140b3dba4dee031633fe614cb592dbb6c9e17bc3"}, + {file = "greenlet-3.2.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:4d1378601b85e2e5171b99be8d2dc85f594c79967599328f95c1dc1a40f1c633"}, + {file = "greenlet-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0db5594dce18db94f7d1650d7489909b57afde4c580806b8d9203b6e79cdc079"}, + {file = "greenlet-3.2.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8"}, + {file = "greenlet-3.2.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52"}, + {file = "greenlet-3.2.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:55e9c5affaa6775e2c6b67659f3a71684de4c549b3dd9afca3bc773533d284fa"}, + {file = "greenlet-3.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:9c40adce87eaa9ddb593ccb0fa6a07caf34015a29bf8d344811665b573138db9"}, + {file = "greenlet-3.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd"}, + {file = "greenlet-3.2.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb"}, + {file = "greenlet-3.2.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f28588772bb5fb869a8eb331374ec06f24a83a9c25bfa1f38b6993afe9c1e968"}, + {file = "greenlet-3.2.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:5c9320971821a7cb77cfab8d956fa8e39cd07ca44b6070db358ceb7f8797c8c9"}, + {file = "greenlet-3.2.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c60a6d84229b271d44b70fb6e5fa23781abb5d742af7b808ae3f6efd7c9c60f6"}, + {file = "greenlet-3.2.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0"}, + {file = "greenlet-3.2.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0"}, + {file = "greenlet-3.2.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20fb936b4652b6e307b8f347665e2c615540d4b42b3b4c8a321d8286da7e520f"}, + {file = "greenlet-3.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:a7d4e128405eea3814a12cc2605e0e6aedb4035bf32697f72deca74de4105e02"}, + {file = "greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31"}, + {file = "greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945"}, + {file = "greenlet-3.2.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:710638eb93b1fa52823aa91bf75326f9ecdfd5e0466f00789246a5280f4ba0fc"}, + {file = "greenlet-3.2.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c5111ccdc9c88f423426df3fd1811bfc40ed66264d35aa373420a34377efc98a"}, + {file = "greenlet-3.2.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76383238584e9711e20ebe14db6c88ddcedc1829a9ad31a584389463b5aa504"}, + {file = "greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671"}, + {file = "greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b"}, + {file = "greenlet-3.2.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d25c5091190f2dc0eaa3f950252122edbbadbb682aa7b1ef2f8af0f8c0afefae"}, + {file = "greenlet-3.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:554b03b6e73aaabec3745364d6239e9e012d64c68ccd0b8430c64ccc14939a8b"}, + {file = "greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0"}, + {file = "greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f"}, + {file = "greenlet-3.2.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c17b6b34111ea72fc5a4e4beec9711d2226285f0386ea83477cbb97c30a3f3a5"}, + {file = "greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1"}, + {file = "greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735"}, + {file = "greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337"}, + {file = "greenlet-3.2.4-cp314-cp314-win_amd64.whl", hash = "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01"}, + {file = "greenlet-3.2.4-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:b6a7c19cf0d2742d0809a4c05975db036fdff50cd294a93632d6a310bf9ac02c"}, + {file = "greenlet-3.2.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:27890167f55d2387576d1f41d9487ef171849ea0359ce1510ca6e06c8bece11d"}, + {file = "greenlet-3.2.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:18d9260df2b5fbf41ae5139e1be4e796d99655f023a636cd0e11e6406cca7d58"}, + {file = "greenlet-3.2.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:671df96c1f23c4a0d4077a325483c1503c96a1b7d9db26592ae770daa41233d4"}, + {file = "greenlet-3.2.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:16458c245a38991aa19676900d48bd1a6f2ce3e16595051a4db9d012154e8433"}, + {file = "greenlet-3.2.4-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9913f1a30e4526f432991f89ae263459b1c64d1608c0d22a5c79c287b3c70df"}, + {file = "greenlet-3.2.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b90654e092f928f110e0007f572007c9727b5265f7632c2fa7415b4689351594"}, + {file = "greenlet-3.2.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:81701fd84f26330f0d5f4944d4e92e61afe6319dcd9775e39396e39d7c3e5f98"}, + {file = "greenlet-3.2.4-cp39-cp39-win32.whl", hash = "sha256:65458b409c1ed459ea899e939f0e1cdb14f58dbc803f2f93c5eab5694d32671b"}, + {file = "greenlet-3.2.4-cp39-cp39-win_amd64.whl", hash = "sha256:d2e685ade4dafd447ede19c31277a224a239a0a1a4eca4e6390efedf20260cfb"}, + {file = "greenlet-3.2.4.tar.gz", hash = "sha256:0dca0d95ff849f9a364385f36ab49f50065d76964944638be9691e1832e9f86d"}, ] [package.extras] docs = ["Sphinx", "furo"] -test = ["objgraph", "psutil"] +test = ["objgraph", "psutil", "setuptools"] [[package]] name = "gunicorn" @@ -1524,13 +1369,13 @@ tornado = ["tornado (>=0.2)"] [[package]] name = "h11" -version = "0.14.0" +version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, ] [[package]] @@ -1590,13 +1435,13 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 [[package]] name = "importlib-resources" -version = "6.4.5" +version = "6.5.2" description = "Read resources from Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "importlib_resources-6.4.5-py3-none-any.whl", hash = "sha256:ac29d5f956f01d5e4bb63102a5a19957f1b9175e45649977264a1416783bb717"}, - {file = "importlib_resources-6.4.5.tar.gz", hash = "sha256:980862a1d16c9e147a59603677fa2aa5fd82b87f223b6cb870695bcfce830065"}, + {file = "importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec"}, + {file = "importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c"}, ] [package.dependencies] @@ -1641,13 +1486,13 @@ files = [ [[package]] name = "iniconfig" -version = "2.0.0" +version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] [[package]] @@ -1788,13 +1633,13 @@ files = [ [[package]] name = "jsonschema" -version = "4.23.0" +version = "4.25.1" description = "An implementation of JSON Schema validation for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, - {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, + {file = "jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63"}, + {file = "jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85"}, ] [package.dependencies] @@ -1805,17 +1650,17 @@ rpds-py = ">=0.7.1" [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "rfc3987-syntax (>=1.1.0)", "uri-template", "webcolors (>=24.6.0)"] [[package]] name = "jsonschema-specifications" -version = "2024.10.1" +version = "2025.9.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.9" files = [ - {file = "jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf"}, - {file = "jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272"}, + {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, + {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, ] [package.dependencies] @@ -1959,97 +1804,92 @@ files = [ [[package]] name = "msgpack" -version = "1.1.0" +version = "1.1.1" description = "MessagePack serializer" optional = false python-versions = ">=3.8" files = [ - {file = "msgpack-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd"}, - {file = "msgpack-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d"}, - {file = "msgpack-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5"}, - {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5"}, - {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e"}, - {file = "msgpack-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b"}, - {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f"}, - {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68"}, - {file = "msgpack-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b"}, - {file = "msgpack-1.1.0-cp310-cp310-win32.whl", hash = "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044"}, - {file = "msgpack-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f"}, - {file = "msgpack-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7"}, - {file = "msgpack-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa"}, - {file = "msgpack-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701"}, - {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6"}, - {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59"}, - {file = "msgpack-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0"}, - {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e"}, - {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6"}, - {file = "msgpack-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5"}, - {file = "msgpack-1.1.0-cp311-cp311-win32.whl", hash = "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88"}, - {file = "msgpack-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788"}, - {file = "msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d"}, - {file = "msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2"}, - {file = "msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420"}, - {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2"}, - {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39"}, - {file = "msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f"}, - {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247"}, - {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c"}, - {file = "msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b"}, - {file = "msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b"}, - {file = "msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f"}, - {file = "msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf"}, - {file = "msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330"}, - {file = "msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734"}, - {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e"}, - {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca"}, - {file = "msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915"}, - {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d"}, - {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434"}, - {file = "msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c"}, - {file = "msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc"}, - {file = "msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f"}, - {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c40ffa9a15d74e05ba1fe2681ea33b9caffd886675412612d93ab17b58ea2fec"}, - {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1ba6136e650898082d9d5a5217d5906d1e138024f836ff48691784bbe1adf96"}, - {file = "msgpack-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0856a2b7e8dcb874be44fea031d22e5b3a19121be92a1e098f46068a11b0870"}, - {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:471e27a5787a2e3f974ba023f9e265a8c7cfd373632247deb225617e3100a3c7"}, - {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:646afc8102935a388ffc3914b336d22d1c2d6209c773f3eb5dd4d6d3b6f8c1cb"}, - {file = "msgpack-1.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:13599f8829cfbe0158f6456374e9eea9f44eee08076291771d8ae93eda56607f"}, - {file = "msgpack-1.1.0-cp38-cp38-win32.whl", hash = "sha256:8a84efb768fb968381e525eeeb3d92857e4985aacc39f3c47ffd00eb4509315b"}, - {file = "msgpack-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:879a7b7b0ad82481c52d3c7eb99bf6f0645dbdec5134a4bddbd16f3506947feb"}, - {file = "msgpack-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:53258eeb7a80fc46f62fd59c876957a2d0e15e6449a9e71842b6d24419d88ca1"}, - {file = "msgpack-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7e7b853bbc44fb03fbdba34feb4bd414322180135e2cb5164f20ce1c9795ee48"}, - {file = "msgpack-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3e9b4936df53b970513eac1758f3882c88658a220b58dcc1e39606dccaaf01c"}, - {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46c34e99110762a76e3911fc923222472c9d681f1094096ac4102c18319e6468"}, - {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a706d1e74dd3dea05cb54580d9bd8b2880e9264856ce5068027eed09680aa74"}, - {file = "msgpack-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:534480ee5690ab3cbed89d4c8971a5c631b69a8c0883ecfea96c19118510c846"}, - {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8cf9e8c3a2153934a23ac160cc4cba0ec035f6867c8013cc6077a79823370346"}, - {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3180065ec2abbe13a4ad37688b61b99d7f9e012a535b930e0e683ad6bc30155b"}, - {file = "msgpack-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5a91481a3cc573ac8c0d9aace09345d989dc4a0202b7fcb312c88c26d4e71a8"}, - {file = "msgpack-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f80bc7d47f76089633763f952e67f8214cb7b3ee6bfa489b3cb6a84cfac114cd"}, - {file = "msgpack-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325"}, - {file = "msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e"}, + {file = "msgpack-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:353b6fc0c36fde68b661a12949d7d49f8f51ff5fa019c1e47c87c4ff34b080ed"}, + {file = "msgpack-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:79c408fcf76a958491b4e3b103d1c417044544b68e96d06432a189b43d1215c8"}, + {file = "msgpack-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78426096939c2c7482bf31ef15ca219a9e24460289c00dd0b94411040bb73ad2"}, + {file = "msgpack-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b17ba27727a36cb73aabacaa44b13090feb88a01d012c0f4be70c00f75048b4"}, + {file = "msgpack-1.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a17ac1ea6ec3c7687d70201cfda3b1e8061466f28f686c24f627cae4ea8efd0"}, + {file = "msgpack-1.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:88d1e966c9235c1d4e2afac21ca83933ba59537e2e2727a999bf3f515ca2af26"}, + {file = "msgpack-1.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f6d58656842e1b2ddbe07f43f56b10a60f2ba5826164910968f5933e5178af75"}, + {file = "msgpack-1.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:96decdfc4adcbc087f5ea7ebdcfd3dee9a13358cae6e81d54be962efc38f6338"}, + {file = "msgpack-1.1.1-cp310-cp310-win32.whl", hash = "sha256:6640fd979ca9a212e4bcdf6eb74051ade2c690b862b679bfcb60ae46e6dc4bfd"}, + {file = "msgpack-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:8b65b53204fe1bd037c40c4148d00ef918eb2108d24c9aaa20bc31f9810ce0a8"}, + {file = "msgpack-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:71ef05c1726884e44f8b1d1773604ab5d4d17729d8491403a705e649116c9558"}, + {file = "msgpack-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:36043272c6aede309d29d56851f8841ba907a1a3d04435e43e8a19928e243c1d"}, + {file = "msgpack-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a32747b1b39c3ac27d0670122b57e6e57f28eefb725e0b625618d1b59bf9d1e0"}, + {file = "msgpack-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a8b10fdb84a43e50d38057b06901ec9da52baac6983d3f709d8507f3889d43f"}, + {file = "msgpack-1.1.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba0c325c3f485dc54ec298d8b024e134acf07c10d494ffa24373bea729acf704"}, + {file = "msgpack-1.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:88daaf7d146e48ec71212ce21109b66e06a98e5e44dca47d853cbfe171d6c8d2"}, + {file = "msgpack-1.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8b55ea20dc59b181d3f47103f113e6f28a5e1c89fd5b67b9140edb442ab67f2"}, + {file = "msgpack-1.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4a28e8072ae9779f20427af07f53bbb8b4aa81151054e882aee333b158da8752"}, + {file = "msgpack-1.1.1-cp311-cp311-win32.whl", hash = "sha256:7da8831f9a0fdb526621ba09a281fadc58ea12701bc709e7b8cbc362feabc295"}, + {file = "msgpack-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:5fd1b58e1431008a57247d6e7cc4faa41c3607e8e7d4aaf81f7c29ea013cb458"}, + {file = "msgpack-1.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae497b11f4c21558d95de9f64fff7053544f4d1a17731c866143ed6bb4591238"}, + {file = "msgpack-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:33be9ab121df9b6b461ff91baac6f2731f83d9b27ed948c5b9d1978ae28bf157"}, + {file = "msgpack-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f64ae8fe7ffba251fecb8408540c34ee9df1c26674c50c4544d72dbf792e5ce"}, + {file = "msgpack-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a494554874691720ba5891c9b0b39474ba43ffb1aaf32a5dac874effb1619e1a"}, + {file = "msgpack-1.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb643284ab0ed26f6957d969fe0dd8bb17beb567beb8998140b5e38a90974f6c"}, + {file = "msgpack-1.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d275a9e3c81b1093c060c3837e580c37f47c51eca031f7b5fb76f7b8470f5f9b"}, + {file = "msgpack-1.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4fd6b577e4541676e0cc9ddc1709d25014d3ad9a66caa19962c4f5de30fc09ef"}, + {file = "msgpack-1.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb29aaa613c0a1c40d1af111abf025f1732cab333f96f285d6a93b934738a68a"}, + {file = "msgpack-1.1.1-cp312-cp312-win32.whl", hash = "sha256:870b9a626280c86cff9c576ec0d9cbcc54a1e5ebda9cd26dab12baf41fee218c"}, + {file = "msgpack-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:5692095123007180dca3e788bb4c399cc26626da51629a31d40207cb262e67f4"}, + {file = "msgpack-1.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3765afa6bd4832fc11c3749be4ba4b69a0e8d7b728f78e68120a157a4c5d41f0"}, + {file = "msgpack-1.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8ddb2bcfd1a8b9e431c8d6f4f7db0773084e107730ecf3472f1dfe9ad583f3d9"}, + {file = "msgpack-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:196a736f0526a03653d829d7d4c5500a97eea3648aebfd4b6743875f28aa2af8"}, + {file = "msgpack-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d592d06e3cc2f537ceeeb23d38799c6ad83255289bb84c2e5792e5a8dea268a"}, + {file = "msgpack-1.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4df2311b0ce24f06ba253fda361f938dfecd7b961576f9be3f3fbd60e87130ac"}, + {file = "msgpack-1.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e4141c5a32b5e37905b5940aacbc59739f036930367d7acce7a64e4dec1f5e0b"}, + {file = "msgpack-1.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b1ce7f41670c5a69e1389420436f41385b1aa2504c3b0c30620764b15dded2e7"}, + {file = "msgpack-1.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4147151acabb9caed4e474c3344181e91ff7a388b888f1e19ea04f7e73dc7ad5"}, + {file = "msgpack-1.1.1-cp313-cp313-win32.whl", hash = "sha256:500e85823a27d6d9bba1d057c871b4210c1dd6fb01fbb764e37e4e8847376323"}, + {file = "msgpack-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:6d489fba546295983abd142812bda76b57e33d0b9f5d5b71c09a583285506f69"}, + {file = "msgpack-1.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bba1be28247e68994355e028dcd668316db30c1f758d3241a7b903ac78dcd285"}, + {file = "msgpack-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8f93dcddb243159c9e4109c9750ba5b335ab8d48d9522c5308cd05d7e3ce600"}, + {file = "msgpack-1.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fbbc0b906a24038c9958a1ba7ae0918ad35b06cb449d398b76a7d08470b0ed9"}, + {file = "msgpack-1.1.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:61e35a55a546a1690d9d09effaa436c25ae6130573b6ee9829c37ef0f18d5e78"}, + {file = "msgpack-1.1.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:1abfc6e949b352dadf4bce0eb78023212ec5ac42f6abfd469ce91d783c149c2a"}, + {file = "msgpack-1.1.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:996f2609ddf0142daba4cefd767d6db26958aac8439ee41db9cc0db9f4c4c3a6"}, + {file = "msgpack-1.1.1-cp38-cp38-win32.whl", hash = "sha256:4d3237b224b930d58e9d83c81c0dba7aacc20fcc2f89c1e5423aa0529a4cd142"}, + {file = "msgpack-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:da8f41e602574ece93dbbda1fab24650d6bf2a24089f9e9dbb4f5730ec1e58ad"}, + {file = "msgpack-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5be6b6bc52fad84d010cb45433720327ce886009d862f46b26d4d154001994b"}, + {file = "msgpack-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a89cd8c087ea67e64844287ea52888239cbd2940884eafd2dcd25754fb72232"}, + {file = "msgpack-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d75f3807a9900a7d575d8d6674a3a47e9f227e8716256f35bc6f03fc597ffbf"}, + {file = "msgpack-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d182dac0221eb8faef2e6f44701812b467c02674a322c739355c39e94730cdbf"}, + {file = "msgpack-1.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b13fe0fb4aac1aa5320cd693b297fe6fdef0e7bea5518cbc2dd5299f873ae90"}, + {file = "msgpack-1.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:435807eeb1bc791ceb3247d13c79868deb22184e1fc4224808750f0d7d1affc1"}, + {file = "msgpack-1.1.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4835d17af722609a45e16037bb1d4d78b7bdf19d6c0128116d178956618c4e88"}, + {file = "msgpack-1.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a8ef6e342c137888ebbfb233e02b8fbd689bb5b5fcc59b34711ac47ebd504478"}, + {file = "msgpack-1.1.1-cp39-cp39-win32.whl", hash = "sha256:61abccf9de335d9efd149e2fff97ed5974f2481b3353772e8e2dd3402ba2bd57"}, + {file = "msgpack-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:40eae974c873b2992fd36424a5d9407f93e97656d999f43fca9d29f820899084"}, + {file = "msgpack-1.1.1.tar.gz", hash = "sha256:77b79ce34a2bdab2594f490c8e80dd62a02d650b91a75159a63ec413b8d104cd"}, ] [[package]] name = "mypy-extensions" -version = "1.0.0" +version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, + {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, + {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, ] [[package]] name = "oauthlib" -version = "3.2.2" +version = "3.3.1" description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, - {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, + {file = "oauthlib-3.3.1-py3-none-any.whl", hash = "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1"}, + {file = "oauthlib-3.3.1.tar.gz", hash = "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9"}, ] [package.extras] @@ -2073,24 +1913,24 @@ pyyaml = "*" [[package]] name = "packaging" -version = "24.2" +version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, - {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, ] [[package]] name = "parso" -version = "0.8.4" +version = "0.8.5" description = "A Python Parser" optional = false python-versions = ">=3.6" files = [ - {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, - {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, + {file = "parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887"}, + {file = "parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a"}, ] [package.extras] @@ -2221,19 +2061,19 @@ xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "4.3.6" +version = "4.4.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, - {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, + {file = "platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85"}, + {file = "platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.11.2)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] [[package]] name = "pluggy" @@ -2251,55 +2091,18 @@ dev = ["pre-commit", "tox"] [[package]] name = "prompt-toolkit" -version = "3.0.48" +version = "3.0.52" description = "Library for building powerful interactive command lines in Python" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8" files = [ - {file = "prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e"}, - {file = "prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90"}, + {file = "prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955"}, + {file = "prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855"}, ] [package.dependencies] wcwidth = "*" -[[package]] -name = "proto-plus" -version = "1.25.0" -description = "Beautiful, Pythonic protocol buffers." -optional = false -python-versions = ">=3.7" -files = [ - {file = "proto_plus-1.25.0-py3-none-any.whl", hash = "sha256:c91fc4a65074ade8e458e95ef8bac34d4008daa7cce4a12d6707066fca648961"}, - {file = "proto_plus-1.25.0.tar.gz", hash = "sha256:fbb17f57f7bd05a68b7707e745e26528b0b3c34e378db91eef93912c54982d91"}, -] - -[package.dependencies] -protobuf = ">=3.19.0,<6.0.0dev" - -[package.extras] -testing = ["google-api-core (>=1.31.5)"] - -[[package]] -name = "protobuf" -version = "5.29.0" -description = "" -optional = false -python-versions = ">=3.8" -files = [ - {file = "protobuf-5.29.0-cp310-abi3-win32.whl", hash = "sha256:ea7fb379b257911c8c020688d455e8f74efd2f734b72dc1ea4b4d7e9fd1326f2"}, - {file = "protobuf-5.29.0-cp310-abi3-win_amd64.whl", hash = "sha256:34a90cf30c908f47f40ebea7811f743d360e202b6f10d40c02529ebd84afc069"}, - {file = "protobuf-5.29.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:c931c61d0cc143a2e756b1e7f8197a508de5365efd40f83c907a9febf36e6b43"}, - {file = "protobuf-5.29.0-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:85286a47caf63b34fa92fdc1fd98b649a8895db595cfa746c5286eeae890a0b1"}, - {file = "protobuf-5.29.0-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:0d10091d6d03537c3f902279fcf11e95372bdd36a79556311da0487455791b20"}, - {file = "protobuf-5.29.0-cp38-cp38-win32.whl", hash = "sha256:0cd67a1e5c2d88930aa767f702773b2d054e29957432d7c6a18f8be02a07719a"}, - {file = "protobuf-5.29.0-cp38-cp38-win_amd64.whl", hash = "sha256:e467f81fdd12ded9655cea3e9b83dc319d93b394ce810b556fb0f421d8613e86"}, - {file = "protobuf-5.29.0-cp39-cp39-win32.whl", hash = "sha256:17d128eebbd5d8aee80300aed7a43a48a25170af3337f6f1333d1fac2c6839ac"}, - {file = "protobuf-5.29.0-cp39-cp39-win_amd64.whl", hash = "sha256:6c3009e22717c6cc9e6594bb11ef9f15f669b19957ad4087214d69e08a213368"}, - {file = "protobuf-5.29.0-py3-none-any.whl", hash = "sha256:88c4af76a73183e21061881360240c0cdd3c39d263b4e8fb570aaf83348d608f"}, - {file = "protobuf-5.29.0.tar.gz", hash = "sha256:445a0c02483869ed8513a585d80020d012c6dc60075f96fa0563a724987b1001"}, -] - [[package]] name = "psycopg2-binary" version = "2.8.6" @@ -2393,17 +2196,17 @@ files = [ [[package]] name = "pyasn1-modules" -version = "0.4.1" +version = "0.4.2" description = "A collection of ASN.1-based protocols modules" optional = false python-versions = ">=3.8" files = [ - {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, - {file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"}, + {file = "pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a"}, + {file = "pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6"}, ] [package.dependencies] -pyasn1 = ">=0.4.6,<0.7.0" +pyasn1 = ">=0.6.1,<0.7.0" [[package]] name = "pycodestyle" @@ -2418,13 +2221,13 @@ files = [ [[package]] name = "pycparser" -version = "2.22" +version = "2.23" description = "C parser in Python" optional = false python-versions = ">=3.8" files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, + {file = "pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"}, + {file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"}, ] [[package]] @@ -2468,17 +2271,18 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pyopenssl" -version = "24.3.0" +version = "25.3.0" description = "Python wrapper module around the OpenSSL library" optional = false python-versions = ">=3.7" files = [ - {file = "pyOpenSSL-24.3.0-py3-none-any.whl", hash = "sha256:e474f5a473cd7f92221cc04976e48f4d11502804657a08a989fb3be5514c904a"}, - {file = "pyopenssl-24.3.0.tar.gz", hash = "sha256:49f7a019577d834746bc55c5fce6ecbcec0f2b4ec5ce1cf43a9a173b8138bb36"}, + {file = "pyopenssl-25.3.0-py3-none-any.whl", hash = "sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6"}, + {file = "pyopenssl-25.3.0.tar.gz", hash = "sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329"}, ] [package.dependencies] -cryptography = ">=41.0.5,<45" +cryptography = ">=45.0.7,<47" +typing-extensions = {version = ">=4.9", markers = "python_version < \"3.13\" and python_version >= \"3.8\""} [package.extras] docs = ["sphinx (!=5.2.0,!=5.2.0.post0,!=7.2.5)", "sphinx_rtd_theme"] @@ -2569,13 +2373,13 @@ six = ">=1.5" [[package]] name = "python-dotenv" -version = "1.0.1" +version = "1.1.1" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, - {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, + {file = "python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc"}, + {file = "python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab"}, ] [package.extras] @@ -2601,13 +2405,13 @@ postgresql = ["psycopg2"] [[package]] name = "pytz" -version = "2024.2" +version = "2025.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, - {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, + {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"}, + {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"}, ] [[package]] @@ -2645,36 +2449,38 @@ files = [ [[package]] name = "redis" -version = "5.2.0" +version = "6.4.0" description = "Python client for Redis database and key-value store" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "redis-5.2.0-py3-none-any.whl", hash = "sha256:ae174f2bb3b1bf2b09d54bf3e51fbc1469cf6c10aa03e21141f51969801a7897"}, - {file = "redis-5.2.0.tar.gz", hash = "sha256:0b1087665a771b1ff2e003aa5bdd354f15a70c9e25d5a7dbf9c722c16528a7b0"}, + {file = "redis-6.4.0-py3-none-any.whl", hash = "sha256:f0544fa9604264e9464cdf4814e7d4830f74b165d52f2a330a760a88dd248b7f"}, + {file = "redis-6.4.0.tar.gz", hash = "sha256:b01bc7282b8444e28ec36b261df5375183bb47a07eb9c603f284e89cbc5ef010"}, ] [package.dependencies] async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""} [package.extras] -hiredis = ["hiredis (>=3.0.0)"] -ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==23.2.1)", "requests (>=2.31.0)"] +hiredis = ["hiredis (>=3.2.0)"] +jwt = ["pyjwt (>=2.9.0)"] +ocsp = ["cryptography (>=36.0.1)", "pyopenssl (>=20.0.1)", "requests (>=2.31.0)"] [[package]] name = "referencing" -version = "0.35.1" +version = "0.36.2" description = "JSON Referencing + Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, - {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, + {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"}, + {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"}, ] [package.dependencies] attrs = ">=22.2.0" rpds-py = ">=0.7.0" +typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "requests" @@ -2728,143 +2534,181 @@ files = [ [[package]] name = "rpds-py" -version = "0.22.1" +version = "0.27.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.9" files = [ - {file = "rpds_py-0.22.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ab27dd4edd84b13309f268ffcdfc07aef8339135ffab7b6d43f16884307a2a48"}, - {file = "rpds_py-0.22.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9d5b925156a746dc1f5f52376fdd1fbdd3f6ffe1fcd6f5e06f77ca79abb940a3"}, - {file = "rpds_py-0.22.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201650b309c419143775c15209c620627de3c09a27c7fb58375325aec5cce260"}, - {file = "rpds_py-0.22.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31264187fc934ff1024a4f56775f33c9252d3f4f3e27ec07d1995a26b52702c3"}, - {file = "rpds_py-0.22.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97c5ffe47ccf92d8b17e10f8a5ce28d015aa1196edc3359684cf31504eae6a14"}, - {file = "rpds_py-0.22.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9ac7280bd045f472b50306d7efeee051b69e3a2dd1b90f46bd7e86e63b1efa2"}, - {file = "rpds_py-0.22.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f941fb86195f97be7f6efe04a21b223f05dfe4d1dfb159999e2f8d101e44cc4"}, - {file = "rpds_py-0.22.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f91bfc39f7a64168e08ab831fa497ec5438c1d6c6e2f9e12848d95ad11ac8523"}, - {file = "rpds_py-0.22.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:effcae2152afe7937a28376dbabb25c770ef99ed4e16a4ffeb8e6a4f7c4f06aa"}, - {file = "rpds_py-0.22.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:2177e59c033bf0d1bf7de1ced561205963583caf3242c6c700a723034bfb5f8e"}, - {file = "rpds_py-0.22.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:66f4f48a89cdd30ab3a47335df81c76e9a63799d0d84b29c0618371c66fa37b0"}, - {file = "rpds_py-0.22.1-cp310-cp310-win32.whl", hash = "sha256:b07fa9e634234e84096adfa4be3828c8f26e238679c122824b2b3d7131bec578"}, - {file = "rpds_py-0.22.1-cp310-cp310-win_amd64.whl", hash = "sha256:ca4657e9fd0b1b5376942d403d634ce188f79064f0873aa853ab05b10185ceec"}, - {file = "rpds_py-0.22.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:608c84699b2db09c6a8743845b1a3dad36fae53eaaecb241d45b13dff74405fb"}, - {file = "rpds_py-0.22.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9dae4eb9b5534e09ba6c6ab496a757e5e394b7e7b08767d25ca37e8d36491114"}, - {file = "rpds_py-0.22.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09a1f000c5f6e08b298275bae00921e9fbbf2a35dae0a86db2821c058c2201a9"}, - {file = "rpds_py-0.22.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:580ccbf11f02f948add4cb641843030a89f1463d7c0740cbfc9aca91e9dc34b3"}, - {file = "rpds_py-0.22.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96559e05bdf938b2048353e10a7920b98f853cefe4482c2064a718d7d0a50bd7"}, - {file = "rpds_py-0.22.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:128cbaed7ba26116820bcb992405d6a13ea18c8fca1b8c4f59906d858e91e979"}, - {file = "rpds_py-0.22.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:734783dd7da58f76222f458346ddebdb3621686a1a2a667db5049caf0c9956b9"}, - {file = "rpds_py-0.22.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c9ce6b83597d45bec44a2690857ede62fc98223772135f8a7fa90884eb726501"}, - {file = "rpds_py-0.22.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bca4428c4a957b78ded3e6e62884ab03f029dce8fa8d34818da0f80f61332b49"}, - {file = "rpds_py-0.22.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1ded65691a1d3fd7d2aa89d2c91aa51f941601bb2ce099739909034d957fef4b"}, - {file = "rpds_py-0.22.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:72407065ad459db9f3d052ea8c51e02534f02533fc61e51cbab3bd94166f086c"}, - {file = "rpds_py-0.22.1-cp311-cp311-win32.whl", hash = "sha256:eb013aa01b404219f28dc973d9e6310fd4db216d7299253dd355629952e0564e"}, - {file = "rpds_py-0.22.1-cp311-cp311-win_amd64.whl", hash = "sha256:8bd9ec1db79a664f4cbb12878693b73416f4d2cb425d3e27eccc1bdfbdc826ef"}, - {file = "rpds_py-0.22.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8ec41049c90d204a6561238a9ad6c7263ebb7009d9759c98b58078d9d2fec9ba"}, - {file = "rpds_py-0.22.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:102be79c4cc47a4aeb5912401185c404cd2601c15a7163bbecff7f1bfe20b669"}, - {file = "rpds_py-0.22.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a603155db408f773637f9e3a712c6e3cbc521aaa8fa2b99f9ba6106c59a2496"}, - {file = "rpds_py-0.22.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5dbff9402c2bdf00bf0df9905694b3c292a3847c725651938a72f554351a5fcb"}, - {file = "rpds_py-0.22.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96b3759d8ab2323324e0a92b2f44834f9d88089b8d1ab6f533b61f4be3411cef"}, - {file = "rpds_py-0.22.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3029f481b31f329b1fdb4ec4b56935d82210ddd9c6f86ea5a87c06f1e97b161"}, - {file = "rpds_py-0.22.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d280b4bf09f719b89fd9aab3b71067acc0d0449b7d1eba99a2ade4939cef8296"}, - {file = "rpds_py-0.22.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c8e97e19aa7b0b0d801a159f932ce4435f1049c8c38e2bb372bb5bee559ce50"}, - {file = "rpds_py-0.22.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:50e4b5d291105f7063259fe0125b1af902fb34499444d7c5c521dd8328b00939"}, - {file = "rpds_py-0.22.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d3777c446bb1c5fcd82dc3f8776e1a146cd91e80cc1892f8634575ace438d22f"}, - {file = "rpds_py-0.22.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:447ae1104fb32197b9262f772d565d38e834cc2e9edd89350b37b88fed636e70"}, - {file = "rpds_py-0.22.1-cp312-cp312-win32.whl", hash = "sha256:55d371b9d8b0c2a68a50413a8cb01c3c3ce1ea4f768bf77b66669a9a486e101e"}, - {file = "rpds_py-0.22.1-cp312-cp312-win_amd64.whl", hash = "sha256:413a30a99d8683dace3765885920ed27ab662efbb6c98d81db76c397ad1ffd71"}, - {file = "rpds_py-0.22.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:aa2ba0176037c915d8660a4e46581d645e2c22b5373e466bc8640a794d45861a"}, - {file = "rpds_py-0.22.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4ba6c66fbc6015b2f99e7176fec41793cecb00c4cc357cad038dff85e6ac42ab"}, - {file = "rpds_py-0.22.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15fa4ca658f8ad22645d3531682b17e5580832efbfa87304c3e62214c79c1e8a"}, - {file = "rpds_py-0.22.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d7833ef6f5d6cb634f296abfd93452fb3eb44c4e9a6ae95c1021eab704c1cee2"}, - {file = "rpds_py-0.22.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c0467838c90435b80793cde486a318fc916ee57f2af54e4b10c72b20cbdcbaa9"}, - {file = "rpds_py-0.22.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d962e2e89b3a95e3597a34b8c93ced1e98958502c5b8096c9fd69deff279f561"}, - {file = "rpds_py-0.22.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ce729f1dc8a4a190c34b69f75377bddc004079b2963ab722ab91fafe040be6d"}, - {file = "rpds_py-0.22.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8080467df22feca0fc9c46567001777c6fbc2b4a2683a7137420896051874ca1"}, - {file = "rpds_py-0.22.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0f9eb37d3a60b262a98ab51ee899cac039de9ca0ce68dcf1a6518a09719020b0"}, - {file = "rpds_py-0.22.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:153248f48d6f90a295a502f53ec544a3ffbd21b0bb32f5dca39c4b93a764d6a2"}, - {file = "rpds_py-0.22.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0a53592cdf98cec3dfcdb24ffec8a4797e7656b65700099af43ec7df023b6de4"}, - {file = "rpds_py-0.22.1-cp313-cp313-win32.whl", hash = "sha256:e8056adcefa2dcb67e8bc91ea5eee26df66e8b297a8cd6ff0903f85c70908fa0"}, - {file = "rpds_py-0.22.1-cp313-cp313-win_amd64.whl", hash = "sha256:a451dba533be77454ebcffc85189108fc05f279100835ac76e7989edacb89156"}, - {file = "rpds_py-0.22.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:2ea23f1525d4f64286dbe0947c929d45c3ffe963b2dbed1d3844a2e4938bda42"}, - {file = "rpds_py-0.22.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3aaa22487477de9618ce3b37f99fbe81219ba96f3c2ca84f576f0ab451b83aba"}, - {file = "rpds_py-0.22.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8954b9ffe60f479a0c0ba40987db2546c735ab02a725ea7fd89342152d4d821d"}, - {file = "rpds_py-0.22.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8502a02ae3ae67084f5a0bf5a8253b19fa7a887f824e41e016cdb0ac532a06f"}, - {file = "rpds_py-0.22.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a083221b6a4ecdef38a60c95d8d3223d99449cb4da2544e9644958dc16664eb9"}, - {file = "rpds_py-0.22.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:542eb246d5be31b5e0a9c8ddb9539416f9b31f58f75bd4ee328bff2b5c58d6fd"}, - {file = "rpds_py-0.22.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffae97d28ea4f2c613a751d087b75a97fb78311b38cc2e9a2f4587e473ace167"}, - {file = "rpds_py-0.22.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0ff8d5b13ce2357fa8b33a0a2e3775aa71df5bf7c8ba060634c9d15ab12f357"}, - {file = "rpds_py-0.22.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0f057a0c546c42964836b209d8de9ea1a4f4b0432006c6343cbe633d8ca14571"}, - {file = "rpds_py-0.22.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:48ee97c7c6027fd423058675b5a39d0b5f7a1648250b671563d5c9f74ff13ff0"}, - {file = "rpds_py-0.22.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:babec324e8654a59122aaa66936a9a483faa03276db9792f51332475c2dddc4a"}, - {file = "rpds_py-0.22.1-cp313-cp313t-win32.whl", hash = "sha256:e69acdbc132c9592c8dc393af85e38e206ca847c7019a953ff625191c3a12312"}, - {file = "rpds_py-0.22.1-cp313-cp313t-win_amd64.whl", hash = "sha256:c783e4ed68200f4e03c125690d23158b1c49c4b186d458a18debc109bbdc3c2e"}, - {file = "rpds_py-0.22.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2143c3aed85992604d758bbe67da839fb4aab3dd2e1c6dddab5b3ca7162b34a2"}, - {file = "rpds_py-0.22.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f57e2d0f8022783426121b586d7c842ea40ea832a29e28ca36c881b54c74fb28"}, - {file = "rpds_py-0.22.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c0c324879d483504b07f7b18eb1b50567c434263bbe4866ecce33056162668a"}, - {file = "rpds_py-0.22.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c40e02cc4f3e18fd39344edb10eebe04bd11cfd13119606b5771e5ea51630d3"}, - {file = "rpds_py-0.22.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f76c6f319e57007ad52e671ec741d801324760a377e3d4992c9bb8200333ebac"}, - {file = "rpds_py-0.22.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5cae9b415ea8a6a563566dbf46650222eccc5971c7daa16fbee63aef92ae543"}, - {file = "rpds_py-0.22.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b09209cdfcacf5eba9cf80367130532e6c02e695252e1f64d3cfcc2356e6e19f"}, - {file = "rpds_py-0.22.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dbe428d0ac6eacaf05402adbaf137f59ad6063848182d1ff294f95ce0f24005b"}, - {file = "rpds_py-0.22.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:626b9feb01bff049a5aec4804f0c58db12585778b4902e5376a95b01f80a7a16"}, - {file = "rpds_py-0.22.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec1ccc2a9f764cd632fb8ab28fdde166250df54fc8d97315a4a6948dc5367639"}, - {file = "rpds_py-0.22.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ef92b1fbe6aa2e7885eb90853cc016b1fc95439a8cc8da6d526880e9e2148695"}, - {file = "rpds_py-0.22.1-cp39-cp39-win32.whl", hash = "sha256:c88535f83f7391cf3a45af990237e3939a6fdfbedaed2571633bfdd0bceb36b0"}, - {file = "rpds_py-0.22.1-cp39-cp39-win_amd64.whl", hash = "sha256:7839b7528faa4d134c183b1f2dd1ee4dc2ca2f899f4f0cfdf00fc04c255262a7"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a0ed14a4162c2c2b21a162c9fcf90057e3e7da18cd171ab344c1e1664f75090e"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:05fdeae9010533e47715c37df83264df0122584e40d691d50cf3607c060952a3"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4659b2e4a5008715099e216050f5c6976e5a4329482664411789968b82e3f17d"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a18aedc032d6468b73ebbe4437129cb30d54fe543cde2f23671ecad76c3aea24"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149b4d875ef9b12a8f5e303e86a32a58f8ef627e57ec97a7d0e4be819069d141"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdaee3947eaaa52dae3ceb9d9f66329e13d8bae35682b1e5dd54612938693934"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36ce951800ed2acc6772fd9f42150f29d567f0423989748052fdb39d9e2b5795"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ab784621d3e2a41916e21f13a483602cc989fd45fff637634b9231ba43d4383b"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:c2a214bf5b79bd39a9de1c991353aaaacafda83ba1374178309e92be8e67d411"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:85060e96953647871957d41707adb8d7bff4e977042fd0deb4fc1881b98dd2fe"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c6f3fd617db422c9d4e12cb8d84c984fe07d6d9cb0950cbf117f3bccc6268d05"}, - {file = "rpds_py-0.22.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f2d1b58a0c3a73f0361759642e80260a6d28eee6501b40fe25b82af33ef83f21"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:76eaa4c087a061a2c8a0a92536405069878a8f530c00e84a9eaf332e70f5561f"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:959ae04ed30cde606f3a0320f0a1f4167a107e685ef5209cce28c5080590bd31"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:198067aa6f3d942ff5d0d655bb1e91b59ae85279d47590682cba2834ac1b97d2"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3e7e99e2af59c56c59b6c964d612511b8203480d39d1ef83edc56f2cb42a3f5d"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0545928bdf53dfdfcab284468212efefb8a6608ca3b6910c7fb2e5ed8bdc2dc0"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef7282d8a14b60dd515e47060638687710b1d518f4b5e961caad43fb3a3606f9"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe3f245c2f39a5692d9123c174bc48f6f9fe3e96407e67c6d04541a767d99e72"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efb2ad60ca8637d5f9f653f9a9a8d73964059972b6b95036be77e028bffc68a3"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d8306f27418361b788e3fca9f47dec125457f80122e7e31ba7ff5cdba98343f8"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:4c8dc7331e8cbb1c0ea2bcb550adb1777365944ffd125c69aa1117fdef4887f5"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:776a06cb5720556a549829896a49acebb5bdd96c7bba100191a994053546975a"}, - {file = "rpds_py-0.22.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e4f91d702b9ce1388660b3d4a28aa552614a1399e93f718ed0dacd68f23b3d32"}, - {file = "rpds_py-0.22.1.tar.gz", hash = "sha256:157a023bded0618a1eea54979fe2e0f9309e9ddc818ef4b8fc3b884ff38fedd5"}, -] - -[[package]] -name = "rsa" -version = "4.9" -description = "Pure-Python RSA implementation" -optional = false -python-versions = ">=3.6,<4" -files = [ - {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, - {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, -] - -[package.dependencies] -pyasn1 = ">=0.1.3" + {file = "rpds_py-0.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:68afeec26d42ab3b47e541b272166a0b4400313946871cba3ed3a4fc0cab1cef"}, + {file = "rpds_py-0.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74e5b2f7bb6fa38b1b10546d27acbacf2a022a8b5543efb06cfebc72a59c85be"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9024de74731df54546fab0bfbcdb49fae19159ecaecfc8f37c18d2c7e2c0bd61"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31d3ebadefcd73b73928ed0b2fd696f7fefda8629229f81929ac9c1854d0cffb"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2e7f8f169d775dd9092a1743768d771f1d1300453ddfe6325ae3ab5332b4657"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d905d16f77eb6ab2e324e09bfa277b4c8e5e6b8a78a3e7ff8f3cdf773b4c013"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50c946f048209e6362e22576baea09193809f87687a95a8db24e5fbdb307b93a"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:3deab27804d65cd8289eb814c2c0e807c4b9d9916c9225e363cb0cf875eb67c1"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b61097f7488de4be8244c89915da8ed212832ccf1e7c7753a25a394bf9b1f10"}, + {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a3f29aba6e2d7d90528d3c792555a93497fe6538aa65eb675b44505be747808"}, + {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd6cd0485b7d347304067153a6dc1d73f7d4fd995a396ef32a24d24b8ac63ac8"}, + {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f4461bf931108c9fa226ffb0e257c1b18dc2d44cd72b125bec50ee0ab1248a9"}, + {file = "rpds_py-0.27.1-cp310-cp310-win32.whl", hash = "sha256:ee5422d7fb21f6a00c1901bf6559c49fee13a5159d0288320737bbf6585bd3e4"}, + {file = "rpds_py-0.27.1-cp310-cp310-win_amd64.whl", hash = "sha256:3e039aabf6d5f83c745d5f9a0a381d031e9ed871967c0a5c38d201aca41f3ba1"}, + {file = "rpds_py-0.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:be898f271f851f68b318872ce6ebebbc62f303b654e43bf72683dbdc25b7c881"}, + {file = "rpds_py-0.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62ac3d4e3e07b58ee0ddecd71d6ce3b1637de2d373501412df395a0ec5f9beb5"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4708c5c0ceb2d034f9991623631d3d23cb16e65c83736ea020cdbe28d57c0a0e"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:abfa1171a9952d2e0002aba2ad3780820b00cc3d9c98c6630f2e93271501f66c"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b507d19f817ebaca79574b16eb2ae412e5c0835542c93fe9983f1e432aca195"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168b025f8fd8d8d10957405f3fdcef3dc20f5982d398f90851f4abc58c566c52"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb56c6210ef77caa58e16e8c17d35c63fe3f5b60fd9ba9d424470c3400bcf9ed"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:d252f2d8ca0195faa707f8eb9368955760880b2b42a8ee16d382bf5dd807f89a"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6e5e54da1e74b91dbc7996b56640f79b195d5925c2b78efaa8c5d53e1d88edde"}, + {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ffce0481cc6e95e5b3f0a47ee17ffbd234399e6d532f394c8dce320c3b089c21"}, + {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a205fdfe55c90c2cd8e540ca9ceba65cbe6629b443bc05db1f590a3db8189ff9"}, + {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:689fb5200a749db0415b092972e8eba85847c23885c8543a8b0f5c009b1a5948"}, + {file = "rpds_py-0.27.1-cp311-cp311-win32.whl", hash = "sha256:3182af66048c00a075010bc7f4860f33913528a4b6fc09094a6e7598e462fe39"}, + {file = "rpds_py-0.27.1-cp311-cp311-win_amd64.whl", hash = "sha256:b4938466c6b257b2f5c4ff98acd8128ec36b5059e5c8f8372d79316b1c36bb15"}, + {file = "rpds_py-0.27.1-cp311-cp311-win_arm64.whl", hash = "sha256:2f57af9b4d0793e53266ee4325535a31ba48e2f875da81a9177c9926dfa60746"}, + {file = "rpds_py-0.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ae2775c1973e3c30316892737b91f9283f9908e3cc7625b9331271eaaed7dc90"}, + {file = "rpds_py-0.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2643400120f55c8a96f7c9d858f7be0c88d383cd4653ae2cf0d0c88f668073e5"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16323f674c089b0360674a4abd28d5042947d54ba620f72514d69be4ff64845e"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a1f4814b65eacac94a00fc9a526e3fdafd78e439469644032032d0d63de4881"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ba32c16b064267b22f1850a34051121d423b6f7338a12b9459550eb2096e7ec"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5c20f33fd10485b80f65e800bbe5f6785af510b9f4056c5a3c612ebc83ba6cb"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:466bfe65bd932da36ff279ddd92de56b042f2266d752719beb97b08526268ec5"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:41e532bbdcb57c92ba3be62c42e9f096431b4cf478da9bc3bc6ce5c38ab7ba7a"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f149826d742b406579466283769a8ea448eed82a789af0ed17b0cd5770433444"}, + {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80c60cfb5310677bd67cb1e85a1e8eb52e12529545441b43e6f14d90b878775a"}, + {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7ee6521b9baf06085f62ba9c7a3e5becffbc32480d2f1b351559c001c38ce4c1"}, + {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a512c8263249a9d68cac08b05dd59d2b3f2061d99b322813cbcc14c3c7421998"}, + {file = "rpds_py-0.27.1-cp312-cp312-win32.whl", hash = "sha256:819064fa048ba01b6dadc5116f3ac48610435ac9a0058bbde98e569f9e785c39"}, + {file = "rpds_py-0.27.1-cp312-cp312-win_amd64.whl", hash = "sha256:d9199717881f13c32c4046a15f024971a3b78ad4ea029e8da6b86e5aa9cf4594"}, + {file = "rpds_py-0.27.1-cp312-cp312-win_arm64.whl", hash = "sha256:33aa65b97826a0e885ef6e278fbd934e98cdcfed80b63946025f01e2f5b29502"}, + {file = "rpds_py-0.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e4b9fcfbc021633863a37e92571d6f91851fa656f0180246e84cbd8b3f6b329b"}, + {file = "rpds_py-0.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1441811a96eadca93c517d08df75de45e5ffe68aa3089924f963c782c4b898cf"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55266dafa22e672f5a4f65019015f90336ed31c6383bd53f5e7826d21a0e0b83"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78827d7ac08627ea2c8e02c9e5b41180ea5ea1f747e9db0915e3adf36b62dcf"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae92443798a40a92dc5f0b01d8a7c93adde0c4dc965310a29ae7c64d72b9fad2"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c46c9dd2403b66a2a3b9720ec4b74d4ab49d4fabf9f03dfdce2d42af913fe8d0"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2efe4eb1d01b7f5f1939f4ef30ecea6c6b3521eec451fb93191bf84b2a522418"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:15d3b4d83582d10c601f481eca29c3f138d44c92187d197aff663a269197c02d"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ed2e16abbc982a169d30d1a420274a709949e2cbdef119fe2ec9d870b42f274"}, + {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a75f305c9b013289121ec0f1181931975df78738cdf650093e6b86d74aa7d8dd"}, + {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:67ce7620704745881a3d4b0ada80ab4d99df390838839921f99e63c474f82cf2"}, + {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d992ac10eb86d9b6f369647b6a3f412fc0075cfd5d799530e84d335e440a002"}, + {file = "rpds_py-0.27.1-cp313-cp313-win32.whl", hash = "sha256:4f75e4bd8ab8db624e02c8e2fc4063021b58becdbe6df793a8111d9343aec1e3"}, + {file = "rpds_py-0.27.1-cp313-cp313-win_amd64.whl", hash = "sha256:f9025faafc62ed0b75a53e541895ca272815bec18abe2249ff6501c8f2e12b83"}, + {file = "rpds_py-0.27.1-cp313-cp313-win_arm64.whl", hash = "sha256:ed10dc32829e7d222b7d3b93136d25a406ba9788f6a7ebf6809092da1f4d279d"}, + {file = "rpds_py-0.27.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:92022bbbad0d4426e616815b16bc4127f83c9a74940e1ccf3cfe0b387aba0228"}, + {file = "rpds_py-0.27.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:47162fdab9407ec3f160805ac3e154df042e577dd53341745fc7fb3f625e6d92"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb89bec23fddc489e5d78b550a7b773557c9ab58b7946154a10a6f7a214a48b2"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e48af21883ded2b3e9eb48cb7880ad8598b31ab752ff3be6457001d78f416723"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f5b7bd8e219ed50299e58551a410b64daafb5017d54bbe822e003856f06a802"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08f1e20bccf73b08d12d804d6e1c22ca5530e71659e6673bce31a6bb71c1e73f"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dc5dceeaefcc96dc192e3a80bbe1d6c410c469e97bdd47494a7d930987f18b2"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d76f9cc8665acdc0c9177043746775aa7babbf479b5520b78ae4002d889f5c21"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134fae0e36022edad8290a6661edf40c023562964efea0cc0ec7f5d392d2aaef"}, + {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb11a4f1b2b63337cfd3b4d110af778a59aae51c81d195768e353d8b52f88081"}, + {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:13e608ac9f50a0ed4faec0e90ece76ae33b34c0e8656e3dceb9a7db994c692cd"}, + {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dd2135527aa40f061350c3f8f89da2644de26cd73e4de458e79606384f4f68e7"}, + {file = "rpds_py-0.27.1-cp313-cp313t-win32.whl", hash = "sha256:3020724ade63fe320a972e2ffd93b5623227e684315adce194941167fee02688"}, + {file = "rpds_py-0.27.1-cp313-cp313t-win_amd64.whl", hash = "sha256:8ee50c3e41739886606388ba3ab3ee2aae9f35fb23f833091833255a31740797"}, + {file = "rpds_py-0.27.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:acb9aafccaae278f449d9c713b64a9e68662e7799dbd5859e2c6b3c67b56d334"}, + {file = "rpds_py-0.27.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b7fb801aa7f845ddf601c49630deeeccde7ce10065561d92729bfe81bd21fb33"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0dd05afb46597b9a2e11c351e5e4283c741237e7f617ffb3252780cca9336a"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b6dfb0e058adb12d8b1d1b25f686e94ffa65d9995a5157afe99743bf7369d62b"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed090ccd235f6fa8bb5861684567f0a83e04f52dfc2e5c05f2e4b1309fcf85e7"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf876e79763eecf3e7356f157540d6a093cef395b65514f17a356f62af6cc136"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12ed005216a51b1d6e2b02a7bd31885fe317e45897de81d86dcce7d74618ffff"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:ee4308f409a40e50593c7e3bb8cbe0b4d4c66d1674a316324f0c2f5383b486f9"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b08d152555acf1f455154d498ca855618c1378ec810646fcd7c76416ac6dc60"}, + {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:dce51c828941973a5684d458214d3a36fcd28da3e1875d659388f4f9f12cc33e"}, + {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:c1476d6f29eb81aa4151c9a31219b03f1f798dc43d8af1250a870735516a1212"}, + {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3ce0cac322b0d69b63c9cdb895ee1b65805ec9ffad37639f291dd79467bee675"}, + {file = "rpds_py-0.27.1-cp314-cp314-win32.whl", hash = "sha256:dfbfac137d2a3d0725758cd141f878bf4329ba25e34979797c89474a89a8a3a3"}, + {file = "rpds_py-0.27.1-cp314-cp314-win_amd64.whl", hash = "sha256:a6e57b0abfe7cc513450fcf529eb486b6e4d3f8aee83e92eb5f1ef848218d456"}, + {file = "rpds_py-0.27.1-cp314-cp314-win_arm64.whl", hash = "sha256:faf8d146f3d476abfee026c4ae3bdd9ca14236ae4e4c310cbd1cf75ba33d24a3"}, + {file = "rpds_py-0.27.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:ba81d2b56b6d4911ce735aad0a1d4495e808b8ee4dc58715998741a26874e7c2"}, + {file = "rpds_py-0.27.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:84f7d509870098de0e864cad0102711c1e24e9b1a50ee713b65928adb22269e4"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e960fc78fecd1100539f14132425e1d5fe44ecb9239f8f27f079962021523e"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62f85b665cedab1a503747617393573995dac4600ff51869d69ad2f39eb5e817"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fed467af29776f6556250c9ed85ea5a4dd121ab56a5f8b206e3e7a4c551e48ec"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2729615f9d430af0ae6b36cf042cb55c0936408d543fb691e1a9e36648fd35a"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b207d881a9aef7ba753d69c123a35d96ca7cb808056998f6b9e8747321f03b8"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:639fd5efec029f99b79ae47e5d7e00ad8a773da899b6309f6786ecaf22948c48"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fecc80cb2a90e28af8a9b366edacf33d7a91cbfe4c2c4544ea1246e949cfebeb"}, + {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42a89282d711711d0a62d6f57d81aa43a1368686c45bc1c46b7f079d55692734"}, + {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:cf9931f14223de59551ab9d38ed18d92f14f055a5f78c1d8ad6493f735021bbb"}, + {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f39f58a27cc6e59f432b568ed8429c7e1641324fbe38131de852cd77b2d534b0"}, + {file = "rpds_py-0.27.1-cp314-cp314t-win32.whl", hash = "sha256:d5fa0ee122dc09e23607a28e6d7b150da16c662e66409bbe85230e4c85bb528a"}, + {file = "rpds_py-0.27.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772"}, + {file = "rpds_py-0.27.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c918c65ec2e42c2a78d19f18c553d77319119bf43aa9e2edf7fb78d624355527"}, + {file = "rpds_py-0.27.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fea2b1a922c47c51fd07d656324531adc787e415c8b116530a1d29c0516c62d"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbf94c58e8e0cd6b6f38d8de67acae41b3a515c26169366ab58bdca4a6883bb8"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c2a8fed130ce946d5c585eddc7c8eeef0051f58ac80a8ee43bd17835c144c2cc"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:037a2361db72ee98d829bc2c5b7cc55598ae0a5e0ec1823a56ea99374cfd73c1"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5281ed1cc1d49882f9997981c88df1a22e140ab41df19071222f7e5fc4e72125"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fd50659a069c15eef8aa3d64bbef0d69fd27bb4a50c9ab4f17f83a16cbf8905"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:c4b676c4ae3921649a15d28ed10025548e9b561ded473aa413af749503c6737e"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:079bc583a26db831a985c5257797b2b5d3affb0386e7ff886256762f82113b5e"}, + {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4e44099bd522cba71a2c6b97f68e19f40e7d85399de899d66cdb67b32d7cb786"}, + {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e202e6d4188e53c6661af813b46c37ca2c45e497fc558bacc1a7630ec2695aec"}, + {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f41f814b8eaa48768d1bb551591f6ba45f87ac76899453e8ccd41dba1289b04b"}, + {file = "rpds_py-0.27.1-cp39-cp39-win32.whl", hash = "sha256:9e71f5a087ead99563c11fdaceee83ee982fd39cf67601f4fd66cb386336ee52"}, + {file = "rpds_py-0.27.1-cp39-cp39-win_amd64.whl", hash = "sha256:71108900c9c3c8590697244b9519017a400d9ba26a36c48381b3f64743a44aab"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7ba22cb9693df986033b91ae1d7a979bc399237d45fccf875b76f62bb9e52ddf"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b640501be9288c77738b5492b3fd3abc4ba95c50c2e41273c8a1459f08298d3"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb08b65b93e0c6dd70aac7f7890a9c0938d5ec71d5cb32d45cf844fb8ae47636"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d7ff07d696a7a38152ebdb8212ca9e5baab56656749f3d6004b34ab726b550b8"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb7c72262deae25366e3b6c0c0ba46007967aea15d1eea746e44ddba8ec58dcc"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b002cab05d6339716b03a4a3a2ce26737f6231d7b523f339fa061d53368c9d8"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23f6b69d1c26c4704fec01311963a41d7de3ee0570a84ebde4d544e5a1859ffc"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:530064db9146b247351f2a0250b8f00b289accea4596a033e94be2389977de71"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b90b0496570bd6b0321724a330d8b545827c4df2034b6ddfc5f5275f55da2ad"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:879b0e14a2da6a1102a3fc8af580fc1ead37e6d6692a781bd8c83da37429b5ab"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:0d807710df3b5faa66c731afa162ea29717ab3be17bdc15f90f2d9f183da4059"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3adc388fc3afb6540aec081fa59e6e0d3908722771aa1e37ffe22b220a436f0b"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c796c0c1cc68cb08b0284db4229f5af76168172670c74908fdbd4b7d7f515819"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cdfe4bb2f9fe7458b7453ad3c33e726d6d1c7c0a72960bcc23800d77384e42df"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fabb8fd848a5f75a2324e4a84501ee3a5e3c78d8603f83475441866e60b94a3"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda8719d598f2f7f3e0f885cba8646644b55a187762bec091fa14a2b819746a9"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c64d07e95606ec402a0a1c511fe003873fa6af630bda59bac77fac8b4318ebc"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93a2ed40de81bcff59aabebb626562d48332f3d028ca2036f1d23cbb52750be4"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:387ce8c44ae94e0ec50532d9cb0edce17311024c9794eb196b90e1058aadeb66"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaf94f812c95b5e60ebaf8bfb1898a7d7cb9c1af5744d4a67fa47796e0465d4e"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:4848ca84d6ded9b58e474dfdbad4b8bfb450344c0551ddc8d958bf4b36aa837c"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bde09cbcf2248b73c7c323be49b280180ff39fadcfe04e7b6f54a678d02a7cf"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:94c44ee01fd21c9058f124d2d4f0c9dc7634bec93cd4b38eefc385dabe71acbf"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:df8b74962e35c9249425d90144e721eed198e6555a0e22a563d29fe4486b51f6"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dc23e6820e3b40847e2f4a7726462ba0cf53089512abe9ee16318c366494c17a"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa8933159edc50be265ed22b401125c9eebff3171f570258854dbce3ecd55475"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a50431bf02583e21bf273c71b89d710e7a710ad5e39c725b14e685610555926f"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78af06ddc7fe5cc0e967085a9115accee665fb912c22a3f54bad70cc65b05fe6"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70d0738ef8fee13c003b100c2fbd667ec4f133468109b3472d249231108283a3"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2f6fd8a1cea5bbe599b6e78a6e5ee08db434fc8ffea51ff201c8765679698b3"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8177002868d1426305bb5de1e138161c2ec9eb2d939be38291d7c431c4712df8"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:008b839781d6c9bf3b6a8984d1d8e56f0ec46dc56df61fd669c49b58ae800400"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:a55b9132bb1ade6c734ddd2759c8dc132aa63687d259e725221f106b83a0e485"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a46fdec0083a26415f11d5f236b79fa1291c32aaa4a17684d82f7017a1f818b1"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:8a63b640a7845f2bdd232eb0d0a4a2dd939bcdd6c57e6bb134526487f3160ec5"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7e32721e5d4922deaaf963469d795d5bde6093207c52fec719bd22e5d1bedbc4"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2c426b99a068601b5f4623573df7a7c3d72e87533a2dd2253353a03e7502566c"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4fc9b7fe29478824361ead6e14e4f5aed570d477e06088826537e202d25fe859"}, + {file = "rpds_py-0.27.1.tar.gz", hash = "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8"}, +] [[package]] name = "ruamel-yaml" -version = "0.18.6" +version = "0.18.15" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "ruamel.yaml-0.18.6-py3-none-any.whl", hash = "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636"}, - {file = "ruamel.yaml-0.18.6.tar.gz", hash = "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b"}, + {file = "ruamel.yaml-0.18.15-py3-none-any.whl", hash = "sha256:148f6488d698b7a5eded5ea793a025308b25eca97208181b6a026037f391f701"}, + {file = "ruamel.yaml-0.18.15.tar.gz", hash = "sha256:dbfca74b018c4c3fba0b9cc9ee33e53c371194a9000e694995e620490fd40700"}, ] [package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""} +"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.14\""} [package.extras] docs = ["mercurial (>5.7)", "ryd"] @@ -2872,52 +2716,55 @@ jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] [[package]] name = "ruamel-yaml-clib" -version = "0.2.12" +version = "0.2.14" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" optional = false python-versions = ">=3.9" files = [ - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bc5f1e1c28e966d61d2519f2a3d451ba989f9ea0f2307de7bc45baa526de9e45"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a0e060aace4c24dcaf71023bbd7d42674e3b230f7e7b97317baf1e953e5b519"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b"}, - {file = "ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f"}, + {file = "ruamel.yaml.clib-0.2.14-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:aef953f3b8bd0b50bd52a2e52fb54a6a2171a1889d8dea4a5959d46c6624c451"}, + {file = "ruamel.yaml.clib-0.2.14-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a0ac90efbc7a77b0d796c03c8cc4e62fd710b3f1e4c32947713ef2ef52e09543"}, + {file = "ruamel.yaml.clib-0.2.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9bf6b699223afe6c7fe9f2ef76e0bfa6dd892c21e94ce8c957478987ade76cd8"}, + {file = "ruamel.yaml.clib-0.2.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d73a0187718f6eec5b2f729b0f98e4603f7bd9c48aa65d01227d1a5dcdfbe9e8"}, + {file = "ruamel.yaml.clib-0.2.14-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b28caeaf3e670c08cb7e8de221266df8494c169bd6ed8875493fab45be9607a4"}, + {file = "ruamel.yaml.clib-0.2.14-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:94f3efb718f8f49b031f2071ec7a27dd20cbfe511b4dfd54ecee54c956da2b31"}, + {file = "ruamel.yaml.clib-0.2.14-cp310-cp310-win32.whl", hash = "sha256:27c070cf3888e90d992be75dd47292ff9aa17dafd36492812a6a304a1aedc182"}, + {file = "ruamel.yaml.clib-0.2.14-cp310-cp310-win_amd64.whl", hash = "sha256:4f4a150a737fccae13fb51234d41304ff2222e3b7d4c8e9428ed1a6ab48389b8"}, + {file = "ruamel.yaml.clib-0.2.14-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:0a54e5e40a7a691a426c2703b09b0d61a14294d25cfacc00631aa6f9c964df0d"}, + {file = "ruamel.yaml.clib-0.2.14-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:10d9595b6a19778f3269399eff6bab642608e5966183abc2adbe558a42d4efc9"}, + {file = "ruamel.yaml.clib-0.2.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dba72975485f2b87b786075e18a6e5d07dc2b4d8973beb2732b9b2816f1bad70"}, + {file = "ruamel.yaml.clib-0.2.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29757bdb7c142f9595cc1b62ec49a3d1c83fab9cef92db52b0ccebaad4eafb98"}, + {file = "ruamel.yaml.clib-0.2.14-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:26a8de280ab0d22b6e3ec745b4a5a07151a0f74aad92dd76ab9c8d8d7087720d"}, + {file = "ruamel.yaml.clib-0.2.14-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e501c096aa3889133d674605ebd018471bc404a59cbc17da3c5924421c54d97c"}, + {file = "ruamel.yaml.clib-0.2.14-cp311-cp311-win32.whl", hash = "sha256:915748cfc25b8cfd81b14d00f4bfdb2ab227a30d6d43459034533f4d1c207a2a"}, + {file = "ruamel.yaml.clib-0.2.14-cp311-cp311-win_amd64.whl", hash = "sha256:4ccba93c1e5a40af45b2f08e4591969fa4697eae951c708f3f83dcbf9f6c6bb1"}, + {file = "ruamel.yaml.clib-0.2.14-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:5e56ac47260c0eed992789fa0b8efe43404a9adb608608631a948cee4fc2b052"}, + {file = "ruamel.yaml.clib-0.2.14-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:a911aa73588d9a8b08d662b9484bc0567949529824a55d3885b77e8dd62a127a"}, + {file = "ruamel.yaml.clib-0.2.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a05ba88adf3d7189a974b2de7a9d56731548d35dc0a822ec3dc669caa7019b29"}, + {file = "ruamel.yaml.clib-0.2.14-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb04c5650de6668b853623eceadcdb1a9f2fee381f5d7b6bc842ee7c239eeec4"}, + {file = "ruamel.yaml.clib-0.2.14-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fbc08c02e9b147a11dfcaa1ac8a83168b699863493e183f7c0c8b12850b7d259"}, + {file = "ruamel.yaml.clib-0.2.14-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c099cafc1834d3c5dac305865d04235f7c21c167c8dd31ebc3d6bbc357e2f023"}, + {file = "ruamel.yaml.clib-0.2.14-cp312-cp312-win32.whl", hash = "sha256:b5b0f7e294700b615a3bcf6d28b26e6da94e8eba63b079f4ec92e9ba6c0d6b54"}, + {file = "ruamel.yaml.clib-0.2.14-cp312-cp312-win_amd64.whl", hash = "sha256:a37f40a859b503304dd740686359fcf541d6fb3ff7fc10f539af7f7150917c68"}, + {file = "ruamel.yaml.clib-0.2.14-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:dd7546c851e59c06197a7c651335755e74aa383a835878ca86d2c650c07a2f85"}, + {file = "ruamel.yaml.clib-0.2.14-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:1c1acc3a0209ea9042cc3cfc0790edd2eddd431a2ec3f8283d081e4d5018571e"}, + {file = "ruamel.yaml.clib-0.2.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2070bf0ad1540d5c77a664de07ebcc45eebd1ddcab71a7a06f26936920692beb"}, + {file = "ruamel.yaml.clib-0.2.14-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd8fe07f49c170e09d76773fb86ad9135e0beee44f36e1576a201b0676d3d1d"}, + {file = "ruamel.yaml.clib-0.2.14-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1f118b707eece8cf84ecbc3e3ec94d9db879d85ed608f95870d39b2d2efa5dca"}, + {file = "ruamel.yaml.clib-0.2.14-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b30110b29484adc597df6bd92a37b90e63a8c152ca8136aad100a02f8ba6d1b6"}, + {file = "ruamel.yaml.clib-0.2.14-cp313-cp313-win32.whl", hash = "sha256:f4e97a1cf0b7a30af9e1d9dad10a5671157b9acee790d9e26996391f49b965a2"}, + {file = "ruamel.yaml.clib-0.2.14-cp313-cp313-win_amd64.whl", hash = "sha256:090782b5fb9d98df96509eecdbcaffd037d47389a89492320280d52f91330d78"}, + {file = "ruamel.yaml.clib-0.2.14-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:70eda7703b8126f5e52fcf276e6c0f40b0d314674f896fc58c47b0aef2b9ae83"}, + {file = "ruamel.yaml.clib-0.2.14-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a0cb71ccc6ef9ce36eecb6272c81afdc2f565950cdcec33ae8e6cd8f7fc86f27"}, + {file = "ruamel.yaml.clib-0.2.14-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e7cb9ad1d525d40f7d87b6df7c0ff916a66bc52cb61b66ac1b2a16d0c1b07640"}, + {file = "ruamel.yaml.clib-0.2.14-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:d8354515ab62f95a07deaf7f845886cc50e2f345ceab240a3d2d09a9f7d77853"}, + {file = "ruamel.yaml.clib-0.2.14-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:275f938692013a3883edbd848edde6d9f26825d65c9a2eb1db8baa1adc96a05d"}, + {file = "ruamel.yaml.clib-0.2.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16a60d69f4057ad9a92f3444e2367c08490daed6428291aa16cefb445c29b0e9"}, + {file = "ruamel.yaml.clib-0.2.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ac5ff9425d8acb8f59ac5b96bcb7fd3d272dc92d96a7c730025928ffcc88a7a"}, + {file = "ruamel.yaml.clib-0.2.14-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:83bbd8354f6abb3fdfb922d1ed47ad8d1db3ea72b0523dac8d07cdacfe1c0fcf"}, + {file = "ruamel.yaml.clib-0.2.14-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:808c7190a0fe7ae7014c42f73897cf8e9ef14ff3aa533450e51b1e72ec5239ad"}, + {file = "ruamel.yaml.clib-0.2.14-cp39-cp39-win32.whl", hash = "sha256:6d5472f63a31b042aadf5ed28dd3ef0523da49ac17f0463e10fda9c4a2773352"}, + {file = "ruamel.yaml.clib-0.2.14-cp39-cp39-win_amd64.whl", hash = "sha256:8dd3c2cc49caa7a8d64b67146462aed6723a0495e44bf0aa0a2e94beaa8432f6"}, + {file = "ruamel.yaml.clib-0.2.14.tar.gz", hash = "sha256:803f5044b13602d58ea378576dd75aa759f52116a0232608e8fdada4da33752e"}, ] [[package]] @@ -2974,23 +2821,23 @@ tests = ["coverage[toml] (>=5.0.2)", "pytest"] [[package]] name = "setuptools" -version = "75.6.0" +version = "80.9.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" files = [ - {file = "setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d"}, - {file = "setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6"}, + {file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}, + {file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"] -core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"] +core = ["importlib_metadata (>=6)", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "six" @@ -3048,13 +2895,13 @@ saml = ["python-saml (>=2.2.0)", "python3-saml (>=1.2.1)"] [[package]] name = "sqlparse" -version = "0.5.2" +version = "0.5.3" description = "A non-validating SQL parser." optional = false python-versions = ">=3.8" files = [ - {file = "sqlparse-0.5.2-py3-none-any.whl", hash = "sha256:e99bc85c78160918c3e1d9230834ab8d80fc06c59d03f8db2618f65f65dda55e"}, - {file = "sqlparse-0.5.2.tar.gz", hash = "sha256:9e37b35e16d1cc652a2545f0997c1deb23ea28fa1f3eefe609eee3063c3b105f"}, + {file = "sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca"}, + {file = "sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272"}, ] [package.extras] @@ -3184,50 +3031,51 @@ windows-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)" [[package]] name = "txaio" -version = "23.1.1" +version = "23.6.1" description = "Compatibility API between asyncio/Twisted/Trollius" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "txaio-23.1.1-py2.py3-none-any.whl", hash = "sha256:aaea42f8aad50e0ecfb976130ada140797e9dcb85fad2cf72b0f37f8cefcb490"}, - {file = "txaio-23.1.1.tar.gz", hash = "sha256:f9a9216e976e5e3246dfd112ad7ad55ca915606b60b84a757ac769bd404ff704"}, + {file = "txaio-23.6.1-py2.py3-none-any.whl", hash = "sha256:ed993341154a20e38787fce8fcbd0297c2efd3ff90942e06475a299f354c40b6"}, + {file = "txaio-23.6.1.tar.gz", hash = "sha256:2e040bc849cb57a0abd2ec3dec78d540c474bcf6de0634e788764741c04aab93"}, ] [package.extras] all = ["twisted (>=20.3.0)", "zope.interface (>=5.2.0)"] -dev = ["pep8 (>=1.6.2)", "pyenchant (>=1.6.6)", "pytest (>=2.6.4)", "pytest-cov (>=1.8.1)", "sphinx (>=1.2.3)", "sphinx-rtd-theme (>=0.1.9)", "sphinxcontrib-spelling (>=2.1.2)", "tox (>=2.1.1)", "tox-gh-actions (>=2.2.0)", "twine (>=1.6.5)", "wheel"] +dev = ["black (>=25.1.0)", "flake8 (>=7.3.0)", "pyenchant (>=1.6.6)", "pytest (>=2.6.4)", "pytest-cov (>=1.8.1)", "sphinx (>=7.2.6)", "sphinx-autoapi (>=3.0.0)", "sphinx-rtd-theme (>=2.0.0)", "sphinxcontrib-bibtex (>=2.6.1)", "sphinxcontrib-images (>=0.9.4)", "sphinxcontrib-spelling (>=2.1.2)", "tox (>=2.1.1)", "tox-gh-actions (>=2.2.0)", "twine (>=1.6.5)", "wheel"] twisted = ["twisted (>=20.3.0)", "zope.interface (>=5.2.0)"] [[package]] name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" +version = "4.15.0" +description = "Backported and Experimental Type Hints for Python 3.9+" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, + {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] [[package]] -name = "unicodecsv" -version = "0.14.1" -description = "Python2's stdlib csv module is nice, but it doesn't support unicode. This module is a drop-in replacement which *does*." +name = "tzdata" +version = "2025.2" +description = "Provider of IANA time zone data" optional = false -python-versions = "*" +python-versions = ">=2" files = [ - {file = "unicodecsv-0.14.1.tar.gz", hash = "sha256:018c08037d48649a0412063ff4eda26eaa81eff1546dbffa51fa5293276ff7fc"}, + {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, + {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, ] [[package]] name = "uritemplate" -version = "4.1.1" +version = "4.2.0" description = "Implementation of RFC 6570 URI Templates" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" files = [ - {file = "uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e"}, - {file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"}, + {file = "uritemplate-4.2.0-py3-none-any.whl", hash = "sha256:962201ba1c4edcab02e60f9a0d3821e82dfc5d2d6662a21abd533879bdb8a686"}, + {file = "uritemplate-4.2.0.tar.gz", hash = "sha256:480c2ed180878955863323eea31b0ede668795de182617fef9c6ca09e6ec9d0e"}, ] [[package]] @@ -3384,13 +3232,13 @@ files = [ [[package]] name = "wcwidth" -version = "0.2.13" +version = "0.2.14" description = "Measures the displayed width of unicode strings in a terminal" optional = false -python-versions = "*" +python-versions = ">=3.6" files = [ - {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, - {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, + {file = "wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1"}, + {file = "wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605"}, ] [[package]] @@ -3451,13 +3299,13 @@ brotli = ["Brotli"] [[package]] name = "zipp" -version = "3.21.0" +version = "3.23.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.9" files = [ - {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, - {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, + {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, + {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, ] [package.extras] @@ -3465,53 +3313,47 @@ check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] [[package]] name = "zope-interface" -version = "7.2" +version = "8.0" description = "Interfaces for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "zope.interface-7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ce290e62229964715f1011c3dbeab7a4a1e4971fd6f31324c4519464473ef9f2"}, - {file = "zope.interface-7.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:05b910a5afe03256b58ab2ba6288960a2892dfeef01336dc4be6f1b9ed02ab0a"}, - {file = "zope.interface-7.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:550f1c6588ecc368c9ce13c44a49b8d6b6f3ca7588873c679bd8fd88a1b557b6"}, - {file = "zope.interface-7.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ef9e2f865721553c6f22a9ff97da0f0216c074bd02b25cf0d3af60ea4d6931d"}, - {file = "zope.interface-7.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27f926f0dcb058211a3bb3e0e501c69759613b17a553788b2caeb991bed3b61d"}, - {file = "zope.interface-7.2-cp310-cp310-win_amd64.whl", hash = "sha256:144964649eba4c5e4410bb0ee290d338e78f179cdbfd15813de1a664e7649b3b"}, - {file = "zope.interface-7.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1909f52a00c8c3dcab6c4fad5d13de2285a4b3c7be063b239b8dc15ddfb73bd2"}, - {file = "zope.interface-7.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:80ecf2451596f19fd607bb09953f426588fc1e79e93f5968ecf3367550396b22"}, - {file = "zope.interface-7.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:033b3923b63474800b04cba480b70f6e6243a62208071fc148354f3f89cc01b7"}, - {file = "zope.interface-7.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a102424e28c6b47c67923a1f337ede4a4c2bba3965b01cf707978a801fc7442c"}, - {file = "zope.interface-7.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25e6a61dcb184453bb00eafa733169ab6d903e46f5c2ace4ad275386f9ab327a"}, - {file = "zope.interface-7.2-cp311-cp311-win_amd64.whl", hash = "sha256:3f6771d1647b1fc543d37640b45c06b34832a943c80d1db214a37c31161a93f1"}, - {file = "zope.interface-7.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:086ee2f51eaef1e4a52bd7d3111a0404081dadae87f84c0ad4ce2649d4f708b7"}, - {file = "zope.interface-7.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:21328fcc9d5b80768bf051faa35ab98fb979080c18e6f84ab3f27ce703bce465"}, - {file = "zope.interface-7.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6dd02ec01f4468da0f234da9d9c8545c5412fef80bc590cc51d8dd084138a89"}, - {file = "zope.interface-7.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e7da17f53e25d1a3bde5da4601e026adc9e8071f9f6f936d0fe3fe84ace6d54"}, - {file = "zope.interface-7.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cab15ff4832580aa440dc9790b8a6128abd0b88b7ee4dd56abacbc52f212209d"}, - {file = "zope.interface-7.2-cp312-cp312-win_amd64.whl", hash = "sha256:29caad142a2355ce7cfea48725aa8bcf0067e2b5cc63fcf5cd9f97ad12d6afb5"}, - {file = "zope.interface-7.2-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:3e0350b51e88658d5ad126c6a57502b19d5f559f6cb0a628e3dc90442b53dd98"}, - {file = "zope.interface-7.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15398c000c094b8855d7d74f4fdc9e73aa02d4d0d5c775acdef98cdb1119768d"}, - {file = "zope.interface-7.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:802176a9f99bd8cc276dcd3b8512808716492f6f557c11196d42e26c01a69a4c"}, - {file = "zope.interface-7.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb23f58a446a7f09db85eda09521a498e109f137b85fb278edb2e34841055398"}, - {file = "zope.interface-7.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a71a5b541078d0ebe373a81a3b7e71432c61d12e660f1d67896ca62d9628045b"}, - {file = "zope.interface-7.2-cp313-cp313-win_amd64.whl", hash = "sha256:4893395d5dd2ba655c38ceb13014fd65667740f09fa5bb01caa1e6284e48c0cd"}, - {file = "zope.interface-7.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d3a8ffec2a50d8ec470143ea3d15c0c52d73df882eef92de7537e8ce13475e8a"}, - {file = "zope.interface-7.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:31d06db13a30303c08d61d5fb32154be51dfcbdb8438d2374ae27b4e069aac40"}, - {file = "zope.interface-7.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e204937f67b28d2dca73ca936d3039a144a081fc47a07598d44854ea2a106239"}, - {file = "zope.interface-7.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:224b7b0314f919e751f2bca17d15aad00ddbb1eadf1cb0190fa8175edb7ede62"}, - {file = "zope.interface-7.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baf95683cde5bc7d0e12d8e7588a3eb754d7c4fa714548adcd96bdf90169f021"}, - {file = "zope.interface-7.2-cp38-cp38-win_amd64.whl", hash = "sha256:7dc5016e0133c1a1ec212fc87a4f7e7e562054549a99c73c8896fa3a9e80cbc7"}, - {file = "zope.interface-7.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bd449c306ba006c65799ea7912adbbfed071089461a19091a228998b82b1fdb"}, - {file = "zope.interface-7.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a19a6cc9c6ce4b1e7e3d319a473cf0ee989cbbe2b39201d7c19e214d2dfb80c7"}, - {file = "zope.interface-7.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72cd1790b48c16db85d51fbbd12d20949d7339ad84fd971427cf00d990c1f137"}, - {file = "zope.interface-7.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52e446f9955195440e787596dccd1411f543743c359eeb26e9b2c02b077b0519"}, - {file = "zope.interface-7.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ad9913fd858274db8dd867012ebe544ef18d218f6f7d1e3c3e6d98000f14b75"}, - {file = "zope.interface-7.2-cp39-cp39-win_amd64.whl", hash = "sha256:1090c60116b3da3bfdd0c03406e2f14a1ff53e5771aebe33fec1edc0a350175d"}, - {file = "zope.interface-7.2.tar.gz", hash = "sha256:8b49f1a3d1ee4cdaf5b32d2e738362c7f5e40ac8b46dd7d1a65e82a4872728fe"}, + {file = "zope_interface-8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:daf4d6ba488a0fb560980b575244aa962a75e77b7c86984138b8d52bd4b5465f"}, + {file = "zope_interface-8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0caca2915522451e92c96c2aec404d2687e9c5cb856766940319b3973f62abb8"}, + {file = "zope_interface-8.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:a26ae2fe77c58b4df8c39c2b7c3aadedfd44225a1b54a1d74837cd27057b2fc8"}, + {file = "zope_interface-8.0-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:453d2c6668778b8d2215430ed61e04417386e51afb23637ef2e14972b047b700"}, + {file = "zope_interface-8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a2c107cc6dff954be25399cd81ddc390667f79af306802fc0c1de98614348b70"}, + {file = "zope_interface-8.0-cp310-cp310-win_amd64.whl", hash = "sha256:c23af5b4c4e332253d721ec1222c809ad27ceae382ad5b8ff22c4c4fb6eb8ed5"}, + {file = "zope_interface-8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ec1da7b9156ae000cea2d19bad83ddb5c50252f9d7b186da276d17768c67a3cb"}, + {file = "zope_interface-8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:160ba50022b342451baf516de3e3a2cd2d8c8dbac216803889a5eefa67083688"}, + {file = "zope_interface-8.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:879bb5bf937cde4acd738264e87f03c7bf7d45478f7c8b9dc417182b13d81f6c"}, + {file = "zope_interface-8.0-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7fb931bf55c66a092c5fbfb82a0ff3cc3221149b185bde36f0afc48acb8dcd92"}, + {file = "zope_interface-8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1858d1e5bb2c5ae766890708184a603eb484bb7454e306e967932a9f3c558b07"}, + {file = "zope_interface-8.0-cp311-cp311-win_amd64.whl", hash = "sha256:7e88c66ebedd1e839082f308b8372a50ef19423e01ee2e09600b80e765a10234"}, + {file = "zope_interface-8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b80447a3a5c7347f4ebf3e50de319c8d2a5dabd7de32f20899ac50fc275b145d"}, + {file = "zope_interface-8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:67047a4470cb2fddb5ba5105b0160a1d1c30ce4b300cf264d0563136adac4eac"}, + {file = "zope_interface-8.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:1bee9c1b42513148f98d3918affd829804a5c992c000c290dc805f25a75a6a3f"}, + {file = "zope_interface-8.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:804ebacb2776eb89a57d9b5e9abec86930e0ee784a0005030801ae2f6c04d5d8"}, + {file = "zope_interface-8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c4d9d3982aaa88b177812cd911ceaf5ffee4829e86ab3273c89428f2c0c32cc4"}, + {file = "zope_interface-8.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea1f2e47bc0124a03ee1e5fb31aee5dfde876244bcc552b9e3eb20b041b350d7"}, + {file = "zope_interface-8.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:ee9ecad04269c2da4b1be403a47993981531ffd557064b870eab4094730e5062"}, + {file = "zope_interface-8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a9a8a71c38628af82a9ea1f7be58e5d19360a38067080c8896f6cbabe167e4f8"}, + {file = "zope_interface-8.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:c0cc51ebd984945362fd3abdc1e140dbd837c3e3b680942b3fa24fe3aac26ef8"}, + {file = "zope_interface-8.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:07405019f635a93b318807cb2ec7b05a5ef30f67cf913d11eb2f156ddbcead0d"}, + {file = "zope_interface-8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:450ab3357799eed6093f3a9f1fa22761b3a9de9ebaf57f416da2c9fb7122cdcb"}, + {file = "zope_interface-8.0-cp313-cp313-win_amd64.whl", hash = "sha256:e38bb30a58887d63b80b01115ab5e8be6158b44d00b67197186385ec7efe44c7"}, + {file = "zope_interface-8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:778458ea69413cf8131a3fcc6f0ea2792d07df605422fb03ad87daca3f8f78ce"}, + {file = "zope_interface-8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b207966f39c2e6fcfe9b68333acb7b19afd3fdda29eccc4643f8d52c180a3185"}, + {file = "zope_interface-8.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:e3cf57f90a760c56c55668f650ba20c3444cde8332820db621c9a1aafc217471"}, + {file = "zope_interface-8.0-cp39-cp39-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5cffe23eb610e32a83283dde5413ab7a17938fa3fbd023ca3e529d724219deb0"}, + {file = "zope_interface-8.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4d639d5015c1753031e180b8ef81e72bb7d47b0aca0218694ad1f19b0a6c6b63"}, + {file = "zope_interface-8.0-cp39-cp39-win_amd64.whl", hash = "sha256:dee2d1db1067e8a4b682dde7eb4bff21775412358e142f4f98c9066173f9dacd"}, + {file = "zope_interface-8.0.tar.gz", hash = "sha256:b14d5aac547e635af749ce20bf49a3f5f93b8a854d2a6b1e95d4d5e5dc618f7d"}, ] [package.dependencies] @@ -3525,4 +3367,4 @@ testing = ["coverage[toml]", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "3.9.20" -content-hash = "a9888830b33f3c14c881e92e942cf2428918f20a18cd820a28758c5e39ada365" +content-hash = "76effc1abf53840d5b5ed9ca2e8d058412ca14235ffc3bc75923891630851109" diff --git a/pyproject.toml b/pyproject.toml index 29968523c..b2757daaf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,14 +8,14 @@ package-mode = false [tool.poetry.dependencies] python = "3.9.20" -django = "2.2.28" -django-oauth-toolkit = "1.0.0" +django = "3.2.0" +django-oauth-toolkit = "1.2.0" django-cors-middleware = "1.5.0" social-auth-core = "2.0.0" social-auth-app-django = "3.1.0" six = "1.16.0" django-extensions = "2.2.6" -channels = "2.4" +channels = "3.0.0" channels-redis = "4.0.0" django-extra-fields = "0.9" pillow = "10.3.0" @@ -41,20 +41,19 @@ django-ajax-selects = "2.0.0" dj-database-url = "0.4.2" psycopg2-binary = "2.8.6" django-redis = "4.12.1" -django-storages = {version = "1.7.2", extras = ["azure", "google"]} +django-storages = "1.9.1" azure-storage-blob = "2.1.0" azure-storage-common = "2.1.0" boto3 = "1.9.68" whitenoise = "5.2.0" coreapi = "2.3.3" -djangorestframework = "3.9.1" -djangorestframework-csv = "2.1.0" +djangorestframework = "3.12.0" +djangorestframework-csv = "3.0.1" drf-extensions = "0.4.0" markdown = "2.6.11" pygments = "2.2.0" -drf-writable-nested = "0.5.4" +drf-writable-nested = "0.6.2" django-filter = "2.4.0" -drf-yasg = {version = "1.11.0", extras = ["validation"]} flex = "6.12.0" pyrabbit2 = "1.0.7" django-enforce-host = "1.0.1" @@ -67,6 +66,9 @@ pytest-pythonpath = "0.7.3" selenium = "3.141.0" jinja2 = "3.1.4" requests = "2.32.2" +drf-extra-fields = "3.0.2" +drf-yasg2 = "^1.19.4" +swagger-spec-validator = "^3.0.4" [build-system] requires = ["poetry-core"] diff --git a/src/apps/api/serializers/competitions.py b/src/apps/api/serializers/competitions.py index c9488997e..d4557a1c6 100644 --- a/src/apps/api/serializers/competitions.py +++ b/src/apps/api/serializers/competitions.py @@ -329,7 +329,28 @@ def update(self, instance, validated_data): validated_data.pop('whitelist_emails', None) # Continue with the regular update process - super(CompetitionSerializer, self).update(instance, validated_data) + collaborators = validated_data.get('collaborators', None) + instance = super(CompetitionSerializer, self).update(instance, validated_data) + + # Django 3.0 doesn't automatically cascade updates through many to many relationships + # Rationale is that there is too much "magic" in database operations through ORM + # Therefore we need to explicitly create collaborator users in the CompetitionParticipant table + if collaborators is not None: + # First update the M2M relationship + instance.collaborators.set(collaborators) + + # Then ensure each collaborator has a CompetitionParticipant entry + # Also set to 'pending' as '_ensure_organizer_participants_accepted' in + # src/aops/api/views/competitions.py 'CompetitionViewSet' + # adjusts the status to 'approved' + for collaborator in collaborators: + CompetitionParticipant.objects.get_or_create( + user=collaborator, + competition=instance, + defaults={ + 'status': 'pending', + } + ) return instance diff --git a/src/apps/api/serializers/datasets.py b/src/apps/api/serializers/datasets.py index 127f97478..110aba43f 100644 --- a/src/apps/api/serializers/datasets.py +++ b/src/apps/api/serializers/datasets.py @@ -78,8 +78,15 @@ class DataDetailSerializer(serializers.ModelSerializer): created_by = serializers.CharField(source='created_by.username', read_only=True) owner_display_name = serializers.SerializerMethodField() competition = serializers.SerializerMethodField() + file_size = serializers.SerializerMethodField() value = serializers.CharField(source='key', required=False) + # These fields will be conditionally returned for type == SUBMISSION only + submission_file_size = serializers.SerializerMethodField() + prediction_result_file_size = serializers.SerializerMethodField() + scoring_result_file_size = serializers.SerializerMethodField() + detailed_result_file_size = serializers.SerializerMethodField() + class Meta: model = Data fields = ( @@ -96,11 +103,72 @@ class Meta: 'value', 'was_created_by_competition', 'in_use', - 'file_size', 'competition', 'file_name', + 'file_size', + 'submission_file_size', + 'prediction_result_file_size', + 'scoring_result_file_size', + 'detailed_result_file_size', ) + def to_representation(self, instance): + """ + Called automatically by DRF when serializing a model instance to JSON. + + This method customizes the serialized output of the DataDetailSerializer. + Specifically, it removes detailed file size fields when the data type is not 'SUBMISSION'. + + Example: For input_data or scoring_program types, submission-related fields + are not relevant and will be excluded from the output. + """ + # First, generate the default serialized representation using the parent method + rep = super().to_representation(instance) + + # If this data object is NOT of type 'submission', remove the following fields + if instance.type != Data.SUBMISSION: + # These fields are only meaningful for submission-type data + rep.pop('submission_file_size', None) + rep.pop('prediction_result_file_size', None) + rep.pop('scoring_result_file_size', None) + rep.pop('detailed_result_file_size', None) + + # Return the final customized representation + return rep + + def get_file_size(self, obj): + # Check if the data object is of type 'SUBMISSION' + if obj.type == Data.SUBMISSION: + # Start with the base file size of the data file itself (if present) + total_size = obj.file_size or 0 + + # Loop through all submissions that use this data + for submission in obj.submission.all(): + # Add the size of the prediction result file (if any) + total_size += submission.prediction_result_file_size or 0 + # Add the size of the scoring result file (if any) + total_size += submission.scoring_result_file_size or 0 + # Add the size of the detailed result file (if any) + total_size += submission.detailed_result_file_size or 0 + + # Return the combined size of data file and all associated result files + return total_size + + # For non-submission data types, just return the file size as-is + return obj.file_size + + def get_submission_file_size(self, obj): + return obj.file_size or 0 + + def get_prediction_result_file_size(self, obj): + return sum([s.prediction_result_file_size or 0 for s in obj.submission.all()]) + + def get_scoring_result_file_size(self, obj): + return sum([s.scoring_result_file_size or 0 for s in obj.submission.all()]) + + def get_detailed_result_file_size(self, obj): + return sum([s.detailed_result_file_size or 0 for s in obj.submission.all()]) + def get_competition(self, obj): if obj.competition: # Submission diff --git a/src/apps/api/serializers/tasks.py b/src/apps/api/serializers/tasks.py index 7cf13d1cc..639f6e594 100644 --- a/src/apps/api/serializers/tasks.py +++ b/src/apps/api/serializers/tasks.py @@ -78,7 +78,10 @@ class Meta: ) def get_validated(self, instance): - return hasattr(instance, 'validated') and instance.validated is not None + # We should get the results of TaskViewSet's evaluation + # for whether a task is validated or not vs just whether + # or not the attribute 'validated' exists...it could be false. + return getattr(instance, 'validated', False) class TaskDetailSerializer(WritableNestedModelSerializer): @@ -116,7 +119,10 @@ class Meta: ) def get_validated(self, instance): - return hasattr(instance, 'validated') and instance.validated is not None + # We should get the results of TaskViewSet's evaluation + # for whether a task is validated or not vs just whether + # or not the attribute 'validated' exists...it could be false. + return getattr(instance, 'validated', False) def get_competitions(self, instance): diff --git a/src/apps/api/tests/test_competitions.py b/src/apps/api/tests/test_competitions.py index 59ebc216c..b85b0e2f9 100644 --- a/src/apps/api/tests/test_competitions.py +++ b/src/apps/api/tests/test_competitions.py @@ -48,6 +48,7 @@ def test_adding_organizer_creates_accepted_participant(self): resp = self.client.put(url, data=json.dumps(data), content_type="application/json") assert resp.status_code == 200 + assert CompetitionParticipant.objects.filter( user=self.other_user, competition=self.comp, diff --git a/src/apps/api/tests/test_submissions.py b/src/apps/api/tests/test_submissions.py index fb5b3966f..a12e3ef13 100644 --- a/src/apps/api/tests/test_submissions.py +++ b/src/apps/api/tests/test_submissions.py @@ -554,6 +554,7 @@ def setUp(self): self.leaderboard = LeaderboardFactory() self.comp = CompetitionFactory(created_by=self.creator) self.phase = PhaseFactory(competition=self.comp) + self.organization = OrganizationFactory() # Approved participant CompetitionParticipantFactory(user=self.participant, competition=self.comp, status=CompetitionParticipant.APPROVED) @@ -591,6 +592,15 @@ def setUp(self): leaderboard=None ) + self.organization_submission = SubmissionFactory( + phase=self.phase, + owner=self.participant, + status=Submission.FINISHED, + is_soft_deleted=False, + leaderboard=None, + organization=self.organization + ) + def test_cannot_delete_submission_if_not_owner(self): """Ensure that a non-owner cannot soft delete a submission.""" self.client.login(username="other_user", password="other") @@ -639,3 +649,17 @@ def test_can_soft_delete_submission_successfully(self): # Refresh from DB to verify self.submission.refresh_from_db() assert self.submission.is_soft_deleted is True + + def test_organization_is_removed_from_soft_deleted_submission(self): + """Ensure a organization reference is removed from soft-deleted submission""" + self.client.login(username="participant", password="participant") + url = reverse("submission-soft-delete", args=[self.organization_submission.pk]) + resp = self.client.delete(url) + + assert resp.status_code == 200 + assert resp.data["message"] == "Submission deleted successfully" + + # Refresh from DB to verify + self.organization_submission.refresh_from_db() + assert self.organization_submission.is_soft_deleted is True + assert self.organization_submission.organization is None diff --git a/src/apps/api/tests/test_tasks.py b/src/apps/api/tests/test_tasks.py index 257fa5aaa..7b00b76cc 100644 --- a/src/apps/api/tests/test_tasks.py +++ b/src/apps/api/tests/test_tasks.py @@ -3,52 +3,51 @@ from rest_framework.test import APITestCase from rest_framework import status -from competitions.models import Submission -from factories import UserFactory, CompetitionFactory, TaskFactory, SolutionFactory, PhaseFactory, SubmissionFactory, DataFactory - - -class TestTasks(APITestCase): - def test_task_shown_as_validated_properly(self): - user = UserFactory(username='test') - solution = SolutionFactory(md5="12345") - task = TaskFactory(created_by=user, solutions=[solution]) - competition = CompetitionFactory(created_by=user) - phase = PhaseFactory(competition=competition, tasks=[task]) - submission = SubmissionFactory(md5="12345", phase=phase, status=Submission.FINISHED) - url = reverse('task-detail', kwargs={'pk': task.id}) - self.client.login(username=user.username, password='test') - - # task should be validated because we have a successful submission matching - # our solution - resp = self.client.get(url) - assert resp.status_code == 200 - assert resp.data["validated"] - - # make submission anything but Submission.FINISHED, task -> invalidated - submission.status = Submission.FAILED - submission.save() - resp = self.client.get(url) - assert resp.status_code == 200 - assert not resp.data["validated"] - - # make submission Submission.Finished, task -> re-validated - submission.status = Submission.FINISHED - submission.save() - resp = self.client.get(url) - assert resp.status_code == 200 - assert resp.data["validated"] - - # delete submission, task -> re-invalidated - submission.delete() - resp = self.client.get(url) - assert resp.status_code == 200 - assert not resp.data["validated"] - - # make submission with different Sha -> still invalid - SubmissionFactory(md5="different", phase=phase, status=Submission.FINISHED) - resp = self.client.get(url) - assert resp.status_code == 200 - assert not resp.data["validated"] +from factories import UserFactory, DataFactory + +# Removed this test because of the changes of this PR : https://github.com/codalab/codabench/pull/1963 +# class TestTasks(APITestCase): +# def test_task_shown_as_validated_properly(self): +# user = UserFactory(username='test') +# solution = SolutionFactory(md5="12345") +# task = TaskFactory(created_by=user, solutions=[solution]) +# competition = CompetitionFactory(created_by=user) +# phase = PhaseFactory(competition=competition, tasks=[task]) +# submission = SubmissionFactory(md5="12345", phase=phase, status=Submission.FINISHED) +# url = reverse('task-detail', kwargs={'pk': task.id}) +# self.client.login(username=user.username, password='test') + +# # task should be validated because we have a successful submission matching +# # our solution +# resp = self.client.get(url) +# assert resp.status_code == 200 +# assert resp.data["validated"] + +# # make submission anything but Submission.FINISHED, task -> invalidated +# submission.status = Submission.FAILED +# submission.save() +# resp = self.client.get(url) +# assert resp.status_code == 200 +# assert not resp.data["validated"] + +# # make submission Submission.Finished, task -> re-validated +# submission.status = Submission.FINISHED +# submission.save() +# resp = self.client.get(url) +# assert resp.status_code == 200 +# assert resp.data["validated"] + +# # delete submission, task -> re-invalidated +# submission.delete() +# resp = self.client.get(url) +# assert resp.status_code == 200 +# assert not resp.data["validated"] + +# # make submission with different Sha -> still invalid +# SubmissionFactory(md5="different", phase=phase, status=Submission.FINISHED) +# resp = self.client.get(url) +# assert resp.status_code == 200 +# assert not resp.data["validated"] class TestUploadTask(APITestCase): diff --git a/src/apps/api/urls.py b/src/apps/api/urls.py index c116104ea..d0195fbc1 100644 --- a/src/apps/api/urls.py +++ b/src/apps/api/urls.py @@ -1,7 +1,7 @@ from django.conf.urls import include from django.urls import path, re_path -from drf_yasg import openapi -from drf_yasg.views import get_schema_view +from drf_yasg2 import openapi +from drf_yasg2.views import get_schema_view from rest_framework.authtoken.views import obtain_auth_token from rest_framework.routers import SimpleRouter from rest_framework.permissions import AllowAny diff --git a/src/apps/api/views/competitions.py b/src/apps/api/views/competitions.py index 056cb34bf..2a09bf8c5 100644 --- a/src/apps/api/views/competitions.py +++ b/src/apps/api/views/competitions.py @@ -8,7 +8,7 @@ from django.db import IntegrityError from django.db.models import Subquery, OuterRef, Q from django_filters.rest_framework import DjangoFilterBackend -from drf_yasg.utils import swagger_auto_schema, no_body +from drf_yasg2.utils import swagger_auto_schema, no_body from rest_framework import status from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied, ValidationError @@ -775,24 +775,7 @@ def get_leaderboard(self, request, pk): submissions_keys = {} submission_detailed_results = {} for submission in query['submissions']: - # count number of entries/number of submissions for the owner of this submission for this phase - # count all submissions except: - # - child submissions (submissions who has a parent i.e. parent field is not null) - # - Failed submissions - # - Cancelled submissions - num_entries = 1 # TMP, remove counting - # num_entries = Submission.objects.filter( - # Q(owner__username=submission['owner']) | - # Q(parent__owner__username=submission['owner']), - # phase=phase, - # ).exclude( - # Q(status=Submission.FAILED) | - # Q(status=Submission.CANCELLED) | - # Q(parent__isnull=False) - # ).count() - submission_key = f"{submission['owner']}{submission['parent'] or submission['id']}" - # gather detailed result from submissions for each task # detailed_results are gathered based on submission key # `id` is used to fetch the right detailed result in detailed results page @@ -813,7 +796,6 @@ def get_leaderboard(self, request, pk): 'fact_sheet_answers': submission['fact_sheet_answers'], 'slug_url': submission['slug_url'], 'organization': submission['organization'], - 'num_entries': num_entries, 'created_when': submission['created_when'] }) for score in submission['scores']: diff --git a/src/apps/api/views/datasets.py b/src/apps/api/views/datasets.py index dade6bff9..8618af38e 100644 --- a/src/apps/api/views/datasets.py +++ b/src/apps/api/views/datasets.py @@ -52,8 +52,15 @@ def get_queryset(self): # filter datasets and programs if is_dataset: - qs = qs.filter(~Q(type=Data.SUBMISSION)) - qs = qs.exclude(Q(type=Data.COMPETITION_BUNDLE)) + qs = qs.filter(type__in=[ + Data.INPUT_DATA, + Data.PUBLIC_DATA, + Data.REFERENCE_DATA, + Data.INGESTION_PROGRAM, + Data.SCORING_PROGRAM, + Data.STARTING_KIT, + Data.SOLUTION + ]) # filter bundles if is_bundle: diff --git a/src/apps/api/views/profiles.py b/src/apps/api/views/profiles.py index 494b76a46..7c7f6dcd8 100644 --- a/src/apps/api/views/profiles.py +++ b/src/apps/api/views/profiles.py @@ -13,6 +13,7 @@ from rest_framework.response import Response from rest_framework import status from django.urls import reverse +from django.db import IntegrityError from api.permissions import IsUserAdminOrIsSelf, IsOrganizationEditor from api.serializers.profiles import MyProfileSerializer, UserSerializer, \ @@ -257,17 +258,24 @@ def delete_organization(self, request, pk=None): try: org = Organization.objects.get(id=pk) member = org.membership_set.get(user=request.user) - if member.group == Membership.OWNER: - org.delete() - return Response({ - "success": True, - "message": "Organization deleted!" - }) - else: + if member.group != Membership.OWNER: return Response({ "success": False, "message": "You do not have delete rights!" }) + + org.delete() + return Response({ + "success": True, + "message": "Organization deleted!" + }) + + except IntegrityError: + return Response({ + "success": False, + "message": "This organization cannot be deleted because it is associated with existing submissions. Please remove those submissions first." + }) + except Exception as e: return Response({ "success": False, diff --git a/src/apps/api/views/tasks.py b/src/apps/api/views/tasks.py index 31a3b027c..9bed7c2fd 100644 --- a/src/apps/api/views/tasks.py +++ b/src/apps/api/views/tasks.py @@ -3,8 +3,10 @@ import zipfile from django.core.files.uploadedfile import InMemoryUploadedFile from collections import defaultdict -from django.db.models import Q, OuterRef, Subquery + +from django.db.models import Q, Value, BooleanField from django.db import transaction + from rest_framework import status from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied @@ -15,7 +17,7 @@ from api.pagination import BasicPagination from api.serializers import tasks as serializers -from competitions.models import Submission, Phase +from competitions.models import Phase from profiles.models import User from tasks.models import Task from datasets.models import Data @@ -24,8 +26,6 @@ # TODO:// TaskViewSimple uses simple serializer from tasks, which exists purely for the use of Select2 on phase modal # is there a better way to do it using get_serializer_class() method? - - class TaskViewSet(ModelViewSet): queryset = Task.objects.all() serializer_class = serializers.TaskSerializer @@ -46,7 +46,6 @@ def get_queryset(self): 'solutions', 'solutions__data' ) - task_filter = Q(created_by=self.request.user) | Q(shared_with=self.request.user) # when there is `public` in the query params, it means user has checked on the front-end # the Show public tasks checkbox. @@ -54,20 +53,10 @@ def get_queryset(self): # the public task to the user and hence we check the `retrieve` action if self.request.query_params.get('public') or self.action == 'retrieve': task_filter |= Q(is_public=True) - + # Removed the "task validation" process (https://github.com/codalab/codabench/pull/1962) + # We now always set "validated" to False. The "task validation" was only partly implemented and never used. qs = qs.filter(task_filter) - - # Determine whether a task is "valid" by finding some solution with a - # passing submission - task_validate_qs = Submission.objects.filter( - md5__in=OuterRef("solutions__md5"), - status=Submission.FINISHED, - # TODO: This line causes our query to take ~10 seconds. Is this important? - # phase__in=OuterRef("phases") - ) - # We have to grab something from task_validate_qs here, so i grab pk - qs = qs.annotate(validated=Subquery(task_validate_qs.values('pk')[:1])) - + qs = qs.annotate(validated=Value(False, output_field=BooleanField())) return qs.order_by('-created_when').distinct() def get_serializer_class(self): diff --git a/src/apps/competitions/admin.py b/src/apps/competitions/admin.py index b991555da..942133b4b 100644 --- a/src/apps/competitions/admin.py +++ b/src/apps/competitions/admin.py @@ -1,12 +1,48 @@ from django.contrib import admin +from django.utils.translation import gettext_lazy as _ from . import models +class privateCompetitionsFilter(admin.SimpleListFilter): + # Human-readable title which will be displayed in the + # right admin sidebar just above the filter options. + title = _("Private non-test") + + # Parameter for the filter that will be used in the URL query. + parameter_name = "private" + + def lookups(self, request, model_admin): + """ + Returns a list of tuples. The first element in each + tuple is the coded value for the option that will + appear in the URL query. The second element is the + human-readable name for the option that will appear + in the right sidebar. + """ + return [ + ("privateSmall", _("Submissions >= 25 and Participants >= 10")), + ] + + def queryset(self, request, queryset): + """ + Returns the filtered queryset based on the value + provided in the query string and retrievable via + `self.value()`. + """ + # Only show private competitions with >= 25 submissions and >=10 participants + if self.value() == "privateSmall": + return queryset.filter( + published=False, + submissions_count__gte=10, + participants_count__gte=5 + ) + + class CompetitionAdmin(admin.ModelAdmin): search_fields = ['title', 'docker_image', 'created_by__username'] list_display = ['id', 'title', 'created_by', 'is_featured'] - list_filter = ['is_featured'] + list_filter = ['is_featured', privateCompetitionsFilter] admin.site.register(models.Competition, CompetitionAdmin) diff --git a/src/apps/competitions/consumers.py b/src/apps/competitions/consumers.py index cff9d1596..3fc22a21d 100644 --- a/src/apps/competitions/consumers.py +++ b/src/apps/competitions/consumers.py @@ -1,7 +1,12 @@ import json import logging +import time + +from asgiref.sync import sync_to_async +from django.contrib.auth import get_user_model from channels.generic.websocket import AsyncWebsocketConsumer +# from channels.exceptions import DenyConnection from django_redis import get_redis_connection from competitions.models import Submission from utils.data import make_url_sassy @@ -15,8 +20,11 @@ class SubmissionIOConsumer(AsyncWebsocketConsumer): async def connect(self): submission_id = self.scope['url_route']['kwargs']['submission_id'] secret = self.scope['url_route']['kwargs']['secret'] + logger.debug(f"CONSUMER_MARKER: Connecting for submission {submission_id} with secret {secret}") try: - Submission.objects.get(pk=submission_id, secret=secret) + _ = await sync_to_async(Submission.objects.get)( + pk=submission_id, secret=secret + ) except Submission.DoesNotExist: return await self.close() @@ -25,44 +33,80 @@ async def connect(self): async def receive(self, text_data=None, bytes_data=None): user_pk = self.scope['url_route']['kwargs']['user_pk'] submission_id = self.scope['url_route']['kwargs']['submission_id'] - - logger.debug(f"Received websocket input for user = {user_pk}, submission = {submission_id}, text_data = {text_data}") + logger.debug(f"CONSUMER_MARKER: Received data for submission {submission_id} | {text_data}") try: - sub = Submission.objects.get(pk=submission_id) - except Submission.DoesNotExist: - return await self.close() - - if sub.phase.hide_output and not sub.phase.competition.user_has_admin_permission(user_pk): - return - - data = json.loads(text_data) - if data['kind'] == 'detailed_result_update': - data['result_url'] = make_url_sassy(Submission.objects.get(id=submission_id).detailed_result.name) - # update text data to include the newly added sas url for retrieval on page refresh - text_data = json.dumps(data) - - con = get_redis_connection("default") - con.append(f':1:submission-{submission_id}-log', f'{text_data}\n') + # Get all necessary data in one transaction if possible + sub = await sync_to_async(Submission.objects.get)(pk=submission_id) + User = get_user_model() + user = await sync_to_async(User.objects.get)(pk=user_pk) + phase = await sync_to_async(lambda: sub.phase)() + competition = await sync_to_async(lambda: phase.competition)() + has_admin = await sync_to_async(lambda: competition.user_has_admin_permission(user))() + + if phase.hide_output and not has_admin: + logger.warning(f"User {user_pk} attempted to access hidden output for submission {submission_id}") + return + + data = json.loads(text_data) + + if data['kind'] == 'detailed_result_update': + # No need to fetch the submission again, we already have it + data['result_url'] = make_url_sassy(sub.detailed_result.name) + # update text data to include the newly added sas url for retrieval on page refresh + text_data = json.dumps(data) + + # Store in Redis + con = get_redis_connection("default") + con.append(f':1:submission-{submission_id}-log', f'{text_data}\n') + + # Send to channel layer + try: + await self.channel_layer.group_send(f"submission_listening_{user_pk}", { + 'type': 'submission_message', + 'text': data, + 'submission_id': submission_id, + }) + logger.debug(f"RELAY_MARKER: Sent message to channel layer for user {user_pk}, submission {submission_id}") + except Exception as e: + logger.error(f"Error sending to channel layer: {e}") - await self.channel_layer.group_send(f"submission_listening_{user_pk}", { - 'type': 'submission.message', - 'text': data, - 'submission_id': submission_id, - }) + except Submission.DoesNotExist: + logger.warning(f"Submission {submission_id} does not exist") + await self.close(code=4004) # Custom code for "Resource not found" + except Exception as e: + logger.error(f"Error in WebSocket receive: {e}") + await self.close(code=1011) # Internal error class SubmissionOutputConsumer(AsyncWebsocketConsumer): async def connect(self): if not self.scope["user"].is_authenticated: return await self.close() + # raise DenyConnection() + + try: + await self.accept() + logger.debug(f"WebSocket connected for user {self.scope['user'].pk}") + except RuntimeError as e: + logger.warning(f"WebSocket accept failed: {e}") + return # prevent group_add - await self.accept() await self.channel_layer.group_add(f"submission_listening_{self.scope['user'].pk}", self.channel_name) + logger.debug(f"WebSocket connection established for user {self.scope['user'].pk}") + + # Send confirmation to client that the connection is ready + await self.send(json.dumps({ + "type": "connection_ready", + "status": "connected" + })) async def disconnect(self, close_code): - await self.channel_layer.group_discard(f"submission_listening_{self.scope['user'].pk}", self.channel_name) - await self.close() + logger.debug(f"WebSocket disconnecting with code {close_code} for user {self.scope['user'].pk}") + try: + await self.channel_layer.group_discard(f"submission_listening_{self.scope['user'].pk}", self.channel_name) + except Exception as e: + logger.warning(f"Error during group_discard: {e}") def group_send(self, text, submission_id, full_text=False): return self.channel_layer.group_send(f"submission_listening_{self.scope['user'].pk}", { @@ -81,7 +125,10 @@ async def receive(self, text_data=None, bytes_data=None): if submission_ids: # Filter out submissions not by this user - submissions = Submission.objects.filter(id__in=submission_ids, owner=self.scope["user"]) + # submissions = Submission.objects.filter(id__in=submission_ids, owner=self.scope["user"]) + submissions = await sync_to_async(lambda: list(Submission.objects.filter( + id__in=submission_ids, owner=self.scope["user"] + )))() con = get_redis_connection("default") for sub in submissions: @@ -90,9 +137,17 @@ async def receive(self, text_data=None, bytes_data=None): await self.group_send(text.decode('utf-8'), sub.id, full_text=True) async def submission_message(self, event): + logger.debug(f"FRONTEND_MARKER: Processing message for submission {event['submission_id']}") + + time.sleep(0.3) # Simulate some processing delay data = { "type": "catchup" if event.get('full_text') else "message", "submission_id": event['submission_id'], "data": event['text'] } - await self.send(json.dumps(data)) + + try: + await self.send(json.dumps(data)) + logger.debug(f"FRONTEND_MARKER: Successfully sent message to frontend for submission {event['submission_id']}") + except Exception as e: + logger.warning(f"Failed to send WebSocket message: {e}") diff --git a/src/apps/competitions/models.py b/src/apps/competitions/models.py index d8ce83dad..97b29ef8b 100644 --- a/src/apps/competitions/models.py +++ b/src/apps/competitions/models.py @@ -576,6 +576,7 @@ def soft_delete(self): """ Soft delete the submission: remove files but keep record in DB. Also deletes associated SubmissionDetails and cleans up storage. + Also removes organization reference from the submission """ # Remove related files from storage @@ -600,6 +601,9 @@ def soft_delete(self): # Clear the data field for this submission self.data = None + # Clear the organization field for this submission + self.organization = None + # Mark submission as deleted self.is_soft_deleted = True self.soft_deleted_when = now() diff --git a/src/apps/profiles/views.py b/src/apps/profiles/views.py index 9fbc2daba..8868c154a 100644 --- a/src/apps/profiles/views.py +++ b/src/apps/profiles/views.py @@ -95,7 +95,7 @@ def activate(request, uidb64, token): def activateEmail(request, user, to_email): mail_subject = 'Activate your user account.' message = render_to_string('profiles/emails/template_activate_account.html', { - 'user': user.username, + 'username': user.username, 'domain': get_current_site(request).domain, 'uid': urlsafe_base64_encode(force_bytes(user.pk)), 'token': account_activation_token.make_token(user), @@ -103,8 +103,8 @@ def activateEmail(request, user, to_email): }) email = EmailMessage(mail_subject, message, to=[to_email]) if email.send(): - messages.success(request, f'Dear {user.username}, please go to you email {to_email} inbox and click on \ - received activation link to confirm and complete the registration. *Note: Check your spam folder.') + messages.success(request, f'Dear {user.username}, please go to your email {to_email} inbox and click on \ + the activation link to confirm and complete the registration. *Note: Check your spam folder.') else: messages.error(request, f'Problem sending confirmation email to {to_email}, check if you typed it correctly.') diff --git a/src/asgi.py b/src/asgi.py index 2d7df19f4..30a04946d 100644 --- a/src/asgi.py +++ b/src/asgi.py @@ -1,12 +1,22 @@ -""" -ASGI entrypoint. Configures Django and then runs the application -defined in the ASGI_APPLICATION setting. -""" - import os import django -from channels.routing import get_default_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings.develop") django.setup() -application = get_default_application() + +# Django components must be imported after django.setup() - ignore flake8 import order +from channels.routing import ProtocolTypeRouter, URLRouter # noqa: E402 +from channels.auth import AuthMiddlewareStack # noqa: E402 +from django.core.asgi import get_asgi_application # noqa: E402 + +import routing # noqa: E402 + + +application = ProtocolTypeRouter({ + "http": get_asgi_application(), + "websocket": AuthMiddlewareStack( + URLRouter( + routing.websocket_urlpatterns + ) + ), +}) diff --git a/src/routing.py b/src/routing.py index 1f28120e8..2ef280e73 100644 --- a/src/routing.py +++ b/src/routing.py @@ -1,16 +1,7 @@ -from channels.auth import AuthMiddlewareStack -from django.urls import path -from channels.routing import ProtocolTypeRouter, URLRouter +from django.urls import re_path +from apps.competitions.consumers import SubmissionIOConsumer, SubmissionOutputConsumer -from competitions import consumers - - -application = ProtocolTypeRouter({ - # (http->django views is added by default) - - "websocket": AuthMiddlewareStack(URLRouter([ - path("submission_input////", consumers.SubmissionIOConsumer), - path("submission_output/", consumers.SubmissionOutputConsumer), - # path(r".*", consumers.SubmissionOutputConsumer), - ])), -}) +websocket_urlpatterns = [ + re_path(r'submission_input/(?P\d+)/(?P\d+)/(?P[^/]+)/$', SubmissionIOConsumer.as_asgi()), + re_path(r'submission_output/$', SubmissionOutputConsumer.as_asgi()), +] diff --git a/src/settings/base.py b/src/settings/base.py index dba14455c..bac58ac03 100644 --- a/src/settings/base.py +++ b/src/settings/base.py @@ -43,7 +43,7 @@ 'django_filters', 'storages', 'channels', - 'drf_yasg', + 'drf_yasg2', 'redis', ) OUR_APPS = ( @@ -158,7 +158,7 @@ # ============================================================================= # Debugging # ============================================================================= -DEBUG = os.environ.get("DEBUG", False) +DEBUG = os.environ.get("DEBUG", "False").lower() == "true" # ============================================================================= # Database @@ -320,13 +320,17 @@ 'handlers': ['console'], 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'), }, + 'channels': { + 'handlers': ['console'], + 'level': 'DEBUG', + }, }, } # ============================================================================= # Channels # ============================================================================= -ASGI_APPLICATION = "routing.application" +ASGI_APPLICATION = "asgi.application" CHANNEL_LAYERS = { "default": { diff --git a/src/static/js/ours/latex_markdown_html.js b/src/static/js/ours/latex_markdown_html.js index 6ee169f08..eba1b874d 100644 --- a/src/static/js/ours/latex_markdown_html.js +++ b/src/static/js/ours/latex_markdown_html.js @@ -1,29 +1,103 @@ -// Function to render Markdown, HTML and Latex and return updated content +// Function to render Markdown content that may include: +// - Code blocks (```...```) +// - Inline and block LaTeX ($...$ or $$...$$) +// - HTML +// The function returns an array of DOM nodes generated from the fully rendered and processed content. function renderMarkdownWithLatex(content) { - if(content === null){ - return [] - } - const parsedHtml = new DOMParser().parseFromString(marked(content), "text/html") - - const traverseAndRenderLatex = (node) => { - if (node.nodeType === Node.ELEMENT_NODE) { - const latexPattern = /\$\$([\s\S]*?)\$\$|\$([^\$\n]*?)\$/g - const hasLatex = latexPattern.test(node.textContent) - if (hasLatex) { - const tempDiv = document.createElement('div') - tempDiv.innerHTML = node.innerHTML.replace(latexPattern, (_, formula1, formula2) => { - const formula = formula1 || formula2 - const decodedFormula = formula.replace(/</g, '<').replace(/>/g, '>') - return katex.renderToString(decodedFormula, { throwOnError: false }) - }); - node.innerHTML = tempDiv.innerHTML - } + if (!content) return [] // Return empty if content is null or empty + + // --------------------------------------------------------- + // Step 1: Extract and temporarily replace all code blocks + // --------------------------------------------------------- + + // Regex to match code blocks in Markdown: ```[language]\n[code]``` + const codeBlockPattern = /```(\w*)\n([\s\S]*?)```/g + const codeBlocks = [] // Store original code blocks and their tokens + let codeIndex = 0 // Counter to generate unique tokens for code blocks + + // Replace each code block with a unique token and store the original + const contentWithoutCode = content.replace(codeBlockPattern, (_, lang, code) => { + const token = `%%CODE_BLOCK_${codeIndex++}%%` + codeBlocks.push({ token, lang, code }) // Store the token and the original code + return token // Replace the block with its token in the text + }) + + // --------------------------------------------------------- + // Step 2: Extract and replace LaTeX expressions with placeholders + // --------------------------------------------------------- + + // Regex to match inline ($...$) and block ($$...$$) LaTeX formulas + const latexPattern = /\$\$([\s\S]+?)\$\$|\$([^\$\n]+?)\$/g + const latexBlocks = [] // Store rendered LaTeX HTML and their tokens + let latexIndex = 0 // Counter for LaTeX token IDs + + // Replace LaTeX expressions with unique tokens and store rendered HTML + const contentWithLatexPlaceholders = contentWithoutCode.replace(latexPattern, (_, block, inline) => { + const formula = block || inline // Pick block or inline formula content + const displayMode = !!block // Use displayMode for block ($$...$$) + let rendered // Store the rendered HTML from KaTeX + + try { + // Render LaTeX to HTML using KaTeX + rendered = katex.renderToString(formula, { + throwOnError: false, + displayMode, + }) + } catch (e) { + console.error("KaTeX error:", e) + rendered = `${formula}` // If render fails, fallback to raw code } - node.childNodes.forEach(traverseAndRenderLatex) - }; + const token = `%%LATEX_BLOCK_${latexIndex++}%%` + latexBlocks.push({ token, rendered }) // Store the token and rendered HTML + return token // Replace formula with its token in the text + }) + + // --------------------------------------------------------- + // Step 3: Convert Markdown to HTML + // --------------------------------------------------------- + + // Run the Markdown parser on the content (now safe with all code and LaTeX replaced by tokens) + let html = marked(contentWithLatexPlaceholders) - traverseAndRenderLatex(parsedHtml.body) + // --------------------------------------------------------- + // Step 4: Restore rendered LaTeX blocks into the HTML + // --------------------------------------------------------- + // Replace each LaTeX token with the rendered KaTeX HTML + for (const { token, rendered } of latexBlocks) { + html = html.replace(token, rendered) + } + + // --------------------------------------------------------- + // Step 5: Restore escaped code blocks back into the HTML + // --------------------------------------------------------- + + // Replace each code block token with HTML-safe
 block
+  for (const { token, code, lang } of codeBlocks) {
+    const safeCode = escapeHtml(code) // Escape HTML-sensitive characters inside code
+    html = html.replace(token, `
${safeCode}
`) + } + + + // --------------------------------------------------------- + // Step 6: Convert final HTML string into DOM nodes and return + // --------------------------------------------------------- + + // Parse the final HTML string into actual DOM nodes + const parsedHtml = new DOMParser().parseFromString(html, "text/html") + + // Return child nodes from the parsed HTML body return parsedHtml.body.childNodes -} \ No newline at end of file +} + +// Utility function to escape HTML special characters inside code blocks +function escapeHtml(text) { + return text + .replace(/&/g, "&") // escape ampersands + .replace(//g, ">") // escape > + .replace(/"/g, """) // escape double quotes + .replace(/'/g, "'") // escape single quotes +} + diff --git a/src/static/riot/competitions/detail/leaderboards.tag b/src/static/riot/competitions/detail/leaderboards.tag index b004d5ce9..319539833 100644 --- a/src/static/riot/competitions/detail/leaderboards.tag +++ b/src/static/riot/competitions/detail/leaderboards.tag @@ -28,13 +28,12 @@ Task: - + { task.name } # Participant - Entries Date ID {column.title} @@ -83,7 +82,6 @@ { submission.owner } { submission.organization.name } - {submission.num_entries} { pretty_date(submission.created_when) } {submission.id} @@ -256,10 +254,10 @@ color #8c8c8c .index-column min-width 55px - .leaderboard-title - position absolute - left 50% - transform translate(-50%, 50%) + .leaderboard-title + position: absolute + left: 50% + transform: translate(-50%, -50%) .ui.table > thead > tr.task-row > th background-color: #e8f6ff !important .eye-icon-link diff --git a/src/static/riot/competitions/detail/participant_manager.tag b/src/static/riot/competitions/detail/participant_manager.tag index b8ebeca13..f3f93b823 100644 --- a/src/static/riot/competitions/detail/participant_manager.tag +++ b/src/static/riot/competitions/detail/participant_manager.tag @@ -16,7 +16,16 @@ -
Email all participants
+
+ +
+ Email all participants +
+ +
+ Download all participants +
+
@@ -204,5 +213,40 @@ $(self.refs.email_modal).modal('hide') } + // Function to download participants in csv file + self.download_participants_csv = () => { + // Show warning when there is no participant + if (!self.participants || self.participants.length === 0) { + toastr.warning('No participants to download') + return + } + + // prepare csv header + const headers = ['ID', 'Username', 'Email', 'Is Bot', 'Status']; + // prepare csv rows + const rows = self.participants.map(p => [ + p.id, + p.username, + p.email, + p.is_bot ? 'Yes' : 'No', + p.status + ]); + + // prepare csv content using header and rows + const csvContent = [headers, ...rows] + .map(e => e.map(v => `"${(v ?? '').toString().replace(/"/g, '""')}"`).join(',')) + .join('\n') + + // Download prepared csv as `participants.csv` + const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }) + const url = URL.createObjectURL(blob) + const link = document.createElement("a") + link.setAttribute("href", url) + link.setAttribute("download", "participants.csv") + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + } + diff --git a/src/static/riot/competitions/detail/submission_upload.tag b/src/static/riot/competitions/detail/submission_upload.tag index 0a56ca02f..61c57b197 100644 --- a/src/static/riot/competitions/detail/submission_upload.tag +++ b/src/static/riot/competitions/detail/submission_upload.tag @@ -225,16 +225,30 @@ } self.setup_websocket = function () { + // Add message tracking + self.processed_messages = new Set(); // Submission stream handler var url = new URL('/submission_output/', window.location.href); url.protocol = url.protocol.replace('http', 'ws'); var options = { - automaticOpen: false + automaticOpen: false, + maxReconnectAttempts: 10, + reconnectInterval: 1000 // milliseconds } self.ws = new ReconnectingWebSocket(url, null, options) self.ws.addEventListener("message", function (event) { self.autoscroll_output() let event_data = JSON.parse(event.data) + // Generate message signature for deduplication + const msg_signature = `${event_data.type}-${event_data.submission_id}-${JSON.stringify(event_data.data)}`; + // Skip if we've already processed this exact message + if (self.processed_messages.has(msg_signature)) { + console.log("Skipping duplicate message:", msg_signature); + return; + } + + // Track this message + self.processed_messages.add(msg_signature); switch (event_data.type) { case 'catchup': let detailed_result_url = '' @@ -255,10 +269,17 @@ } }) self.ws.addEventListener("open", function(event){ + console.log("WebSocket connected"); // we're connected, so now try to pull logs (otherwise we may hit a race condition, // maybe we don't have submissions yet?) self.pull_logs() }) + self.ws.addEventListener("close", function(event) { + console.log("WebSocket disconnected, reconnecting..."); + }) + self.ws.addEventListener("error", function(event) { + console.error("WebSocket error:", event); + }) self.ws.open() } diff --git a/src/static/riot/submissions/resource_submissions.tag b/src/static/riot/submissions/resource_submissions.tag index 7fb10942e..f88983abd 100644 --- a/src/static/riot/submissions/resource_submissions.tag +++ b/src/static/riot/submissions/resource_submissions.tag @@ -125,6 +125,31 @@ {selected_row.description} +
+ + + + + + + + + + + + + + + + + + + + + + + +
File Sizes
Submission:{pretty_bytes(selected_row.submission_file_size)}
Prediction result:{pretty_bytes(selected_row.prediction_result_file_size)}
Scoring result:{pretty_bytes(selected_row.scoring_result_file_size)}
Detailed result:{pretty_bytes(selected_row.detailed_result_file_size)}