diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..094c32693 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,35 @@ +# http://editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 +end_of_line = lf + +[*.py] +indent_size = 4 +max_line_length = 120 + +[*.md] +indent_size = 4 + +[*.yml] +indent_size = 4 + +[*.html] +max_line_length = off + +[*.js] +max_line_length = off + +[*.css] +indent_size = 4 +max_line_length = off + +# Tests can violate line width restrictions in the interest of clarity. +[**/test_*.py] +max_line_length = off diff --git a/.github/workflows/.hatch-run.yml b/.github/workflows/.hatch-run.yml deleted file mode 100644 index b312869e4..000000000 --- a/.github/workflows/.hatch-run.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: hatch-run - -on: - workflow_call: - inputs: - job-name: - required: true - type: string - hatch-run: - required: true - type: string - runs-on-array: - required: false - type: string - default: '["ubuntu-latest"]' - python-version-array: - required: false - type: string - default: '["3.x"]' - node-registry-url: - required: false - type: string - default: "" - secrets: - node-auth-token: - required: false - pypi-username: - required: false - pypi-password: - required: false - -jobs: - hatch: - name: ${{ format(inputs.job-name, matrix.python-version, matrix.runs-on) }} - strategy: - matrix: - python-version: ${{ fromJson(inputs.python-version-array) }} - runs-on: ${{ fromJson(inputs.runs-on-array) }} - runs-on: ${{ matrix.runs-on }} - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: "14.x" - registry-url: ${{ inputs.node-registry-url }} - - name: Pin NPM Version - run: npm install -g npm@8.19.3 - - name: Use Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install Python Dependencies - run: pip install hatch poetry - - name: Run Scripts - env: - NODE_AUTH_TOKEN: ${{ secrets.node-auth-token }} - PYPI_USERNAME: ${{ secrets.pypi-username }} - PYPI_PASSWORD: ${{ secrets.pypi-password }} - run: hatch run ${{ inputs.hatch-run }} diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml deleted file mode 100644 index af768579c..000000000 --- a/.github/workflows/check.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: check - -on: - push: - branches: - - main - pull_request: - branches: - - main - schedule: - - cron: "0 0 * * 0" - -jobs: - test-py-cov: - uses: ./.github/workflows/.hatch-run.yml - with: - job-name: "python-{0}" - hatch-run: "test-py" - lint-py: - uses: ./.github/workflows/.hatch-run.yml - with: - job-name: "python-{0}" - hatch-run: "lint-py" - test-py-matrix: - uses: ./.github/workflows/.hatch-run.yml - with: - job-name: "python-{0} {1}" - hatch-run: "test-py --no-cov" - runs-on-array: '["ubuntu-latest", "macos-latest", "windows-latest"]' - python-version-array: '["3.9", "3.10", "3.11"]' - test-docs: - uses: ./.github/workflows/.hatch-run.yml - with: - job-name: "python-{0}" - hatch-run: "test-docs" - test-js: - uses: ./.github/workflows/.hatch-run.yml - with: - job-name: "{1}" - hatch-run: "test-js" - lint-js: - uses: ./.github/workflows/.hatch-run.yml - with: - job-name: "{1}" - hatch-run: "lint-js" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index b4f77ee00..000000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,71 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: codeql - -on: - push: - branches: [main] - pull_request: - # The branches below must be a subset of the branches above - branches: [main] - schedule: - - cron: "43 3 * * 3" - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: ["javascript", "python"] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml deleted file mode 100644 index 7337f505b..000000000 --- a/.github/workflows/deploy-docs.yml +++ /dev/null @@ -1,30 +0,0 @@ -# This workflows will upload a Python Package using Twine when a release is created -# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries - -name: deploy-docs - -on: - push: - branches: - - "main" - tags: - - "*" - -jobs: - deploy-documentation: - runs-on: ubuntu-latest - steps: - - name: Check out src from Git - uses: actions/checkout@v2 - - name: Get history and tags for SCM versioning to work - run: | - git fetch --prune --unshallow - git fetch --depth=1 origin +refs/tags/*:refs/tags/* - - name: Login to Heroku Container Registry - run: echo ${{ secrets.HEROKU_API_KEY }} | docker login -u ${{ secrets.HEROKU_EMAIL }} --password-stdin registry.heroku.com - - name: Build Docker Image - run: docker build . --file docs/Dockerfile --tag registry.heroku.com/${{ secrets.HEROKU_APP_NAME }}/web - - name: Push Docker Image - run: docker push registry.heroku.com/${{ secrets.HEROKU_APP_NAME }}/web - - name: Deploy - run: HEROKU_API_KEY=${{ secrets.HEROKU_API_KEY }} heroku container:release web --app ${{ secrets.HEROKU_APP_NAME }} diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml new file mode 100644 index 000000000..199bc1766 --- /dev/null +++ b/.github/workflows/publish-docs.yml @@ -0,0 +1,17 @@ +name: Publish Docs +on: + push: + branches: + - new-docs +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - run: pip install -r docs/requirements.txt + - run: cd docs && mkdocs gh-deploy --force diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index e9271cbd5..000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,20 +0,0 @@ -# This workflows will upload a Javscript Package using NPM to npmjs.org when a release is created -# For more information see: https://docs.github.com/en/actions/guides/publishing-nodejs-packages - -name: publish - -on: - release: - types: [published] - -jobs: - publish: - uses: ./.github/workflows/.hatch-run.yml - with: - job-name: "publish" - hatch-run: "publish" - node-registry-url: "https://registry.npmjs.org" - secrets: - node-auth-token: ${{ secrets.NODE_AUTH_TOKEN }} - pypi-username: ${{ secrets.PYPI_USERNAME }} - pypi-password: ${{ secrets.PYPI_PASSWORD }} diff --git a/.gitignore b/.gitignore index 20c041e11..788d5a329 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ +# --- Build Artifacts --- +src/reactpy/static/index.js* +src/reactpy/static/morphdom/ +src/reactpy/static/pyscript/ + # --- Jupyter --- *.ipynb_checkpoints *Untitled*.ipynb @@ -11,8 +16,9 @@ .jupyter # --- Python --- -.venv -venv +.hatch +.venv* +venv* MANIFEST build dist @@ -28,6 +34,7 @@ pip-wheel-metadata .python-version # -- Python Tests --- +.coverage.* *.coverage *.pytest_cache *.mypy_cache @@ -38,4 +45,3 @@ pip-wheel-metadata # --- JS --- node_modules - diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..d7bd784cf --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,27 @@ +# Changelog + +All notable changes to this project will be documented in this file. + + + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + + + + + + +## [Unreleased] + +- Nothing (yet) + +[unreleased]: https://github.com/reactive-python/reactpy/compare/1.0.0...HEAD diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 5caf76c93..000000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2019-2022 Ryan S. Morshead - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..f5423c3d3 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,9 @@ +## The MIT License (MIT) + +#### Copyright (c) Reactive Python and affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 83241e19a..d24c250a4 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,21 @@ -# ReactPy +Temporary branch being used to rewrite ReactPy's documentation. -

- - - - - - - - - - - - - - - -

+Many of these pages are in progress, and are using the [original ReactJS docs](https://react.dev/learn) as placeholders. +See live preview here: https://reactive-python.github.io/reactpy -[ReactPy](https://reactpy.dev/) is a library for building user interfaces in Python without Javascript. ReactPy interfaces are made from components that look and behave similar to those found in [ReactJS](https://reactjs.org/). Designed with simplicity in mind, ReactPy can be used by those without web development experience while also being powerful enough to grow with your ambitions. +In order to set up an environment to develop these docs... - - - - - - - - - - - - - - - -
Supported Backends
Built-inExternal
- - Flask, FastAPI, Sanic, Tornado - - - Django, - Jupyter, - Plotly-Dash -
+1. Install [Python](https://www.python.org/downloads/) 3.9 or higher +2. Fork and clone this repository +3. _Optional_: Create a Python virtual environment with the following command: `python3 -m venv venv` +4. _Optional_: Activate the virtual environment (this method will vary based on operating system) +5. Install the dependencies with the following command: `pip install -r docs/requirements.txt` +6. Run the following command: `mkdocs serve` +7. Follow the on-screen prompts to view the documentation in your browser +8. You can now edit the markdown files located within `docs/src/` and see the changes in real time -# At a Glance +🚧 : Unfinished tab +🚫 : Tab is blocked from being started due to external factors -To get a rough idea of how to write apps in ReactPy, take a look at this tiny _Hello World_ application. - -```python -from reactpy import component, html, run - -@component -def hello_world(): - return html.h1("Hello, World!") - -run(hello_world) -``` - -# Resources - -Follow the links below to find out more about this project. - -- [Try ReactPy (Jupyter Notebook)](https://mybinder.org/v2/gh/reactive-python/reactpy-jupyter/main?urlpath=lab/tree/notebooks/introduction.ipynb) -- [Documentation](https://reactpy.dev/) -- [GitHub Discussions](https://github.com/reactive-python/reactpy/discussions) -- [Discord](https://discord.gg/uNb5P4hA9X) -- [Contributor Guide](https://reactpy.dev/docs/about/contributor-guide.html) -- [Code of Conduct](https://github.com/reactive-python/reactpy/blob/main/CODE_OF_CONDUCT.md) +Feel free to PR this branch with any changes you make to the documentation. If you have any questions, feel free to ask in the [Discord server](https://discord.gg/uNb5P4hA9X). diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index ea38eebf8..000000000 --- a/docs/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -build -source/_auto -source/_static/custom.js -source/vdom-json-schema.json diff --git a/docs/Dockerfile b/docs/Dockerfile deleted file mode 100644 index 76a8ad7ee..000000000 --- a/docs/Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -FROM python:3.9 - -WORKDIR /app/ - -# Install NodeJS -# -------------- -RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - -RUN apt-get install -yq nodejs build-essential -RUN npm install -g npm@8.5.0 - -# Install Poetry -# -------------- -RUN pip install poetry - -# Create/Activate Python Venv -# --------------------------- -ENV VIRTUAL_ENV=/opt/venv -RUN python3 -m venv $VIRTUAL_ENV -ENV PATH="$VIRTUAL_ENV/bin:$PATH" -RUN pip install --upgrade pip - -# Copy Files -# ---------- -COPY LICENSE ./ -COPY src ./src -COPY docs ./docs -COPY branding ./branding - -# Install and Build Docs -# ---------------------- -WORKDIR /app/docs -RUN poetry install -RUN sphinx-build -v -W -b html source build - -# Define Entrypoint -# ----------------- -ENV PORT 5000 -ENV REACTPY_DEBUG_MODE=1 -ENV REACTPY_CHECK_VDOM_SPEC=0 -CMD python main.py diff --git a/docs/LICENSE.md b/docs/LICENSE.md new file mode 100644 index 000000000..d21a91a91 --- /dev/null +++ b/docs/LICENSE.md @@ -0,0 +1,393 @@ +Attribution 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of +these terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the +Licensed Material available under these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public licenses. +Notwithstanding, Creative Commons may elect to apply one of its public +licenses to material it publishes and in those instances will be +considered the "Licensor." Except for the limited purpose of indicating +that material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the public +licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 1360bc825..000000000 --- a/docs/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# ReactPy's Documentation - -We provide two main ways to run the docs. Both use -[`nox`](https://pypi.org/project/nox/): - -- `nox -s docs` - displays the docs and rebuilds when files are modified. -- `nox -s docs-in-docker` - builds a docker image and runs the docs from there. - -If any changes to the core of the documentation are made (i.e. to non-`*.rst` files), -then you should run a manual test of the documentation using the `docs_in_docker` -session. - -If you wish to build and run the docs by hand you need to perform two commands, each -being run from the root of the repository: - -- `sphinx-build -b html docs/source docs/build` -- `python scripts/run_docs.py` - -The first command constructs the static HTML and any Javascript. The latter actually -runs the web server that serves the content. diff --git a/docs/docs_app/app.py b/docs/docs_app/app.py deleted file mode 100644 index 3fe4669ff..000000000 --- a/docs/docs_app/app.py +++ /dev/null @@ -1,59 +0,0 @@ -from logging import getLogger -from pathlib import Path - -from sanic import Sanic, response - -from docs_app.examples import get_normalized_example_name, load_examples -from reactpy import component -from reactpy.backend.sanic import Options, configure, use_request -from reactpy.core.types import ComponentConstructor - -THIS_DIR = Path(__file__).parent -DOCS_DIR = THIS_DIR.parent -DOCS_BUILD_DIR = DOCS_DIR / "build" - -REACTPY_MODEL_SERVER_URL_PREFIX = "/_reactpy" - -logger = getLogger(__name__) - - -REACTPY_MODEL_SERVER_URL_PREFIX = "/_reactpy" - - -@component -def Example(): - raw_view_id = use_request().get_args().get("view_id") - view_id = get_normalized_example_name(raw_view_id) - return _get_examples()[view_id]() - - -def _get_examples(): - if not _EXAMPLES: - _EXAMPLES.update(load_examples()) - return _EXAMPLES - - -def reload_examples(): - _EXAMPLES.clear() - _EXAMPLES.update(load_examples()) - - -_EXAMPLES: dict[str, ComponentConstructor] = {} - - -def make_app(name: str): - app = Sanic(name) - - app.static("/docs", str(DOCS_BUILD_DIR)) - - @app.route("/") - async def forward_to_index(_): - return response.redirect("/docs/index.html") - - configure( - app, - Example, - Options(url_prefix=REACTPY_MODEL_SERVER_URL_PREFIX), - ) - - return app diff --git a/docs/docs_app/dev.py b/docs/docs_app/dev.py deleted file mode 100644 index 5d661924d..000000000 --- a/docs/docs_app/dev.py +++ /dev/null @@ -1,104 +0,0 @@ -import asyncio -import os -import threading -import time -import webbrowser - -from sphinx_autobuild.cli import ( - Server, - _get_build_args, - _get_ignore_handler, - find_free_port, - get_builder, - get_parser, -) - -from docs_app.app import make_app, reload_examples -from reactpy.backend.sanic import serve_development_app -from reactpy.testing import clear_reactpy_web_modules_dir - -# these environment variable are used in custom Sphinx extensions -os.environ["REACTPY_DOC_EXAMPLE_SERVER_HOST"] = "127.0.0.1:5555" -os.environ["REACTPY_DOC_STATIC_SERVER_HOST"] = "" - - -def wrap_builder(old_builder): - # This is the bit that we're injecting to get the example components to reload too - - app = make_app("docs_dev_app") - - thread_started = threading.Event() - - def run_in_thread(): - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - - server_started = asyncio.Event() - - async def set_thread_event_when_started(): - await server_started.wait() - thread_started.set() - - loop.run_until_complete( - asyncio.gather( - serve_development_app(app, "127.0.0.1", 5555, server_started), - set_thread_event_when_started(), - ) - ) - - threading.Thread(target=run_in_thread, daemon=True).start() - - thread_started.wait() - - def new_builder(): - clear_reactpy_web_modules_dir() - reload_examples() - old_builder() - - return new_builder - - -def main(): - # Mostly copied from https://github.com/executablebooks/sphinx-autobuild/blob/b54fb08afc5112bfcda1d844a700c5a20cd6ba5e/src/sphinx_autobuild/cli.py - parser = get_parser() - args = parser.parse_args() - - srcdir = os.path.realpath(args.sourcedir) - outdir = os.path.realpath(args.outdir) - if not os.path.exists(outdir): - os.makedirs(outdir) - - server = Server() - - build_args, pre_build_commands = _get_build_args(args) - builder = wrap_builder( - get_builder( - server.watcher, - build_args, - host=args.host, - port=args.port, - pre_build_commands=pre_build_commands, - ) - ) - - ignore_handler = _get_ignore_handler(args) - server.watch(srcdir, builder, ignore=ignore_handler) - for dirpath in args.additional_watched_dirs: - real_dirpath = os.path.realpath(dirpath) - server.watch(real_dirpath, builder, ignore=ignore_handler) - server.watch(outdir, ignore=ignore_handler) - - if not args.no_initial_build: - builder() - - # Find the free port - portn = args.port or find_free_port() - if args.openbrowser is True: - - def opener(): - time.sleep(args.delay) - webbrowser.open(f"http://{args.host}:{args.port}/index.html") - - threading.Thread(target=opener, daemon=True).start() - - server.serve(port=portn, host=args.host, root=outdir) diff --git a/docs/docs_app/examples.py b/docs/docs_app/examples.py deleted file mode 100644 index a71a0b111..000000000 --- a/docs/docs_app/examples.py +++ /dev/null @@ -1,177 +0,0 @@ -from __future__ import annotations - -from collections.abc import Iterator -from io import StringIO -from pathlib import Path -from traceback import format_exc -from typing import Callable - -import reactpy -from reactpy.types import ComponentType - -HERE = Path(__file__) -SOURCE_DIR = HERE.parent.parent / "source" -CONF_FILE = SOURCE_DIR / "conf.py" -RUN_ReactPy = reactpy.run - - -def load_examples() -> Iterator[tuple[str, Callable[[], ComponentType]]]: - for name in all_example_names(): - yield name, load_one_example(name) - - -def all_example_names() -> set[str]: - names = set() - for file in _iter_example_files(SOURCE_DIR): - path = file.parent if file.name == "main.py" else file - names.add("/".join(path.relative_to(SOURCE_DIR).with_suffix("").parts)) - return names - - -def load_one_example(file_or_name: Path | str) -> Callable[[], ComponentType]: - return lambda: ( - # we use a lambda to ensure each instance is fresh - _load_one_example(file_or_name) - ) - - -def get_normalized_example_name( - name: str, relative_to: str | Path | None = SOURCE_DIR -) -> str: - return "/".join( - _get_root_example_path_by_name(name, relative_to).relative_to(SOURCE_DIR).parts - ) - - -def get_main_example_file_by_name( - name: str, relative_to: str | Path | None = SOURCE_DIR -) -> Path: - path = _get_root_example_path_by_name(name, relative_to) - if path.is_dir(): - return path / "main.py" - else: - return path.with_suffix(".py") - - -def get_example_files_by_name( - name: str, relative_to: str | Path | None = SOURCE_DIR -) -> list[Path]: - path = _get_root_example_path_by_name(name, relative_to) - if path.is_dir(): - return [p for p in path.glob("*") if not p.is_dir()] - else: - path = path.with_suffix(".py") - return [path] if path.exists() else [] - - -def _iter_example_files(root: Path) -> Iterator[Path]: - for path in root.iterdir(): - if path.is_dir(): - if not path.name.startswith("_") or path.name == "_examples": - yield from _iter_example_files(path) - elif path.suffix == ".py" and path != CONF_FILE: - yield path - - -def _load_one_example(file_or_name: Path | str) -> ComponentType: - if isinstance(file_or_name, str): - file = get_main_example_file_by_name(file_or_name) - else: - file = file_or_name - - if not file.exists(): - raise FileNotFoundError(str(file)) - - print_buffer = _PrintBuffer() - - def capture_print(*args, **kwargs): - buffer = StringIO() - print(*args, file=buffer, **kwargs) - print_buffer.write(buffer.getvalue()) - - captured_component_constructor = None - - def capture_component(component_constructor): - nonlocal captured_component_constructor - captured_component_constructor = component_constructor - - reactpy.run = capture_component - try: - code = compile(file.read_text(), str(file), "exec") - exec( - code, - { - "print": capture_print, - "__file__": str(file), - "__name__": file.stem, - }, - ) - except Exception: - return _make_error_display(format_exc()) - finally: - reactpy.run = RUN_ReactPy - - if captured_component_constructor is None: - return _make_example_did_not_run(str(file)) - - @reactpy.component - def Wrapper(): - return reactpy.html.div(captured_component_constructor(), PrintView()) - - @reactpy.component - def PrintView(): - text, set_text = reactpy.hooks.use_state(print_buffer.getvalue()) - print_buffer.set_callback(set_text) - return ( - reactpy.html.pre({"class_name": "printout"}, text) - if text - else reactpy.html.div() - ) - - return Wrapper() - - -def _get_root_example_path_by_name(name: str, relative_to: str | Path | None) -> Path: - if not name.startswith("/") and relative_to is not None: - rel_path = Path(relative_to) - rel_path = rel_path.parent if rel_path.is_file() else rel_path - else: - rel_path = SOURCE_DIR - return rel_path.joinpath(*name.split("/")).resolve() - - -class _PrintBuffer: - def __init__(self, max_lines: int = 10): - self._callback = None - self._lines = () - self._max_lines = max_lines - - def set_callback(self, function: Callable[[str], None]) -> None: - self._callback = function - - def getvalue(self) -> str: - return "".join(self._lines) - - def write(self, text: str) -> None: - if len(self._lines) == self._max_lines: - self._lines = self._lines[1:] + (text,) - else: - self._lines += (text,) - if self._callback is not None: - self._callback(self.getvalue()) - - -def _make_example_did_not_run(example_name): - @reactpy.component - def ExampleDidNotRun(): - return reactpy.html.code(f"Example {example_name} did not run") - - return ExampleDidNotRun() - - -def _make_error_display(message): - @reactpy.component - def ShowError(): - return reactpy.html.pre(message) - - return ShowError() diff --git a/docs/docs_app/prod.py b/docs/docs_app/prod.py deleted file mode 100644 index 0acf12432..000000000 --- a/docs/docs_app/prod.py +++ /dev/null @@ -1,14 +0,0 @@ -import os - -from docs_app.app import make_app - -app = make_app("docs_prod_app") - - -def main() -> None: - app.run( - host="0.0.0.0", # noqa: S104 - port=int(os.environ.get("PORT", 5000)), - workers=int(os.environ.get("WEB_CONCURRENCY", 1)), - debug=bool(int(os.environ.get("DEBUG", "0"))), - ) diff --git a/docs/examples/add_react_to_an_existing_project/asgi_component.py b/docs/examples/add_react_to_an_existing_project/asgi_component.py new file mode 100644 index 000000000..ed1a6b25b --- /dev/null +++ b/docs/examples/add_react_to_an_existing_project/asgi_component.py @@ -0,0 +1,6 @@ +from reactpy import component, html + + +@component +def hello_world(): + return html.div("Hello World") diff --git a/docs/examples/add_react_to_an_existing_project/asgi_configure_jinja.py b/docs/examples/add_react_to_an_existing_project/asgi_configure_jinja.py new file mode 100644 index 000000000..e22212e75 --- /dev/null +++ b/docs/examples/add_react_to_an_existing_project/asgi_configure_jinja.py @@ -0,0 +1,20 @@ +from jinja2 import Environment, FileSystemLoader +from starlette.applications import Starlette +from starlette.routing import Route +from starlette.templating import Jinja2Templates + +from reactpy.templatetags import ReactPyJinja + +jinja_templates = Jinja2Templates( + env=Environment( + loader=FileSystemLoader("path/to/my_templates"), + extensions=[ReactPyJinja], + ) +) + + +async def example_webpage(request): + return jinja_templates.TemplateResponse(request, "my_template.html") + + +starlette_app = Starlette(routes=[Route("/", example_webpage)]) diff --git a/docs/examples/add_react_to_an_existing_project/asgi_middleware.py b/docs/examples/add_react_to_an_existing_project/asgi_middleware.py new file mode 100644 index 000000000..2e397be02 --- /dev/null +++ b/docs/examples/add_react_to_an_existing_project/asgi_middleware.py @@ -0,0 +1,22 @@ +from jinja2 import Environment, FileSystemLoader +from starlette.applications import Starlette +from starlette.routing import Route +from starlette.templating import Jinja2Templates + +from reactpy.executors.asgi import ReactPyMiddleware +from reactpy.templatetags import ReactPyJinja + +jinja_templates = Jinja2Templates( + env=Environment( + loader=FileSystemLoader("path/to/my_templates"), + extensions=[ReactPyJinja], + ) +) + + +async def example_webpage(request): + return jinja_templates.TemplateResponse(request, "my_template.html") + + +starlette_app = Starlette(routes=[Route("/", example_webpage)]) +reactpy_app = ReactPyMiddleware(starlette_app, ["my_components.hello_world"]) diff --git a/docs/examples/add_react_to_an_existing_project/asgi_template.html b/docs/examples/add_react_to_an_existing_project/asgi_template.html new file mode 100644 index 000000000..4fe678b8b --- /dev/null +++ b/docs/examples/add_react_to_an_existing_project/asgi_template.html @@ -0,0 +1,12 @@ + + + + + ReactPy in Django + + + + {% component "my_components.hello_world" %} + + + diff --git a/docs/examples/creating_a_react_app/asgi_csr.py b/docs/examples/creating_a_react_app/asgi_csr.py new file mode 100644 index 000000000..506930d33 --- /dev/null +++ b/docs/examples/creating_a_react_app/asgi_csr.py @@ -0,0 +1,7 @@ +from pathlib import Path + +from reactpy.executors.asgi import ReactPyCsr + +my_app = ReactPyCsr( + Path(__file__).parent / "components" / "root.py", initial="Loading..." +) diff --git a/docs/examples/creating_a_react_app/asgi_csr_root.py b/docs/examples/creating_a_react_app/asgi_csr_root.py new file mode 100644 index 000000000..8a6c17c55 --- /dev/null +++ b/docs/examples/creating_a_react_app/asgi_csr_root.py @@ -0,0 +1,6 @@ +from reactpy import component, html + + +@component +def root(): + return html.div("Hello World") diff --git a/docs/examples/creating_a_react_app/asgi_ssr.py b/docs/examples/creating_a_react_app/asgi_ssr.py new file mode 100644 index 000000000..d2e9b72ff --- /dev/null +++ b/docs/examples/creating_a_react_app/asgi_ssr.py @@ -0,0 +1,10 @@ +from reactpy import component, html +from reactpy.executors.asgi import ReactPy + + +@component +def hello_world(): + return html.div("Hello World") + + +my_app = ReactPy(hello_world) diff --git a/docs/examples/quick_start/adding_styles.css b/docs/examples/quick_start/adding_styles.css new file mode 100644 index 000000000..4d02060e1 --- /dev/null +++ b/docs/examples/quick_start/adding_styles.css @@ -0,0 +1,4 @@ +/* In your CSS */ +.avatar { + border-radius: 50%; +} diff --git a/docs/examples/quick_start/adding_styles.py b/docs/examples/quick_start/adding_styles.py new file mode 100644 index 000000000..8e1c7931b --- /dev/null +++ b/docs/examples/quick_start/adding_styles.py @@ -0,0 +1,4 @@ +from reactpy import html + +# start +html.img({"className": "avatar"}) diff --git a/docs/examples/quick_start/conditional_rendering.py b/docs/examples/quick_start/conditional_rendering.py new file mode 100644 index 000000000..d89e097a4 --- /dev/null +++ b/docs/examples/quick_start/conditional_rendering.py @@ -0,0 +1,22 @@ +from reactpy import component, html + + +def admin_panel(): + return [] + + +def login_form(): + return [] + + +is_logged_in = True + + +# start +@component +def my_component(): + if is_logged_in: + content = admin_panel() + else: + content = login_form() + return html.div(content) diff --git a/docs/examples/quick_start/conditional_rendering_logical_and.py b/docs/examples/quick_start/conditional_rendering_logical_and.py new file mode 100644 index 000000000..07e752bba --- /dev/null +++ b/docs/examples/quick_start/conditional_rendering_logical_and.py @@ -0,0 +1,14 @@ +from reactpy import component, html + + +def admin_panel(): + return [] + + +is_logged_in = True + + +# start +@component +def my_component(): + return html.div(is_logged_in and admin_panel()) diff --git a/docs/examples/quick_start/conditional_rendering_ternary.py b/docs/examples/quick_start/conditional_rendering_ternary.py new file mode 100644 index 000000000..2490cb5f9 --- /dev/null +++ b/docs/examples/quick_start/conditional_rendering_ternary.py @@ -0,0 +1,18 @@ +from reactpy import component, html + + +def admin_panel(): + return [] + + +def login_form(): + return [] + + +is_logged_in = True + + +# start +@component +def my_component(): + return html.div(admin_panel() if is_logged_in else login_form()) diff --git a/docs/examples/quick_start/creating_and_nesting_components.py b/docs/examples/quick_start/creating_and_nesting_components.py new file mode 100644 index 000000000..99ff909a2 --- /dev/null +++ b/docs/examples/quick_start/creating_and_nesting_components.py @@ -0,0 +1,14 @@ +from reactpy import component, html + + +@component +def my_button(): + return html.button("I'm a button!") + + +@component +def my_app(): + return html.div( + html.h1("Welcome to my app"), + my_button(), + ) diff --git a/docs/examples/quick_start/displaying_data.css b/docs/examples/quick_start/displaying_data.css new file mode 100644 index 000000000..9f5a392c1 --- /dev/null +++ b/docs/examples/quick_start/displaying_data.css @@ -0,0 +1,7 @@ +.avatar { + border-radius: 50%; +} + +.large { + border: 4px solid gold; +} diff --git a/docs/examples/quick_start/displaying_data.py b/docs/examples/quick_start/displaying_data.py new file mode 100644 index 000000000..3edf62674 --- /dev/null +++ b/docs/examples/quick_start/displaying_data.py @@ -0,0 +1,25 @@ +from reactpy import component, html + +user = { + "name": "Hedy Lamarr", + "image_url": "https://i.imgur.com/yXOvdOSs.jpg", + "image_size": 90, +} + + +@component +def profile(): + return html.div( + html.h3(user["name"]), + html.img( + { + "className": "avatar", + "src": user["image_url"], + "alt": f"Photo of {user['name']}", + "style": { + "width": user["image_size"], + "height": user["image_size"], + }, + } + ), + ) diff --git a/docs/examples/quick_start/my_app.py b/docs/examples/quick_start/my_app.py new file mode 100644 index 000000000..1616d54d1 --- /dev/null +++ b/docs/examples/quick_start/my_app.py @@ -0,0 +1,12 @@ +from reactpy import component, html + +from .my_button import my_button + + +# start +@component +def my_app(): + return html.div( + html.h1("Welcome to my app"), + my_button(), + ) diff --git a/docs/examples/quick_start/my_button.py b/docs/examples/quick_start/my_button.py new file mode 100644 index 000000000..0016632ca --- /dev/null +++ b/docs/examples/quick_start/my_button.py @@ -0,0 +1,7 @@ +from reactpy import component, html + + +# start +@component +def my_button(): + return html.button("I'm a button!") diff --git a/docs/examples/quick_start/rendering_lists.py b/docs/examples/quick_start/rendering_lists.py new file mode 100644 index 000000000..be75f8ce2 --- /dev/null +++ b/docs/examples/quick_start/rendering_lists.py @@ -0,0 +1,23 @@ +from reactpy import component, html + +products = [ + {"title": "Cabbage", "is_fruit": False, "id": 1}, + {"title": "Garlic", "is_fruit": False, "id": 2}, + {"title": "Apple", "is_fruit": True, "id": 3}, +] + + +@component +def shopping_list(): + list_items = [ + html.li( + { + "key": product["id"], + "style": {"color": "magenta" if product["is_fruit"] else "darkgreen"}, + }, + product["title"], + ) + for product in products + ] + + return html.ul(list_items) diff --git a/docs/examples/quick_start/rendering_lists_list_items.py b/docs/examples/quick_start/rendering_lists_list_items.py new file mode 100644 index 000000000..43e108f36 --- /dev/null +++ b/docs/examples/quick_start/rendering_lists_list_items.py @@ -0,0 +1,6 @@ +from reactpy import html + +from .rendering_lists_products import products + +# start +list_items = [html.li({"key": product["id"]}, product["title"]) for product in products] diff --git a/docs/examples/quick_start/rendering_lists_products.py b/docs/examples/quick_start/rendering_lists_products.py new file mode 100644 index 000000000..c2d6a5e31 --- /dev/null +++ b/docs/examples/quick_start/rendering_lists_products.py @@ -0,0 +1,5 @@ +products = [ + {"title": "Cabbage", "id": 1}, + {"title": "Garlic", "id": 2}, + {"title": "Apple", "id": 3}, +] diff --git a/docs/examples/quick_start/responding_to_events.py b/docs/examples/quick_start/responding_to_events.py new file mode 100644 index 000000000..613f11ca2 --- /dev/null +++ b/docs/examples/quick_start/responding_to_events.py @@ -0,0 +1,13 @@ +from reactpy import component, html + + +# start +@component +def my_button(): + def handle_click(event): + print("You clicked me!") + + return html.button( + {"onClick": handle_click}, + "Click me", + ) diff --git a/docs/examples/quick_start/sharing_data_between_components.css b/docs/examples/quick_start/sharing_data_between_components.css new file mode 100644 index 000000000..6081b7ef4 --- /dev/null +++ b/docs/examples/quick_start/sharing_data_between_components.css @@ -0,0 +1,4 @@ +button { + display: block; + margin-bottom: 5px; +} diff --git a/docs/examples/quick_start/sharing_data_between_components.py b/docs/examples/quick_start/sharing_data_between_components.py new file mode 100644 index 000000000..f781bca9b --- /dev/null +++ b/docs/examples/quick_start/sharing_data_between_components.py @@ -0,0 +1,20 @@ +from reactpy import component, html, use_state + + +@component +def my_app(): + count, set_count = use_state(0) + + def handle_click(event): + set_count(count + 1) + + return html.div( + html.h1("Counters that update together"), + my_button(count, handle_click), + my_button(count, handle_click), + ) + + +@component +def my_button(count, on_click): + return html.button({"onClick": on_click}, f"Clicked {count} times") diff --git a/docs/examples/quick_start/sharing_data_between_components_button.py b/docs/examples/quick_start/sharing_data_between_components_button.py new file mode 100644 index 000000000..a9a4911f2 --- /dev/null +++ b/docs/examples/quick_start/sharing_data_between_components_button.py @@ -0,0 +1,7 @@ +from reactpy import component, html + + +# start +@component +def my_button(count, on_click): + return html.button({"onClick": on_click}, f"Clicked {count} times") diff --git a/docs/examples/quick_start/sharing_data_between_components_move_state.py b/docs/examples/quick_start/sharing_data_between_components_move_state.py new file mode 100644 index 000000000..a3c6126c2 --- /dev/null +++ b/docs/examples/quick_start/sharing_data_between_components_move_state.py @@ -0,0 +1,20 @@ +from reactpy import component, html, use_state + +# start +@component +def my_app(): + count, set_count = use_state(0) + + def handle_click(event): + set_count(count + 1) + + return html.div( + html.h1("Counters that update separately"), + my_button(), + my_button(), + ) + + +@component +def my_button(): + # ... we're moving code from here ... diff --git a/docs/examples/quick_start/sharing_data_between_components_props.py b/docs/examples/quick_start/sharing_data_between_components_props.py new file mode 100644 index 000000000..52294076a --- /dev/null +++ b/docs/examples/quick_start/sharing_data_between_components_props.py @@ -0,0 +1,22 @@ +from reactpy import component, html, use_state + + +# start +@component +def my_app(): + count, set_count = use_state(0) + + def handle_click(event): + set_count(count + 1) + + return html.div( + html.h1("Counters that update together"), + my_button(count, handle_click), + my_button(count, handle_click), + ) + # end + + +@component +def my_button(count, on_click): + ... diff --git a/docs/examples/quick_start/updating_the_screen.css b/docs/examples/quick_start/updating_the_screen.css new file mode 100644 index 000000000..6081b7ef4 --- /dev/null +++ b/docs/examples/quick_start/updating_the_screen.css @@ -0,0 +1,4 @@ +button { + display: block; + margin-bottom: 5px; +} diff --git a/docs/examples/quick_start/updating_the_screen.py b/docs/examples/quick_start/updating_the_screen.py new file mode 100644 index 000000000..36d810529 --- /dev/null +++ b/docs/examples/quick_start/updating_the_screen.py @@ -0,0 +1,20 @@ +from reactpy import component, html, use_state + + +@component +def my_app(): + return html.div( + html.h1("Counters that update separately"), + my_button(), + my_button(), + ) + + +@component +def my_button(): + count, set_count = use_state(0) + + def handle_click(event): + set_count(count + 1) + + return html.button({"onClick": handle_click}, f"Clicked {count} times") diff --git a/docs/examples/quick_start/updating_the_screen_event.py b/docs/examples/quick_start/updating_the_screen_event.py new file mode 100644 index 000000000..60699955d --- /dev/null +++ b/docs/examples/quick_start/updating_the_screen_event.py @@ -0,0 +1,12 @@ +from reactpy import component, html, use_state + + +# start +@component +def my_button(): + count, set_count = use_state(0) + + def handle_click(event): + set_count(count + 1) + + return html.button({"onClick": handle_click}, f"Clicked {count} times") diff --git a/docs/examples/quick_start/updating_the_screen_use_state.py b/docs/examples/quick_start/updating_the_screen_use_state.py new file mode 100644 index 000000000..010487c33 --- /dev/null +++ b/docs/examples/quick_start/updating_the_screen_use_state.py @@ -0,0 +1,5 @@ +from reactpy import use_state + +# end + +use_state() diff --git a/docs/examples/quick_start/updating_the_screen_use_state_button.py b/docs/examples/quick_start/updating_the_screen_use_state_button.py new file mode 100644 index 000000000..c331ee6c9 --- /dev/null +++ b/docs/examples/quick_start/updating_the_screen_use_state_button.py @@ -0,0 +1,8 @@ +from reactpy import component, use_state + + +# start +@component +def my_button(): + count, set_count = use_state(0) + # ... diff --git a/docs/examples/responding_to_events/simple_button.py b/docs/examples/responding_to_events/simple_button.py new file mode 100644 index 000000000..7753b4a70 --- /dev/null +++ b/docs/examples/responding_to_events/simple_button.py @@ -0,0 +1,7 @@ +from reactpy import component, html + + +# start +@component +def button(): + return html.button("I don't do anything") diff --git a/docs/examples/responding_to_events/simple_button_event.css b/docs/examples/responding_to_events/simple_button_event.css new file mode 100644 index 000000000..4fc2d52a0 --- /dev/null +++ b/docs/examples/responding_to_events/simple_button_event.css @@ -0,0 +1,3 @@ +button { + margin-right: 10px; +} diff --git a/docs/examples/responding_to_events/simple_button_event.py b/docs/examples/responding_to_events/simple_button_event.py new file mode 100644 index 000000000..df3e170fd --- /dev/null +++ b/docs/examples/responding_to_events/simple_button_event.py @@ -0,0 +1,9 @@ +from reactpy import component, html + + +@component +def button(): + def handle_click(event): + print("You clicked me!") + + return html.button({"onClick": handle_click}, "Click me") diff --git a/docs/examples/thinking_in_react/add_inverse_data_flow.css b/docs/examples/thinking_in_react/add_inverse_data_flow.css new file mode 100644 index 000000000..4be625123 --- /dev/null +++ b/docs/examples/thinking_in_react/add_inverse_data_flow.css @@ -0,0 +1,14 @@ +body { + padding: 5px; +} +label { + display: block; + margin-top: 5px; + margin-bottom: 5px; +} +th { + padding: 4px; +} +td { + padding: 2px; +} diff --git a/docs/examples/thinking_in_react/add_inverse_data_flow.py b/docs/examples/thinking_in_react/add_inverse_data_flow.py new file mode 100644 index 000000000..540bff825 --- /dev/null +++ b/docs/examples/thinking_in_react/add_inverse_data_flow.py @@ -0,0 +1,108 @@ +from reactpy import component, html, use_state + + +@component +def filterable_product_table(products): + filter_text, set_filter_text = use_state("") + in_stock_only, set_in_stock_only = use_state(False) + + return html.div( + search_bar( + filter_text=filter_text, + in_stock_only=in_stock_only, + set_filter_text=set_filter_text, + set_in_stock_only=set_in_stock_only, + ), + product_table( + products=products, filter_text=filter_text, in_stock_only=in_stock_only + ), + ) + + +@component +def product_category_row(category): + return html.tr( + html.th({"colspan": 2}, category), + ) + + +@component +def product_row(product): + if product["stocked"]: + name = product["name"] + else: + name = html.span({"style": {"color": "red"}}, product["name"]) + + return html.tr( + html.td(name), + html.td(product["price"]), + ) + + +@component +def product_table(products, filter_text, in_stock_only): + rows = [] + last_category = None + + for product in products: + if filter_text.lower() not in product["name"].lower(): + continue + if in_stock_only and not product["stocked"]: + continue + if product["category"] != last_category: + rows.append( + product_category_row(product["category"], key=product["category"]) + ) + rows.append(product_row(product, key=product["name"])) + last_category = product["category"] + + return html.table( + html.thead( + html.tr( + html.th("Name"), + html.th("Price"), + ), + ), + html.tbody(rows), + ) + + +@component +def search_bar(filter_text, in_stock_only, set_filter_text, set_in_stock_only): + return html.form( + html.input( + { + "type": "text", + "value": filter_text, + "placeholder": "Search...", + "onChange": lambda event: set_filter_text(event["target"]["value"]), + } + ), + html.label( + html.input( + { + "type": "checkbox", + "checked": in_stock_only, + "onChange": lambda event: set_in_stock_only( + event["target"]["checked"] + ), + } + ), + "Only show products in stock", + ), + ) + + +PRODUCTS = [ + {"category": "Fruits", "price": "$1", "stocked": True, "name": "Apple"}, + {"category": "Fruits", "price": "$1", "stocked": True, "name": "Dragonfruit"}, + {"category": "Fruits", "price": "$2", "stocked": False, "name": "Passionfruit"}, + {"category": "Vegetables", "price": "$2", "stocked": True, "name": "Spinach"}, + {"category": "Vegetables", "price": "$4", "stocked": False, "name": "Pumpkin"}, + {"category": "Vegetables", "price": "$1", "stocked": True, "name": "Peas"}, +] + + +@component +def app(): + return filterable_product_table(PRODUCTS) diff --git a/docs/examples/thinking_in_react/build_a_static_version_in_react.css b/docs/examples/thinking_in_react/build_a_static_version_in_react.css new file mode 100644 index 000000000..5b8624389 --- /dev/null +++ b/docs/examples/thinking_in_react/build_a_static_version_in_react.css @@ -0,0 +1,15 @@ +body { + padding: 5px; +} +label { + display: block; + margin-top: 5px; + margin-bottom: 5px; +} +th { + padding-top: 10px; +} +td { + padding: 2px; + padding-right: 40px; +} diff --git a/docs/examples/thinking_in_react/build_a_static_version_in_react.py b/docs/examples/thinking_in_react/build_a_static_version_in_react.py new file mode 100644 index 000000000..3c8c46761 --- /dev/null +++ b/docs/examples/thinking_in_react/build_a_static_version_in_react.py @@ -0,0 +1,60 @@ +from reactpy import component, html + + +@component +def product_category_row(category): + return html.tr(html.th({"colSpan": "2"}, category)) + + +@component +def product_row(product): + if product["stocked"]: + name = product["name"] + else: + name = html.span({"style": {"color": "red"}}, product["name"]) + return html.tr(html.td(name), html.td(product["price"])) + + +@component +def product_table(products): + rows = [] + last_category = None + for product in products: + if product["category"] != last_category: + rows.append( + product_category_row(product["category"], key=product["category"]) + ) + rows.append(product_row(product, key=product["name"])) + last_category = product["category"] + + return html.table( + html.thead(html.tr(html.th("Name"), html.th("Price"))), html.tbody(rows) + ) + + +@component +def search_bar(): + return html.form( + html.input({"type": "text", "placeholder": "Search..."}), + html.label(html.input({"type": "checkbox"}), "Only show products in stock"), + ) + + +@component +def filterable_product_table(products): + return html.div(search_bar(), product_table(products)) + + +PRODUCTS = [ + {"category": "Fruits", "price": "$1", "stocked": True, "name": "Apple"}, + {"category": "Fruits", "price": "$1", "stocked": True, "name": "Dragonfruit"}, + {"category": "Fruits", "price": "$2", "stocked": False, "name": "Passionfruit"}, + {"category": "Vegetables", "price": "$2", "stocked": True, "name": "Spinach"}, + {"category": "Vegetables", "price": "$4", "stocked": False, "name": "Pumpkin"}, + {"category": "Vegetables", "price": "$1", "stocked": True, "name": "Peas"}, +] + + +@component +def app(): + return filterable_product_table(PRODUCTS) diff --git a/docs/examples/thinking_in_react/error_example.py b/docs/examples/thinking_in_react/error_example.py new file mode 100644 index 000000000..e1ae45c3c --- /dev/null +++ b/docs/examples/thinking_in_react/error_example.py @@ -0,0 +1,19 @@ +from reactpy import component, html + + +# start +@component +def search_bar(filter_text, in_stock_only): + return html.form( + html.input( + { + "type": "text", + "value": filter_text, + "placeholder": "Search...", + } + ), + html.p( + html.input({"type": "checkbox", "checked": in_stock_only}), + "Only show products in stock", + ), + ) diff --git a/docs/examples/thinking_in_react/event_handlers.py b/docs/examples/thinking_in_react/event_handlers.py new file mode 100644 index 000000000..81eb99611 --- /dev/null +++ b/docs/examples/thinking_in_react/event_handlers.py @@ -0,0 +1,17 @@ +from reactpy import html + +filter_text = "" + + +def set_filter_text(value): ... + + +# start +html.input( + { + "type": "text", + "value": filter_text, + "placeholder": "Search...", + "onChange": lambda event: set_filter_text(event["target"]["value"]), + } +) diff --git a/docs/examples/thinking_in_react/identify_where_your_state_should_live.css b/docs/examples/thinking_in_react/identify_where_your_state_should_live.css new file mode 100644 index 000000000..b811252a1 --- /dev/null +++ b/docs/examples/thinking_in_react/identify_where_your_state_should_live.css @@ -0,0 +1,14 @@ +body { + padding: 5px; +} +label { + display: block; + margin-top: 5px; + margin-bottom: 5px; +} +th { + padding-top: 5px; +} +td { + padding: 2px; +} diff --git a/docs/examples/thinking_in_react/identify_where_your_state_should_live.py b/docs/examples/thinking_in_react/identify_where_your_state_should_live.py new file mode 100644 index 000000000..f81a2cd03 --- /dev/null +++ b/docs/examples/thinking_in_react/identify_where_your_state_should_live.py @@ -0,0 +1,88 @@ +from reactpy import component, html, use_state + + +@component +def filterable_product_table(products): + filter_text, set_filter_text = use_state("") + in_stock_only, set_in_stock_only = use_state(False) + + return html.div( + search_bar(filter_text=filter_text, in_stock_only=in_stock_only), + product_table( + products=products, filter_text=filter_text, in_stock_only=in_stock_only + ), + ) + + +@component +def product_category_row(category): + return html.tr( + html.th({"colspan": 2}, category), + ) + + +@component +def product_row(product): + if product["stocked"]: + name = product["name"] + else: + name = html.span({"style": {"color": "red"}}, product["name"]) + + return html.tr( + html.td(name), + html.td(product["price"]), + ) + + +@component +def product_table(products, filter_text, in_stock_only): + rows = [] + last_category = None + + for product in products: + if filter_text.lower() not in product["name"].lower(): + continue + if in_stock_only and not product["stocked"]: + continue + if product["category"] != last_category: + rows.append( + product_category_row(product["category"], key=product["category"]) + ) + rows.append(product_row(product, key=product["name"])) + last_category = product["category"] + + return html.table( + html.thead( + html.tr( + html.th("Name"), + html.th("Price"), + ), + ), + html.tbody(rows), + ) + + +@component +def search_bar(filter_text, in_stock_only): + return html.form( + html.input({"type": "text", "value": filter_text, "placeholder": "Search..."}), + html.label( + html.input({"type": "checkbox", "checked": in_stock_only}), + "Only show products in stock", + ), + ) + + +PRODUCTS = [ + {"category": "Fruits", "price": "$1", "stocked": True, "name": "Apple"}, + {"category": "Fruits", "price": "$1", "stocked": True, "name": "Dragonfruit"}, + {"category": "Fruits", "price": "$2", "stocked": False, "name": "Passionfruit"}, + {"category": "Vegetables", "price": "$2", "stocked": True, "name": "Spinach"}, + {"category": "Vegetables", "price": "$4", "stocked": False, "name": "Pumpkin"}, + {"category": "Vegetables", "price": "$1", "stocked": True, "name": "Peas"}, +] + + +@component +def app(): + return filterable_product_table(PRODUCTS) diff --git a/docs/examples/thinking_in_react/set_state_props.py b/docs/examples/thinking_in_react/set_state_props.py new file mode 100644 index 000000000..821249933 --- /dev/null +++ b/docs/examples/thinking_in_react/set_state_props.py @@ -0,0 +1,20 @@ +from reactpy import component, hooks, html + + +def search_bar(**_kws): ... + + +# start +@component +def filterable_product_table(products): + filter_text, set_filter_text = hooks.use_state("") + in_stock_only, set_in_stock_only = hooks.use_state(False) + + return html.div( + search_bar( + filter_text=filter_text, + in_stock_only=in_stock_only, + set_filter_text=set_filter_text, + set_in_stock_only=set_in_stock_only, + ) + ) diff --git a/docs/examples/thinking_in_react/start_with_the_mockup.json b/docs/examples/thinking_in_react/start_with_the_mockup.json new file mode 100644 index 000000000..f49a528b0 --- /dev/null +++ b/docs/examples/thinking_in_react/start_with_the_mockup.json @@ -0,0 +1,38 @@ +[ + { + "category": "Fruits", + "price": "$1", + "stocked": true, + "name": "Apple" + }, + { + "category": "Fruits", + "price": "$1", + "stocked": true, + "name": "Dragonfruit" + }, + { + "category": "Fruits", + "price": "$2", + "stocked": false, + "name": "Passionfruit" + }, + { + "category": "Vegetables", + "price": "$2", + "stocked": true, + "name": "Spinach" + }, + { + "category": "Vegetables", + "price": "$4", + "stocked": false, + "name": "Pumpkin" + }, + { + "category": "Vegetables", + "price": "$1", + "stocked": true, + "name": "Peas" + } +] diff --git a/docs/examples/thinking_in_react/use_state.py b/docs/examples/thinking_in_react/use_state.py new file mode 100644 index 000000000..437554974 --- /dev/null +++ b/docs/examples/thinking_in_react/use_state.py @@ -0,0 +1,8 @@ +from reactpy import component, use_state + + +# start +@component +def filterable_product_table(products): + filter_text, set_filter_text = use_state("") + in_stock_only, set_in_stock_only = use_state(False) diff --git a/docs/examples/thinking_in_react/use_state_with_components.py b/docs/examples/thinking_in_react/use_state_with_components.py new file mode 100644 index 000000000..2964929ea --- /dev/null +++ b/docs/examples/thinking_in_react/use_state_with_components.py @@ -0,0 +1,17 @@ +from reactpy import html + +filter_text = "" +in_stock_only = False +products = () + +def search_bar(**_kw): + ... + +def product_table(**_kw): + ... + +# start +html.div( + search_bar(filter_text=filter_text, in_stock_only=in_stock_only), + product_table(products=products, filter_text=filter_text, in_stock_only=in_stock_only), +) diff --git a/docs/examples/tutorial_tic_tac_toe/setup_for_the_tutorial.css b/docs/examples/tutorial_tic_tac_toe/setup_for_the_tutorial.css new file mode 100644 index 000000000..e3efaf92a --- /dev/null +++ b/docs/examples/tutorial_tic_tac_toe/setup_for_the_tutorial.css @@ -0,0 +1,42 @@ +* { + box-sizing: border-box; +} + +body { + font-family: sans-serif; + margin: 20px; + padding: 0; +} + +.square { + background: #fff; + border: 1px solid #999; + float: left; + font-size: 24px; + font-weight: bold; + line-height: 34px; + height: 34px; + margin-right: -1px; + margin-top: -1px; + padding: 0; + text-align: center; + width: 34px; +} + +.board-row:after { + clear: both; + content: ""; + display: table; +} + +.status { + margin-bottom: 10px; +} +.game { + display: flex; + flex-direction: row; +} + +.game-info { + margin-left: 20px; +} diff --git a/docs/examples/tutorial_tic_tac_toe/setup_for_the_tutorial.py b/docs/examples/tutorial_tic_tac_toe/setup_for_the_tutorial.py new file mode 100644 index 000000000..e0893d6b4 --- /dev/null +++ b/docs/examples/tutorial_tic_tac_toe/setup_for_the_tutorial.py @@ -0,0 +1,7 @@ +from reactpy import component, html + + +# start +@component +def square(): + return html.button({"className": "square"}, "X") diff --git a/docs/examples/tutorial_tic_tac_toe/tic_tac_toe.css b/docs/examples/tutorial_tic_tac_toe/tic_tac_toe.css new file mode 100644 index 000000000..87876ec02 --- /dev/null +++ b/docs/examples/tutorial_tic_tac_toe/tic_tac_toe.css @@ -0,0 +1,42 @@ +* { + box-sizing: border-box; +} + +body { + font-family: sans-serif; + margin: 20px; + padding: 0; +} + +.square { + background: #fff; + border: 1px solid #999; + float: left; + font-size: 24px; + font-weight: bold; + line-height: 34px; + height: 34px; + margin-right: -1px; + margin-top: -1px; + padding: 0; + text-align: center; + width: 34px; +} + +.board-row:after { + clear: both; + content: ""; + display: table; +} + +.status { + margin-bottom: 10px; +} +.game { + display: flex; + flex-direction: row; +} + +.game-info { + margin-left: 20px; +} diff --git a/docs/examples/tutorial_tic_tac_toe/tic_tac_toe.py b/docs/examples/tutorial_tic_tac_toe/tic_tac_toe.py new file mode 100644 index 000000000..5eed504d1 --- /dev/null +++ b/docs/examples/tutorial_tic_tac_toe/tic_tac_toe.py @@ -0,0 +1,115 @@ +from copy import deepcopy + +from reactpy import component, html, use_state + + +@component +def square(value, on_square_click): + return html.button( + {"className": "square", "onClick": on_square_click}, + value, + ) + + +@component +def board(x_is_next, squares, on_play): + def handle_click(i): + def inner(event): + """ + Due to a quirk of Python, if your event handler needs args other than + `event`, you will need to create a wrapper function as seen above. + Ref: https://pylint.readthedocs.io/en/stable/user_guide/messages/warning/cell-var-from-loop.html + """ + if calculate_winner(squares) or squares[i]: + return + + next_squares = squares.copy() + next_squares[i] = "X" if x_is_next else "O" + on_play(next_squares) + + return inner + + winner = calculate_winner(squares) + status = ( + f"Winner: {winner}" if winner else "Next player: " + ("X" if x_is_next else "O") + ) + + return html._( + html.div({"className": "status"}, status), + html.div( + {"className": "board-row"}, + square(squares[0], handle_click(0)), + square(squares[1], handle_click(1)), + square(squares[2], handle_click(2)), + ), + html.div( + {"className": "board-row"}, + square(squares[3], handle_click(3)), + square(squares[4], handle_click(4)), + square(squares[5], handle_click(5)), + ), + html.div( + {"className": "board-row"}, + square(squares[6], handle_click(6)), + square(squares[7], handle_click(7)), + square(squares[8], handle_click(8)), + ), + ) + + +@component +def game(): + history, set_history = use_state([[None] * 9]) + current_move, set_current_move = use_state(0) + x_is_next = current_move % 2 == 0 + current_squares = history[current_move] + + def handle_play(next_squares): + next_history = deepcopy(history[: current_move + 1]) + next_history.append(next_squares) + set_history(next_history) + set_current_move(len(next_history) - 1) + + def jump_to(next_move): + return lambda _event: set_current_move(next_move) + + moves = [] + for move, _squares in enumerate(history): + description = f"Go to move #{move}" if move > 0 else "Go to game start" + + moves.append( + html.li( + {"key": move}, + html.button({"onClick": jump_to(move)}, description), + ) + ) + + return html.div( + {"className": "game"}, + html.div( + {"className": "game-board"}, + board(x_is_next, current_squares, handle_play), + ), + html.div({"className": "game-info"}, html.ol(moves)), + ) + + +def calculate_winner(squares): + lines = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [0, 3, 6], + [1, 4, 7], + [2, 5, 8], + [0, 4, 8], + [2, 4, 6], + ] + for line in lines: + a, b, c = line + if not squares: + continue + if squares[a] and squares[a] == squares[b] and squares[a] == squares[c]: + return squares[a] + + return None diff --git a/docs/main.py b/docs/main.py deleted file mode 100644 index e3181f393..000000000 --- a/docs/main.py +++ /dev/null @@ -1,9 +0,0 @@ -import sys - -from docs_app import dev, prod - -if __name__ == "__main__": - if len(sys.argv) == 1: - prod.main() - else: - dev.main() diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 000000000..77af61224 --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,224 @@ +--- +nav: + - Home: index.md + - Get Started: + - Quick Start: + - learn/quick-start.md + - "Tutorial: Tic-Tac-Toe 🚧": learn/tutorial-tic-tac-toe.md + - Thinking in React: learn/thinking-in-react.md + - Installation: + - Creating a Standalone React App: learn/creating-a-react-app.md + - Add React to an Existing Project: learn/add-react-to-an-existing-project.md + - Setup: + - Editor Setup: learn/editor-setup.md + # - ReactPy Developer Tools 🚫: learn/react-developer-tools.md + - Tools, Modules, and Packages 🚧: learn/extra-tools-and-packages.md + # - More Tutorials: + # - "Tutorial: React Bootstrap 🚫": learn/tutorial-react-bootstrap.md + # - "Tutorial: Material UI 🚫": learn/tutorial-material-ui.md + - Learn: + - Describing the UI: + - Your First Component 🚧: learn/your-first-component.md + - Importing and Exporting Components 🚧: learn/importing-and-exporting-components.md + # - Writing Markup with PSX 🚫: learn/writing-markup-with-psx.md + # - Python in PSX with Curly Braces 🚫: learn/python-in-psx-with-curly-braces.md + - Passing Props to a Component 🚧: learn/passing-props-to-a-component.md + - Conditional Rendering 🚧: learn/conditional-rendering.md + - Rendering Lists 🚧: learn/rendering-lists.md + - Keeping Components Pure 🚧: learn/keeping-components-pure.md + - Adding Interactivity: + - Responding to Events 🚧: learn/responding-to-events.md + - "State: A Component's Memory 🚧": learn/state-a-components-memory.md + - Render and Commit 🚧: learn/render-and-commit.md + - State as a Snapshot 🚧: learn/state-as-a-snapshot.md + - Queueing a Series of State Updates 🚧: learn/queueing-a-series-of-state-updates.md + - Updating Objects in State 🚧: learn/updating-objects-in-state.md + - Updating Arrays in State 🚧: learn/updating-arrays-in-state.md + - Managing State: + - Reacting to Input with State 🚧: learn/reacting-to-input-with-state.md + - Choosing the State Structure 🚧: learn/choosing-the-state-structure.md + - Sharing State Between Components 🚧: learn/sharing-state-between-components.md + - Preserving and Resetting State 🚧: learn/preserving-and-resetting-state.md + - Extracting State Logic into a Reducer 🚧: learn/extracting-state-logic-into-a-reducer.md + - Passing Data Deeply with Context 🚧: learn/passing-data-deeply-with-context.md + - Scaling Up with Reducer and Context 🚧: learn/scaling-up-with-reducer-and-context.md + - Escape Hatches: + - Referencing Values with Refs 🚧: learn/referencing-values-with-refs.md + - Manipulating the DOM with Refs 🚧: learn/manipulating-the-dom-with-refs.md + - Synchronizing with Effects 🚧: learn/synchronizing-with-effects.md + - You Might Not Need an Effect 🚧: learn/you-might-not-need-an-effect.md + - Lifecycle of Reactive Effects 🚧: learn/lifecycle-of-reactive-effects.md + - Separating Events from Effects 🚧: learn/separating-events-from-effects.md + - Removing Effect Dependencies 🚧: learn/removing-effect-dependencies.md + - Reusing Logic with Custom Hooks 🚧: learn/reusing-logic-with-custom-hooks.md + - Communicating Data Between Server and Client 🚧: learn/communicate-data-between-server-and-client.md + - Convert Between VDOM and HTML 🚧: learn/convert-between-vdom-and-html.md + - VDOM Mutations 🚧: learn/vdom-mutations.md + - Creating VDOM Event Handlers 🚧: learn/creating-vdom-event-handlers.md + - Creating HTML Tags 🚧: learn/creating-html-tags.md + - Creating Backends 🚧: learn/creating-backends.md + - Manually Register a Client 🚧: learn/manually-register-a-client.md + - Reference: + - Overview: reference/overview.md + - Hooks: + - Use State 🚧: reference/use-state.md + - Use Effect 🚧: reference/use-effect.md + - Use Async Effect 🚧: reference/use-async-effect.md + - Use Context 🚧: reference/use-context.md + - Use Reducer 🚧: reference/use-reducer.md + - Use Callback 🚧: reference/use-callback.md + - Use Memo 🚧: reference/use-memo.md + - Use Ref 🚧: reference/use-ref.md + - Use Debug Value 🚧: reference/use-debug-value.md + - Use Connection 🚧: reference/use-connection.md + - Use Scope 🚧: reference/use-scope.md + - Use Location 🚧: reference/use-location.md + - HTML Tags: + - Common Props 🚧: reference/common-props.md + - Usage 🚧: reference/usage.md + - Executors: + - ReactPy: reference/reactpy.md + - ReactPyCsr 🚧: reference/reactpy-csr.md + - ReactPyMiddleware 🚧: reference/reactpy-middleware.md + - Rules of React: + - Overview 🚧: reference/rules-of-react.md + - Components and Hooks must be pure 🚧: reference/components-and-hooks-must-be-pure.md + - React calls Components and Hooks 🚧: reference/react-calls-components-and-hooks.md + - Rules of Hooks 🚧: reference/rules-of-hooks.md + # - Template Tags: + # - Jinja 🚧: reference/jinja.md + - Protocol Structure 🚧: reference/protocol-structure.md + - Client API 🚧: reference/client-api.md + - About: + - Changelog 🚧: about/changelog.md + - Community 🚧: about/community.md + - Running Tests 🚧: about/running-tests.md + - Contributing Code 🚧: about/code.md + - Contributing Documentation 🚧: about/docs.md + - Licenses 🚧: about/licenses.md + +theme: + name: material + custom_dir: overrides + palette: + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/white-balance-sunny + name: Switch to light mode + primary: red # We use red to indicate that something is unthemed + accent: red + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/weather-night + name: Switch to dark mode + primary: white + accent: red + features: + # - navigation.instant + - navigation.tabs + - navigation.tabs.sticky + - navigation.top + - content.code.copy + - search.highlight + icon: + repo: fontawesome/brands/github + admonition: + note: fontawesome/solid/note-sticky + logo: https://raw.githubusercontent.com/reactive-python/reactpy/main/branding/svg/reactpy-logo-square.svg + favicon: https://raw.githubusercontent.com/reactive-python/reactpy/main/branding/svg/reactpy-logo-square.svg + +markdown_extensions: + - toc: + permalink: true + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.tabbed: + alternate_style: true + - pymdownx.highlight: + linenums: true + - pymdownx.superfences + - pymdownx.details + - pymdownx.inlinehilite + - admonition + - attr_list + - md_in_html + - pymdownx.keys + +plugins: + - search + - include-markdown + - git-authors + # - section-index + - minify: + minify_html: true + minify_js: true + minify_css: true + cache_safe: true + - git-revision-date-localized: + fallback_to_build_date: true + # - spellcheck: + # known_words: dictionary.txt + # allow_unicode: no + - mkdocstrings: + default_handler: python + handlers: + python: + paths: ["../"] + import: + - https://installer.readthedocs.io/en/stable/objects.inv + options: + signature_crossrefs: true + scoped_crossrefs: true + relative_crossrefs: true + modernize_annotations: true + unwrap_annotated: true + find_stubs_package: true + show_root_members_full_path: true + show_bases: false + show_source: false + show_root_toc_entry: false + show_labels: false + show_symbol_type_toc: true + show_symbol_type_heading: true + show_object_full_path: true + heading_level: 3 + +extra: + generator: false + version: + provider: mike + +extra_javascript: + - assets/js/main.js + +extra_css: + - assets/css/main.css + - assets/css/button.css + - assets/css/admonition.css + - assets/css/banner.css + - assets/css/sidebar.css + - assets/css/navbar.css + - assets/css/table-of-contents.css + - assets/css/code.css + - assets/css/footer.css + - assets/css/home.css + +watch: + - "../docs" + - ../README.md + - ../CHANGELOG.md + - ../LICENSE.md + - "../src" + +site_name: ReactPy +site_author: Archmonger +site_description: It's React, but in Python. +copyright: '©
Reactive Python and affiliates.' +repo_url: https://github.com/reactive-python/reactpy +site_url: https://reactive-python.github.io/reactpy +repo_name: ReactPy +edit_uri: edit/main/docs/src +docs_dir: src diff --git a/docs/overrides/home.html b/docs/overrides/home.html new file mode 100644 index 000000000..77446c7c8 --- /dev/null +++ b/docs/overrides/home.html @@ -0,0 +1,135 @@ + +{% extends "main.html" %} + + +{% block content %}{% endblock %} + + +{% block tabs %} + +
+
+ +

{{ config.site_name }}

+

{{ config.site_description }}

+ +
+ +
+

Create user interfaces from components

+

+ ReactPy lets you build user interfaces out of individual pieces called components. Create your own ReactPy + components like thumbnail, like_button, and video. Then combine + them into entire screens, pages, and apps. +

+
+ {% with image="create-user-interfaces.png", class="pop-left" %} + {% include "homepage_examples/code_block.html" %} + {% endwith %} + {% include "homepage_examples/create_user_interfaces_demo.html" %} +
+

+ Whether you work on your own or with thousands of other developers, using React feels the same. It is + designed to let you seamlessly combine components written by independent people, teams, and + organizations. +

+
+ +
+

Write components with pure Python code

+

+ ReactPy components are Python functions. Want to show some content conditionally? Use an + if statement. Displaying a list? Try using + list comprehension. + Learning ReactPy is learning programming. +

+
+ {% with image="write-components-with-python.png", class="pop-left" %} + {% include "homepage_examples/code_block.html" %} + {% endwith %} + {% include "homepage_examples/write_components_with_python_demo.html" %} + +
+
+ +
+

Add interactivity wherever you need it

+

+ ReactPy components receive data and return what should appear on the screen. You can pass them new data in + response to an interaction, like when the user types into an input. ReactPy will then update the screen to + match the new data. +

+
+ {% with image="add-interactivity.png" %} + {% include "homepage_examples/code_block.html" %} + {% endwith %} + {% include "homepage_examples/add_interactivity_demo.html" %} +
+

+ You don't have to build your whole page in ReactPy. Add React to your existing HTML page, and render + interactive ReactPy components anywhere on it. +

+
+ +
+

Go full-stack with a framework

+

+ ReactPy is a library. It lets you put components together, but it doesn't prescribe how to do routing and + data fetching. To build an entire app with ReactPy, we recommend a backend framework like + Django or Starlette. +

+ + Get Started + +
+
+{% endblock %} diff --git a/docs/overrides/homepage_examples/add_interactivity.py b/docs/overrides/homepage_examples/add_interactivity.py new file mode 100644 index 000000000..9a7bf76f1 --- /dev/null +++ b/docs/overrides/homepage_examples/add_interactivity.py @@ -0,0 +1,29 @@ +# ruff: noqa: INP001 +from reactpy import component, html, use_state + + +def filter_videos(*_, **__): + return [] + + +def search_input(*_, **__): ... + + +def video_list(*_, **__): ... + + +@component +def searchable_video_list(videos): + search_text, set_search_text = use_state("") + found_videos = filter_videos(videos, search_text) + + return html._( + search_input( + {"onChange": lambda event: set_search_text(event["target"]["value"])}, + value=search_text, + ), + video_list( + videos=found_videos, + empty_heading=f"No matches for “{search_text}”", + ), + ) diff --git a/docs/overrides/homepage_examples/add_interactivity_demo.html b/docs/overrides/homepage_examples/add_interactivity_demo.html new file mode 100644 index 000000000..ec8c1e4db --- /dev/null +++ b/docs/overrides/homepage_examples/add_interactivity_demo.html @@ -0,0 +1,172 @@ +
+
+ +
+
+ + + + example.com/videos.html +
+
+ +
+
+

Searchable Videos

+

Type a search query below.

+ +
+ +

5 Videos

+ +
+
+ + + +
+
+

ReactPy: The Documentary

+

From web library to taco delivery service

+
+ +
+ +
+
+ + + +
+
+

Code using Worst Practices

+

Harriet Potter (2013)

+
+ +
+ +
+
+ + + +
+
+

Introducing ReactPy Foriegn

+

Tim Cooker (2015)

+
+ +
+ +
+
+ + + +
+
+

Introducing ReactPy Cooks

+

Soap Boat and Dinosaur Dan (2018)

+
+ +
+ +
+
+ + + +
+
+

Introducing Quantum Components

+

Isaac Asimov and Lauren-kun (2020)

+
+ +
+

+
+ + +
+
diff --git a/docs/overrides/homepage_examples/code_block.html b/docs/overrides/homepage_examples/code_block.html new file mode 100644 index 000000000..27b362046 --- /dev/null +++ b/docs/overrides/homepage_examples/code_block.html @@ -0,0 +1,7 @@ +
+ +
+
+ +
+
diff --git a/docs/overrides/homepage_examples/create_user_interfaces.py b/docs/overrides/homepage_examples/create_user_interfaces.py new file mode 100644 index 000000000..7878aa6b5 --- /dev/null +++ b/docs/overrides/homepage_examples/create_user_interfaces.py @@ -0,0 +1,21 @@ +# ruff: noqa: INP001 +from reactpy import component, html + + +def thumbnail(*_, **__): ... + + +def like_button(*_, **__): ... + + +@component +def video(data): + return html.div( + thumbnail(data), + html.a( + {"href": data.url}, + html.h3(data.title), + html.p(data.description), + ), + like_button(data), + ) diff --git a/docs/overrides/homepage_examples/create_user_interfaces_demo.html b/docs/overrides/homepage_examples/create_user_interfaces_demo.html new file mode 100644 index 000000000..9ec25437e --- /dev/null +++ b/docs/overrides/homepage_examples/create_user_interfaces_demo.html @@ -0,0 +1,24 @@ +
+
+
+
+ + + +
+
+

My video

+

Video description

+
+ +
+
+
diff --git a/docs/overrides/homepage_examples/write_components_with_python.py b/docs/overrides/homepage_examples/write_components_with_python.py new file mode 100644 index 000000000..5993046c9 --- /dev/null +++ b/docs/overrides/homepage_examples/write_components_with_python.py @@ -0,0 +1,19 @@ +# ruff: noqa: INP001 +from reactpy import component, html + + +def video(*_, **__): ... + + +@component +def video_list(videos, empty_heading): + count = len(videos) + heading = empty_heading + if count > 0: + noun = "Videos" if count > 1 else "Video" + heading = f"{count} {noun}" + + return html.section( + html.h2(heading), + [video(x, key=x.id) for x in videos], + ) diff --git a/docs/overrides/homepage_examples/write_components_with_python_demo.html b/docs/overrides/homepage_examples/write_components_with_python_demo.html new file mode 100644 index 000000000..779f7abbe --- /dev/null +++ b/docs/overrides/homepage_examples/write_components_with_python_demo.html @@ -0,0 +1,65 @@ +
+
+

3 Videos

+
+
+ + + +
+
+

First video

+

Video description

+
+ +
+
+
+ + + +
+
+

Second video

+

Video description

+
+ +
+
+
+ + + +
+
+

Third video

+

Video description

+
+ +
+
+
diff --git a/docs/overrides/main.html b/docs/overrides/main.html new file mode 100644 index 000000000..c63ca9e71 --- /dev/null +++ b/docs/overrides/main.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} + +{% block content %} +{{ super() }} + +{% if git_page_authors %} +
+ + Authors: {{ git_page_authors | default('enable mkdocs-git-authors-plugin') }} + +
+{% endif %} +{% endblock %} + +{% block outdated %} +You're not viewing the latest release. + + Click here to go to latest. + +{% endblock %} diff --git a/docs/poetry.lock b/docs/poetry.lock deleted file mode 100644 index 8e1daef24..000000000 --- a/docs/poetry.lock +++ /dev/null @@ -1,2269 +0,0 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. - -[[package]] -name = "aiofiles" -version = "23.1.0" -description = "File support for asyncio." -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "aiofiles-23.1.0-py3-none-any.whl", hash = "sha256:9312414ae06472eb6f1d163f555e466a23aed1c8f60c30cccf7121dba2e53eb2"}, - {file = "aiofiles-23.1.0.tar.gz", hash = "sha256:edd247df9a19e0db16534d4baaf536d6609a43e1de5401d7a4c1c148753a1635"}, -] - -[[package]] -name = "alabaster" -version = "0.7.13" -description = "A configurable sidebar-enabled Sphinx theme" -optional = false -python-versions = ">=3.6" -files = [ - {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, - {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, -] - -[[package]] -name = "anyio" -version = "3.7.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.7" -files = [ - {file = "anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0"}, - {file = "anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce"}, -] - -[package.dependencies] -exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" - -[package.extras] -doc = ["Sphinx (>=6.1.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme", "sphinxcontrib-jquery"] -test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (<0.22)"] - -[[package]] -name = "asgiref" -version = "3.7.2" -description = "ASGI specs, helper code, and adapters" -optional = false -python-versions = ">=3.7" -files = [ - {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"}, - {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} - -[package.extras] -tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] - -[[package]] -name = "babel" -version = "2.12.1" -description = "Internationalization utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, - {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, -] - -[[package]] -name = "beautifulsoup4" -version = "4.12.2" -description = "Screen-scraping library" -optional = false -python-versions = ">=3.6.0" -files = [ - {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"}, - {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"}, -] - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "certifi" -version = "2023.5.7" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, - {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.1.0" -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.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, -] - -[[package]] -name = "click" -version = "8.1.3" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "colorlog" -version = "6.7.0" -description = "Add colours to the output of Python's logging module." -optional = false -python-versions = ">=3.6" -files = [ - {file = "colorlog-6.7.0-py2.py3-none-any.whl", hash = "sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662"}, - {file = "colorlog-6.7.0.tar.gz", hash = "sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} - -[package.extras] -development = ["black", "flake8", "mypy", "pytest", "types-colorama"] - -[[package]] -name = "contourpy" -version = "1.0.7" -description = "Python library for calculating contours of 2D quadrilateral grids" -optional = false -python-versions = ">=3.8" -files = [ - {file = "contourpy-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:95c3acddf921944f241b6773b767f1cbce71d03307270e2d769fd584d5d1092d"}, - {file = "contourpy-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc1464c97579da9f3ab16763c32e5c5d5bb5fa1ec7ce509a4ca6108b61b84fab"}, - {file = "contourpy-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8acf74b5d383414401926c1598ed77825cd530ac7b463ebc2e4f46638f56cce6"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c71fdd8f1c0f84ffd58fca37d00ca4ebaa9e502fb49825484da075ac0b0b803"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f99e9486bf1bb979d95d5cffed40689cb595abb2b841f2991fc894b3452290e8"}, - {file = "contourpy-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87f4d8941a9564cda3f7fa6a6cd9b32ec575830780677932abdec7bcb61717b0"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9e20e5a1908e18aaa60d9077a6d8753090e3f85ca25da6e25d30dc0a9e84c2c6"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a877ada905f7d69b2a31796c4b66e31a8068b37aa9b78832d41c82fc3e056ddd"}, - {file = "contourpy-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6381fa66866b0ea35e15d197fc06ac3840a9b2643a6475c8fff267db8b9f1e69"}, - {file = "contourpy-1.0.7-cp310-cp310-win32.whl", hash = "sha256:3c184ad2433635f216645fdf0493011a4667e8d46b34082f5a3de702b6ec42e3"}, - {file = "contourpy-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:3caea6365b13119626ee996711ab63e0c9d7496f65641f4459c60a009a1f3e80"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ed33433fc3820263a6368e532f19ddb4c5990855e4886088ad84fd7c4e561c71"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38e2e577f0f092b8e6774459317c05a69935a1755ecfb621c0a98f0e3c09c9a5"}, - {file = "contourpy-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ae90d5a8590e5310c32a7630b4b8618cef7563cebf649011da80874d0aa8f414"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130230b7e49825c98edf0b428b7aa1125503d91732735ef897786fe5452b1ec2"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58569c491e7f7e874f11519ef46737cea1d6eda1b514e4eb5ac7dab6aa864d02"}, - {file = "contourpy-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d43960d809c4c12508a60b66cb936e7ed57d51fb5e30b513934a4a23874fae"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:152fd8f730c31fd67fe0ffebe1df38ab6a669403da93df218801a893645c6ccc"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9056c5310eb1daa33fc234ef39ebfb8c8e2533f088bbf0bc7350f70a29bde1ac"}, - {file = "contourpy-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a9d7587d2fdc820cc9177139b56795c39fb8560f540bba9ceea215f1f66e1566"}, - {file = "contourpy-1.0.7-cp311-cp311-win32.whl", hash = "sha256:4ee3ee247f795a69e53cd91d927146fb16c4e803c7ac86c84104940c7d2cabf0"}, - {file = "contourpy-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:5caeacc68642e5f19d707471890f037a13007feba8427eb7f2a60811a1fc1350"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd7dc0e6812b799a34f6d12fcb1000539098c249c8da54f3566c6a6461d0dbad"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0f9d350b639db6c2c233d92c7f213d94d2e444d8e8fc5ca44c9706cf72193772"}, - {file = "contourpy-1.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e96a08b62bb8de960d3a6afbc5ed8421bf1a2d9c85cc4ea73f4bc81b4910500f"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:031154ed61f7328ad7f97662e48660a150ef84ee1bc8876b6472af88bf5a9b98"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e9ebb4425fc1b658e13bace354c48a933b842d53c458f02c86f371cecbedecc"}, - {file = "contourpy-1.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efb8f6d08ca7998cf59eaf50c9d60717f29a1a0a09caa46460d33b2924839dbd"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6c180d89a28787e4b73b07e9b0e2dac7741261dbdca95f2b489c4f8f887dd810"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b8d587cc39057d0afd4166083d289bdeff221ac6d3ee5046aef2d480dc4b503c"}, - {file = "contourpy-1.0.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:769eef00437edf115e24d87f8926955f00f7704bede656ce605097584f9966dc"}, - {file = "contourpy-1.0.7-cp38-cp38-win32.whl", hash = "sha256:62398c80ef57589bdbe1eb8537127321c1abcfdf8c5f14f479dbbe27d0322e66"}, - {file = "contourpy-1.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:57119b0116e3f408acbdccf9eb6ef19d7fe7baf0d1e9aaa5381489bc1aa56556"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30676ca45084ee61e9c3da589042c24a57592e375d4b138bd84d8709893a1ba4"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e927b3868bd1e12acee7cc8f3747d815b4ab3e445a28d2e5373a7f4a6e76ba1"}, - {file = "contourpy-1.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:366a0cf0fc079af5204801786ad7a1c007714ee3909e364dbac1729f5b0849e5"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ba9bb365446a22411f0673abf6ee1fea3b2cf47b37533b970904880ceb72f3"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:71b0bf0c30d432278793d2141362ac853859e87de0a7dee24a1cea35231f0d50"}, - {file = "contourpy-1.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7281244c99fd7c6f27c1c6bfafba878517b0b62925a09b586d88ce750a016d2"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b6d0f9e1d39dbfb3977f9dd79f156c86eb03e57a7face96f199e02b18e58d32a"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7f6979d20ee5693a1057ab53e043adffa1e7418d734c1532e2d9e915b08d8ec2"}, - {file = "contourpy-1.0.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5dd34c1ae752515318224cba7fc62b53130c45ac6a1040c8b7c1a223c46e8967"}, - {file = "contourpy-1.0.7-cp39-cp39-win32.whl", hash = "sha256:c5210e5d5117e9aec8c47d9156d1d3835570dd909a899171b9535cb4a3f32693"}, - {file = "contourpy-1.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:60835badb5ed5f4e194a6f21c09283dd6e007664a86101431bf870d9e86266c4"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ce41676b3d0dd16dbcfabcc1dc46090aaf4688fd6e819ef343dbda5a57ef0161"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a011cf354107b47c58ea932d13b04d93c6d1d69b8b6dce885e642531f847566"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31a55dccc8426e71817e3fe09b37d6d48ae40aae4ecbc8c7ad59d6893569c436"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69f8ff4db108815addd900a74df665e135dbbd6547a8a69333a68e1f6e368ac2"}, - {file = "contourpy-1.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efe99298ba37e37787f6a2ea868265465410822f7bea163edcc1bd3903354ea9"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a1e97b86f73715e8670ef45292d7cc033548266f07d54e2183ecb3c87598888f"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc331c13902d0f50845099434cd936d49d7a2ca76cb654b39691974cb1e4812d"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24847601071f740837aefb730e01bd169fbcaa610209779a78db7ebb6e6a7051"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abf298af1e7ad44eeb93501e40eb5a67abbf93b5d90e468d01fc0c4451971afa"}, - {file = "contourpy-1.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:64757f6460fc55d7e16ed4f1de193f362104285c667c112b50a804d482777edd"}, - {file = "contourpy-1.0.7.tar.gz", hash = "sha256:d8165a088d31798b59e91117d1f5fc3df8168d8b48c4acc10fc0df0d0bdbcc5e"}, -] - -[package.dependencies] -numpy = ">=1.16" - -[package.extras] -bokeh = ["bokeh", "chromedriver", "selenium"] -docs = ["furo", "sphinx-copybutton"] -mypy = ["contourpy[bokeh]", "docutils-stubs", "mypy (==0.991)", "types-Pillow"] -test = ["Pillow", "matplotlib", "pytest"] -test-no-images = ["pytest"] - -[[package]] -name = "cycler" -version = "0.11.0" -description = "Composable style cycles" -optional = false -python-versions = ">=3.6" -files = [ - {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, - {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, -] - -[[package]] -name = "docutils" -version = "0.17.1" -description = "Docutils -- Python Documentation Utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, - {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, -] - -[[package]] -name = "exceptiongroup" -version = "1.1.1" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "fastapi" -version = "0.96.0" -description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -optional = false -python-versions = ">=3.7" -files = [ - {file = "fastapi-0.96.0-py3-none-any.whl", hash = "sha256:b8e11fe81e81eab4e1504209917338e0b80f783878a42c2b99467e5e1019a1e9"}, - {file = "fastapi-0.96.0.tar.gz", hash = "sha256:71232d47c2787446991c81c41c249f8a16238d52d779c0e6b43927d3773dbe3c"}, -] - -[package.dependencies] -pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" -starlette = ">=0.27.0,<0.28.0" - -[package.extras] -all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] -dev = ["pre-commit (>=2.17.0,<3.0.0)", "ruff (==0.0.138)", "uvicorn[standard] (>=0.12.0,<0.21.0)"] -doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer-cli (>=0.0.13,<0.0.14)", "typer[all] (>=0.6.1,<0.8.0)"] -test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6.5.0,<8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.7)", "pyyaml (>=5.3.1,<7.0.0)", "ruff (==0.0.138)", "sqlalchemy (>=1.3.18,<1.4.43)", "types-orjson (==3.6.2)", "types-ujson (==5.7.0.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"] - -[[package]] -name = "fastjsonschema" -version = "2.17.1" -description = "Fastest Python implementation of JSON schema" -optional = false -python-versions = "*" -files = [ - {file = "fastjsonschema-2.17.1-py3-none-any.whl", hash = "sha256:4b90b252628ca695280924d863fe37234eebadc29c5360d322571233dc9746e0"}, - {file = "fastjsonschema-2.17.1.tar.gz", hash = "sha256:f4eeb8a77cef54861dbf7424ac8ce71306f12cbb086c45131bcba2c6a4f726e3"}, -] - -[package.extras] -devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] - -[[package]] -name = "flask" -version = "2.1.3" -description = "A simple framework for building complex web applications." -optional = false -python-versions = ">=3.7" -files = [ - {file = "Flask-2.1.3-py3-none-any.whl", hash = "sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c"}, - {file = "Flask-2.1.3.tar.gz", hash = "sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb"}, -] - -[package.dependencies] -click = ">=8.0" -importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} -itsdangerous = ">=2.0" -Jinja2 = ">=3.0" -Werkzeug = ">=2.0" - -[package.extras] -async = ["asgiref (>=3.2)"] -dotenv = ["python-dotenv"] - -[[package]] -name = "flask-cors" -version = "3.0.10" -description = "A Flask extension adding a decorator for CORS support" -optional = false -python-versions = "*" -files = [ - {file = "Flask-Cors-3.0.10.tar.gz", hash = "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de"}, - {file = "Flask_Cors-3.0.10-py2.py3-none-any.whl", hash = "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438"}, -] - -[package.dependencies] -Flask = ">=0.9" -Six = "*" - -[[package]] -name = "flask-sock" -version = "0.6.0" -description = "WebSocket support for Flask" -optional = false -python-versions = ">=3.6" -files = [ - {file = "flask-sock-0.6.0.tar.gz", hash = "sha256:435cf81bb497ac7622cd1dda554fbfa3e369e629daea0a1d21b73a24f1bd6229"}, - {file = "flask_sock-0.6.0-py3-none-any.whl", hash = "sha256:593fffb186928080a5b5b03d717efc56dac2d5ed690ce6bfff333b3597a2f518"}, -] - -[package.dependencies] -flask = ">=2" -simple-websocket = ">=0.5.1" - -[[package]] -name = "fonttools" -version = "4.39.4" -description = "Tools to manipulate font files" -optional = false -python-versions = ">=3.8" -files = [ - {file = "fonttools-4.39.4-py3-none-any.whl", hash = "sha256:106caf6167c4597556b31a8d9175a3fdc0356fdcd70ab19973c3b0d4c893c461"}, - {file = "fonttools-4.39.4.zip", hash = "sha256:dba8d7cdb8e2bac1b3da28c5ed5960de09e59a2fe7e63bb73f5a59e57b0430d2"}, -] - -[package.extras] -all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.0.0)", "xattr", "zopfli (>=0.1.4)"] -graphite = ["lz4 (>=1.7.4.2)"] -interpolatable = ["munkres", "scipy"] -lxml = ["lxml (>=4.0,<5)"] -pathops = ["skia-pathops (>=0.5.0)"] -plot = ["matplotlib"] -repacker = ["uharfbuzz (>=0.23.0)"] -symfont = ["sympy"] -type1 = ["xattr"] -ufo = ["fs (>=2.2.0,<3)"] -unicode = ["unicodedata2 (>=15.0.0)"] -woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] - -[[package]] -name = "furo" -version = "2022.4.7" -description = "A clean customisable Sphinx documentation theme." -optional = false -python-versions = ">=3.6" -files = [ - {file = "furo-2022.4.7-py3-none-any.whl", hash = "sha256:7f3e3d2fb977483590f8ecb2c2cd511bd82661b79c18efb24de9558bc9cdf2d7"}, - {file = "furo-2022.4.7.tar.gz", hash = "sha256:96204ab7cd047e4b6c523996e0279c4c629a8fc31f4f109b2efd470c17f49c80"}, -] - -[package.dependencies] -beautifulsoup4 = "*" -pygments = ">=2.7,<3.0" -sphinx = ">=4.0,<5.0" - -[[package]] -name = "greenlet" -version = "2.0.2" -description = "Lightweight in-process concurrent programming" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -files = [ - {file = "greenlet-2.0.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d"}, - {file = "greenlet-2.0.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9"}, - {file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"}, - {file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"}, - {file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"}, - {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"}, - {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"}, - {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"}, - {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470"}, - {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a"}, - {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"}, - {file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"}, - {file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"}, - {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"}, - {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"}, - {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"}, - {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19"}, - {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3"}, - {file = "greenlet-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5"}, - {file = "greenlet-2.0.2-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6"}, - {file = "greenlet-2.0.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43"}, - {file = "greenlet-2.0.2-cp35-cp35m-win32.whl", hash = "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a"}, - {file = "greenlet-2.0.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394"}, - {file = "greenlet-2.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75"}, - {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf"}, - {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292"}, - {file = "greenlet-2.0.2-cp36-cp36m-win32.whl", hash = "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9"}, - {file = "greenlet-2.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f"}, - {file = "greenlet-2.0.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73"}, - {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86"}, - {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33"}, - {file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"}, - {file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"}, - {file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857"}, - {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a"}, - {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"}, - {file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"}, - {file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"}, - {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b"}, - {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8"}, - {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9"}, - {file = "greenlet-2.0.2-cp39-cp39-win32.whl", hash = "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5"}, - {file = "greenlet-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564"}, - {file = "greenlet-2.0.2.tar.gz", hash = "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0"}, -] - -[package.extras] -docs = ["Sphinx", "docutils (<0.18)"] -test = ["objgraph", "psutil"] - -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.7" -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "html5tagger" -version = "1.3.0" -description = "Pythonic HTML generation/templating (no template files)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "html5tagger-1.3.0-py3-none-any.whl", hash = "sha256:ce14313515edffec8ed8a36c5890d023922641171b4e6e5774ad1a74998f5351"}, - {file = "html5tagger-1.3.0.tar.gz", hash = "sha256:84fa3dfb49e5c83b79bbd856ab7b1de8e2311c3bb46a8be925f119e3880a8da9"}, -] - -[[package]] -name = "httptools" -version = "0.5.0" -description = "A collection of framework independent HTTP protocol utils." -optional = false -python-versions = ">=3.5.0" -files = [ - {file = "httptools-0.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8f470c79061599a126d74385623ff4744c4e0f4a0997a353a44923c0b561ee51"}, - {file = "httptools-0.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e90491a4d77d0cb82e0e7a9cb35d86284c677402e4ce7ba6b448ccc7325c5421"}, - {file = "httptools-0.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1d2357f791b12d86faced7b5736dea9ef4f5ecdc6c3f253e445ee82da579449"}, - {file = "httptools-0.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f90cd6fd97c9a1b7fe9215e60c3bd97336742a0857f00a4cb31547bc22560c2"}, - {file = "httptools-0.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5230a99e724a1bdbbf236a1b58d6e8504b912b0552721c7c6b8570925ee0ccde"}, - {file = "httptools-0.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a47a34f6015dd52c9eb629c0f5a8a5193e47bf2a12d9a3194d231eaf1bc451a"}, - {file = "httptools-0.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:24bb4bb8ac3882f90aa95403a1cb48465de877e2d5298ad6ddcfdebec060787d"}, - {file = "httptools-0.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e67d4f8734f8054d2c4858570cc4b233bf753f56e85217de4dfb2495904cf02e"}, - {file = "httptools-0.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7e5eefc58d20e4c2da82c78d91b2906f1a947ef42bd668db05f4ab4201a99f49"}, - {file = "httptools-0.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0297822cea9f90a38df29f48e40b42ac3d48a28637368f3ec6d15eebefd182f9"}, - {file = "httptools-0.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:557be7fbf2bfa4a2ec65192c254e151684545ebab45eca5d50477d562c40f986"}, - {file = "httptools-0.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:54465401dbbec9a6a42cf737627fb0f014d50dc7365a6b6cd57753f151a86ff0"}, - {file = "httptools-0.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4d9ebac23d2de960726ce45f49d70eb5466725c0087a078866043dad115f850f"}, - {file = "httptools-0.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:e8a34e4c0ab7b1ca17b8763613783e2458e77938092c18ac919420ab8655c8c1"}, - {file = "httptools-0.5.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f659d7a48401158c59933904040085c200b4be631cb5f23a7d561fbae593ec1f"}, - {file = "httptools-0.5.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef1616b3ba965cd68e6f759eeb5d34fbf596a79e84215eeceebf34ba3f61fdc7"}, - {file = "httptools-0.5.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3625a55886257755cb15194efbf209584754e31d336e09e2ffe0685a76cb4b60"}, - {file = "httptools-0.5.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:72ad589ba5e4a87e1d404cc1cb1b5780bfcb16e2aec957b88ce15fe879cc08ca"}, - {file = "httptools-0.5.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:850fec36c48df5a790aa735417dca8ce7d4b48d59b3ebd6f83e88a8125cde324"}, - {file = "httptools-0.5.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f222e1e9d3f13b68ff8a835574eda02e67277d51631d69d7cf7f8e07df678c86"}, - {file = "httptools-0.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3cb8acf8f951363b617a8420768a9f249099b92e703c052f9a51b66342eea89b"}, - {file = "httptools-0.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:550059885dc9c19a072ca6d6735739d879be3b5959ec218ba3e013fd2255a11b"}, - {file = "httptools-0.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a04fe458a4597aa559b79c7f48fe3dceabef0f69f562daf5c5e926b153817281"}, - {file = "httptools-0.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d0c1044bce274ec6711f0770fd2d5544fe392591d204c68328e60a46f88843b"}, - {file = "httptools-0.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c6eeefd4435055a8ebb6c5cc36111b8591c192c56a95b45fe2af22d9881eee25"}, - {file = "httptools-0.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5b65be160adcd9de7a7e6413a4966665756e263f0d5ddeffde277ffeee0576a5"}, - {file = "httptools-0.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fe9c766a0c35b7e3d6b6939393c8dfdd5da3ac5dec7f971ec9134f284c6c36d6"}, - {file = "httptools-0.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:85b392aba273566c3d5596a0a490978c085b79700814fb22bfd537d381dd230c"}, - {file = "httptools-0.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5e3088f4ed33947e16fd865b8200f9cfae1144f41b64a8cf19b599508e096bc"}, - {file = "httptools-0.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c2a56b6aad7cc8f5551d8e04ff5a319d203f9d870398b94702300de50190f63"}, - {file = "httptools-0.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9b571b281a19762adb3f48a7731f6842f920fa71108aff9be49888320ac3e24d"}, - {file = "httptools-0.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa47ffcf70ba6f7848349b8a6f9b481ee0f7637931d91a9860a1838bfc586901"}, - {file = "httptools-0.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:bede7ee075e54b9a5bde695b4fc8f569f30185891796b2e4e09e2226801d09bd"}, - {file = "httptools-0.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:64eba6f168803a7469866a9c9b5263a7463fa8b7a25b35e547492aa7322036b6"}, - {file = "httptools-0.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4b098e4bb1174096a93f48f6193e7d9aa7071506a5877da09a783509ca5fff42"}, - {file = "httptools-0.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9423a2de923820c7e82e18980b937893f4aa8251c43684fa1772e341f6e06887"}, - {file = "httptools-0.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca1b7becf7d9d3ccdbb2f038f665c0f4857e08e1d8481cbcc1a86a0afcfb62b2"}, - {file = "httptools-0.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:50d4613025f15f4b11f1c54bbed4761c0020f7f921b95143ad6d58c151198142"}, - {file = "httptools-0.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8ffce9d81c825ac1deaa13bc9694c0562e2840a48ba21cfc9f3b4c922c16f372"}, - {file = "httptools-0.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:1af91b3650ce518d226466f30bbba5b6376dbd3ddb1b2be8b0658c6799dd450b"}, - {file = "httptools-0.5.0.tar.gz", hash = "sha256:295874861c173f9101960bba332429bb77ed4dcd8cdf5cee9922eb00e4f6bc09"}, -] - -[package.extras] -test = ["Cython (>=0.29.24,<0.30.0)"] - -[[package]] -name = "idna" -version = "3.4" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, -] - -[[package]] -name = "imagesize" -version = "1.4.1" -description = "Getting image size from png/jpeg/jpeg2000/gif file" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, - {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, -] - -[[package]] -name = "importlib-metadata" -version = "6.6.0" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"}, - {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"}, -] - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] - -[[package]] -name = "importlib-resources" -version = "5.12.0" -description = "Read resources from Python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "importlib_resources-5.12.0-py3-none-any.whl", hash = "sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a"}, - {file = "importlib_resources-5.12.0.tar.gz", hash = "sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6"}, -] - -[package.dependencies] -zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - -[[package]] -name = "itsdangerous" -version = "2.1.2" -description = "Safely pass data to untrusted environments and back." -optional = false -python-versions = ">=3.7" -files = [ - {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, - {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, -] - -[[package]] -name = "jinja2" -version = "3.1.2" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jsonpatch" -version = "1.32" -description = "Apply JSON-Patches (RFC 6902)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "jsonpatch-1.32-py2.py3-none-any.whl", hash = "sha256:26ac385719ac9f54df8a2f0827bb8253aa3ea8ab7b3368457bcdb8c14595a397"}, - {file = "jsonpatch-1.32.tar.gz", hash = "sha256:b6ddfe6c3db30d81a96aaeceb6baf916094ffa23d7dd5fa2c13e13f8b6e600c2"}, -] - -[package.dependencies] -jsonpointer = ">=1.9" - -[[package]] -name = "jsonpointer" -version = "2.3" -description = "Identify specific nodes in a JSON document (RFC 6901)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "jsonpointer-2.3-py2.py3-none-any.whl", hash = "sha256:51801e558539b4e9cd268638c078c6c5746c9ac96bc38152d443400e4f3793e9"}, - {file = "jsonpointer-2.3.tar.gz", hash = "sha256:97cba51526c829282218feb99dab1b1e6bdf8efd1c43dc9d57be093c0d69c99a"}, -] - -[[package]] -name = "kiwisolver" -version = "1.4.4" -description = "A fast implementation of the Cassowary constraint solver" -optional = false -python-versions = ">=3.7" -files = [ - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6"}, - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c"}, - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c79ebe8f3676a4c6630fd3f777f3cfecf9289666c84e775a67d1d358578dc2e3"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:abbe9fa13da955feb8202e215c4018f4bb57469b1b78c7a4c5c7b93001699938"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7577c1987baa3adc4b3c62c33bd1118c3ef5c8ddef36f0f2c950ae0b199e100d"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ed58b8acf29798b036d347791141767ccf65eee7f26bde03a71c944449e53de"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a68b62a02953b9841730db7797422f983935aeefceb1679f0fc85cbfbd311c32"}, - {file = "kiwisolver-1.4.4-cp310-cp310-win32.whl", hash = "sha256:e92a513161077b53447160b9bd8f522edfbed4bd9759e4c18ab05d7ef7e49408"}, - {file = "kiwisolver-1.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:3fe20f63c9ecee44560d0e7f116b3a747a5d7203376abeea292ab3152334d004"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ea21f66820452a3f5d1655f8704a60d66ba1191359b96541eaf457710a5fc6"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bc9db8a3efb3e403e4ecc6cd9489ea2bac94244f80c78e27c31dcc00d2790ac2"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d5b61785a9ce44e5a4b880272baa7cf6c8f48a5180c3e81c59553ba0cb0821ca"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c2dbb44c3f7e6c4d3487b31037b1bdbf424d97687c1747ce4ff2895795c9bf69"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6295ecd49304dcf3bfbfa45d9a081c96509e95f4b9d0eb7ee4ec0530c4a96514"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bd472dbe5e136f96a4b18f295d159d7f26fd399136f5b17b08c4e5f498cd494"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf7d9fce9bcc4752ca4a1b80aabd38f6d19009ea5cbda0e0856983cf6d0023f5"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d6601aed50c74e0ef02f4204da1816147a6d3fbdc8b3872d263338a9052c51"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:877272cf6b4b7e94c9614f9b10140e198d2186363728ed0f701c6eee1baec1da"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:db608a6757adabb32f1cfe6066e39b3706d8c3aa69bbc353a5b61edad36a5cb4"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5853eb494c71e267912275e5586fe281444eb5e722de4e131cddf9d442615626"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f0a1dbdb5ecbef0d34eb77e56fcb3e95bbd7e50835d9782a45df81cc46949750"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:283dffbf061a4ec60391d51e6155e372a1f7a4f5b15d59c8505339454f8989e4"}, - {file = "kiwisolver-1.4.4-cp311-cp311-win32.whl", hash = "sha256:d06adcfa62a4431d404c31216f0f8ac97397d799cd53800e9d3efc2fbb3cf14e"}, - {file = "kiwisolver-1.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e7da3fec7408813a7cebc9e4ec55afed2d0fd65c4754bc376bf03498d4e92686"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:62ac9cc684da4cf1778d07a89bf5f81b35834cb96ca523d3a7fb32509380cbf6"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41dae968a94b1ef1897cb322b39360a0812661dba7c682aa45098eb8e193dbdf"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0611a0a2a518464c05ddd5a3a1a0e856ccc10e67079bb17f265ad19ab3c7597"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:db5283d90da4174865d520e7366801a93777201e91e79bacbac6e6927cbceede"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-win32.whl", hash = "sha256:a553dadda40fef6bfa1456dc4be49b113aa92c2a9a9e8711e955618cd69622e3"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:841293b17ad704d70c578f1f0013c890e219952169ce8a24ebc063eecf775454"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f4f270de01dd3e129a72efad823da90cc4d6aafb64c410c9033aba70db9f1ff0"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c97528e64cb9ebeff9701e7938653a9951922f2a38bd847787d4a8e498cc83ae"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d1573129aa0fd901076e2bfb4275a35f5b7aa60fbfb984499d661ec950320b0"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad881edc7ccb9d65b0224f4e4d05a1e85cf62d73aab798943df6d48ab0cd79a1"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b428ef021242344340460fa4c9185d0b1f66fbdbfecc6c63eff4b7c29fad429d"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2e407cb4bd5a13984a6c2c0fe1845e4e41e96f183e5e5cd4d77a857d9693494c"}, - {file = "kiwisolver-1.4.4-cp38-cp38-win32.whl", hash = "sha256:75facbe9606748f43428fc91a43edb46c7ff68889b91fa31f53b58894503a191"}, - {file = "kiwisolver-1.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bce61af018b0cb2055e0e72e7d65290d822d3feee430b7b8203d8a855e78766"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8c808594c88a025d4e322d5bb549282c93c8e1ba71b790f539567932722d7bd8"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0a71d85ecdd570ded8ac3d1c0f480842f49a40beb423bb8014539a9f32a5897"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b533558eae785e33e8c148a8d9921692a9fe5aa516efbdff8606e7d87b9d5824"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:efda5fc8cc1c61e4f639b8067d118e742b812c930f708e6667a5ce0d13499e29"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7c43e1e1206cd421cd92e6b3280d4385d41d7166b3ed577ac20444b6995a445f"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc8d3bd6c72b2dd9decf16ce70e20abcb3274ba01b4e1c96031e0c4067d1e7cd"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ea39b0ccc4f5d803e3337dd46bcce60b702be4d86fd0b3d7531ef10fd99a1ac"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:968f44fdbf6dd757d12920d63b566eeb4d5b395fd2d00d29d7ef00a00582aac9"}, - {file = "kiwisolver-1.4.4-cp39-cp39-win32.whl", hash = "sha256:da7e547706e69e45d95e116e6939488d62174e033b763ab1496b4c29b76fabea"}, - {file = "kiwisolver-1.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:ba59c92039ec0a66103b1d5fe588fa546373587a7d68f5c96f743c3396afc04b"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:91672bacaa030f92fc2f43b620d7b337fd9a5af28b0d6ed3f77afc43c4a64b5a"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:787518a6789009c159453da4d6b683f468ef7a65bbde796bcea803ccf191058d"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da152d8cdcab0e56e4f45eb08b9aea6455845ec83172092f09b0e077ece2cf7a"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ecb1fa0db7bf4cff9dac752abb19505a233c7f16684c5826d1f11ebd9472b871"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:28bc5b299f48150b5f822ce68624e445040595a4ac3d59251703779836eceff9"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:81e38381b782cc7e1e46c4e14cd997ee6040768101aefc8fa3c24a4cc58e98f8"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2a66fdfb34e05b705620dd567f5a03f239a088d5a3f321e7b6ac3239d22aa286"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:872b8ca05c40d309ed13eb2e582cab0c5a05e81e987ab9c521bf05ad1d5cf5cb"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:70e7c2e7b750585569564e2e5ca9845acfaa5da56ac46df68414f29fea97be9f"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9f85003f5dfa867e86d53fac6f7e6f30c045673fa27b603c397753bebadc3008"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e307eb9bd99801f82789b44bb45e9f541961831c7311521b13a6c85afc09767"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1792d939ec70abe76f5054d3f36ed5656021dcad1322d1cc996d4e54165cef9"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b"}, - {file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"}, -] - -[[package]] -name = "livereload" -version = "2.6.3" -description = "Python LiveReload is an awesome tool for web developers" -optional = false -python-versions = "*" -files = [ - {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"}, - {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, -] - -[package.dependencies] -six = "*" -tornado = {version = "*", markers = "python_version > \"2.7\""} - -[[package]] -name = "lxml" -version = "4.9.2" -description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" -files = [ - {file = "lxml-4.9.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:76cf573e5a365e790396a5cc2b909812633409306c6531a6877c59061e42c4f2"}, - {file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b1f42b6921d0e81b1bcb5e395bc091a70f41c4d4e55ba99c6da2b31626c44892"}, - {file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9f102706d0ca011de571de32c3247c6476b55bb6bc65a20f682f000b07a4852a"}, - {file = "lxml-4.9.2-cp27-cp27m-win32.whl", hash = "sha256:8d0b4612b66ff5d62d03bcaa043bb018f74dfea51184e53f067e6fdcba4bd8de"}, - {file = "lxml-4.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:4c8f293f14abc8fd3e8e01c5bd86e6ed0b6ef71936ded5bf10fe7a5efefbaca3"}, - {file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2899456259589aa38bfb018c364d6ae7b53c5c22d8e27d0ec7609c2a1ff78b50"}, - {file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6749649eecd6a9871cae297bffa4ee76f90b4504a2a2ab528d9ebe912b101975"}, - {file = "lxml-4.9.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:a08cff61517ee26cb56f1e949cca38caabe9ea9fbb4b1e10a805dc39844b7d5c"}, - {file = "lxml-4.9.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:85cabf64adec449132e55616e7ca3e1000ab449d1d0f9d7f83146ed5bdcb6d8a"}, - {file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8340225bd5e7a701c0fa98284c849c9b9fc9238abf53a0ebd90900f25d39a4e4"}, - {file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1ab8f1f932e8f82355e75dda5413a57612c6ea448069d4fb2e217e9a4bed13d4"}, - {file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:699a9af7dffaf67deeae27b2112aa06b41c370d5e7633e0ee0aea2e0b6c211f7"}, - {file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9cc34af337a97d470040f99ba4282f6e6bac88407d021688a5d585e44a23184"}, - {file = "lxml-4.9.2-cp310-cp310-win32.whl", hash = "sha256:d02a5399126a53492415d4906ab0ad0375a5456cc05c3fc0fc4ca11771745cda"}, - {file = "lxml-4.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:a38486985ca49cfa574a507e7a2215c0c780fd1778bb6290c21193b7211702ab"}, - {file = "lxml-4.9.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c83203addf554215463b59f6399835201999b5e48019dc17f182ed5ad87205c9"}, - {file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:2a87fa548561d2f4643c99cd13131acb607ddabb70682dcf1dff5f71f781a4bf"}, - {file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:d6b430a9938a5a5d85fc107d852262ddcd48602c120e3dbb02137c83d212b380"}, - {file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3efea981d956a6f7173b4659849f55081867cf897e719f57383698af6f618a92"}, - {file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:df0623dcf9668ad0445e0558a21211d4e9a149ea8f5666917c8eeec515f0a6d1"}, - {file = "lxml-4.9.2-cp311-cp311-win32.whl", hash = "sha256:da248f93f0418a9e9d94b0080d7ebc407a9a5e6d0b57bb30db9b5cc28de1ad33"}, - {file = "lxml-4.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:3818b8e2c4b5148567e1b09ce739006acfaa44ce3156f8cbbc11062994b8e8dd"}, - {file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca989b91cf3a3ba28930a9fc1e9aeafc2a395448641df1f387a2d394638943b0"}, - {file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:822068f85e12a6e292803e112ab876bc03ed1f03dddb80154c395f891ca6b31e"}, - {file = "lxml-4.9.2-cp35-cp35m-win32.whl", hash = "sha256:be7292c55101e22f2a3d4d8913944cbea71eea90792bf914add27454a13905df"}, - {file = "lxml-4.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:998c7c41910666d2976928c38ea96a70d1aa43be6fe502f21a651e17483a43c5"}, - {file = "lxml-4.9.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:b26a29f0b7fc6f0897f043ca366142d2b609dc60756ee6e4e90b5f762c6adc53"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:ab323679b8b3030000f2be63e22cdeea5b47ee0abd2d6a1dc0c8103ddaa56cd7"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:689bb688a1db722485e4610a503e3e9210dcc20c520b45ac8f7533c837be76fe"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f49e52d174375a7def9915c9f06ec4e569d235ad428f70751765f48d5926678c"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:36c3c175d34652a35475a73762b545f4527aec044910a651d2bf50de9c3352b1"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a35f8b7fa99f90dd2f5dc5a9fa12332642f087a7641289ca6c40d6e1a2637d8e"}, - {file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:58bfa3aa19ca4c0f28c5dde0ff56c520fbac6f0daf4fac66ed4c8d2fb7f22e74"}, - {file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc718cd47b765e790eecb74d044cc8d37d58562f6c314ee9484df26276d36a38"}, - {file = "lxml-4.9.2-cp36-cp36m-win32.whl", hash = "sha256:d5bf6545cd27aaa8a13033ce56354ed9e25ab0e4ac3b5392b763d8d04b08e0c5"}, - {file = "lxml-4.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:3ab9fa9d6dc2a7f29d7affdf3edebf6ece6fb28a6d80b14c3b2fb9d39b9322c3"}, - {file = "lxml-4.9.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:05ca3f6abf5cf78fe053da9b1166e062ade3fa5d4f92b4ed688127ea7d7b1d03"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:a5da296eb617d18e497bcf0a5c528f5d3b18dadb3619fbdadf4ed2356ef8d941"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:04876580c050a8c5341d706dd464ff04fd597095cc8c023252566a8826505726"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c9ec3eaf616d67db0764b3bb983962b4f385a1f08304fd30c7283954e6a7869b"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2a29ba94d065945944016b6b74e538bdb1751a1db6ffb80c9d3c2e40d6fa9894"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a82d05da00a58b8e4c0008edbc8a4b6ec5a4bc1e2ee0fb6ed157cf634ed7fa45"}, - {file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:223f4232855ade399bd409331e6ca70fb5578efef22cf4069a6090acc0f53c0e"}, - {file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d17bc7c2ccf49c478c5bdd447594e82692c74222698cfc9b5daae7ae7e90743b"}, - {file = "lxml-4.9.2-cp37-cp37m-win32.whl", hash = "sha256:b64d891da92e232c36976c80ed7ebb383e3f148489796d8d31a5b6a677825efe"}, - {file = "lxml-4.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a0a336d6d3e8b234a3aae3c674873d8f0e720b76bc1d9416866c41cd9500ffb9"}, - {file = "lxml-4.9.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:da4dd7c9c50c059aba52b3524f84d7de956f7fef88f0bafcf4ad7dde94a064e8"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:821b7f59b99551c69c85a6039c65b75f5683bdc63270fec660f75da67469ca24"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:e5168986b90a8d1f2f9dc1b841467c74221bd752537b99761a93d2d981e04889"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8e20cb5a47247e383cf4ff523205060991021233ebd6f924bca927fcf25cf86f"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13598ecfbd2e86ea7ae45ec28a2a54fb87ee9b9fdb0f6d343297d8e548392c03"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:880bbbcbe2fca64e2f4d8e04db47bcdf504936fa2b33933efd945e1b429bea8c"}, - {file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d2278d59425777cfcb19735018d897ca8303abe67cc735f9f97177ceff8027f"}, - {file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5344a43228767f53a9df6e5b253f8cdca7dfc7b7aeae52551958192f56d98457"}, - {file = "lxml-4.9.2-cp38-cp38-win32.whl", hash = "sha256:925073b2fe14ab9b87e73f9a5fde6ce6392da430f3004d8b72cc86f746f5163b"}, - {file = "lxml-4.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:9b22c5c66f67ae00c0199f6055705bc3eb3fcb08d03d2ec4059a2b1b25ed48d7"}, - {file = "lxml-4.9.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5f50a1c177e2fa3ee0667a5ab79fdc6b23086bc8b589d90b93b4bd17eb0e64d1"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:090c6543d3696cbe15b4ac6e175e576bcc3f1ccfbba970061b7300b0c15a2140"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:63da2ccc0857c311d764e7d3d90f429c252e83b52d1f8f1d1fe55be26827d1f4"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:5b4545b8a40478183ac06c073e81a5ce4cf01bf1734962577cf2bb569a5b3bbf"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2e430cd2824f05f2d4f687701144556646bae8f249fd60aa1e4c768ba7018947"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6804daeb7ef69e7b36f76caddb85cccd63d0c56dedb47555d2fc969e2af6a1a5"}, - {file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a6e441a86553c310258aca15d1c05903aaf4965b23f3bc2d55f200804e005ee5"}, - {file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ca34efc80a29351897e18888c71c6aca4a359247c87e0b1c7ada14f0ab0c0fb2"}, - {file = "lxml-4.9.2-cp39-cp39-win32.whl", hash = "sha256:6b418afe5df18233fc6b6093deb82a32895b6bb0b1155c2cdb05203f583053f1"}, - {file = "lxml-4.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f1496ea22ca2c830cbcbd473de8f114a320da308438ae65abad6bab7867fe38f"}, - {file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b264171e3143d842ded311b7dccd46ff9ef34247129ff5bf5066123c55c2431c"}, - {file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0dc313ef231edf866912e9d8f5a042ddab56c752619e92dfd3a2c277e6a7299a"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:16efd54337136e8cd72fb9485c368d91d77a47ee2d42b057564aae201257d419"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0f2b1e0d79180f344ff9f321327b005ca043a50ece8713de61d1cb383fb8ac05"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:7b770ed79542ed52c519119473898198761d78beb24b107acf3ad65deae61f1f"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efa29c2fe6b4fdd32e8ef81c1528506895eca86e1d8c4657fda04c9b3786ddf9"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7e91ee82f4199af8c43d8158024cbdff3d931df350252288f0d4ce656df7f3b5"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b23e19989c355ca854276178a0463951a653309fb8e57ce674497f2d9f208746"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:01d36c05f4afb8f7c20fd9ed5badca32a2029b93b1750f571ccc0b142531caf7"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7b515674acfdcadb0eb5d00d8a709868173acece5cb0be3dd165950cbfdf5409"}, - {file = "lxml-4.9.2.tar.gz", hash = "sha256:2455cfaeb7ac70338b3257f41e21f0724f4b5b0c0e7702da67ee6c3640835b67"}, -] - -[package.extras] -cssselect = ["cssselect (>=0.7)"] -html5 = ["html5lib"] -htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=0.29.7)"] - -[[package]] -name = "markupsafe" -version = "2.0.1" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.6" -files = [ - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"}, - {file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, - {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, -] - -[[package]] -name = "matplotlib" -version = "3.7.1" -description = "Python plotting package" -optional = false -python-versions = ">=3.8" -files = [ - {file = "matplotlib-3.7.1-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:95cbc13c1fc6844ab8812a525bbc237fa1470863ff3dace7352e910519e194b1"}, - {file = "matplotlib-3.7.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:08308bae9e91aca1ec6fd6dda66237eef9f6294ddb17f0d0b3c863169bf82353"}, - {file = "matplotlib-3.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:544764ba51900da4639c0f983b323d288f94f65f4024dc40ecb1542d74dc0500"}, - {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56d94989191de3fcc4e002f93f7f1be5da476385dde410ddafbb70686acf00ea"}, - {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99bc9e65901bb9a7ce5e7bb24af03675cbd7c70b30ac670aa263240635999a4"}, - {file = "matplotlib-3.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb7d248c34a341cd4c31a06fd34d64306624c8cd8d0def7abb08792a5abfd556"}, - {file = "matplotlib-3.7.1-cp310-cp310-win32.whl", hash = "sha256:ce463ce590f3825b52e9fe5c19a3c6a69fd7675a39d589e8b5fbe772272b3a24"}, - {file = "matplotlib-3.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:3d7bc90727351fb841e4d8ae620d2d86d8ed92b50473cd2b42ce9186104ecbba"}, - {file = "matplotlib-3.7.1-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:770a205966d641627fd5cf9d3cb4b6280a716522cd36b8b284a8eb1581310f61"}, - {file = "matplotlib-3.7.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f67bfdb83a8232cb7a92b869f9355d677bce24485c460b19d01970b64b2ed476"}, - {file = "matplotlib-3.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2bf092f9210e105f414a043b92af583c98f50050559616930d884387d0772aba"}, - {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89768d84187f31717349c6bfadc0e0d8c321e8eb34522acec8a67b1236a66332"}, - {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83111e6388dec67822e2534e13b243cc644c7494a4bb60584edbff91585a83c6"}, - {file = "matplotlib-3.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a867bf73a7eb808ef2afbca03bcdb785dae09595fbe550e1bab0cd023eba3de0"}, - {file = "matplotlib-3.7.1-cp311-cp311-win32.whl", hash = "sha256:fbdeeb58c0cf0595efe89c05c224e0a502d1aa6a8696e68a73c3efc6bc354304"}, - {file = "matplotlib-3.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:c0bd19c72ae53e6ab979f0ac6a3fafceb02d2ecafa023c5cca47acd934d10be7"}, - {file = "matplotlib-3.7.1-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:6eb88d87cb2c49af00d3bbc33a003f89fd9f78d318848da029383bfc08ecfbfb"}, - {file = "matplotlib-3.7.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:cf0e4f727534b7b1457898c4f4ae838af1ef87c359b76dcd5330fa31893a3ac7"}, - {file = "matplotlib-3.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:46a561d23b91f30bccfd25429c3c706afe7d73a5cc64ef2dfaf2b2ac47c1a5dc"}, - {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8704726d33e9aa8a6d5215044b8d00804561971163563e6e6591f9dcf64340cc"}, - {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4cf327e98ecf08fcbb82685acaf1939d3338548620ab8dfa02828706402c34de"}, - {file = "matplotlib-3.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:617f14ae9d53292ece33f45cba8503494ee199a75b44de7717964f70637a36aa"}, - {file = "matplotlib-3.7.1-cp38-cp38-win32.whl", hash = "sha256:7c9a4b2da6fac77bcc41b1ea95fadb314e92508bf5493ceff058e727e7ecf5b0"}, - {file = "matplotlib-3.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:14645aad967684e92fc349493fa10c08a6da514b3d03a5931a1bac26e6792bd1"}, - {file = "matplotlib-3.7.1-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:81a6b377ea444336538638d31fdb39af6be1a043ca5e343fe18d0f17e098770b"}, - {file = "matplotlib-3.7.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:28506a03bd7f3fe59cd3cd4ceb2a8d8a2b1db41afede01f66c42561b9be7b4b7"}, - {file = "matplotlib-3.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8c587963b85ce41e0a8af53b9b2de8dddbf5ece4c34553f7bd9d066148dc719c"}, - {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8bf26ade3ff0f27668989d98c8435ce9327d24cffb7f07d24ef609e33d582439"}, - {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:def58098f96a05f90af7e92fd127d21a287068202aa43b2a93476170ebd99e87"}, - {file = "matplotlib-3.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f883a22a56a84dba3b588696a2b8a1ab0d2c3d41be53264115c71b0a942d8fdb"}, - {file = "matplotlib-3.7.1-cp39-cp39-win32.whl", hash = "sha256:4f99e1b234c30c1e9714610eb0c6d2f11809c9c78c984a613ae539ea2ad2eb4b"}, - {file = "matplotlib-3.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:3ba2af245e36990facf67fde840a760128ddd71210b2ab6406e640188d69d136"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3032884084f541163f295db8a6536e0abb0db464008fadca6c98aaf84ccf4717"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a2cb34336110e0ed8bb4f650e817eed61fa064acbefeb3591f1b33e3a84fd96"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b867e2f952ed592237a1828f027d332d8ee219ad722345b79a001f49df0936eb"}, - {file = "matplotlib-3.7.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:57bfb8c8ea253be947ccb2bc2d1bb3862c2bccc662ad1b4626e1f5e004557042"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:438196cdf5dc8d39b50a45cb6e3f6274edbcf2254f85fa9b895bf85851c3a613"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:21e9cff1a58d42e74d01153360de92b326708fb205250150018a52c70f43c290"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75d4725d70b7c03e082bbb8a34639ede17f333d7247f56caceb3801cb6ff703d"}, - {file = "matplotlib-3.7.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:97cc368a7268141afb5690760921765ed34867ffb9655dd325ed207af85c7529"}, - {file = "matplotlib-3.7.1.tar.gz", hash = "sha256:7b73305f25eab4541bd7ee0b96d87e53ae9c9f1823be5659b806cd85786fe882"}, -] - -[package.dependencies] -contourpy = ">=1.0.1" -cycler = ">=0.10" -fonttools = ">=4.22.0" -importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} -kiwisolver = ">=1.0.1" -numpy = ">=1.20" -packaging = ">=20.0" -pillow = ">=6.2.0" -pyparsing = ">=2.3.1" -python-dateutil = ">=2.7" - -[[package]] -name = "multidict" -version = "6.0.4" -description = "multidict implementation" -optional = false -python-versions = ">=3.7" -files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, -] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -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"}, -] - -[[package]] -name = "numpy" -version = "1.24.3" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"}, - {file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"}, - {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"}, - {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"}, - {file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"}, - {file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"}, - {file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"}, - {file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"}, - {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"}, - {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"}, - {file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"}, - {file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"}, - {file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"}, - {file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"}, - {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"}, - {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"}, - {file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"}, - {file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"}, - {file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"}, - {file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"}, - {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"}, - {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"}, - {file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"}, - {file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"}, - {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"}, -] - -[[package]] -name = "packaging" -version = "23.1" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, - {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, -] - -[[package]] -name = "pillow" -version = "9.5.0" -description = "Python Imaging Library (Fork)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "Pillow-9.5.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16"}, - {file = "Pillow-9.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d"}, - {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903"}, - {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a"}, - {file = "Pillow-9.5.0-cp310-cp310-win32.whl", hash = "sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44"}, - {file = "Pillow-9.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb"}, - {file = "Pillow-9.5.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32"}, - {file = "Pillow-9.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625"}, - {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579"}, - {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296"}, - {file = "Pillow-9.5.0-cp311-cp311-win32.whl", hash = "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec"}, - {file = "Pillow-9.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4"}, - {file = "Pillow-9.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089"}, - {file = "Pillow-9.5.0-cp312-cp312-win32.whl", hash = "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb"}, - {file = "Pillow-9.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b"}, - {file = "Pillow-9.5.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47"}, - {file = "Pillow-9.5.0-cp37-cp37m-win32.whl", hash = "sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7"}, - {file = "Pillow-9.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6"}, - {file = "Pillow-9.5.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597"}, - {file = "Pillow-9.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51"}, - {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96"}, - {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f"}, - {file = "Pillow-9.5.0-cp38-cp38-win32.whl", hash = "sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc"}, - {file = "Pillow-9.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569"}, - {file = "Pillow-9.5.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66"}, - {file = "Pillow-9.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1"}, - {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a"}, - {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865"}, - {file = "Pillow-9.5.0-cp39-cp39-win32.whl", hash = "sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964"}, - {file = "Pillow-9.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799"}, - {file = "Pillow-9.5.0.tar.gz", hash = "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1"}, -] - -[package.extras] -docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] -tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] - -[[package]] -name = "playwright" -version = "1.34.0" -description = "A high-level API to automate web browsers" -optional = false -python-versions = ">=3.7" -files = [ - {file = "playwright-1.34.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:69bb9b3296e366a23a99277b4c7673cb54ce71a3f5d630f114f7701b61f98f25"}, - {file = "playwright-1.34.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:402d946631c8458436e099d7731bbf54cf79c9e62e3acae0ea8421e72616926b"}, - {file = "playwright-1.34.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:462251cda0fcbb273497d357dbe14b11e43ebceb0bac9b892beda041ff209aa9"}, - {file = "playwright-1.34.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:a8ba124ea302596a03a66993cd500484fb255cbc10fe0757fa4d49f974267a80"}, - {file = "playwright-1.34.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf0cb6aac49d24335fe361868aea72b11f276a95e7809f1a5d1c69b4120c46ac"}, - {file = "playwright-1.34.0-py3-none-win32.whl", hash = "sha256:c50fef189d87243cc09ae0feb8e417fbe434359ccbcc863fb19ba06d46d31c33"}, - {file = "playwright-1.34.0-py3-none-win_amd64.whl", hash = "sha256:42e16c930e1e910461f4c551a72fc1b900f37124431bf2b6a6d9ddae70042db4"}, -] - -[package.dependencies] -greenlet = "2.0.2" -pyee = "9.0.4" - -[[package]] -name = "pydantic" -version = "1.10.8" -description = "Data validation and settings management using python type hints" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic-1.10.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1243d28e9b05003a89d72e7915fdb26ffd1d39bdd39b00b7dbe4afae4b557f9d"}, - {file = "pydantic-1.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0ab53b609c11dfc0c060d94335993cc2b95b2150e25583bec37a49b2d6c6c3f"}, - {file = "pydantic-1.10.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9613fadad06b4f3bc5db2653ce2f22e0de84a7c6c293909b48f6ed37b83c61f"}, - {file = "pydantic-1.10.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df7800cb1984d8f6e249351139667a8c50a379009271ee6236138a22a0c0f319"}, - {file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0c6fafa0965b539d7aab0a673a046466d23b86e4b0e8019d25fd53f4df62c277"}, - {file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e82d4566fcd527eae8b244fa952d99f2ca3172b7e97add0b43e2d97ee77f81ab"}, - {file = "pydantic-1.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:ab523c31e22943713d80d8d342d23b6f6ac4b792a1e54064a8d0cf78fd64e800"}, - {file = "pydantic-1.10.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:666bdf6066bf6dbc107b30d034615d2627e2121506c555f73f90b54a463d1f33"}, - {file = "pydantic-1.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:35db5301b82e8661fa9c505c800d0990bc14e9f36f98932bb1d248c0ac5cada5"}, - {file = "pydantic-1.10.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90c1e29f447557e9e26afb1c4dbf8768a10cc676e3781b6a577841ade126b85"}, - {file = "pydantic-1.10.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93e766b4a8226e0708ef243e843105bf124e21331694367f95f4e3b4a92bbb3f"}, - {file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:88f195f582851e8db960b4a94c3e3ad25692c1c1539e2552f3df7a9e972ef60e"}, - {file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:34d327c81e68a1ecb52fe9c8d50c8a9b3e90d3c8ad991bfc8f953fb477d42fb4"}, - {file = "pydantic-1.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:d532bf00f381bd6bc62cabc7d1372096b75a33bc197a312b03f5838b4fb84edd"}, - {file = "pydantic-1.10.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7d5b8641c24886d764a74ec541d2fc2c7fb19f6da2a4001e6d580ba4a38f7878"}, - {file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f6cb446470b7ddf86c2e57cd119a24959af2b01e552f60705910663af09a4"}, - {file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c33b60054b2136aef8cf190cd4c52a3daa20b2263917c49adad20eaf381e823b"}, - {file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1952526ba40b220b912cdc43c1c32bcf4a58e3f192fa313ee665916b26befb68"}, - {file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bb14388ec45a7a0dc429e87def6396f9e73c8c77818c927b6a60706603d5f2ea"}, - {file = "pydantic-1.10.8-cp37-cp37m-win_amd64.whl", hash = "sha256:16f8c3e33af1e9bb16c7a91fc7d5fa9fe27298e9f299cff6cb744d89d573d62c"}, - {file = "pydantic-1.10.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ced8375969673929809d7f36ad322934c35de4af3b5e5b09ec967c21f9f7887"}, - {file = "pydantic-1.10.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93e6bcfccbd831894a6a434b0aeb1947f9e70b7468f274154d03d71fabb1d7c6"}, - {file = "pydantic-1.10.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:191ba419b605f897ede9892f6c56fb182f40a15d309ef0142212200a10af4c18"}, - {file = "pydantic-1.10.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:052d8654cb65174d6f9490cc9b9a200083a82cf5c3c5d3985db765757eb3b375"}, - {file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ceb6a23bf1ba4b837d0cfe378329ad3f351b5897c8d4914ce95b85fba96da5a1"}, - {file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f2e754d5566f050954727c77f094e01793bcb5725b663bf628fa6743a5a9108"}, - {file = "pydantic-1.10.8-cp38-cp38-win_amd64.whl", hash = "sha256:6a82d6cda82258efca32b40040228ecf43a548671cb174a1e81477195ed3ed56"}, - {file = "pydantic-1.10.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e59417ba8a17265e632af99cc5f35ec309de5980c440c255ab1ca3ae96a3e0e"}, - {file = "pydantic-1.10.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:84d80219c3f8d4cad44575e18404099c76851bc924ce5ab1c4c8bb5e2a2227d0"}, - {file = "pydantic-1.10.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e4148e635994d57d834be1182a44bdb07dd867fa3c2d1b37002000646cc5459"}, - {file = "pydantic-1.10.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12f7b0bf8553e310e530e9f3a2f5734c68699f42218bf3568ef49cd9b0e44df4"}, - {file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42aa0c4b5c3025483240a25b09f3c09a189481ddda2ea3a831a9d25f444e03c1"}, - {file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17aef11cc1b997f9d574b91909fed40761e13fac438d72b81f902226a69dac01"}, - {file = "pydantic-1.10.8-cp39-cp39-win_amd64.whl", hash = "sha256:66a703d1983c675a6e0fed8953b0971c44dba48a929a2000a493c3772eb61a5a"}, - {file = "pydantic-1.10.8-py3-none-any.whl", hash = "sha256:7456eb22ed9aaa24ff3e7b4757da20d9e5ce2a81018c1b3ebd81a0b88a18f3b2"}, - {file = "pydantic-1.10.8.tar.gz", hash = "sha256:1410275520dfa70effadf4c21811d755e7ef9bb1f1d077a21958153a92c8d9ca"}, -] - -[package.dependencies] -typing-extensions = ">=4.2.0" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] - -[[package]] -name = "pyee" -version = "9.0.4" -description = "A port of node.js's EventEmitter to python." -optional = false -python-versions = "*" -files = [ - {file = "pyee-9.0.4-py2.py3-none-any.whl", hash = "sha256:9f066570130c554e9cc12de5a9d86f57c7ee47fece163bbdaa3e9c933cfbdfa5"}, - {file = "pyee-9.0.4.tar.gz", hash = "sha256:2770c4928abc721f46b705e6a72b0c59480c4a69c9a83ca0b00bb994f1ea4b32"}, -] - -[package.dependencies] -typing-extensions = "*" - -[[package]] -name = "pygments" -version = "2.15.1" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.7" -files = [ - {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, - {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, -] - -[package.extras] -plugins = ["importlib-metadata"] - -[[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -optional = false -python-versions = ">=3.6.8" -files = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "python-dateutil" -version = "2.8.2" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "python-dotenv" -version = "1.0.0" -description = "Read key-value pairs from a .env file and set them as environment variables" -optional = false -python-versions = ">=3.8" -files = [ - {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, - {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, -] - -[package.extras] -cli = ["click (>=5.0)"] - -[[package]] -name = "pyyaml" -version = "6.0" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, -] - -[[package]] -name = "reactpy" -version = "1.0.0" -description = "Reactive user interfaces with pure Python" -optional = false -python-versions = ">=3.9" -files = [] -develop = false - -[package.dependencies] -anyio = ">=3" -asgiref = ">=3" -colorlog = ">=6" -fastapi = {version = ">=0.63.0", optional = true, markers = "extra == \"fastapi\""} -fastjsonschema = ">=2.14.5" -flask = {version = "*", optional = true, markers = "extra == \"flask\""} -flask-cors = {version = "*", optional = true, markers = "extra == \"flask\""} -flask-sock = {version = "*", optional = true, markers = "extra == \"flask\""} -jsonpatch = ">=1.32" -lxml = ">=4" -markupsafe = {version = ">=1.1.1,<2.1", optional = true, markers = "extra == \"flask\""} -mypy-extensions = ">=0.4.3" -playwright = {version = "*", optional = true, markers = "extra == \"testing\""} -requests = ">=2" -sanic = {version = ">=21", optional = true, markers = "extra == \"sanic\""} -sanic-cors = {version = "*", optional = true, markers = "extra == \"sanic\""} -starlette = {version = ">=0.13.6", optional = true, markers = "extra == \"starlette\""} -tornado = {version = "*", optional = true, markers = "extra == \"tornado\""} -typing-extensions = ">=3.10" -uvicorn = {version = ">=0.19.0", extras = ["standard"], optional = true, markers = "extra == \"fastapi\" or extra == \"sanic\" or extra == \"starlette\""} - -[package.extras] -all = ["reactpy[fastapi,flask,sanic,starlette,testing,tornado]"] -fastapi = ["fastapi (>=0.63.0)", "uvicorn[standard] (>=0.19.0)"] -flask = ["flask", "flask-cors", "flask-sock", "markupsafe (>=1.1.1,<2.1)"] -sanic = ["sanic (>=21)", "sanic-cors", "uvicorn[standard] (>=0.19.0)"] -starlette = ["starlette (>=0.13.6)", "uvicorn[standard] (>=0.19.0)"] -testing = ["playwright"] -tornado = ["tornado"] - -[package.source] -type = "directory" -url = "../src/py/reactpy" - -[[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.7" -files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "sanic" -version = "23.3.0" -description = "A web server and web framework that's written to go fast. Build fast. Run fast." -optional = false -python-versions = ">=3.7" -files = [ - {file = "sanic-23.3.0-py3-none-any.whl", hash = "sha256:7cafbd63da9c6c6d8aeb8cb4304addf8a274352ab812014386c63e55f474fbee"}, - {file = "sanic-23.3.0.tar.gz", hash = "sha256:b80ebc5c38c983cb45ae5ecc7a669a54c823ec1dff297fbd5f817b1e9e9e49af"}, -] - -[package.dependencies] -aiofiles = ">=0.6.0" -html5tagger = ">=1.2.1" -httptools = ">=0.0.10" -multidict = ">=5.0,<7.0" -sanic-routing = ">=22.8.0" -tracerite = ">=1.0.0" -ujson = {version = ">=1.35", markers = "sys_platform != \"win32\" and implementation_name == \"cpython\""} -uvloop = {version = ">=0.15.0", markers = "sys_platform != \"win32\" and implementation_name == \"cpython\""} -websockets = ">=10.0" - -[package.extras] -all = ["bandit", "beautifulsoup4", "black", "chardet (==3.*)", "coverage", "cryptography", "docutils", "enum-tools[sphinx]", "flake8", "isort (>=5.0.0)", "m2r2", "mistune (<2.0.0)", "mypy (>=0.901,<0.910)", "pygments", "pytest (==7.1.*)", "pytest-benchmark", "pytest-sanic", "sanic-testing (>=23.3.0)", "slotscheck (>=0.8.0,<1)", "sphinx (>=2.1.2)", "sphinx-rtd-theme (>=0.4.3)", "towncrier", "tox", "types-ujson", "uvicorn (<0.15.0)"] -dev = ["bandit", "beautifulsoup4", "black", "chardet (==3.*)", "coverage", "cryptography", "docutils", "flake8", "isort (>=5.0.0)", "mypy (>=0.901,<0.910)", "pygments", "pytest (==7.1.*)", "pytest-benchmark", "pytest-sanic", "sanic-testing (>=23.3.0)", "slotscheck (>=0.8.0,<1)", "towncrier", "tox", "types-ujson", "uvicorn (<0.15.0)"] -docs = ["docutils", "enum-tools[sphinx]", "m2r2", "mistune (<2.0.0)", "pygments", "sphinx (>=2.1.2)", "sphinx-rtd-theme (>=0.4.3)"] -ext = ["sanic-ext"] -http3 = ["aioquic"] -test = ["bandit", "beautifulsoup4", "black", "chardet (==3.*)", "coverage", "docutils", "flake8", "isort (>=5.0.0)", "mypy (>=0.901,<0.910)", "pygments", "pytest (==7.1.*)", "pytest-benchmark", "pytest-sanic", "sanic-testing (>=23.3.0)", "slotscheck (>=0.8.0,<1)", "types-ujson", "uvicorn (<0.15.0)"] - -[[package]] -name = "sanic-cors" -version = "2.2.0" -description = "A Sanic extension adding a decorator for CORS support. Based on flask-cors by Cory Dolphin." -optional = false -python-versions = "*" -files = [ - {file = "Sanic-Cors-2.2.0.tar.gz", hash = "sha256:f8d7515da4c8b837871d422c66314c4b5704396a78894b59c50e26aa72a95873"}, - {file = "Sanic_Cors-2.2.0-py2.py3-none-any.whl", hash = "sha256:c3b133ff1f0bb609a53db35f727f5c371dc4ebeb6be4cc2c37c19dd8b9301115"}, -] - -[package.dependencies] -packaging = ">=21.3" -sanic = ">=21.9.3" - -[[package]] -name = "sanic-routing" -version = "22.8.0" -description = "Core routing component for Sanic" -optional = false -python-versions = "*" -files = [ - {file = "sanic-routing-22.8.0.tar.gz", hash = "sha256:305729b4e0bf01f074044a2a315ff401fa7eeffb009eec1d2c81d35e1038ddfc"}, - {file = "sanic_routing-22.8.0-py3-none-any.whl", hash = "sha256:9a928ed9e19a36bc019223be90a5da0ab88cdd76b101e032510b6a7073c017e9"}, -] - -[[package]] -name = "simple-websocket" -version = "0.10.0" -description = "Simple WebSocket server and client for Python" -optional = false -python-versions = ">=3.6" -files = [ - {file = "simple-websocket-0.10.0.tar.gz", hash = "sha256:82c0b0b1006d5490f09ff66392394d90dd758285635edad241e093e9a8abd3eb"}, - {file = "simple_websocket-0.10.0-py3-none-any.whl", hash = "sha256:fc1bc56c393a187e7268f8ab99da1a8e8da9b5dfb7769a2f3b8dada00067745b"}, -] - -[package.dependencies] -wsproto = "*" - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "sniffio" -version = "1.3.0" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, -] - -[[package]] -name = "snowballstemmer" -version = "2.2.0" -description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -optional = false -python-versions = "*" -files = [ - {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, - {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, -] - -[[package]] -name = "soupsieve" -version = "2.4.1" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.7" -files = [ - {file = "soupsieve-2.4.1-py3-none-any.whl", hash = "sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8"}, - {file = "soupsieve-2.4.1.tar.gz", hash = "sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea"}, -] - -[[package]] -name = "sphinx" -version = "4.5.0" -description = "Python documentation generator" -optional = false -python-versions = ">=3.6" -files = [ - {file = "Sphinx-4.5.0-py3-none-any.whl", hash = "sha256:ebf612653238bcc8f4359627a9b7ce44ede6fdd75d9d30f68255c7383d3a6226"}, - {file = "Sphinx-4.5.0.tar.gz", hash = "sha256:7bf8ca9637a4ee15af412d1a1d9689fec70523a68ca9bb9127c2f3eeb344e2e6"}, -] - -[package.dependencies] -alabaster = ">=0.7,<0.8" -babel = ">=1.3" -colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.14,<0.18" -imagesize = "*" -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} -Jinja2 = ">=2.3" -packaging = "*" -Pygments = ">=2.0" -requests = ">=2.5.0" -snowballstemmer = ">=1.1" -sphinxcontrib-applehelp = "*" -sphinxcontrib-devhelp = "*" -sphinxcontrib-htmlhelp = ">=2.0.0" -sphinxcontrib-jsmath = "*" -sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = ">=1.1.5" - -[package.extras] -docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "isort", "mypy (>=0.931)", "types-requests", "types-typed-ast"] -test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] - -[[package]] -name = "sphinx-autobuild" -version = "2021.3.14" -description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." -optional = false -python-versions = ">=3.6" -files = [ - {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, - {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, -] - -[package.dependencies] -colorama = "*" -livereload = "*" -sphinx = "*" - -[package.extras] -test = ["pytest", "pytest-cov"] - -[[package]] -name = "sphinx-autodoc-typehints" -version = "1.19.1" -description = "Type hints (PEP 484) support for the Sphinx autodoc extension" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sphinx_autodoc_typehints-1.19.1-py3-none-any.whl", hash = "sha256:9be46aeeb1b315eb5df1f3a7cb262149895d16c7d7dcd77b92513c3c3a1e85e6"}, - {file = "sphinx_autodoc_typehints-1.19.1.tar.gz", hash = "sha256:6c841db55e0e9be0483ff3962a2152b60e79306f4288d8c4e7e86ac84486a5ea"}, -] - -[package.dependencies] -Sphinx = ">=4.5" - -[package.extras] -testing = ["covdefaults (>=2.2)", "coverage (>=6.3)", "diff-cover (>=6.4)", "nptyping (>=2.1.2)", "pytest (>=7.1)", "pytest-cov (>=3)", "sphobjinv (>=2)", "typing-extensions (>=4.1)"] -type-comments = ["typed-ast (>=1.5.2)"] - -[[package]] -name = "sphinx-copybutton" -version = "0.5.2" -description = "Add a copy button to each of your code cells." -optional = false -python-versions = ">=3.7" -files = [ - {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}, - {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"}, -] - -[package.dependencies] -sphinx = ">=1.8" - -[package.extras] -code-style = ["pre-commit (==2.12.1)"] -rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] - -[[package]] -name = "sphinx-design" -version = "0.4.1" -description = "A sphinx extension for designing beautiful, view size responsive web components." -optional = false -python-versions = ">=3.7" -files = [ - {file = "sphinx_design-0.4.1-py3-none-any.whl", hash = "sha256:23bf5705eb31296d4451f68b0222a698a8a84396ffe8378dfd9319ba7ab8efd9"}, - {file = "sphinx_design-0.4.1.tar.gz", hash = "sha256:5b6418ba4a2dc3d83592ea0ff61a52a891fe72195a4c3a18b2fa1c7668ce4708"}, -] - -[package.dependencies] -sphinx = ">=4,<7" - -[package.extras] -code-style = ["pre-commit (>=2.12,<3.0)"] -rtd = ["myst-parser (>=0.18.0,<2)"] -testing = ["myst-parser (>=0.18.0,<2)", "pytest (>=7.1,<8.0)", "pytest-cov", "pytest-regressions"] -theme-furo = ["furo (>=2022.06.04,<2022.07)"] -theme-pydata = ["pydata-sphinx-theme (>=0.9.0,<0.10.0)"] -theme-rtd = ["sphinx-rtd-theme (>=1.0,<2.0)"] -theme-sbt = ["sphinx-book-theme (>=0.3.0,<0.4.0)"] - -[[package]] -name = "sphinx-reredirects" -version = "0.1.2" -description = "Handles redirects for moved pages in Sphinx documentation projects" -optional = false -python-versions = ">=3.5" -files = [ - {file = "sphinx_reredirects-0.1.2-py3-none-any.whl", hash = "sha256:3a22161771aadd448bb608a4fe7277252182a337af53c18372b7104531d71489"}, - {file = "sphinx_reredirects-0.1.2.tar.gz", hash = "sha256:a0e7213304759b01edc22f032f1715a1c61176fc8f167164e7a52b9feec9ac64"}, -] - -[package.dependencies] -sphinx = "*" - -[[package]] -name = "sphinx-resolve-py-references" -version = "0.1.0" -description = "Better python object resolution in Sphinx" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sphinx_resolve_py_references-0.1.0-py2.py3-none-any.whl", hash = "sha256:ccf44a6b62d75c3a568285f4e1815734088c1a7cab7bbb7935bb22fbf0d78bc2"}, - {file = "sphinx_resolve_py_references-0.1.0.tar.gz", hash = "sha256:0f87c06b29ec128964aee2e40d170d1d3c0e5f4955b2618a89ca724f42385372"}, -] - -[package.dependencies] -sphinx = "*" - -[[package]] -name = "sphinxcontrib-applehelp" -version = "1.0.4" -description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" -optional = false -python-versions = ">=3.8" -files = [ - {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, - {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, -] - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-devhelp" -version = "1.0.2" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." -optional = false -python-versions = ">=3.5" -files = [ - {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, - {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, -] - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-htmlhelp" -version = "2.0.1" -description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -optional = false -python-versions = ">=3.8" -files = [ - {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, - {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, -] - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["html5lib", "pytest"] - -[[package]] -name = "sphinxcontrib-jsmath" -version = "1.0.1" -description = "A sphinx extension which renders display math in HTML via JavaScript" -optional = false -python-versions = ">=3.5" -files = [ - {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, - {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, -] - -[package.extras] -test = ["flake8", "mypy", "pytest"] - -[[package]] -name = "sphinxcontrib-qthelp" -version = "1.0.3" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." -optional = false -python-versions = ">=3.5" -files = [ - {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, - {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, -] - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-serializinghtml" -version = "1.1.5" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." -optional = false -python-versions = ">=3.5" -files = [ - {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, - {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, -] - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxext-opengraph" -version = "0.8.2" -description = "Sphinx Extension to enable OGP support" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sphinxext-opengraph-0.8.2.tar.gz", hash = "sha256:45a693b6704052c426576f0a1f630649c55b4188bc49eb63e9587e24a923db39"}, - {file = "sphinxext_opengraph-0.8.2-py3-none-any.whl", hash = "sha256:6a05bdfe5176d9dd0a1d58a504f17118362ab976631213cd36fb44c4c40544c9"}, -] - -[package.dependencies] -matplotlib = "*" -sphinx = ">=4.0" - -[[package]] -name = "starlette" -version = "0.27.0" -description = "The little ASGI library that shines." -optional = false -python-versions = ">=3.7" -files = [ - {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, - {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, -] - -[package.dependencies] -anyio = ">=3.4.0,<5" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} - -[package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] - -[[package]] -name = "tornado" -version = "6.3.2" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -optional = false -python-versions = ">= 3.8" -files = [ - {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:c367ab6c0393d71171123ca5515c61ff62fe09024fa6bf299cd1339dc9456829"}, - {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b46a6ab20f5c7c1cb949c72c1994a4585d2eaa0be4853f50a03b5031e964fc7c"}, - {file = "tornado-6.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2de14066c4a38b4ecbbcd55c5cc4b5340eb04f1c5e81da7451ef555859c833f"}, - {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05615096845cf50a895026f749195bf0b10b8909f9be672f50b0fe69cba368e4"}, - {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b17b1cf5f8354efa3d37c6e28fdfd9c1c1e5122f2cb56dac121ac61baa47cbe"}, - {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:29e71c847a35f6e10ca3b5c2990a52ce38b233019d8e858b755ea6ce4dcdd19d"}, - {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:834ae7540ad3a83199a8da8f9f2d383e3c3d5130a328889e4cc991acc81e87a0"}, - {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6a0848f1aea0d196a7c4f6772197cbe2abc4266f836b0aac76947872cd29b411"}, - {file = "tornado-6.3.2-cp38-abi3-win32.whl", hash = "sha256:7efcbcc30b7c654eb6a8c9c9da787a851c18f8ccd4a5a3a95b05c7accfa068d2"}, - {file = "tornado-6.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:0c325e66c8123c606eea33084976c832aa4e766b7dff8aedd7587ea44a604cdf"}, - {file = "tornado-6.3.2.tar.gz", hash = "sha256:4b927c4f19b71e627b13f3db2324e4ae660527143f9e1f2e2fb404f3a187e2ba"}, -] - -[[package]] -name = "tracerite" -version = "1.1.0" -description = "Human-readable HTML tracebacks for Python exceptions" -optional = false -python-versions = "*" -files = [ - {file = "tracerite-1.1.0-py3-none-any.whl", hash = "sha256:4cccac04db05eeeabda45e72b57199e147fa2f73cf64d89cfd625df321bd2ab6"}, - {file = "tracerite-1.1.0.tar.gz", hash = "sha256:041dab8fd4bb405f73506293ac7438a2d311e5f9044378ba7d9a6540392f9e4b"}, -] - -[package.dependencies] -html5tagger = ">=1.2.1" - -[[package]] -name = "typing-extensions" -version = "4.6.3" -description = "Backported and Experimental Type Hints for Python 3.7+" -optional = false -python-versions = ">=3.7" -files = [ - {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"}, - {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"}, -] - -[[package]] -name = "ujson" -version = "5.7.0" -description = "Ultra fast JSON encoder and decoder for Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "ujson-5.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5eba5e69e4361ac3a311cf44fa71bc619361b6e0626768a494771aacd1c2f09b"}, - {file = "ujson-5.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aae4d9e1b4c7b61780f0a006c897a4a1904f862fdab1abb3ea8f45bd11aa58f3"}, - {file = "ujson-5.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2e43ccdba1cb5c6d3448eadf6fc0dae7be6c77e357a3abc968d1b44e265866d"}, - {file = "ujson-5.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54384ce4920a6d35fa9ea8e580bc6d359e3eb961fa7e43f46c78e3ed162d56ff"}, - {file = "ujson-5.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24ad1aa7fc4e4caa41d3d343512ce68e41411fb92adf7f434a4d4b3749dc8f58"}, - {file = "ujson-5.7.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:afff311e9f065a8f03c3753db7011bae7beb73a66189c7ea5fcb0456b7041ea4"}, - {file = "ujson-5.7.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e80f0d03e7e8646fc3d79ed2d875cebd4c83846e129737fdc4c2532dbd43d9e"}, - {file = "ujson-5.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:137831d8a0db302fb6828ee21c67ad63ac537bddc4376e1aab1c8573756ee21c"}, - {file = "ujson-5.7.0-cp310-cp310-win32.whl", hash = "sha256:7df3fd35ebc14dafeea031038a99232b32f53fa4c3ecddb8bed132a43eefb8ad"}, - {file = "ujson-5.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:af4639f684f425177d09ae409c07602c4096a6287027469157bfb6f83e01448b"}, - {file = "ujson-5.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9b0f2680ce8a70f77f5d70aaf3f013d53e6af6d7058727a35d8ceb4a71cdd4e9"}, - {file = "ujson-5.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a19fd8e7d8cc58a169bea99fed5666023adf707a536d8f7b0a3c51dd498abf"}, - {file = "ujson-5.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6abb8e6d8f1ae72f0ed18287245f5b6d40094e2656d1eab6d99d666361514074"}, - {file = "ujson-5.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8cd622c069368d5074bd93817b31bdb02f8d818e57c29e206f10a1f9c6337dd"}, - {file = "ujson-5.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14f9082669f90e18e64792b3fd0bf19f2b15e7fe467534a35ea4b53f3bf4b755"}, - {file = "ujson-5.7.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d7ff6ebb43bc81b057724e89550b13c9a30eda0f29c2f506f8b009895438f5a6"}, - {file = "ujson-5.7.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f7f241488879d91a136b299e0c4ce091996c684a53775e63bb442d1a8e9ae22a"}, - {file = "ujson-5.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5593263a7fcfb934107444bcfba9dde8145b282de0ee9f61e285e59a916dda0f"}, - {file = "ujson-5.7.0-cp311-cp311-win32.whl", hash = "sha256:26c2b32b489c393106e9cb68d0a02e1a7b9d05a07429d875c46b94ee8405bdb7"}, - {file = "ujson-5.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:ed24406454bb5a31df18f0a423ae14beb27b28cdfa34f6268e7ebddf23da807e"}, - {file = "ujson-5.7.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18679484e3bf9926342b1c43a3bd640f93a9eeeba19ef3d21993af7b0c44785d"}, - {file = "ujson-5.7.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ee295761e1c6c30400641f0a20d381633d7622633cdf83a194f3c876a0e4b7e"}, - {file = "ujson-5.7.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b738282e12a05f400b291966630a98d622da0938caa4bc93cf65adb5f4281c60"}, - {file = "ujson-5.7.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00343501dbaa5172e78ef0e37f9ebd08040110e11c12420ff7c1f9f0332d939e"}, - {file = "ujson-5.7.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c0d1f7c3908357ee100aa64c4d1cf91edf99c40ac0069422a4fd5fd23b263263"}, - {file = "ujson-5.7.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a5d2f44331cf04689eafac7a6596c71d6657967c07ac700b0ae1c921178645da"}, - {file = "ujson-5.7.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:16b2254a77b310f118717715259a196662baa6b1f63b1a642d12ab1ff998c3d7"}, - {file = "ujson-5.7.0-cp37-cp37m-win32.whl", hash = "sha256:6faf46fa100b2b89e4db47206cf8a1ffb41542cdd34dde615b2fc2288954f194"}, - {file = "ujson-5.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ff0004c3f5a9a6574689a553d1b7819d1a496b4f005a7451f339dc2d9f4cf98c"}, - {file = "ujson-5.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:75204a1dd7ec6158c8db85a2f14a68d2143503f4bafb9a00b63fe09d35762a5e"}, - {file = "ujson-5.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7312731c7826e6c99cdd3ac503cd9acd300598e7a80bcf41f604fee5f49f566c"}, - {file = "ujson-5.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b9dc5a90e2149643df7f23634fe202fed5ebc787a2a1be95cf23632b4d90651"}, - {file = "ujson-5.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6a6961fc48821d84b1198a09516e396d56551e910d489692126e90bf4887d29"}, - {file = "ujson-5.7.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b01a9af52a0d5c46b2c68e3f258fdef2eacaa0ce6ae3e9eb97983f5b1166edb6"}, - {file = "ujson-5.7.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7316d3edeba8a403686cdcad4af737b8415493101e7462a70ff73dd0609eafc"}, - {file = "ujson-5.7.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ee997799a23227e2319a3f8817ce0b058923dbd31904761b788dc8f53bd3e30"}, - {file = "ujson-5.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dda9aa4c33435147262cd2ea87c6b7a1ca83ba9b3933ff7df34e69fee9fced0c"}, - {file = "ujson-5.7.0-cp38-cp38-win32.whl", hash = "sha256:bea8d30e362180aafecabbdcbe0e1f0b32c9fa9e39c38e4af037b9d3ca36f50c"}, - {file = "ujson-5.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:c96e3b872bf883090ddf32cc41957edf819c5336ab0007d0cf3854e61841726d"}, - {file = "ujson-5.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6411aea4c94a8e93c2baac096fbf697af35ba2b2ed410b8b360b3c0957a952d3"}, - {file = "ujson-5.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d3b3499c55911f70d4e074c626acdb79a56f54262c3c83325ffb210fb03e44d"}, - {file = "ujson-5.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:341f891d45dd3814d31764626c55d7ab3fd21af61fbc99d070e9c10c1190680b"}, - {file = "ujson-5.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f242eec917bafdc3f73a1021617db85f9958df80f267db69c76d766058f7b19"}, - {file = "ujson-5.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3af9f9f22a67a8c9466a32115d9073c72a33ae627b11de6f592df0ee09b98b6"}, - {file = "ujson-5.7.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4a3d794afbf134df3056a813e5c8a935208cddeae975bd4bc0ef7e89c52f0ce0"}, - {file = "ujson-5.7.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:800bf998e78dae655008dd10b22ca8dc93bdcfcc82f620d754a411592da4bbf2"}, - {file = "ujson-5.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b5ac3d5c5825e30b438ea92845380e812a476d6c2a1872b76026f2e9d8060fc2"}, - {file = "ujson-5.7.0-cp39-cp39-win32.whl", hash = "sha256:cd90027e6d93e8982f7d0d23acf88c896d18deff1903dd96140613389b25c0dd"}, - {file = "ujson-5.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:523ee146cdb2122bbd827f4dcc2a8e66607b3f665186bce9e4f78c9710b6d8ab"}, - {file = "ujson-5.7.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e87cec407ec004cf1b04c0ed7219a68c12860123dfb8902ef880d3d87a71c172"}, - {file = "ujson-5.7.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bab10165db6a7994e67001733f7f2caf3400b3e11538409d8756bc9b1c64f7e8"}, - {file = "ujson-5.7.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b522be14a28e6ac1cf818599aeff1004a28b42df4ed4d7bc819887b9dac915fc"}, - {file = "ujson-5.7.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7592f40175c723c032cdbe9fe5165b3b5903604f774ab0849363386e99e1f253"}, - {file = "ujson-5.7.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ed22f9665327a981f288a4f758a432824dc0314e4195a0eaeb0da56a477da94d"}, - {file = "ujson-5.7.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:adf445a49d9a97a5a4c9bb1d652a1528de09dd1c48b29f79f3d66cea9f826bf6"}, - {file = "ujson-5.7.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64772a53f3c4b6122ed930ae145184ebaed38534c60f3d859d8c3f00911eb122"}, - {file = "ujson-5.7.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35209cb2c13fcb9d76d249286105b4897b75a5e7f0efb0c0f4b90f222ce48910"}, - {file = "ujson-5.7.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:90712dfc775b2c7a07d4d8e059dd58636bd6ff1776d79857776152e693bddea6"}, - {file = "ujson-5.7.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:0e4e8981c6e7e9e637e637ad8ffe948a09e5434bc5f52ecbb82b4b4cfc092bfb"}, - {file = "ujson-5.7.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:581c945b811a3d67c27566539bfcb9705ea09cb27c4be0002f7a553c8886b817"}, - {file = "ujson-5.7.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d36a807a24c7d44f71686685ae6fbc8793d784bca1adf4c89f5f780b835b6243"}, - {file = "ujson-5.7.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b4257307e3662aa65e2644a277ca68783c5d51190ed9c49efebdd3cbfd5fa44"}, - {file = "ujson-5.7.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea7423d8a2f9e160c5e011119741682414c5b8dce4ae56590a966316a07a4618"}, - {file = "ujson-5.7.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4c592eb91a5968058a561d358d0fef59099ed152cfb3e1cd14eee51a7a93879e"}, - {file = "ujson-5.7.0.tar.gz", hash = "sha256:e788e5d5dcae8f6118ac9b45d0b891a0d55f7ac480eddcb7f07263f2bcf37b23"}, -] - -[[package]] -name = "urllib3" -version = "2.0.2" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.7" -files = [ - {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, - {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "uvicorn" -version = "0.22.0" -description = "The lightning-fast ASGI server." -optional = false -python-versions = ">=3.7" -files = [ - {file = "uvicorn-0.22.0-py3-none-any.whl", hash = "sha256:e9434d3bbf05f310e762147f769c9f21235ee118ba2d2bf1155a7196448bd996"}, - {file = "uvicorn-0.22.0.tar.gz", hash = "sha256:79277ae03db57ce7d9aa0567830bbb51d7a612f54d6e1e3e92da3ef24c2c8ed8"}, -] - -[package.dependencies] -click = ">=7.0" -colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} -h11 = ">=0.8" -httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} -python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} -pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} -uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""} -watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} -websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} - -[package.extras] -standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] - -[[package]] -name = "uvloop" -version = "0.17.0" -description = "Fast implementation of asyncio event loop on top of libuv" -optional = false -python-versions = ">=3.7" -files = [ - {file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce9f61938d7155f79d3cb2ffa663147d4a76d16e08f65e2c66b77bd41b356718"}, - {file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:68532f4349fd3900b839f588972b3392ee56042e440dd5873dfbbcd2cc67617c"}, - {file = "uvloop-0.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0949caf774b9fcefc7c5756bacbbbd3fc4c05a6b7eebc7c7ad6f825b23998d6d"}, - {file = "uvloop-0.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff3d00b70ce95adce264462c930fbaecb29718ba6563db354608f37e49e09024"}, - {file = "uvloop-0.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a5abddb3558d3f0a78949c750644a67be31e47936042d4f6c888dd6f3c95f4aa"}, - {file = "uvloop-0.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8efcadc5a0003d3a6e887ccc1fb44dec25594f117a94e3127954c05cf144d811"}, - {file = "uvloop-0.17.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3378eb62c63bf336ae2070599e49089005771cc651c8769aaad72d1bd9385a7c"}, - {file = "uvloop-0.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6aafa5a78b9e62493539456f8b646f85abc7093dd997f4976bb105537cf2635e"}, - {file = "uvloop-0.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c686a47d57ca910a2572fddfe9912819880b8765e2f01dc0dd12a9bf8573e539"}, - {file = "uvloop-0.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:864e1197139d651a76c81757db5eb199db8866e13acb0dfe96e6fc5d1cf45fc4"}, - {file = "uvloop-0.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2a6149e1defac0faf505406259561bc14b034cdf1d4711a3ddcdfbaa8d825a05"}, - {file = "uvloop-0.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6708f30db9117f115eadc4f125c2a10c1a50d711461699a0cbfaa45b9a78e376"}, - {file = "uvloop-0.17.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:23609ca361a7fc587031429fa25ad2ed7242941adec948f9d10c045bfecab06b"}, - {file = "uvloop-0.17.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2deae0b0fb00a6af41fe60a675cec079615b01d68beb4cc7b722424406b126a8"}, - {file = "uvloop-0.17.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45cea33b208971e87a31c17622e4b440cac231766ec11e5d22c76fab3bf9df62"}, - {file = "uvloop-0.17.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9b09e0f0ac29eee0451d71798878eae5a4e6a91aa275e114037b27f7db72702d"}, - {file = "uvloop-0.17.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dbbaf9da2ee98ee2531e0c780455f2841e4675ff580ecf93fe5c48fe733b5667"}, - {file = "uvloop-0.17.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a4aee22ece20958888eedbad20e4dbb03c37533e010fb824161b4f05e641f738"}, - {file = "uvloop-0.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:307958f9fc5c8bb01fad752d1345168c0abc5d62c1b72a4a8c6c06f042b45b20"}, - {file = "uvloop-0.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ebeeec6a6641d0adb2ea71dcfb76017602ee2bfd8213e3fcc18d8f699c5104f"}, - {file = "uvloop-0.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1436c8673c1563422213ac6907789ecb2b070f5939b9cbff9ef7113f2b531595"}, - {file = "uvloop-0.17.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8887d675a64cfc59f4ecd34382e5b4f0ef4ae1da37ed665adba0c2badf0d6578"}, - {file = "uvloop-0.17.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3db8de10ed684995a7f34a001f15b374c230f7655ae840964d51496e2f8a8474"}, - {file = "uvloop-0.17.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7d37dccc7ae63e61f7b96ee2e19c40f153ba6ce730d8ba4d3b4e9738c1dccc1b"}, - {file = "uvloop-0.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cbbe908fda687e39afd6ea2a2f14c2c3e43f2ca88e3a11964b297822358d0e6c"}, - {file = "uvloop-0.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d97672dc709fa4447ab83276f344a165075fd9f366a97b712bdd3fee05efae8"}, - {file = "uvloop-0.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1e507c9ee39c61bfddd79714e4f85900656db1aec4d40c6de55648e85c2799c"}, - {file = "uvloop-0.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c092a2c1e736086d59ac8e41f9c98f26bbf9b9222a76f21af9dfe949b99b2eb9"}, - {file = "uvloop-0.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:30babd84706115626ea78ea5dbc7dd8d0d01a2e9f9b306d24ca4ed5796c66ded"}, - {file = "uvloop-0.17.0.tar.gz", hash = "sha256:0ddf6baf9cf11a1a22c71487f39f15b2cf78eb5bde7e5b45fbb99e8a9d91b9e1"}, -] - -[package.extras] -dev = ["Cython (>=0.29.32,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)", "pytest (>=3.6.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] -docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] -test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)"] - -[[package]] -name = "watchfiles" -version = "0.19.0" -description = "Simple, modern and high performance file watching and code reload in python." -optional = false -python-versions = ">=3.7" -files = [ - {file = "watchfiles-0.19.0-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:91633e64712df3051ca454ca7d1b976baf842d7a3640b87622b323c55f3345e7"}, - {file = "watchfiles-0.19.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:b6577b8c6c8701ba8642ea9335a129836347894b666dd1ec2226830e263909d3"}, - {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:18b28f6ad871b82df9542ff958d0c86bb0d8310bb09eb8e87d97318a3b5273af"}, - {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fac19dc9cbc34052394dbe81e149411a62e71999c0a19e1e09ce537867f95ae0"}, - {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:09ea3397aecbc81c19ed7f025e051a7387feefdb789cf768ff994c1228182fda"}, - {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c0376deac92377817e4fb8f347bf559b7d44ff556d9bc6f6208dd3f79f104aaf"}, - {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c75eff897786ee262c9f17a48886f4e98e6cfd335e011c591c305e5d083c056"}, - {file = "watchfiles-0.19.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb5d45c4143c1dd60f98a16187fd123eda7248f84ef22244818c18d531a249d1"}, - {file = "watchfiles-0.19.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:79c533ff593db861ae23436541f481ec896ee3da4e5db8962429b441bbaae16e"}, - {file = "watchfiles-0.19.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3d7d267d27aceeeaa3de0dd161a0d64f0a282264d592e335fff7958cc0cbae7c"}, - {file = "watchfiles-0.19.0-cp37-abi3-win32.whl", hash = "sha256:176a9a7641ec2c97b24455135d58012a5be5c6217fc4d5fef0b2b9f75dbf5154"}, - {file = "watchfiles-0.19.0-cp37-abi3-win_amd64.whl", hash = "sha256:945be0baa3e2440151eb3718fd8846751e8b51d8de7b884c90b17d271d34cae8"}, - {file = "watchfiles-0.19.0-cp37-abi3-win_arm64.whl", hash = "sha256:0089c6dc24d436b373c3c57657bf4f9a453b13767150d17284fc6162b2791911"}, - {file = "watchfiles-0.19.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cae3dde0b4b2078f31527acff6f486e23abed307ba4d3932466ba7cdd5ecec79"}, - {file = "watchfiles-0.19.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f3920b1285a7d3ce898e303d84791b7bf40d57b7695ad549dc04e6a44c9f120"}, - {file = "watchfiles-0.19.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9afd0d69429172c796164fd7fe8e821ade9be983f51c659a38da3faaaaac44dc"}, - {file = "watchfiles-0.19.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68dce92b29575dda0f8d30c11742a8e2b9b8ec768ae414b54f7453f27bdf9545"}, - {file = "watchfiles-0.19.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:5569fc7f967429d4bc87e355cdfdcee6aabe4b620801e2cf5805ea245c06097c"}, - {file = "watchfiles-0.19.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5471582658ea56fca122c0f0d0116a36807c63fefd6fdc92c71ca9a4491b6b48"}, - {file = "watchfiles-0.19.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b538014a87f94d92f98f34d3e6d2635478e6be6423a9ea53e4dd96210065e193"}, - {file = "watchfiles-0.19.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20b44221764955b1e703f012c74015306fb7e79a00c15370785f309b1ed9aa8d"}, - {file = "watchfiles-0.19.0.tar.gz", hash = "sha256:d9b073073e048081e502b6c6b0b88714c026a1a4c890569238d04aca5f9ca74b"}, -] - -[package.dependencies] -anyio = ">=3.0.0" - -[[package]] -name = "websockets" -version = "11.0.3" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3ccc8a0c387629aec40f2fc9fdcb4b9d5431954f934da3eaf16cdc94f67dbfac"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d67ac60a307f760c6e65dad586f556dde58e683fab03323221a4e530ead6f74d"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d27a4832cc1a0ee07cdcf2b0629a8a72db73f4cf6de6f0904f6661227f256f"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7622a89d696fc87af8e8d280d9b421db5133ef5b29d3f7a1ce9f1a7bf7fcfa11"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bceab846bac555aff6427d060f2fcfff71042dba6f5fca7dc4f75cac815e57ca"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54c6e5b3d3a8936a4ab6870d46bdd6ec500ad62bde9e44462c32d18f1e9a8e54"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41f696ba95cd92dc047e46b41b26dd24518384749ed0d99bea0a941ca87404c4"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86d2a77fd490ae3ff6fae1c6ceaecad063d3cc2320b44377efdde79880e11526"}, - {file = "websockets-11.0.3-cp310-cp310-win32.whl", hash = "sha256:2d903ad4419f5b472de90cd2d40384573b25da71e33519a67797de17ef849b69"}, - {file = "websockets-11.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1d2256283fa4b7f4c7d7d3e84dc2ece74d341bce57d5b9bf385df109c2a1a82f"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e848f46a58b9fcf3d06061d17be388caf70ea5b8cc3466251963c8345e13f7eb"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa5003845cdd21ac0dc6c9bf661c5beddd01116f6eb9eb3c8e272353d45b3288"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b58cbf0697721120866820b89f93659abc31c1e876bf20d0b3d03cef14faf84d"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:660e2d9068d2bedc0912af508f30bbeb505bbbf9774d98def45f68278cea20d3"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1f0524f203e3bd35149f12157438f406eff2e4fb30f71221c8a5eceb3617b6b"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b30c6590146e53149f04e85a6e4fcae068df4289e31e4aee1fdf56a0dead8f97"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:619d9f06372b3a42bc29d0cd0354c9bb9fb39c2cbc1a9c5025b4538738dbffaf"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd"}, - {file = "websockets-11.0.3-cp311-cp311-win32.whl", hash = "sha256:e1459677e5d12be8bbc7584c35b992eea142911a6236a3278b9b5ce3326f282c"}, - {file = "websockets-11.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:e7837cb169eca3b3ae94cc5787c4fed99eef74c0ab9506756eea335e0d6f3ed8"}, - {file = "websockets-11.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f59a3c656fef341a99e3d63189852be7084c0e54b75734cde571182c087b152"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2529338a6ff0eb0b50c7be33dc3d0e456381157a31eefc561771ee431134a97f"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fd59a4ac42dff6d4681d8843217137f6bc85ed29722f2f7222bd619d15e95b"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:332d126167ddddec94597c2365537baf9ff62dfcc9db4266f263d455f2f031cb"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6505c1b31274723ccaf5f515c1824a4ad2f0d191cec942666b3d0f3aa4cb4007"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f467ba0050b7de85016b43f5a22b46383ef004c4f672148a8abf32bc999a87f0"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9d9acd80072abcc98bd2c86c3c9cd4ac2347b5a5a0cae7ed5c0ee5675f86d9af"}, - {file = "websockets-11.0.3-cp37-cp37m-win32.whl", hash = "sha256:e590228200fcfc7e9109509e4d9125eace2042fd52b595dd22bbc34bb282307f"}, - {file = "websockets-11.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b16fff62b45eccb9c7abb18e60e7e446998093cdcb50fed33134b9b6878836de"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a34e13a62a59c871064dfd8ffb150867e54291e46d4a7cf11d02c94a5275bae"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4841ed00f1026dfbced6fca7d963c4e7043aa832648671b5138008dc5a8f6d99"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a073fc9ab1c8aff37c99f11f1641e16da517770e31a37265d2755282a5d28aa"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68b977f21ce443d6d378dbd5ca38621755f2063d6fdb3335bda981d552cfff86"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a99a7a71631f0efe727c10edfba09ea6bee4166a6f9c19aafb6c0b5917d09c"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bee9fcb41db2a23bed96c6b6ead6489702c12334ea20a297aa095ce6d31370d0"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4b253869ea05a5a073ebfdcb5cb3b0266a57c3764cf6fe114e4cd90f4bfa5f5e"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1553cb82942b2a74dd9b15a018dce645d4e68674de2ca31ff13ebc2d9f283788"}, - {file = "websockets-11.0.3-cp38-cp38-win32.whl", hash = "sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74"}, - {file = "websockets-11.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:03aae4edc0b1c68498f41a6772d80ac7c1e33c06c6ffa2ac1c27a07653e79d6f"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:777354ee16f02f643a4c7f2b3eff8027a33c9861edc691a2003531f5da4f6bc8"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c82f11964f010053e13daafdc7154ce7385ecc538989a354ccc7067fd7028fd"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3580dd9c1ad0701169e4d6fc41e878ffe05e6bdcaf3c412f9d559389d0c9e016"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f1a3f10f836fab6ca6efa97bb952300b20ae56b409414ca85bff2ad241d2a61"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df41b9bc27c2c25b486bae7cf42fccdc52ff181c8c387bfd026624a491c2671b"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279e5de4671e79a9ac877427f4ac4ce93751b8823f276b681d04b2156713b9dd"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1fdf26fa8a6a592f8f9235285b8affa72748dc12e964a5518c6c5e8f916716f7"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69269f3a0b472e91125b503d3c0b3566bda26da0a3261c49f0027eb6075086d1"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97b52894d948d2f6ea480171a27122d77af14ced35f62e5c892ca2fae9344311"}, - {file = "websockets-11.0.3-cp39-cp39-win32.whl", hash = "sha256:c7f3cb904cce8e1be667c7e6fef4516b98d1a6a0635a58a57528d577ac18a128"}, - {file = "websockets-11.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c792ea4eabc0159535608fc5658a74d1a81020eb35195dd63214dcf07556f67e"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e58f2c36cc52d41f2659e4c0cbf7353e28c8c9e63e30d8c6d3494dc9fdedcf"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de36fe9c02995c7e6ae6efe2e205816f5f00c22fd1fbf343d4d18c3d5ceac2f5"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ac56b661e60edd453585f4bd68eb6a29ae25b5184fd5ba51e97652580458998"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e052b8467dd07d4943936009f46ae5ce7b908ddcac3fda581656b1b19c083d9b"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42cc5452a54a8e46a032521d7365da775823e21bfba2895fb7b77633cce031bb"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e6316827e3e79b7b8e7d8e3b08f4e331af91a48e794d5d8b099928b6f0b85f20"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8531fdcad636d82c517b26a448dcfe62f720e1922b33c81ce695d0edb91eb931"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c114e8da9b475739dde229fd3bc6b05a6537a88a578358bc8eb29b4030fac9c9"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e063b1865974611313a3849d43f2c3f5368093691349cf3c7c8f8f75ad7cb280"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:92b2065d642bf8c0a82d59e59053dd2fdde64d4ed44efe4870fa816c1232647b"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ee68fe502f9031f19d495dae2c268830df2760c0524cbac5d759921ba8c8e82"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcacf2c7a6c3a84e720d1bb2b543c675bf6c40e460300b628bab1b1efc7c034c"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b67c6f5e5a401fc56394f191f00f9b3811fe843ee93f4a70df3c389d1adf857d"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5023a4b6a5b183dc838808087033ec5df77580485fc533e7dab2567851b0a4"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ed058398f55163a79bb9f06a90ef9ccc063b204bb346c4de78efc5d15abfe602"}, - {file = "websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6"}, - {file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"}, -] - -[[package]] -name = "werkzeug" -version = "2.1.2" -description = "The comprehensive WSGI web application library." -optional = false -python-versions = ">=3.7" -files = [ - {file = "Werkzeug-2.1.2-py3-none-any.whl", hash = "sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"}, - {file = "Werkzeug-2.1.2.tar.gz", hash = "sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6"}, -] - -[package.extras] -watchdog = ["watchdog"] - -[[package]] -name = "wsproto" -version = "1.2.0" -description = "WebSockets state-machine based protocol implementation" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, - {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, -] - -[package.dependencies] -h11 = ">=0.9.0,<1" - -[[package]] -name = "zipp" -version = "3.15.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.7" -files = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - -[metadata] -lock-version = "2.0" -python-versions = "^3.9" -content-hash = "629118cfac10f1dab4c39c6ccd50bd69ca68a7fc05dd2baf1d020082d6b19e4e" diff --git a/docs/pyproject.toml b/docs/pyproject.toml deleted file mode 100644 index d2f47c577..000000000 --- a/docs/pyproject.toml +++ /dev/null @@ -1,23 +0,0 @@ -[tool.poetry] -name = "docs" -version = "0.0.0" -description = "docs" -authors = ["rmorshea "] -readme = "README.md" - -[tool.poetry.dependencies] -python = "^3.9" -reactpy = { path = "../src/py/reactpy", extras = ["starlette", "sanic", "fastapi", "flask", "tornado", "testing"], develop = false } -furo = "2022.04.07" -sphinx = "*" -sphinx-autodoc-typehints = "*" -sphinx-copybutton = "*" -sphinx-autobuild = "*" -sphinx-reredirects = "*" -sphinx-design = "*" -sphinx-resolve-py-references = "*" -sphinxext-opengraph = "*" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 000000000..28f64bf4d --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,12 @@ +mkdocs +mkdocs-git-revision-date-localized-plugin +mkdocs-material==9.4.0 +mkdocs-include-markdown-plugin +mkdocs-spellcheck[all] +mkdocs-git-authors-plugin +mkdocs-minify-plugin +mike +mkdocstrings[python] +black +linkcheckmd +mkdocs-section-index diff --git a/docs/source/_custom_js/README.md b/docs/source/_custom_js/README.md deleted file mode 100644 index 4d5d75dc2..000000000 --- a/docs/source/_custom_js/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Custom Javascript for ReactPy's Docs - -Build the javascript with - -``` -npm run build -``` - -This will drop a javascript bundle into `../_static/custom.js` diff --git a/docs/source/_custom_js/package-lock.json b/docs/source/_custom_js/package-lock.json deleted file mode 100644 index 98cbb7014..000000000 --- a/docs/source/_custom_js/package-lock.json +++ /dev/null @@ -1,766 +0,0 @@ -{ - "name": "reactpy-docs-example-loader", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "reactpy-docs-example-loader", - "version": "1.0.0", - "dependencies": { - "@reactpy/client": "file:../../../src/js/packages/@reactpy/client" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^21.0.1", - "@rollup/plugin-node-resolve": "^13.1.1", - "@rollup/plugin-replace": "^3.0.0", - "prettier": "^2.2.1", - "rollup": "^2.35.1" - } - }, - "../../../src/client/packages/@reactpy/client": { - "version": "0.3.1", - "integrity": "sha512-pIK5eNwFSHKXg7ClpASWFVKyZDYxz59MSFpVaX/OqJFkrJaAxBuhKGXNTMXmuyWOL5Iyvb/ErwwDRxQRzMNkfQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "event-to-object": "^0.1.2", - "json-pointer": "^0.6.2" - }, - "devDependencies": { - "@types/json-pointer": "^1.0.31", - "@types/react": "^17.0", - "@types/react-dom": "^17.0", - "typescript": "^4.9.5" - }, - "peerDependencies": { - "react": ">=16 <18", - "react-dom": ">=16 <18" - } - }, - "../../../src/client/packages/client": { - "name": "@reactpy/client", - "version": "0.2.0", - "extraneous": true, - "license": "MIT", - "dependencies": { - "event-to-object": "^0.1.0", - "json-pointer": "^0.6.2" - }, - "devDependencies": { - "@types/json-pointer": "^1.0.31", - "@types/react": "^17.0", - "@types/react-dom": "^17.0", - "prettier": "^3.0.0-alpha.6", - "typescript": "^4.9.5" - }, - "peerDependencies": { - "react": ">=16 <18", - "react-dom": ">=16 <18" - } - }, - "../../../src/js/packages/@reactpy/client": { - "version": "0.3.1", - "license": "MIT", - "dependencies": { - "event-to-object": "^0.1.2", - "json-pointer": "^0.6.2" - }, - "devDependencies": { - "@types/json-pointer": "^1.0.31", - "@types/react": "^17.0", - "@types/react-dom": "^17.0", - "typescript": "^4.9.5" - }, - "peerDependencies": { - "react": ">=16 <18", - "react-dom": ">=16 <18" - } - }, - "node_modules/@reactpy/client": { - "resolved": "../../../src/js/packages/@reactpy/client", - "link": true - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-21.0.1.tgz", - "integrity": "sha512-EA+g22lbNJ8p5kuZJUYyhhDK7WgJckW5g4pNN7n4mAFUM96VuwUnNT3xr2Db2iCZPI1pJPbGyfT5mS9T1dHfMg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^2.38.3" - } - }, - "node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.1.tgz", - "integrity": "sha512-6QKtRevXLrmEig9UiMYt2fSvee9TyltGRfw+qSs6xjUnxwjOzTOqy+/Lpxsgjb8mJn1EQNbCDAvt89O4uzL5kw==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "rollup": "^2.42.0" - } - }, - "node_modules/@rollup/plugin-node-resolve/node_modules/@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@rollup/plugin-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-3.0.0.tgz", - "integrity": "sha512-3c7JCbMuYXM4PbPWT4+m/4Y6U60SgsnDT/cCyAyUKwFHg7pTSfsSQzIpETha3a3ig6OdOKzZz87D9ZXIK3qsDg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "magic-string": "^0.25.7" - }, - "peerDependencies": { - "rollup": "^1.20.0 || ^2.0.0" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "dependencies": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" - } - }, - "node_modules/@rollup/pluginutils/node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, - "node_modules/@types/estree": { - "version": "0.0.48", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz", - "integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==", - "dev": true - }, - "node_modules/@types/node": { - "version": "15.12.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz", - "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/builtin-modules": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", - "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-core-module": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", - "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true - }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.4" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prettier": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz", - "integrity": "sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rollup": { - "version": "2.52.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.1.tgz", - "integrity": "sha512-/SPqz8UGnp4P1hq6wc9gdTqA2bXQXGx13TtoL03GBm6qGRI6Hm3p4Io7GeiHNLl0BsQAne1JNYY+q/apcY933w==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - } - }, - "dependencies": { - "@reactpy/client": { - "version": "file:../../../src/js/packages/@reactpy/client", - "requires": { - "@types/json-pointer": "^1.0.31", - "@types/react": "^17.0", - "@types/react-dom": "^17.0", - "event-to-object": "^0.1.2", - "json-pointer": "^0.6.2", - "typescript": "^4.9.5" - } - }, - "@rollup/plugin-commonjs": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-21.0.1.tgz", - "integrity": "sha512-EA+g22lbNJ8p5kuZJUYyhhDK7WgJckW5g4pNN7n4mAFUM96VuwUnNT3xr2Db2iCZPI1pJPbGyfT5mS9T1dHfMg==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" - }, - "dependencies": { - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - } - } - }, - "@rollup/plugin-node-resolve": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.1.tgz", - "integrity": "sha512-6QKtRevXLrmEig9UiMYt2fSvee9TyltGRfw+qSs6xjUnxwjOzTOqy+/Lpxsgjb8mJn1EQNbCDAvt89O4uzL5kw==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.19.0" - }, - "dependencies": { - "@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "requires": { - "@types/node": "*" - } - } - } - }, - "@rollup/plugin-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-3.0.0.tgz", - "integrity": "sha512-3c7JCbMuYXM4PbPWT4+m/4Y6U60SgsnDT/cCyAyUKwFHg7pTSfsSQzIpETha3a3ig6OdOKzZz87D9ZXIK3qsDg==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "magic-string": "^0.25.7" - } - }, - "@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "requires": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - } - } - }, - "@types/estree": { - "version": "0.0.48", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz", - "integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==", - "dev": true - }, - "@types/node": { - "version": "15.12.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz", - "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "builtin-modules": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", - "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-core-module": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", - "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true - }, - "is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "requires": { - "@types/estree": "*" - } - }, - "magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - }, - "prettier": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz", - "integrity": "sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==", - "dev": true - }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, - "rollup": { - "version": "2.52.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.1.tgz", - "integrity": "sha512-/SPqz8UGnp4P1hq6wc9gdTqA2bXQXGx13TtoL03GBm6qGRI6Hm3p4Io7GeiHNLl0BsQAne1JNYY+q/apcY933w==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - } - } -} diff --git a/docs/source/_custom_js/package.json b/docs/source/_custom_js/package.json deleted file mode 100644 index 78d72b961..000000000 --- a/docs/source/_custom_js/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "reactpy-docs-example-loader", - "version": "1.0.0", - "description": "simple javascript client for ReactPy's documentation", - "main": "index.js", - "scripts": { - "build": "rollup --config", - "format": "prettier --ignore-path .gitignore --write ." - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^21.0.1", - "@rollup/plugin-node-resolve": "^13.1.1", - "@rollup/plugin-replace": "^3.0.0", - "prettier": "^2.2.1", - "rollup": "^2.35.1" - }, - "dependencies": { - "@reactpy/client": "file:../../../src/js/packages/@reactpy/client" - } -} diff --git a/docs/source/_custom_js/rollup.config.js b/docs/source/_custom_js/rollup.config.js deleted file mode 100644 index 48dd535cf..000000000 --- a/docs/source/_custom_js/rollup.config.js +++ /dev/null @@ -1,26 +0,0 @@ -import resolve from "@rollup/plugin-node-resolve"; -import commonjs from "@rollup/plugin-commonjs"; -import replace from "@rollup/plugin-replace"; - -export default { - input: "src/index.js", - output: { - file: "../_static/custom.js", - format: "esm", - }, - plugins: [ - resolve(), - commonjs(), - replace({ - "process.env.NODE_ENV": JSON.stringify("production"), - preventAssignment: true, - }), - ], - onwarn: function (warning) { - if (warning.code === "THIS_IS_UNDEFINED") { - // skip warning where `this` is undefined at the top level of a module - return; - } - console.warn(warning.message); - }, -}; diff --git a/docs/source/_custom_js/src/index.js b/docs/source/_custom_js/src/index.js deleted file mode 100644 index 505adedd0..000000000 --- a/docs/source/_custom_js/src/index.js +++ /dev/null @@ -1,94 +0,0 @@ -import { SimpleReactPyClient, mount } from "@reactpy/client"; - -let didMountDebug = false; - -export function mountWidgetExample( - mountID, - viewID, - reactpyServerHost, - useActivateButton, -) { - let reactpyHost, reactpyPort; - if (reactpyServerHost) { - [reactpyHost, reactpyPort] = reactpyServerHost.split(":", 2); - } else { - reactpyHost = window.location.hostname; - reactpyPort = window.location.port; - } - - const client = new SimpleReactPyClient({ - serverLocation: { - url: `${window.location.protocol}//${reactpyHost}:${reactpyPort}`, - route: "/", - query: `?view_id=${viewID}`, - }, - }); - - const mountEl = document.getElementById(mountID); - let isMounted = false; - triggerIfInViewport(mountEl, () => { - if (!isMounted) { - activateView(mountEl, client, useActivateButton); - isMounted = true; - } - }); -} - -function activateView(mountEl, client, useActivateButton) { - if (!useActivateButton) { - mount(mountEl, client); - return; - } - - const enableWidgetButton = document.createElement("button"); - enableWidgetButton.appendChild(document.createTextNode("Activate")); - enableWidgetButton.setAttribute("class", "enable-widget-button"); - - enableWidgetButton.addEventListener("click", () => - fadeOutElementThenCallback(enableWidgetButton, () => { - { - mountEl.removeChild(enableWidgetButton); - mountEl.setAttribute("class", "interactive widget-container"); - mountWithLayoutServer(mountEl, serverInfo); - } - }), - ); - - function fadeOutElementThenCallback(element, callback) { - { - var op = 1; // initial opacity - var timer = setInterval(function () { - { - if (op < 0.001) { - { - clearInterval(timer); - element.style.display = "none"; - callback(); - } - } - element.style.opacity = op; - element.style.filter = "alpha(opacity=" + op * 100 + ")"; - op -= op * 0.5; - } - }, 50); - } - } - - mountEl.appendChild(enableWidgetButton); -} - -function triggerIfInViewport(element, callback) { - const observer = new window.IntersectionObserver( - ([entry]) => { - if (entry.isIntersecting) { - callback(); - } - }, - { - root: null, - threshold: 0.1, // set offset 0.1 means trigger if at least 10% of element in viewport - }, - ); - - observer.observe(element); -} diff --git a/docs/source/_exts/async_doctest.py b/docs/source/_exts/async_doctest.py deleted file mode 100644 index 96024d488..000000000 --- a/docs/source/_exts/async_doctest.py +++ /dev/null @@ -1,47 +0,0 @@ -from doctest import DocTest, DocTestRunner -from textwrap import indent -from typing import Any - -from sphinx.application import Sphinx -from sphinx.ext.doctest import DocTestBuilder -from sphinx.ext.doctest import setup as doctest_setup - -test_template = """ -import asyncio as __test_template_asyncio - -async def __test_template__main(): - - {test} - - globals().update(locals()) - -__test_template_asyncio.run(__test_template__main()) -""" - - -class TestRunnerWrapper: - def __init__(self, runner: DocTestRunner): - self._runner = runner - - def __getattr__(self, name: str) -> Any: - return getattr(self._runner, name) - - def run(self, test: DocTest, *args: Any, **kwargs: Any) -> Any: - for ex in test.examples: - ex.source = test_template.format(test=indent(ex.source, " ").strip()) - return self._runner.run(test, *args, **kwargs) - - -class AsyncDoctestBuilder(DocTestBuilder): - @property - def test_runner(self) -> DocTestRunner: - return self._test_runner - - @test_runner.setter - def test_runner(self, value: DocTestRunner) -> None: - self._test_runner = TestRunnerWrapper(value) - - -def setup(app: Sphinx) -> None: - doctest_setup(app) - app.add_builder(AsyncDoctestBuilder, override=True) diff --git a/docs/source/_exts/autogen_api_docs.py b/docs/source/_exts/autogen_api_docs.py deleted file mode 100644 index b95d85a99..000000000 --- a/docs/source/_exts/autogen_api_docs.py +++ /dev/null @@ -1,146 +0,0 @@ -from __future__ import annotations - -import sys -from collections.abc import Collection, Iterator -from pathlib import Path - -from sphinx.application import Sphinx - -HERE = Path(__file__).parent -SRC = HERE.parent.parent.parent / "src" -PYTHON_PACKAGE = SRC / "py" / "reactpy" / "reactpy" - -AUTO_DIR = HERE.parent / "_auto" -AUTO_DIR.mkdir(exist_ok=True) - -API_FILE = AUTO_DIR / "apis.rst" - -# All valid RST section symbols - it shouldn't be realistically possible to exhaust them -SECTION_SYMBOLS = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~""" - -AUTODOC_TEMPLATE_WITH_MEMBERS = """\ -.. automodule:: {module} - :members: - :ignore-module-all: -""" - -AUTODOC_TEMPLATE_WITHOUT_MEMBERS = """\ -.. automodule:: {module} - :ignore-module-all: -""" - -TITLE = """\ -========== -Python API -========== -""" - - -def generate_api_docs(): - content = [TITLE] - - for file in walk_python_files(PYTHON_PACKAGE, ignore_dirs={"__pycache__"}): - if file.name == "__init__.py": - if file.parent != PYTHON_PACKAGE: - content.append(make_package_section(file)) - else: - content.append(make_module_section(file)) - - API_FILE.write_text("\n".join(content)) - - -def make_package_section(file: Path) -> str: - parent_dir = file.parent - symbol = get_section_symbol(parent_dir) - section_name = f"``{parent_dir.name}``" - module_name = get_module_name(parent_dir) - return ( - section_name - + "\n" - + (symbol * len(section_name)) - + "\n" - + AUTODOC_TEMPLATE_WITHOUT_MEMBERS.format(module=module_name) - ) - - -def make_module_section(file: Path) -> str: - symbol = get_section_symbol(file) - section_name = f"``{file.stem}``" - module_name = get_module_name(file) - return ( - section_name - + "\n" - + (symbol * len(section_name)) - + "\n" - + AUTODOC_TEMPLATE_WITH_MEMBERS.format(module=module_name) - ) - - -def get_module_name(path: Path) -> str: - return ".".join(path.with_suffix("").relative_to(PYTHON_PACKAGE.parent).parts) - - -def get_section_symbol(path: Path) -> str: - rel_path = path.relative_to(PYTHON_PACKAGE) - rel_path_parts = rel_path.parts - if len(rel_path_parts) > len(SECTION_SYMBOLS): - msg = f"package structure is too deep - ran out of section symbols: {rel_path}" - raise RuntimeError(msg) - return SECTION_SYMBOLS[len(rel_path_parts) - 1] - - -def walk_python_files(root: Path, ignore_dirs: Collection[str]) -> Iterator[Path]: - """Iterate over Python files - - We yield in a particular order to get the correction title section structure. Given - a directory structure of the form:: - - project/ - __init__.py - /package - __init__.py - module_a.py - module_b.py - - We yield the files in this order:: - - project/__init__.py - project/package/__init__.py - project/package/module_a.py - project/module_b.py - - In this way we generate the section titles in the appropriate order:: - - project - ======= - - project.package - --------------- - - project.package.module_a - ------------------------ - - """ - for path in sorted( - root.iterdir(), - key=lambda path: ( - # __init__.py files first - int(not path.name == "__init__.py"), - # then directories - int(not path.is_dir()), - # sort by file name last - path.name, - ), - ): - if path.is_dir(): - if (path / "__init__.py").exists() and path.name not in ignore_dirs: - yield from walk_python_files(path, ignore_dirs) - elif path.suffix == ".py": - yield path - - -def setup(app: Sphinx) -> None: - if sys.platform == "win32" and sys.version_info[:2] == (3, 7): - return None - generate_api_docs() - return None diff --git a/docs/source/_exts/build_custom_js.py b/docs/source/_exts/build_custom_js.py deleted file mode 100644 index 97857ba74..000000000 --- a/docs/source/_exts/build_custom_js.py +++ /dev/null @@ -1,12 +0,0 @@ -import subprocess -from pathlib import Path - -from sphinx.application import Sphinx - -SOURCE_DIR = Path(__file__).parent.parent -CUSTOM_JS_DIR = SOURCE_DIR / "_custom_js" - - -def setup(app: Sphinx) -> None: - subprocess.run("npm install", cwd=CUSTOM_JS_DIR, shell=True) # noqa S607 - subprocess.run("npm run build", cwd=CUSTOM_JS_DIR, shell=True) # noqa S607 diff --git a/docs/source/_exts/copy_vdom_json_schema.py b/docs/source/_exts/copy_vdom_json_schema.py deleted file mode 100644 index 38fc171ac..000000000 --- a/docs/source/_exts/copy_vdom_json_schema.py +++ /dev/null @@ -1,17 +0,0 @@ -import json -from pathlib import Path - -from sphinx.application import Sphinx - -from reactpy.core.vdom import VDOM_JSON_SCHEMA - - -def setup(app: Sphinx) -> None: - schema_file = Path(__file__).parent.parent / "vdom-json-schema.json" - current_schema = json.dumps(VDOM_JSON_SCHEMA, indent=2, sort_keys=True) - - # We need to make this check because the autoreload system for the docs checks - # to see if the file has changed to determine whether to re-build. Thus we should - # only write to the file if its contents will be different. - if not schema_file.exists() or schema_file.read_text() != current_schema: - schema_file.write_text(current_schema) diff --git a/docs/source/_exts/custom_autosectionlabel.py b/docs/source/_exts/custom_autosectionlabel.py deleted file mode 100644 index 92ff5e2df..000000000 --- a/docs/source/_exts/custom_autosectionlabel.py +++ /dev/null @@ -1,80 +0,0 @@ -"""Mostly copied from sphinx.ext.autosectionlabel - -See Sphinx BSD license: -https://github.com/sphinx-doc/sphinx/blob/f9968594206e538f13fa1c27c065027f10d4ea27/LICENSE -""" - -from __future__ import annotations - -from fnmatch import fnmatch -from typing import Any, cast - -from docutils import nodes -from docutils.nodes import Node -from sphinx.application import Sphinx -from sphinx.domains.std import StandardDomain -from sphinx.locale import __ -from sphinx.util import logging -from sphinx.util.nodes import clean_astext - -logger = logging.getLogger(__name__) - - -def get_node_depth(node: Node) -> int: - i = 0 - cur_node = node - while cur_node.parent != node.document: - cur_node = cur_node.parent - i += 1 - return i - - -def register_sections_as_label(app: Sphinx, document: Node) -> None: - docname = app.env.docname - - for pattern in app.config.autosectionlabel_skip_docs: - if fnmatch(docname, pattern): - return None - - domain = cast(StandardDomain, app.env.get_domain("std")) - for node in document.traverse(nodes.section): - if ( - app.config.autosectionlabel_maxdepth - and get_node_depth(node) >= app.config.autosectionlabel_maxdepth - ): - continue - labelid = node["ids"][0] - - title = cast(nodes.title, node[0]) - ref_name = getattr(title, "rawsource", title.astext()) - if app.config.autosectionlabel_prefix_document: - name = nodes.fully_normalize_name(docname + ":" + ref_name) - else: - name = nodes.fully_normalize_name(ref_name) - sectname = clean_astext(title) - - if name in domain.labels: - logger.warning( - __("duplicate label %s, other instance in %s"), - name, - app.env.doc2path(domain.labels[name][0]), - location=node, - type="autosectionlabel", - subtype=docname, - ) - - domain.anonlabels[name] = docname, labelid - domain.labels[name] = docname, labelid, sectname - - -def setup(app: Sphinx) -> dict[str, Any]: - app.add_config_value("autosectionlabel_prefix_document", False, "env") - app.add_config_value("autosectionlabel_maxdepth", None, "env") - app.add_config_value("autosectionlabel_skip_docs", [], "env") - app.connect("doctree-read", register_sections_as_label) - - return { - "version": "builtin", - "parallel_read_safe": True, - "parallel_write_safe": True, - } diff --git a/docs/source/_exts/patched_html_translator.py b/docs/source/_exts/patched_html_translator.py deleted file mode 100644 index e2f8ed9a4..000000000 --- a/docs/source/_exts/patched_html_translator.py +++ /dev/null @@ -1,24 +0,0 @@ -from sphinx.util.docutils import is_html5_writer_available -from sphinx.writers.html import HTMLTranslator -from sphinx.writers.html5 import HTML5Translator - - -class PatchedHTMLTranslator( - HTML5Translator if is_html5_writer_available() else HTMLTranslator -): - def starttag(self, node, tagname, *args, **attrs): - if ( - tagname == "a" - and "target" not in attrs - and ( - "external" in attrs.get("class", "") - or "external" in attrs.get("classes", []) - ) - ): - attrs["target"] = "_blank" - attrs["ref"] = "noopener noreferrer" - return super().starttag(node, tagname, *args, **attrs) - - -def setup(app): - app.set_translator("html", PatchedHTMLTranslator) diff --git a/docs/source/_exts/reactpy_example.py b/docs/source/_exts/reactpy_example.py deleted file mode 100644 index c6b054c07..000000000 --- a/docs/source/_exts/reactpy_example.py +++ /dev/null @@ -1,180 +0,0 @@ -from __future__ import annotations - -import re -from pathlib import Path -from typing import Any - -from docs_app.examples import ( - SOURCE_DIR, - get_example_files_by_name, - get_normalized_example_name, -) -from docutils.parsers.rst import directives -from docutils.statemachine import StringList -from sphinx.application import Sphinx -from sphinx.util.docutils import SphinxDirective -from sphinx_design.tabs import TabSetDirective - - -class WidgetExample(SphinxDirective): - has_content = False - required_arguments = 1 - _next_id = 0 - - option_spec = { - "result-is-default-tab": directives.flag, - "activate-button": directives.flag, - } - - def run(self): - example_name = get_normalized_example_name( - self.arguments[0], - # only used if example name starts with "/" - self.get_source_info()[0], - ) - - show_linenos = "linenos" in self.options - live_example_is_default_tab = "result-is-default-tab" in self.options - activate_result = "activate-button" not in self.options - - ex_files = get_example_files_by_name(example_name) - if not ex_files: - src_file, line_num = self.get_source_info() - msg = f"Missing example named {example_name!r} referenced by document {src_file}:{line_num}" - raise ValueError(msg) - - labeled_tab_items: list[tuple[str, Any]] = [] - if len(ex_files) == 1: - labeled_tab_items.append( - ( - "main.py", - _literal_include( - path=ex_files[0], - linenos=show_linenos, - ), - ) - ) - else: - for path in sorted( - ex_files, key=lambda p: "" if p.name == "main.py" else p.name - ): - labeled_tab_items.append( - ( - path.name, - _literal_include( - path=path, - linenos=show_linenos, - ), - ) - ) - - result_tab_item = ( - "🚀 result", - _interactive_widget( - name=example_name, - with_activate_button=not activate_result, - ), - ) - if live_example_is_default_tab: - labeled_tab_items.insert(0, result_tab_item) - else: - labeled_tab_items.append(result_tab_item) - - return TabSetDirective( - "WidgetExample", - [], - {}, - _make_tab_items(labeled_tab_items), - self.lineno - 2, - self.content_offset, - "", - self.state, - self.state_machine, - ).run() - - -def _make_tab_items(labeled_content_tuples): - tab_items = "" - for label, content in labeled_content_tuples: - tab_items += _tab_item_template.format( - label=label, - content=content.replace("\n", "\n "), - ) - return _string_to_nested_lines(tab_items) - - -def _literal_include(path: Path, linenos: bool): - try: - language = { - ".py": "python", - ".js": "javascript", - ".json": "json", - }[path.suffix] - except KeyError: - msg = f"Unknown extension type {path.suffix!r}" - raise ValueError(msg) from None - - return _literal_include_template.format( - name=str(path.relative_to(SOURCE_DIR)), - language=language, - options=_join_options(_get_file_options(path)), - ) - - -def _join_options(option_strings: list[str]) -> str: - return "\n ".join(option_strings) - - -OPTION_PATTERN = re.compile(r"#\s:[\w-]+:.*") - - -def _get_file_options(file: Path) -> list[str]: - options = [] - - for line in file.read_text().split("\n"): - if not line.strip(): - continue - if not line.startswith("#"): - break - if not OPTION_PATTERN.match(line): - continue - option_string = line[1:].strip() - if option_string: - options.append(option_string) - - return options - - -def _interactive_widget(name, with_activate_button): - return _interactive_widget_template.format( - name=name, - activate_button_opt=":activate-button:" if with_activate_button else "", - ) - - -_tab_item_template = """ -.. tab-item:: {label} - - {content} -""" - - -_interactive_widget_template = """ -.. reactpy-view:: {name} - {activate_button_opt} -""" - - -_literal_include_template = """ -.. literalinclude:: /{name} - :language: {language} - {options} -""" - - -def _string_to_nested_lines(content): - return StringList(content.split("\n")) - - -def setup(app: Sphinx) -> None: - app.add_directive("reactpy", WidgetExample) diff --git a/docs/source/_exts/reactpy_view.py b/docs/source/_exts/reactpy_view.py deleted file mode 100644 index 7a2bf85a4..000000000 --- a/docs/source/_exts/reactpy_view.py +++ /dev/null @@ -1,63 +0,0 @@ -import os -import sys - -print(sys.path) - -from docs_app.examples import get_normalized_example_name -from docutils.nodes import raw -from docutils.parsers.rst import directives -from sphinx.application import Sphinx -from sphinx.util.docutils import SphinxDirective - -_REACTPY_EXAMPLE_HOST = os.environ.get("REACTPY_DOC_EXAMPLE_SERVER_HOST", "") -_REACTPY_STATIC_HOST = os.environ.get("REACTPY_DOC_STATIC_SERVER_HOST", "/docs").rstrip( - "/" -) - - -class IteractiveWidget(SphinxDirective): - has_content = False - required_arguments = 1 - _next_id = 0 - - option_spec = { - "activate-button": directives.flag, - "margin": float, - } - - def run(self): - IteractiveWidget._next_id += 1 - container_id = f"reactpy-widget-{IteractiveWidget._next_id}" - view_id = get_normalized_example_name( - self.arguments[0], - # only used if example name starts with "/" - self.get_source_info()[0], - ) - return [ - raw( - "", - f""" -
-
- -
- """, - format="html", - ) - ] - - -def setup(app: Sphinx) -> None: - app.add_directive("reactpy-view", IteractiveWidget) diff --git a/docs/source/_static/css/furo-theme-overrides.css b/docs/source/_static/css/furo-theme-overrides.css deleted file mode 100644 index a258e025e..000000000 --- a/docs/source/_static/css/furo-theme-overrides.css +++ /dev/null @@ -1,6 +0,0 @@ -.sidebar-container { - width: 18em; -} -.sidebar-brand-text { - display: none; -} diff --git a/docs/source/_static/css/larger-api-margins.css b/docs/source/_static/css/larger-api-margins.css deleted file mode 100644 index f8b75d592..000000000 --- a/docs/source/_static/css/larger-api-margins.css +++ /dev/null @@ -1,7 +0,0 @@ -:is(.data, .function, .class, .exception).py { - margin-top: 3em; -} - -:is(.attribute, .method).py { - margin-top: 1.8em; -} diff --git a/docs/source/_static/css/larger-headings.css b/docs/source/_static/css/larger-headings.css deleted file mode 100644 index 297ab7202..000000000 --- a/docs/source/_static/css/larger-headings.css +++ /dev/null @@ -1,9 +0,0 @@ -h1, -h2, -h3, -h4, -h5, -h6 { - margin-top: 1.5em !important; - font-weight: 900 !important; -} diff --git a/docs/source/_static/css/reactpy-view.css b/docs/source/_static/css/reactpy-view.css deleted file mode 100644 index 56df74970..000000000 --- a/docs/source/_static/css/reactpy-view.css +++ /dev/null @@ -1,43 +0,0 @@ -.interactive { - -webkit-transition: 0.1s ease-out; - -moz-transition: 0.1s ease-out; - -o-transition: 0.1s ease-out; - transition: 0.1s ease-out; -} -.widget-container { - padding: 15px; - overflow: auto; - background-color: var(--color-code-background); - min-height: 75px; -} - -.widget-container .printout { - margin-top: 20px; - border-top: solid 2px var(--color-foreground-border); - padding-top: 20px; -} - -.widget-container > div { - width: 100%; -} - -.enable-widget-button { - padding: 10px; - color: #ffffff !important; - text-transform: uppercase; - text-decoration: none; - background: #526cfe; - border: 2px solid #526cfe !important; - transition: all 0.1s ease 0s; - box-shadow: 0 5px 10px var(--color-foreground-border); -} -.enable-widget-button:hover { - color: #526cfe !important; - background: #ffffff; - transition: all 0.1s ease 0s; -} -.enable-widget-button:focus { - outline: 0 !important; - transform: scale(0.98); - transition: all 0.1s ease 0s; -} diff --git a/docs/source/_static/css/sphinx-design-overrides.css b/docs/source/_static/css/sphinx-design-overrides.css deleted file mode 100644 index 767d9d16c..000000000 --- a/docs/source/_static/css/sphinx-design-overrides.css +++ /dev/null @@ -1,14 +0,0 @@ -.sd-card-body { - display: flex; - flex-direction: column; - align-items: stretch; -} - -.sd-tab-content .highlight pre { - max-height: 700px; - overflow: auto; -} - -.sd-card-title .sd-badge { - font-size: 1em; -} diff --git a/docs/source/_static/css/widget-output-css-overrides.css b/docs/source/_static/css/widget-output-css-overrides.css deleted file mode 100644 index 7ddf1a792..000000000 --- a/docs/source/_static/css/widget-output-css-overrides.css +++ /dev/null @@ -1,8 +0,0 @@ -.widget-container h1, -.widget-container h2, -.widget-container h3, -.widget-container h4, -.widget-container h5, -.widget-container h6 { - margin: 0 !important; -} diff --git a/docs/source/_static/install-and-run-reactpy.gif b/docs/source/_static/install-and-run-reactpy.gif deleted file mode 100644 index 49d431341..000000000 Binary files a/docs/source/_static/install-and-run-reactpy.gif and /dev/null differ diff --git a/docs/source/about/changelog.rst b/docs/source/about/changelog.rst deleted file mode 100644 index f739ce980..000000000 --- a/docs/source/about/changelog.rst +++ /dev/null @@ -1,1124 +0,0 @@ -Changelog -========= - -.. note:: - - The ReactPy team manages their short and long term plans with `GitHub Projects - `__. If you have questions about what - the team are working on, or have feedback on how issues should be prioritized, feel - free to :discussion-type:`open up a discussion `. - -All notable changes to this project will be recorded in this document. The style of -which is based on `Keep a Changelog `__. The versioning -scheme for the project adheres to `Semantic Versioning `__. For -more info, see the :ref:`Contributor Guide `. - - -.. INSTRUCTIONS FOR CHANGELOG CONTRIBUTORS -.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -.. If you're adding a changelog entry, be sure to read the "Creating a Changelog Entry" -.. section of the documentation before doing so for instructions on how to adhere to the -.. "Keep a Changelog" style guide (https://keepachangelog.com). - -Unreleased ----------- - -No changes. - - -v1.0.0 ------- -:octicon:`milestone` *released on 2023-03-14* - -No changes. - - -v1.0.0-a6 ---------- -:octicon:`milestone` *released on 2023-02-23* - -**Fixed** - -- :pull:`936` - remaining issues from :pull:`934` - - -v1.0.0-a5 ---------- -:octicon:`milestone` *released on 2023-02-21* - -**Fixed** - -- :pull:`934` - minor issues with camelCase rewrite CLI utility - - -v1.0.0-a4 ---------- -:octicon:`milestone` *released on 2023-02-21* - -**Changed** - -- :pull:`919` - Reverts :pull:`841` as per the conclusion in :discussion:`916`. but - preserves the ability to declare attributes with snake_case. - -**Deprecated** - -- :pull:`919` - Declaration of keys via keyword arguments in standard elements. A script - has been added to automatically convert old usages where possible. - - -v1.0.0-a3 ---------- -:octicon:`milestone` *released on 2023-02-02* - -**Fixed** - -- :pull:`908` - minor type hint issue with ``VdomDictConstructor`` - -**Removed** - -- :pull:`907` - accidental import of reactpy.testing - - -v1.0.0-a2 ---------- -:octicon:`milestone` *released on 2023-01-31* - -**Reverted** - -- :pull:`901` - reverts :pull:`886` due to :issue:`896` - -**Fixed** - -- :issue:`896` - Stale event handlers after disconnect/reconnect cycle -- :issue:`898` - Fixed CLI not registered as entry point - - -v1.0.0-a1 ---------- -:octicon:`milestone` *released on 2023-01-28* - -**Changed** - -- :pull:`841` - Revamped element constructor interface. Now instead of passing a - dictionary of attributes to element constructors, attributes are declared using - keyword arguments. For example, instead of writing: - - .. code-block:: - - html.div({"className": "some-class"}, "some", "text") - - You now should write: - - .. code-block:: - - html.div("some", "text", class_name="some-class") - - .. note:: - - All attributes are written using ``snake_case``. - - In conjunction, with these changes, ReactPy now supplies a command line utility that - makes a "best effort" attempt to automatically convert code to the new API. Usage of - this utility is as follows: - - .. code-block:: bash - - reactpy update-html-usages [PATHS] - - Where ``[PATHS]`` is any number of directories or files that should be rewritten. - - .. warning:: - - After running this utility, code comments and formatting may have been altered. It's - recommended that you run a code formatting tool like `Black - `__ and manually review and replace any comments that - may have been moved. - -**Fixed** - -- :issue:`755` - unification of component and VDOM constructor interfaces. See above. - - -v0.44.0 -------- -:octicon:`milestone` *released on 2023-01-27* - -**Deprecated** - -- :pull:`876` - ``reactpy.widgets.hotswap``. The function has no clear uses outside of some - internal applications. For this reason it has been deprecated. - -**Removed** - -- :pull:`886` - Ability to access element value from events via `event['value']` key. - Instead element value should be accessed via `event['target']['value']`. Originally - deprecated in :ref:`v0.34.0`. -- :pull:`886` - old misspelled option ``reactpy.config.REACTPY_WED_MODULES_DIR``. Originally - deprecated in :ref:`v0.36.1`. - - -v0.43.0 -------- -:octicon:`milestone` *released on 2023-01-09* - -**Deprecated** - -- :pull:`870` - ``ComponentType.should_render()``. This method was implemented based on - reading the React/Preact source code. As it turns out though it seems like it's mostly - a vestige from the fact that both these libraries still support class-based - components. The ability for components to not render also caused several bugs. - -**Fixed** - -- :issue:`846` - Nested context does no update value if outer context should not render. -- :issue:`847` - Detached model state on render of context consumer if unmounted and - context value does not change. - - -v0.42.0 -------- -:octicon:`milestone` *released on 2022-12-02* - -**Added** - -- :pull:`835` - Ability to customize the ```` element of ReactPy's built-in client. -- :pull:`835` - ``vdom_to_html`` utility function. -- :pull:`843` - Ability to subscribe to changes that are made to mutable options. -- :pull:`832` - ``del_html_head_body_transform`` to remove ````, ````, and ```` while preserving children. -- :pull:`699` - Support for form element serialization - -**Fixed** - -- :issue:`582` - ``REACTPY_DEBUG_MODE`` is now mutable and can be changed at runtime -- :pull:`832` - Fix ``html_to_vdom`` improperly removing ````, ````, and ```` nodes. - -**Removed** - -- :pull:`832` - Removed ``reactpy.html.body`` as it is currently unusable due to technological limitations, and thus not needed. -- :pull:`840` - remove ``REACTPY_FEATURE_INDEX_AS_DEFAULT_KEY`` option -- :pull:`835` - ``serve_static_files`` option from backend configuration - -**Deprecated** - -- :commit:`8f3785b` - Deprecated ``module_from_template`` - -v0.41.0 -------- -:octicon:`milestone` *released on 2022-11-01* - -**Changed** - -- :pull:`823` - The hooks ``use_location`` and ``use_scope`` are no longer - implementation specific and are now available as top-level imports. Instead of each - backend defining these hooks, backends establish a ``ConnectionContext`` with this - information. -- :pull:`824` - ReactPy's built-in backend server now expose the following routes: - - - ``/_reactpy/assets/`` - - ``/_reactpy/stream/`` - - ``/_reactpy/modules/`` - - ``//`` - - This should allow the browser to cache static resources. Even if your ``url_prefix`` - is ``/_reactpy``, your app should still work as expected. Though if you're using - ``reactpy-router``, ReactPy's server routes will always take priority. -- :pull:`824` - Backend implementations now strip any URL prefix in the pathname for - ``use_location``. -- :pull:`827` - ``use_state`` now returns a named tuple with ``value`` and ``set_value`` - fields. This is convenient for adding type annotations if the initial state value is - not the same as the values you might pass to the state setter. Where previously you - might have to do something like: - - .. code-block:: - - value: int | None = None - value, set_value = use_state(value) - - Now you can annotate your state using the ``State`` class: - - .. code-block:: - - state: State[int | None] = use_state(None) - - # access value and setter - state.value - state.set_value - - # can still destructure if you need to - value, set_value = state - -**Added** - -- :pull:`823` - There is a new ``use_connection`` hook which returns a ``Connection`` - object. This ``Connection`` object contains a ``location`` and ``scope``, along with - a ``carrier`` which is unique to each backend implementation. - - -v0.40.2 -------- -:octicon:`milestone` *released on 2022-09-13* - -**Changed** - -- :pull:`809` - Avoid the use of JSON patch for diffing models. - - -v0.40.1 -------- -:octicon:`milestone` *released on 2022-09-11* - -**Fixed** - -- :issue:`806` - Child models after a component fail to render - - -v0.40.0 (yanked) ----------------- -:octicon:`milestone` *released on 2022-08-13* - -**Fixed** - -- :issue:`777` - Fix edge cases where ``html_to_vdom`` can fail to convert HTML -- :issue:`789` - Conditionally rendered components cannot use contexts -- :issue:`773` - Use strict equality check for text, numeric, and binary types in hooks -- :issue:`801` - Accidental mutation of old model causes invalid JSON Patch - -**Changed** - -- :pull:`123` - set default timeout on playwright page for testing -- :pull:`787` - Track contexts in hooks as state -- :pull:`787` - remove non-standard ``name`` argument from ``create_context`` - -**Added** - -- :pull:`123` - ``asgiref`` as a dependency -- :pull:`795` - ``lxml`` as a dependency - - -v0.39.0 -------- -:octicon:`milestone` *released on 2022-06-20* - -**Fixed** - -- :pull:`763` - ``No module named 'reactpy.server'`` from ``reactpy.run`` -- :pull:`749` - Setting appropriate MIME type for web modules in `sanic` server implementation - -**Changed** - -- :pull:`763` - renamed various: - - - ``reactpy.testing.server -> reactpy.testing.backend`` - - ``ServerFixture -> BackendFixture`` - - ``DisplayFixture.server -> DisplayFixture.backend`` - -- :pull:`765` - ``exports_default`` parameter is removed from ``module_from_template``. - -**Added** - -- :pull:`765` - ability to specify versions with module templates (e.g. - ``module_from_template("react@^17.0.0", ...)``). - - -v0.38.1 -------- -:octicon:`milestone` *released on 2022-04-15* - -**Fixed** - -- `reactive-python/reactpy-jupyter#22 `__ - - a missing file extension was causing a problem with WebPack. - - -v0.38.0 -------- -:octicon:`milestone` *released on 2022-04-15* - -No changes. - - -v0.38.0-a4 ----------- -:octicon:`milestone` *released on 2022-04-15* - -**Added** - -- :pull:`733` - ``use_debug_value`` hook - -**Changed** - -- :pull:`733` - renamed ``assert_reactpy_logged`` testing util to ``assert_reactpy_did_log`` - - -v0.38.0-a3 ----------- -:octicon:`milestone` *released on 2022-04-15* - -**Changed** - -- :pull:`730` - Layout context management is not async - - -v0.38.0-a2 ----------- -:octicon:`milestone` *released on 2022-04-14* - -**Added** - -- :pull:`721` - Implement ``use_location()`` hook. Navigating to any route below the - root of the application will be reflected in the ``location.pathname``. This operates - in concert with how ReactPy's configured routes have changed. This will ultimately work - towards resolving :issue:`569`. - -**Changed** - -- :pull:`721` - The routes ReactPy configures on apps have changed - - .. code-block:: text - - prefix/_api/modules/* web modules - prefix/_api/stream websocket endpoint - prefix/* client react app - - This means that ReactPy's client app is available at any route below the configured - ``url_prefix`` besides ``prefix/_api``. The ``_api`` route will likely remain a route - which is reserved by ReactPy. The route navigated to below the ``prefix`` will be shown - in ``use_location``. - -- :pull:`721` - ReactPy's client now uses Preact instead of React - -- :pull:`726` - Renamed ``reactpy.server`` to ``reactpy.backend``. Other references to "server - implementations" have been renamed to "backend implementations" throughout the - documentation and code. - -**Removed** - -- :pull:`721` - ``redirect_root`` server option - - -v0.38.0-a1 ----------- -:octicon:`milestone` *released on 2022-03-27* - -**Changed** - -- :pull:`703` - How ReactPy integrates with servers. ``reactpy.run`` no longer accepts an app - instance to discourage use outside of testing. ReactPy's server implementations now - provide ``configure()`` functions instead. ``reactpy.testing`` has been completely - reworked in order to support async web drivers -- :pull:`703` - ``PerClientStateServer`` has been functionally replaced by ``configure`` - -**Added** - -- :issue:`669` - Access to underlying server requests via contexts - -**Removed** - -- :issue:`669` - Removed ``reactpy.widgets.multiview`` since basic routing view ``use_scope`` is - now possible as well as all ``SharedClientStateServer`` implementations. - -**Fixed** - -- :issue:`591` - ReactPy's test suite no longer uses sync web drivers -- :issue:`678` - Updated Sanic requirement to ``>=21`` -- :issue:`657` - How we advertise ``reactpy.run`` - - -v0.37.2 -------- -:octicon:`milestone` *released on 2022-03-27* - -**Changed** - -- :pull:`701` - The name of ``proto`` modules to ``types`` and added a top level - ``reactpy.types`` module - -**Fixed** - -- :pull:`716` - A typo caused ReactPy to use the insecure ``ws`` web-socket protocol on - pages loaded with ``https`` instead of the secure ``wss`` protocol - - -v0.37.1 -------- -:octicon:`milestone` *released on 2022-03-05* - -No changes. - - -v0.37.1-a2 ----------- -:octicon:`milestone` *released on 2022-03-02* - -**Fixed:** - -- :issue:`684` - Revert :pull:`694` and by making ``value`` uncontrolled client-side - - -v0.37.1-a1 ----------- -:octicon:`milestone` *released on 2022-02-28* - -**Fixed:** - -- :issue:`684` - ``onChange`` event for inputs missing key strokes - - -v0.37.0 -------- -:octicon:`milestone` *released on 2022-02-27* - -**Added:** - -- :issue:`682` - Support for keys in HTML fragments -- :pull:`585` - Use Context Hook - -**Fixed:** - -- :issue:`690` - React warning about set state in unmounted component -- :pull:`688` - Missing reset of schedule_render_later flag - ----- - -Releases below do not use the "Keep a Changelog" style guidelines. - ----- - -v0.36.3 -------- -:octicon:`milestone` *released on 2022-02-18* - -Misc bug fixes along with a minor improvement that allows components to return ``None`` -to render nothing. - -**Closed Issues** - -- All child states wiped upon any child key change - :issue:`652` -- Allow NoneType returns within components - :issue:`538` - -**Merged Pull Requests** - -- fix #652 - :pull:`672` -- Fix 663 - :pull:`667` - - -v0.36.2 -------- -:octicon:`milestone` *released on 2022-02-02* - -Hot fix for newly introduced ``DeprecatedOption``: - -- :commit:`c146dfb264cbc3d2256a62efdfe9ccf62c795b01` - - -v0.36.1 -------- -:octicon:`milestone` *released on 2022-02-02* - -Includes bug fixes and renames the configuration option ``REACTPY_WED_MODULES_DIR`` to -``REACTPY_WEB_MODULES_DIR`` with a corresponding deprecation warning. - -**Closed Issues** - -- Fix Key Error When Cleaning Up Event Handlers - :issue:`640` -- Update Script Tag Behavior - :issue:`628` - -**Merged Pull Requests** - -- mark old state as None if unmounting - :pull:`641` -- rename REACTPY_WED_MODULES_DIR to REACTPY_WEB_MODULES_DIR - :pull:`638` - - -v0.36.0 -------- -:octicon:`milestone` *released on 2022-01-30* - -This release includes an important fix for errors produced after :pull:`623` was merged. -In addition there is not a new ``http.script`` element which can behave similarly to a -standard HTML `` diff --git a/docs/source/guides/getting-started/_static/embed-reactpy-view/index.html b/docs/source/guides/getting-started/_static/embed-reactpy-view/index.html deleted file mode 100644 index 146d715e4..000000000 --- a/docs/source/guides/getting-started/_static/embed-reactpy-view/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - Example App - - -

This is an Example App

-

Just below is an embedded ReactPy view...

-
- - - diff --git a/docs/source/guides/getting-started/_static/embed-reactpy-view/main.py b/docs/source/guides/getting-started/_static/embed-reactpy-view/main.py deleted file mode 100644 index 6e3687f27..000000000 --- a/docs/source/guides/getting-started/_static/embed-reactpy-view/main.py +++ /dev/null @@ -1,22 +0,0 @@ -from sanic import Sanic -from sanic.response import file - -from reactpy import component, html -from reactpy.backend.sanic import Options, configure - -app = Sanic("MyApp") - - -@app.route("/") -async def index(request): - return await file("index.html") - - -@component -def ReactPyView(): - return html.code("This text came from an ReactPy App") - - -configure(app, ReactPyView, Options(url_prefix="/_reactpy")) - -app.run(host="127.0.0.1", port=5000) diff --git a/docs/source/guides/getting-started/_static/embed-reactpy-view/screenshot.png b/docs/source/guides/getting-started/_static/embed-reactpy-view/screenshot.png deleted file mode 100644 index 7439c83cf..000000000 Binary files a/docs/source/guides/getting-started/_static/embed-reactpy-view/screenshot.png and /dev/null differ diff --git a/docs/source/guides/getting-started/_static/logo-django.svg b/docs/source/guides/getting-started/_static/logo-django.svg deleted file mode 100644 index 1538f0817..000000000 --- a/docs/source/guides/getting-started/_static/logo-django.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - -]> - - - - - - - - - - - - diff --git a/docs/source/guides/getting-started/_static/logo-jupyter.svg b/docs/source/guides/getting-started/_static/logo-jupyter.svg deleted file mode 100644 index fb2921a41..000000000 --- a/docs/source/guides/getting-started/_static/logo-jupyter.svg +++ /dev/null @@ -1,88 +0,0 @@ - -logo.svg -Created using Figma 0.90 - - - - - - - - - - - - - - - - - - diff --git a/docs/source/guides/getting-started/_static/logo-plotly.svg b/docs/source/guides/getting-started/_static/logo-plotly.svg deleted file mode 100644 index 3dd95459a..000000000 --- a/docs/source/guides/getting-started/_static/logo-plotly.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/docs/source/guides/getting-started/_static/reactpy-in-jupyterlab.gif b/docs/source/guides/getting-started/_static/reactpy-in-jupyterlab.gif deleted file mode 100644 index b420ecd8c..000000000 Binary files a/docs/source/guides/getting-started/_static/reactpy-in-jupyterlab.gif and /dev/null differ diff --git a/docs/source/guides/getting-started/_static/shared-client-state-server-slider.gif b/docs/source/guides/getting-started/_static/shared-client-state-server-slider.gif deleted file mode 100644 index 61bb8295f..000000000 Binary files a/docs/source/guides/getting-started/_static/shared-client-state-server-slider.gif and /dev/null differ diff --git a/docs/source/guides/getting-started/index.rst b/docs/source/guides/getting-started/index.rst deleted file mode 100644 index dd210be60..000000000 --- a/docs/source/guides/getting-started/index.rst +++ /dev/null @@ -1,123 +0,0 @@ -Getting Started -=============== - -.. toctree:: - :hidden: - - installing-reactpy - running-reactpy - -.. dropdown:: :octicon:`bookmark-fill;2em` What You'll Learn - :color: info - :animate: fade-in - :open: - - .. grid:: 1 2 2 2 - - .. grid-item-card:: :octicon:`tools` Installing ReactPy - :link: installing-reactpy - :link-type: doc - - Learn how ReactPy can be installed in a variety of different ways - with - different web servers and even in different frameworks. - - .. grid-item-card:: :octicon:`play` Running ReactPy - :link: running-reactpy - :link-type: doc - - See how ReactPy can be run with a variety of different production servers or be - added to existing applications. - -The fastest way to get started with ReactPy is to try it out in a `Juptyer Notebook -`__. -If you want to use a Notebook to work through the examples shown in this documentation, -you'll need to replace calls to ``reactpy.run(App)`` with a line at the end of each cell -that constructs the ``App()`` in question. If that doesn't make sense, the introductory -notebook linked below will demonstrate how to do this: - -.. card:: - :link: https://mybinder.org/v2/gh/reactive-python/reactpy-jupyter/main?urlpath=lab/tree/notebooks/introduction.ipynb - - .. image:: _static/reactpy-in-jupyterlab.gif - :scale: 72% - :align: center - - -Section 1: Installing ReactPy ------------------------------ - -The next fastest option is to install ReactPy along with a supported server (like -``starlette``) with ``pip``: - -.. code-block:: bash - - pip install "reactpy[starlette]" - -To check that everything is working you can run the sample application: - -.. code-block:: bash - - python -c "import reactpy; reactpy.run(reactpy.sample.SampleApp)" - -.. note:: - - This launches a simple development server which is good enough for testing, but - probably not what you want to use in production. When deploying in production, - there's a number of different ways of :ref:`running ReactPy
`. - -You should then see a few log messages: - -.. code-block:: text - - 2022-03-27T11:58:59-0700 | WARNING | You are running a development server. Change this before deploying in production! - 2022-03-27T11:58:59-0700 | INFO | Running with 'Starlette' at http://127.0.0.1:8000 - -The second log message includes a URL indicating where you should go to view the app. -That will usually be http://127.0.0.1:8000. Once you go to that URL you should see -something like this: - -.. card:: - - .. reactpy-view:: _examples/sample_app - -If you get a ``RuntimeError`` similar to the following: - -.. code-block:: text - - Found none of the following builtin server implementations... - -Then be sure you run ``pip install "reactpy[starlette]"`` instead of just ``reactpy``. For -anything else, report your issue in ReactPy's :discussion-type:`discussion forum -`. - -.. card:: - :link: installing-reactpy - :link-type: doc - - :octicon:`book` Read More - ^^^^^^^^^^^^^^^^^^^^^^^^^ - - Learn how ReactPy can be installed in a variety of different ways - with different web - servers and even in different frameworks. - - -Section 2: Running ReactPy --------------------------- - -Once you've :ref:`installed ReactPy `, you'll want to learn how to run an -application. Throughout most of the examples in this documentation, you'll see the -:func:`~reactpy.backend.utils.run` function used. While it's convenient tool for -development it shouldn't be used in production settings - it's slow, and could leak -secrets through debug log messages. - -.. reactpy:: _examples/hello_world - -.. card:: - :link: running-reactpy - :link-type: doc - - :octicon:`book` Read More - ^^^^^^^^^^^^^^^^^^^^^^^^^ - - See how ReactPy can be run with a variety of different production servers or be - added to existing applications. diff --git a/docs/source/guides/getting-started/installing-reactpy.rst b/docs/source/guides/getting-started/installing-reactpy.rst deleted file mode 100644 index 0b2ffc28a..000000000 --- a/docs/source/guides/getting-started/installing-reactpy.rst +++ /dev/null @@ -1,121 +0,0 @@ -Installing ReactPy -================== - -You will typically ``pip`` install ReactPy to alongside one of it's natively supported -backends. For example, if we want to run ReactPy using the `Starlette -`__ backend you would run - -.. code-block:: bash - - pip install "reactpy[starlette]" - -If you want to install a "pure" version of ReactPy **without a backend implementation** -you can do so without any installation extras. You might do this if you wanted to -:ref:`use a custom backend ` or if you wanted to manually pin -the dependencies for your chosen backend: - -.. code-block:: bash - - pip install reactpy - - -Native Backends ---------------- - -ReactPy includes built-in support for a variety backend implementations. To install the -required dependencies for each you should substitute ``starlette`` from the ``pip -install`` command above with one of the options below: - -- ``fastapi`` - https://fastapi.tiangolo.com -- ``flask`` - https://palletsprojects.com/p/flask/ -- ``sanic`` - https://sanicframework.org -- ``starlette`` - https://www.starlette.io/ -- ``tornado`` - https://www.tornadoweb.org/en/stable/ - -If you need to, you can install more than one option by separating them with commas: - -.. code-block:: bash - - pip install "reactpy[fastapi,flask,sanic,starlette,tornado]" - -Once this is complete you should be able to :ref:`run ReactPy ` with your -chosen implementation. - - -Other Backends --------------- - -While ReactPy can run in a variety of contexts, sometimes frameworks require extra work in -order to integrate with them. In these cases, the ReactPy team distributes bindings for -those frameworks as separate Python packages. For documentation on how to install and -run ReactPy in these supported frameworks, follow the links below: - -.. raw:: html - - - -.. role:: transparent-text-color - -.. We add transparent-text-color to the text so it's not visible, but it's still -.. searchable. - -.. grid:: 3 - - .. grid-item-card:: - :link: https://github.com/reactive-python/reactpy-django - :img-background: _static/logo-django.svg - :class-card: card-logo-image - - :transparent-text-color:`Django` - - .. grid-item-card:: - :link: https://github.com/reactive-python/reactpy-jupyter - :img-background: _static/logo-jupyter.svg - :class-card: card-logo-image - - :transparent-text-color:`Jupyter` - - .. grid-item-card:: - :link: https://github.com/reactive-python/reactpy-dash - :img-background: _static/logo-plotly.svg - :class-card: card-logo-image - - :transparent-text-color:`Plotly Dash` - - -For Development ---------------- - -If you want to contribute to the development of ReactPy or modify it, you'll want to -install a development version of ReactPy. This involves cloning the repository where ReactPy's -source is maintained, and setting up a :ref:`development environment`. From there you'll -be able to modifying ReactPy's source code and :ref:`run its tests ` to -ensure the modifications you've made are backwards compatible. If you want to add a new -feature to ReactPy you should write your own test that validates its behavior. - -If you have questions about how to modify ReactPy or help with its development, be sure to -:discussion:`start a discussion `. The ReactPy team are always -excited to :ref:`welcome ` new contributions and contributors -of all kinds - -.. card:: - :link: /about/contributor-guide - :link-type: doc - - :octicon:`book` Read More - ^^^^^^^^^^^^^^^^^^^^^^^^^ - - Learn more about how to contribute to the development of ReactPy. diff --git a/docs/source/guides/getting-started/running-reactpy.rst b/docs/source/guides/getting-started/running-reactpy.rst deleted file mode 100644 index 8abbd574f..000000000 --- a/docs/source/guides/getting-started/running-reactpy.rst +++ /dev/null @@ -1,221 +0,0 @@ -Running ReactPy -=============== - -The simplest way to run ReactPy is with the :func:`~reactpy.backend.utils.run` function. This -is the method you'll see used throughout this documentation. However, this executes your -application using a development server which is great for testing, but probably not what -if you're :ref:`deploying in production `. Below are some -more robust and performant ways of running ReactPy with various supported servers. - - -Running ReactPy in Production ------------------------------ - -The first thing you'll need to do if you want to run ReactPy in production is choose a -backend implementation and follow its documentation on how to create and run an -application. This is the backend :ref:`you probably chose ` when -installing ReactPy. Then you'll need to configure that application with an ReactPy view. We -show the basics of how to set up, and then run, each supported backend below, but all -implementations will follow a pattern similar to the following: - -.. code-block:: - - from my_chosen_backend import Application - - from reactpy import component, html - from reactpy.backend.my_chosen_backend import configure - - - @component - def HelloWorld(): - return html.h1("Hello, world!") - - - app = Application() - configure(app, HelloWorld) - -You'll then run this ``app`` using an `ASGI `__ -or `WSGI `__ server from the command line. - - -Running with `FastAPI `__ -....................................................... - -.. reactpy:: _examples/run_fastapi - -Then assuming you put this in ``main.py``, you can run the ``app`` using the `Uvicorn -`__ ASGI server: - -.. code-block:: bash - - uvicorn main:app - - -Running with `Flask `__ -............................................................. - -.. reactpy:: _examples/run_flask - -Then assuming you put this in ``main.py``, you can run the ``app`` using the `Gunicorn -`__ WSGI server: - -.. code-block:: bash - - gunicorn main:app - - -Running with `Sanic `__ -................................................... - -.. reactpy:: _examples/run_sanic - -Then assuming you put this in ``main.py``, you can run the ``app`` using Sanic's builtin -server: - -.. code-block:: bash - - sanic main.app - - -Running with `Starlette `__ -...................................................... - -.. reactpy:: _examples/run_starlette - -Then assuming you put this in ``main.py``, you can run the application using the -`Uvicorn `__ ASGI server: - -.. code-block:: bash - - uvicorn main:app - - -Running with `Tornado `__ -................................................................ - -.. reactpy:: _examples/run_tornado - -Tornado is run using it's own builtin server rather than an external WSGI or ASGI -server. - - -Running ReactPy in Debug Mode ------------------------------ - -ReactPy provides a debug mode that is turned off by default. This can be enabled when you -run your application by setting the ``REACTPY_DEBUG_MODE`` environment variable. - -.. tab-set:: - - .. tab-item:: Unix Shell - - .. code-block:: - - export REACTPY_DEBUG_MODE=1 - python my_reactpy_app.py - - .. tab-item:: Command Prompt - - .. code-block:: text - - set REACTPY_DEBUG_MODE=1 - python my_reactpy_app.py - - .. tab-item:: PowerShell - - .. code-block:: powershell - - $env:REACTPY_DEBUG_MODE = "1" - python my_reactpy_app.py - -.. danger:: - - Leave debug mode off in production! - -Among other things, running in this mode: - -- Turns on debug log messages -- Adds checks to ensure the :ref:`VDOM` spec is adhered to -- Displays error messages that occur within your app - -Errors will be displayed where the uppermost component is located in the view: - -.. reactpy:: _examples/debug_error_example - - -Backend Configuration Options ------------------------------ - -ReactPy's various backend implementations come with ``Options`` that can be passed to their -respective ``configure()`` functions in the following way: - -.. code-block:: - - from reactpy.backend. import configure, Options - - configure(app, MyComponent, Options(...)) - -To learn more read about the options for your chosen backend ````: - -- :class:`reactpy.backend.fastapi.Options` -- :class:`reactpy.backend.flask.Options` -- :class:`reactpy.backend.sanic.Options` -- :class:`reactpy.backend.starlette.Options` -- :class:`reactpy.backend.tornado.Options` - - -Embed in an Existing Webpage ----------------------------- - -ReactPy provides a Javascript client called ``@reactpy/client`` that can be used to embed -ReactPy views within an existing applications. This is actually how the interactive -examples throughout this documentation have been created. You can try this out by -embedding one the examples from this documentation into your own webpage: - -.. tab-set:: - - .. tab-item:: HTML - - .. literalinclude:: _static/embed-doc-ex.html - :language: html - - .. tab-item:: ▶️ Result - - .. raw:: html - :file: _static/embed-doc-ex.html - -.. note:: - - For more information on how to use the client see the :ref:`Javascript API` - reference. Or if you need to, your can :ref:`write your own backend implementation - `. - -As mentioned though, this is connecting to the server that is hosting this -documentation. If you want to connect to a view from your own server, you'll need to -change the URL above to one you provide. One way to do this might be to add to an -existing application. Another would be to run ReactPy in an adjacent web server instance -that you coordinate with something like `NGINX `__. For the sake -of simplicity, we'll assume you do something similar to the following in an existing -Python app: - -.. tab-set:: - - .. tab-item:: main.py - - .. literalinclude:: _static/embed-reactpy-view/main.py - :language: python - - .. tab-item:: index.html - - .. literalinclude:: _static/embed-reactpy-view/index.html - :language: html - -After running ``python main.py``, you should be able to navigate to -``http://127.0.0.1:8000/index.html`` and see: - -.. card:: - :text-align: center - - .. image:: _static/embed-reactpy-view/screenshot.png - :width: 500px - diff --git a/docs/source/guides/managing-state/combining-contexts-and-reducers/index.rst b/docs/source/guides/managing-state/combining-contexts-and-reducers/index.rst deleted file mode 100644 index b9f274f0a..000000000 --- a/docs/source/guides/managing-state/combining-contexts-and-reducers/index.rst +++ /dev/null @@ -1,6 +0,0 @@ -Combining Contexts and Reducers 🚧 -================================== - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/managing-state/deeply-sharing-state-with-contexts/index.rst b/docs/source/guides/managing-state/deeply-sharing-state-with-contexts/index.rst deleted file mode 100644 index 4a00caa48..000000000 --- a/docs/source/guides/managing-state/deeply-sharing-state-with-contexts/index.rst +++ /dev/null @@ -1,6 +0,0 @@ -Deeply Sharing State with Contexts 🚧 -===================================== - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/managing-state/how-to-structure-state/index.rst b/docs/source/guides/managing-state/how-to-structure-state/index.rst deleted file mode 100644 index 5092370a5..000000000 --- a/docs/source/guides/managing-state/how-to-structure-state/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _Structuring Your State: - -How to Structure State 🚧 -========================= - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/managing-state/index.rst b/docs/source/guides/managing-state/index.rst deleted file mode 100644 index 0578bafdd..000000000 --- a/docs/source/guides/managing-state/index.rst +++ /dev/null @@ -1,127 +0,0 @@ -Managing State -============== - -.. toctree:: - :hidden: - - how-to-structure-state/index - sharing-component-state/index - when-and-how-to-reset-state/index - simplifying-updates-with-reducers/index - deeply-sharing-state-with-contexts/index - combining-contexts-and-reducers/index - -.. dropdown:: :octicon:`bookmark-fill;2em` What You'll Learn - :color: info - :animate: fade-in - :open: - - .. grid:: 1 2 2 2 - - .. grid-item-card:: :octicon:`organization` How to Structure State - :link: how-to-structure-state/index - :link-type: doc - - Make it easy to reason about your application with strategies for organizing - state. - - .. grid-item-card:: :octicon:`link` Sharing Component State - :link: sharing-component-state/index - :link-type: doc - - Allow components to vary vary together, by lifting state into common - parents. - - .. grid-item-card:: :octicon:`light-bulb` When and How to Reset State - :link: when-and-how-to-reset-state/index - :link-type: doc - - Control if and how state is preserved by understanding it's relationship to - the "UI tree". - - .. grid-item-card:: :octicon:`plug` Simplifying Updates with Reducers - :link: simplifying-updates-with-reducers/index - :link-type: doc - - Consolidate state update logic outside your component in a single function, - called a “reducer". - - .. grid-item-card:: :octicon:`broadcast` Deeply Sharing State with Contexts - :link: deeply-sharing-state-with-contexts/index - :link-type: doc - - Instead of passing shared state down deep component trees, bring state into - "contexts" instead. - - .. grid-item-card:: :octicon:`rocket` Combining Contexts and Reducers - :link: combining-contexts-and-reducers/index - :link-type: doc - - You can combine reducers and context together to manage state of a complex - screen. - - -Section 1: How to Structure State ---------------------------------- - -.. note:: - - Under construction 🚧 - - -Section 2: Shared Component State ---------------------------------- - -Sometimes, you want the state of two components to always change together. To do it, -remove state from both of them, move it to their closest common parent, and then pass it -down to them via props. This is known as “lifting state up”, and it’s one of the most -common things you will do writing code with ReactPy. - -In the example below the search input and the list of elements below share the same -state, the state represents the food name. Note how the component ``Table`` gets called -at each change of state. The component is observing the state and reacting to state -changes automatically, just like it would do in React. - -.. reactpy:: sharing-component-state/_examples/synced_inputs - -.. card:: - :link: sharing-component-state/index - :link-type: doc - - :octicon:`book` Read More - ^^^^^^^^^^^^^^^^^^^^^^^^^ - - Allow components to vary vary together, by lifting state into common parents. - - -Section 3: When and How to Reset State --------------------------------------- - -.. note:: - - Under construction 🚧 - - -Section 4: Simplifying Updates with Reducers --------------------------------------------- - -.. note:: - - Under construction 🚧 - - -Section 5: Deeply Sharing State with Contexts ---------------------------------------------- - -.. note:: - - Under construction 🚧 - - - -Section 6: Combining Contexts and Reducers ------------------------------------------- - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/managing-state/sharing-component-state/_examples/filterable_list/data.json b/docs/source/guides/managing-state/sharing-component-state/_examples/filterable_list/data.json deleted file mode 100644 index f977fe9a7..000000000 --- a/docs/source/guides/managing-state/sharing-component-state/_examples/filterable_list/data.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "name": "Sushi", - "description": "Sushi is a traditional Japanese dish of prepared vinegared rice" - }, - { - "name": "Dal", - "description": "The most common way of preparing dal is in the form of a soup to which onions, tomatoes and various spices may be added" - }, - { - "name": "Pierogi", - "description": "Pierogi are filled dumplings made by wrapping unleavened dough around a savoury or sweet filling and cooking in boiling water" - }, - { - "name": "Shish Kebab", - "description": "Shish kebab is a popular meal of skewered and grilled cubes of meat" - }, - { - "name": "Dim sum", - "description": "Dim sum is a large range of small dishes that Cantonese people traditionally enjoy in restaurants for breakfast and lunch" - } -] diff --git a/docs/source/guides/managing-state/sharing-component-state/_examples/filterable_list/main.py b/docs/source/guides/managing-state/sharing-component-state/_examples/filterable_list/main.py deleted file mode 100644 index ca68aedcb..000000000 --- a/docs/source/guides/managing-state/sharing-component-state/_examples/filterable_list/main.py +++ /dev/null @@ -1,44 +0,0 @@ -import json -from pathlib import Path - -from reactpy import component, hooks, html, run - -HERE = Path(__file__) -DATA_PATH = HERE.parent / "data.json" -food_data = json.loads(DATA_PATH.read_text()) - - -@component -def FilterableList(): - value, set_value = hooks.use_state("") - return html.p(Search(value, set_value), html.hr(), Table(value, set_value)) - - -@component -def Search(value, set_value): - def handle_change(event): - set_value(event["target"]["value"]) - - return html.label( - "Search by Food Name: ", - html.input({"value": value, "on_change": handle_change}), - ) - - -@component -def Table(value, set_value): - rows = [] - for row in food_data: - name = html.td(row["name"]) - descr = html.td(row["description"]) - tr = html.tr(name, descr, value) - if not value: - rows.append(tr) - elif value.lower() in row["name"].lower(): - rows.append(tr) - headers = html.tr(html.td(html.b("name")), html.td(html.b("description"))) - table = html.table(html.thead(headers), html.tbody(rows)) - return table - - -run(FilterableList) diff --git a/docs/source/guides/managing-state/sharing-component-state/_examples/synced_inputs/main.py b/docs/source/guides/managing-state/sharing-component-state/_examples/synced_inputs/main.py deleted file mode 100644 index e8bcdf333..000000000 --- a/docs/source/guides/managing-state/sharing-component-state/_examples/synced_inputs/main.py +++ /dev/null @@ -1,23 +0,0 @@ -from reactpy import component, hooks, html, run - - -@component -def SyncedInputs(): - value, set_value = hooks.use_state("") - return html.p( - Input("First input", value, set_value), - Input("Second input", value, set_value), - ) - - -@component -def Input(label, value, set_value): - def handle_change(event): - set_value(event["target"]["value"]) - - return html.label( - label + " ", html.input({"value": value, "on_change": handle_change}) - ) - - -run(SyncedInputs) diff --git a/docs/source/guides/managing-state/sharing-component-state/index.rst b/docs/source/guides/managing-state/sharing-component-state/index.rst deleted file mode 100644 index 54b61335a..000000000 --- a/docs/source/guides/managing-state/sharing-component-state/index.rst +++ /dev/null @@ -1,38 +0,0 @@ -Sharing Component State -======================= - -.. note:: - - Parts of this document are still under construction 🚧 - -Sometimes, you want the state of two components to always change together. To do it, -remove state from both of them, move it to their closest common parent, and then pass it -down to them via props. This is known as “lifting state up”, and it’s one of the most -common things you will do writing code with ReactPy. - - -Synced Inputs -------------- - -In the code below the two input boxes are synchronized, this happens because they share -state. The state is shared via the parent component ``SyncedInputs``. Check the ``value`` -and ``set_value`` variables. - -.. reactpy:: _examples/synced_inputs - - -Filterable List ----------------- - -In the example below the search input and the list of elements below share the -same state, the state represents the food name. - -Note how the component ``Table`` gets called at each change of state. The -component is observing the state and reacting to state changes automatically, -just like it would do in React. - -.. reactpy:: _examples/filterable_list - -.. note:: - - Try typing a food name in the search bar. diff --git a/docs/source/guides/managing-state/simplifying-updates-with-reducers/index.rst b/docs/source/guides/managing-state/simplifying-updates-with-reducers/index.rst deleted file mode 100644 index 08fce5a69..000000000 --- a/docs/source/guides/managing-state/simplifying-updates-with-reducers/index.rst +++ /dev/null @@ -1,6 +0,0 @@ -Simplifying Updates with Reducers 🚧 -==================================== - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/managing-state/when-and-how-to-reset-state/index.rst b/docs/source/guides/managing-state/when-and-how-to-reset-state/index.rst deleted file mode 100644 index 6a96f4b30..000000000 --- a/docs/source/guides/managing-state/when-and-how-to-reset-state/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _When to Reset State: - -When and How to Reset State 🚧 -============================== - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/understanding-reactpy/_static/idom-flow-diagram.svg b/docs/source/guides/understanding-reactpy/_static/idom-flow-diagram.svg deleted file mode 100644 index 9077913ca..000000000 --- a/docs/source/guides/understanding-reactpy/_static/idom-flow-diagram.svg +++ /dev/null @@ -1,383 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - layout - - - - - component - - server - - - - view - - client - - - - event - VDOM diff - VDOM - diff --git a/docs/source/guides/understanding-reactpy/_static/live-examples-in-docs.gif b/docs/source/guides/understanding-reactpy/_static/live-examples-in-docs.gif deleted file mode 100644 index 96a04d68b..000000000 Binary files a/docs/source/guides/understanding-reactpy/_static/live-examples-in-docs.gif and /dev/null differ diff --git a/docs/source/guides/understanding-reactpy/_static/mvc-flow-diagram.svg b/docs/source/guides/understanding-reactpy/_static/mvc-flow-diagram.svg deleted file mode 100644 index a1acbc2cb..000000000 --- a/docs/source/guides/understanding-reactpy/_static/mvc-flow-diagram.svg +++ /dev/null @@ -1,425 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - model - - - - - controller - - server - - - - - model - - - - - view - - client - - - - - event - sync - change - render - diff --git a/docs/source/guides/understanding-reactpy/_static/npm-download-trends.png b/docs/source/guides/understanding-reactpy/_static/npm-download-trends.png deleted file mode 100644 index cf5140b0d..000000000 Binary files a/docs/source/guides/understanding-reactpy/_static/npm-download-trends.png and /dev/null differ diff --git a/docs/source/guides/understanding-reactpy/index.rst b/docs/source/guides/understanding-reactpy/index.rst deleted file mode 100644 index 3e0b2ab72..000000000 --- a/docs/source/guides/understanding-reactpy/index.rst +++ /dev/null @@ -1,17 +0,0 @@ -Understanding ReactPy -===================== - -.. toctree:: - :hidden: - - representing-html - what-are-components - the-rendering-pipeline - why-reactpy-needs-keys - the-rendering-process - layout-render-servers - writing-tests - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/understanding-reactpy/layout-render-servers.rst b/docs/source/guides/understanding-reactpy/layout-render-servers.rst deleted file mode 100644 index 9a7cceb54..000000000 --- a/docs/source/guides/understanding-reactpy/layout-render-servers.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _Layout Render Servers: - -Layout Render Servers 🚧 -======================== - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/understanding-reactpy/representing-html.rst b/docs/source/guides/understanding-reactpy/representing-html.rst deleted file mode 100644 index c2f32ebd9..000000000 --- a/docs/source/guides/understanding-reactpy/representing-html.rst +++ /dev/null @@ -1,76 +0,0 @@ -.. _Representing HTML: - -Representing HTML 🚧 -==================== - -.. note:: - - Under construction 🚧 - -We've already discussed how to construct HTML with ReactPy in a :ref:`previous section `, but we skimmed over the question of the data structure we use to represent -it. Let's reconsider the examples from before - on the top is some HTML and on the -bottom is the corresponding code to create it in ReactPy: - -.. code-block:: html - -
-

My Todo List

-
    -
  • Build a cool new app
  • -
  • Share it with the world!
  • -
-
- -.. testcode:: - - from reactpy import html - - layout = html.div( - html.h1("My Todo List"), - html.ul( - html.li("Build a cool new app"), - html.li("Share it with the world!"), - ) - ) - -Since we've captured our HTML into out the ``layout`` variable, we can inspect what it -contains. And, as it turns out, it holds a dictionary. Printing it produces the -following output: - -.. testsetup:: - - from pprint import pprint - print = lambda *args, **kwargs: pprint(*args, **kwargs, sort_dicts=False) - -.. testcode:: - - assert layout == { - 'tagName': 'div', - 'children': [ - { - 'tagName': 'h1', - 'children': ['My Todo List'] - }, - { - 'tagName': 'ul', - 'children': [ - {'tagName': 'li', 'children': ['Build a cool new app']}, - {'tagName': 'li', 'children': ['Share it with the world!']} - ] - } - ] - } - -This may look complicated, but let's take a moment to consider what's going on here. We -have a series of nested dictionaries that, in some way, represents the HTML structure -given above. If we look at their contents we should see a common form. Each has a -``tagName`` key which contains, as the name would suggest, the tag name of an HTML -element. Then within the ``children`` key is a list that either contains strings or -other dictionaries that represent HTML elements. - -What we're seeing here is called a "virtual document object model" or :ref:`VDOM`. This -is just a fancy way of saying we have a representation of the document object model or -`DOM -`__ -that is not the actual DOM. diff --git a/docs/source/guides/understanding-reactpy/the-rendering-pipeline.rst b/docs/source/guides/understanding-reactpy/the-rendering-pipeline.rst deleted file mode 100644 index cdde27f08..000000000 --- a/docs/source/guides/understanding-reactpy/the-rendering-pipeline.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. _The Rendering Pipeline: - -The Rendering Pipeline 🚧 -========================= - -.. talk about layouts and dispatchers - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/understanding-reactpy/the-rendering-process.rst b/docs/source/guides/understanding-reactpy/the-rendering-process.rst deleted file mode 100644 index 00215a887..000000000 --- a/docs/source/guides/understanding-reactpy/the-rendering-process.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. _The Rendering Process: - -The Rendering Process 🚧 -======================== - -.. refer to https://beta.reactjs.org/learn/render-and-commit - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/understanding-reactpy/what-are-components.rst b/docs/source/guides/understanding-reactpy/what-are-components.rst deleted file mode 100644 index 4c22dda13..000000000 --- a/docs/source/guides/understanding-reactpy/what-are-components.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _What Are Components: - -What Are Components? 🚧 -======================= - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/understanding-reactpy/why-reactpy-needs-keys.rst b/docs/source/guides/understanding-reactpy/why-reactpy-needs-keys.rst deleted file mode 100644 index e570b8f41..000000000 --- a/docs/source/guides/understanding-reactpy/why-reactpy-needs-keys.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _Why ReactPy Needs Keys: - -Why ReactPy Needs Keys 🚧 -========================= - -.. note:: - - Under construction 🚧 diff --git a/docs/source/guides/understanding-reactpy/writing-tests.rst b/docs/source/guides/understanding-reactpy/writing-tests.rst deleted file mode 100644 index ffac27df6..000000000 --- a/docs/source/guides/understanding-reactpy/writing-tests.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _Writing Tests: - -Writing Tests 🚧 -================ - -.. note:: - - Under construction 🚧 diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index 8b21160f6..000000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,206 +0,0 @@ -.. card:: - - This documentation is still under construction 🚧. We welcome your `feedback - `__! - - -ReactPy -======= - -.. toctree:: - :hidden: - :caption: Guides - - guides/getting-started/index - guides/creating-interfaces/index - guides/adding-interactivity/index - guides/managing-state/index - guides/escape-hatches/index - guides/understanding-reactpy/index - -.. toctree:: - :hidden: - :caption: Reference - - reference/browser-events - reference/html-attributes - reference/hooks-api - _auto/apis - reference/javascript-api - reference/specifications - -.. toctree:: - :hidden: - :caption: About - - about/changelog - about/contributor-guide - about/credits-and-licenses - Source Code - Community - -ReactPy is a library for building user interfaces in Python without Javascript. ReactPy -interfaces are made from :ref:`components ` which look and behave -similarly to those found in `ReactJS `__. Designed with simplicity -in mind, ReactPy can be used by those without web development experience while also -being powerful enough to grow with your ambitions. - - -At a Glance ------------ - -To get a rough idea of how to write apps in ReactPy, take a look at the tiny `"hello world" -`__ application below: - -.. reactpy:: guides/getting-started/_examples/hello_world - -.. hint:: - - Try clicking the **🚀 result** tab to see what this displays! - -So what exactly does this code do? First, it imports a few tools from ``reactpy`` that will -get used to describe and execute an application. Then, we create an ``App`` function -which will define the content the application displays. Specifically, it displays a kind -of HTML element called an ``h1`` `section heading -`__. -Importantly though, a ``@component`` decorator has been applied to the ``App`` function -to turn it into a :ref:`component `. Finally, we :ref:`run -` a development web server by passing the ``App`` component to the -``run()`` function. - -.. note:: - - See :ref:`Running ReactPy in Production` to learn how to use a production-grade server - to run ReactPy. - - -Learning ReactPy ----------------- - -This documentation is broken up into chapters and sections that introduce you to -concepts step by step with detailed explanations and lots of examples. You should feel -free to dive into any content that seems interesting. While each chapter assumes -knowledge from those that came before, when you encounter a concept you're unfamiliar -with you should look for links that will help direct you to the place where it was -originally taught. - - -Chapter 1 - :ref:`Getting Started` ------------------------------------ - -If you want to follow along with examples in the sections that follow, you'll want to -start here so you can :ref:`install ReactPy `. This section also contains -more detailed information about how to :ref:`run ReactPy ` in different -contexts. For example, if you want to embed ReactPy into an existing application, or run -ReactPy within a Jupyter Notebook, this is where you can learn how to do those things. - -.. grid:: 1 2 2 2 - - .. grid-item:: - - .. image:: _static/install-and-run-reactpy.gif - - .. grid-item:: - - .. image:: guides/getting-started/_static/reactpy-in-jupyterlab.gif - -.. card:: - :link: guides/getting-started/index - :link-type: doc - - :octicon:`book` Read More - ^^^^^^^^^^^^^^^^^^^^^^^^^ - - Install ReactPy and run it in a variety of different ways - with different web servers - and frameworks. You'll even embed ReactPy into an existing app. - - -Chapter 2 - :ref:`Creating Interfaces` --------------------------------------- - -ReactPy is a Python package for making user interfaces (UI). These interfaces are built -from small elements of functionality like buttons text and images. ReactPy allows you to -combine these elements into reusable :ref:`"components" `. In the -sections that follow you'll learn how these UI elements are created and organized into -components. Then, you'll use this knowledge to create interfaces from raw data: - -.. reactpy:: guides/creating-interfaces/rendering-data/_examples/todo_list_with_keys - -.. card:: - :link: guides/creating-interfaces/index - :link-type: doc - - :octicon:`book` Read More - ^^^^^^^^^^^^^^^^^^^^^^^^^ - - Learn to construct user interfaces from basic HTML elements and reusable components. - - -Chapter 3 - :ref:`Adding Interactivity` ---------------------------------------- - -Components often need to change what’s on the screen as a result of an interaction. For -example, typing into the form should update the input field, clicking a “Comment” button -should bring up a text input field, clicking “Buy” should put a product in the shopping -cart. Components need to “remember” things like the current input value, the current -image, the shopping cart. In ReactPy, this kind of component-specific memory is created and -updated with a "hook" called ``use_state()`` that creates a **state variable** and -**state setter** respectively: - -.. reactpy:: guides/adding-interactivity/components-with-state/_examples/adding_state_variable - -In ReactPy, ``use_state``, as well as any other function whose name starts with ``use``, is -called a "hook". These are special functions that should only be called while ReactPy is -:ref:`rendering `. They let you "hook into" the different -capabilities of ReactPy's components of which ``use_state`` is just one (well get into the -other :ref:`later `). - -.. card:: - :link: guides/adding-interactivity/index - :link-type: doc - - :octicon:`book` Read More - ^^^^^^^^^^^^^^^^^^^^^^^^^ - - Learn how user interfaces can be made to respond to user interaction in real-time. - - -Chapter 4 - :ref:`Managing State` ---------------------------------- - -.. card:: - :link: guides/managing-state/index - :link-type: doc - - :octicon:`book` Read More - ^^^^^^^^^^^^^^^^^^^^^^^^^ - - Under construction 🚧 - - - -Chapter 5 - :ref:`Escape Hatches` ---------------------------------- - -.. card:: - :link: guides/escape-hatches/index - :link-type: doc - - :octicon:`book` Read More - ^^^^^^^^^^^^^^^^^^^^^^^^^ - - Under construction 🚧 - - -Chapter 6 - :ref:`Understanding ReactPy` ----------------------------------------- - -.. card:: - :link: guides/escape-hatches/index - :link-type: doc - - :octicon:`book` Read More - ^^^^^^^^^^^^^^^^^^^^^^^^^ - - Under construction 🚧 - diff --git a/docs/source/reference/_examples/character_movement/main.py b/docs/source/reference/_examples/character_movement/main.py deleted file mode 100644 index 9545b0c0a..000000000 --- a/docs/source/reference/_examples/character_movement/main.py +++ /dev/null @@ -1,73 +0,0 @@ -from pathlib import Path -from typing import NamedTuple - -from reactpy import component, html, run, use_state -from reactpy.widgets import image - -HERE = Path(__file__) -CHARACTER_IMAGE = (HERE.parent / "static" / "bunny.png").read_bytes() - - -class Position(NamedTuple): - x: int - y: int - angle: int - - -def rotate(degrees): - return lambda old_position: Position( - old_position.x, - old_position.y, - old_position.angle + degrees, - ) - - -def translate(x=0, y=0): - return lambda old_position: Position( - old_position.x + x, - old_position.y + y, - old_position.angle, - ) - - -@component -def Scene(): - position, set_position = use_state(Position(100, 100, 0)) - - return html.div( - {"style": {"width": "225px"}}, - html.div( - { - "style": { - "width": "200px", - "height": "200px", - "background_color": "slategray", - } - }, - image( - "png", - CHARACTER_IMAGE, - { - "style": { - "position": "relative", - "left": f"{position.x}px", - "top": f"{position.y}.px", - "transform": f"rotate({position.angle}deg) scale(2, 2)", - } - }, - ), - ), - html.button( - {"on_click": lambda e: set_position(translate(x=-10))}, "Move Left" - ), - html.button( - {"on_click": lambda e: set_position(translate(x=10))}, "Move Right" - ), - html.button({"on_click": lambda e: set_position(translate(y=-10))}, "Move Up"), - html.button({"on_click": lambda e: set_position(translate(y=10))}, "Move Down"), - html.button({"on_click": lambda e: set_position(rotate(-30))}, "Rotate Left"), - html.button({"on_click": lambda e: set_position(rotate(30))}, "Rotate Right"), - ) - - -run(Scene) diff --git a/docs/source/reference/_examples/character_movement/static/bunny.png b/docs/source/reference/_examples/character_movement/static/bunny.png deleted file mode 100644 index ce1f989c5..000000000 Binary files a/docs/source/reference/_examples/character_movement/static/bunny.png and /dev/null differ diff --git a/docs/source/reference/_examples/click_count.py b/docs/source/reference/_examples/click_count.py deleted file mode 100644 index 3ee2c89c5..000000000 --- a/docs/source/reference/_examples/click_count.py +++ /dev/null @@ -1,13 +0,0 @@ -import reactpy - - -@reactpy.component -def ClickCount(): - count, set_count = reactpy.hooks.use_state(0) - - return reactpy.html.button( - {"on_click": lambda event: set_count(count + 1)}, [f"Click count: {count}"] - ) - - -reactpy.run(ClickCount) diff --git a/docs/source/reference/_examples/material_ui_switch.py b/docs/source/reference/_examples/material_ui_switch.py deleted file mode 100644 index 704ae3145..000000000 --- a/docs/source/reference/_examples/material_ui_switch.py +++ /dev/null @@ -1,22 +0,0 @@ -import reactpy - -mui = reactpy.web.module_from_template("react", "@material-ui/core@^5.0", fallback="⌛") -Switch = reactpy.web.export(mui, "Switch") - - -@reactpy.component -def DayNightSwitch(): - checked, set_checked = reactpy.hooks.use_state(False) - - return reactpy.html.div( - Switch( - { - "checked": checked, - "onChange": lambda event, checked: set_checked(checked), - } - ), - "🌞" if checked else "🌚", - ) - - -reactpy.run(DayNightSwitch) diff --git a/docs/source/reference/_examples/matplotlib_plot.py b/docs/source/reference/_examples/matplotlib_plot.py deleted file mode 100644 index 5c4d616fe..000000000 --- a/docs/source/reference/_examples/matplotlib_plot.py +++ /dev/null @@ -1,85 +0,0 @@ -from io import BytesIO - -import matplotlib.pyplot as plt - -import reactpy -from reactpy.widgets import image - - -@reactpy.component -def PolynomialPlot(): - coefficients, set_coefficients = reactpy.hooks.use_state([0]) - - x = list(linspace(-1, 1, 50)) - y = [polynomial(value, coefficients) for value in x] - - return reactpy.html.div( - plot(f"{len(coefficients)} Term Polynomial", x, y), - ExpandableNumberInputs(coefficients, set_coefficients), - ) - - -@reactpy.component -def ExpandableNumberInputs(values, set_values): - inputs = [] - for i in range(len(values)): - - def set_value_at_index(event, index=i): - new_value = float(event["target"]["value"] or 0) - set_values(values[:index] + [new_value] + values[index + 1 :]) - - inputs.append(poly_coef_input(i + 1, set_value_at_index)) - - def add_input(): - set_values([*values, 0]) - - def del_input(): - set_values(values[:-1]) - - return reactpy.html.div( - reactpy.html.div( - "add/remove term:", - reactpy.html.button({"on_click": lambda event: add_input()}, "+"), - reactpy.html.button({"on_click": lambda event: del_input()}, "-"), - ), - inputs, - ) - - -def plot(title, x, y): - fig, axes = plt.subplots() - axes.plot(x, y) - axes.set_title(title) - buffer = BytesIO() - fig.savefig(buffer, format="png") - plt.close(fig) - return image("png", buffer.getvalue()) - - -def poly_coef_input(index, callback): - return reactpy.html.div( - {"style": {"margin-top": "5px"}, "key": index}, - reactpy.html.label( - "C", - reactpy.html.sub(index), - " x X", - reactpy.html.sup(index), - ), - reactpy.html.input({"type": "number", "on_change": callback}), - ) - - -def polynomial(x, coefficients): - return sum(c * (x ** (i + 1)) for i, c in enumerate(coefficients)) - - -def linspace(start, stop, n): - if n == 1: - yield stop - return - h = (stop - start) / (n - 1) - for i in range(n): - yield start + h * i - - -reactpy.run(PolynomialPlot) diff --git a/docs/source/reference/_examples/network_graph.py b/docs/source/reference/_examples/network_graph.py deleted file mode 100644 index 79b1092f3..000000000 --- a/docs/source/reference/_examples/network_graph.py +++ /dev/null @@ -1,40 +0,0 @@ -import random - -import reactpy - -react_cytoscapejs = reactpy.web.module_from_template( - "react", - "react-cytoscapejs", - fallback="⌛", -) -Cytoscape = reactpy.web.export(react_cytoscapejs, "default") - - -@reactpy.component -def RandomNetworkGraph(): - return Cytoscape( - { - "style": {"width": "100%", "height": "200px"}, - "elements": random_network(20), - "layout": {"name": "cose"}, - } - ) - - -def random_network(number_of_nodes): - conns = [] - nodes = [{"data": {"id": 0, "label": 0}}] - - for src_node_id in range(1, number_of_nodes + 1): - tgt_node = random.choice(nodes) - src_node = {"data": {"id": src_node_id, "label": src_node_id}} - - new_conn = {"data": {"source": src_node_id, "target": tgt_node["data"]["id"]}} - - nodes.append(src_node) - conns.append(new_conn) - - return nodes + conns - - -reactpy.run(RandomNetworkGraph) diff --git a/docs/source/reference/_examples/pigeon_maps.py b/docs/source/reference/_examples/pigeon_maps.py deleted file mode 100644 index 1ddf04fdc..000000000 --- a/docs/source/reference/_examples/pigeon_maps.py +++ /dev/null @@ -1,46 +0,0 @@ -import reactpy - -pigeon_maps = reactpy.web.module_from_template("react", "pigeon-maps", fallback="⌛") -Map, Marker = reactpy.web.export(pigeon_maps, ["Map", "Marker"]) - - -@reactpy.component -def MapWithMarkers(): - marker_anchor, add_marker_anchor, remove_marker_anchor = use_set() - - markers = [ - Marker( - { - "anchor": anchor, - "onClick": lambda event, a=anchor: remove_marker_anchor(a), - }, - key=str(anchor), - ) - for anchor in marker_anchor - ] - - return Map( - { - "defaultCenter": (37.774, -122.419), - "defaultZoom": 12, - "height": "300px", - "metaWheelZoom": True, - "onClick": lambda event: add_marker_anchor(tuple(event["latLng"])), - }, - markers, - ) - - -def use_set(initial_value=None): - values, set_values = reactpy.hooks.use_state(initial_value or set()) - - def add_value(lat_lon): - set_values(values.union({lat_lon})) - - def remove_value(lat_lon): - set_values(values.difference({lat_lon})) - - return values, add_value, remove_value - - -reactpy.run(MapWithMarkers) diff --git a/docs/source/reference/_examples/simple_dashboard.py b/docs/source/reference/_examples/simple_dashboard.py deleted file mode 100644 index 66913fc84..000000000 --- a/docs/source/reference/_examples/simple_dashboard.py +++ /dev/null @@ -1,102 +0,0 @@ -import asyncio -import random -import time - -import reactpy -from reactpy.widgets import Input - -victory = reactpy.web.module_from_template( - "react", - "victory-line", - fallback="⌛", - # not usually required (see issue #461 for more info) - unmount_before_update=True, -) -VictoryLine = reactpy.web.export(victory, "VictoryLine") - - -@reactpy.component -def RandomWalk(): - mu = reactpy.hooks.use_ref(0) - sigma = reactpy.hooks.use_ref(1) - - return reactpy.html.div( - RandomWalkGraph(mu, sigma), - reactpy.html.style( - """ - .number-input-container {margin-bottom: 20px} - .number-input-container input {width: 48%;float: left} - .number-input-container input + input {margin-left: 4%} - """ - ), - NumberInput( - "Mean", - mu.current, - mu.set_current, - (-1, 1, 0.01), - ), - NumberInput( - "Standard Deviation", - sigma.current, - sigma.set_current, - (0, 1, 0.01), - ), - ) - - -@reactpy.component -def RandomWalkGraph(mu, sigma): - interval = use_interval(0.5) - data, set_data = reactpy.hooks.use_state([{"x": 0, "y": 0}] * 50) - - @reactpy.hooks.use_effect - async def animate(): - await interval - last_data_point = data[-1] - next_data_point = { - "x": last_data_point["x"] + 1, - "y": last_data_point["y"] + random.gauss(mu.current, sigma.current), - } - set_data(data[1:] + [next_data_point]) - - return VictoryLine( - { - "data": data, - "style": { - "parent": {"width": "100%"}, - "data": {"stroke": "royalblue"}, - }, - } - ) - - -@reactpy.component -def NumberInput(label, value, set_value_callback, domain): - minimum, maximum, step = domain - attrs = {"min": minimum, "max": maximum, "step": step} - - value, set_value = reactpy.hooks.use_state(value) - - def update_value(value): - set_value(value) - set_value_callback(value) - - return reactpy.html.fieldset( - {"class_name": "number-input-container"}, - reactpy.html.legend({"style": {"font-size": "medium"}}, label), - Input(update_value, "number", value, attributes=attrs, cast=float), - Input(update_value, "range", value, attributes=attrs, cast=float), - ) - - -def use_interval(rate): - usage_time = reactpy.hooks.use_ref(time.time()) - - async def interval() -> None: - await asyncio.sleep(rate - (time.time() - usage_time.current)) - usage_time.current = time.time() - - return asyncio.ensure_future(interval()) - - -reactpy.run(RandomWalk) diff --git a/docs/source/reference/_examples/slideshow.py b/docs/source/reference/_examples/slideshow.py deleted file mode 100644 index b490b3feb..000000000 --- a/docs/source/reference/_examples/slideshow.py +++ /dev/null @@ -1,20 +0,0 @@ -import reactpy - - -@reactpy.component -def Slideshow(): - index, set_index = reactpy.hooks.use_state(0) - - def next_image(event): - set_index(index + 1) - - return reactpy.html.img( - { - "src": f"https://picsum.photos/id/{index}/800/300", - "style": {"cursor": "pointer"}, - "on_click": next_image, - } - ) - - -reactpy.run(Slideshow) diff --git a/docs/source/reference/_examples/snake_game.py b/docs/source/reference/_examples/snake_game.py deleted file mode 100644 index 36916410e..000000000 --- a/docs/source/reference/_examples/snake_game.py +++ /dev/null @@ -1,188 +0,0 @@ -import asyncio -import enum -import random -import time - -import reactpy - - -class GameState(enum.Enum): - init = 0 - lost = 1 - won = 2 - play = 3 - - -@reactpy.component -def GameView(): - game_state, set_game_state = reactpy.hooks.use_state(GameState.init) - - if game_state == GameState.play: - return GameLoop(grid_size=6, block_scale=50, set_game_state=set_game_state) - - start_button = reactpy.html.button( - {"on_click": lambda event: set_game_state(GameState.play)}, "Start" - ) - - if game_state == GameState.won: - menu = reactpy.html.div(reactpy.html.h3("You won!"), start_button) - elif game_state == GameState.lost: - menu = reactpy.html.div(reactpy.html.h3("You lost"), start_button) - else: - menu = reactpy.html.div(reactpy.html.h3("Click to play"), start_button) - - menu_style = reactpy.html.style( - """ - .snake-game-menu h3 { - margin-top: 0px !important; - } - """ - ) - - return reactpy.html.div({"class_name": "snake-game-menu"}, menu_style, menu) - - -class Direction(enum.Enum): - ArrowUp = (0, -1) - ArrowLeft = (-1, 0) - ArrowDown = (0, 1) - ArrowRight = (1, 0) - - -@reactpy.component -def GameLoop(grid_size, block_scale, set_game_state): - # we `use_ref` here to capture the latest direction press without any delay - direction = reactpy.hooks.use_ref(Direction.ArrowRight.value) - # capture the last direction of travel that was rendered - last_direction = direction.current - - snake, set_snake = reactpy.hooks.use_state( - [(grid_size // 2 - 1, grid_size // 2 - 1)] - ) - food, set_food = use_snake_food(grid_size, snake) - - grid = create_grid(grid_size, block_scale) - - @reactpy.event(prevent_default=True) - def on_direction_change(event): - if hasattr(Direction, event["key"]): - maybe_new_direction = Direction[event["key"]].value - direction_vector_sum = tuple( - map(sum, zip(last_direction, maybe_new_direction)) - ) - if direction_vector_sum != (0, 0): - direction.current = maybe_new_direction - - grid_wrapper = reactpy.html.div({"on_key_down": on_direction_change}, grid) - - assign_grid_block_color(grid, food, "blue") - - for location in snake: - assign_grid_block_color(grid, location, "white") - - new_game_state = None - if snake[-1] in snake[:-1]: - assign_grid_block_color(grid, snake[-1], "red") - new_game_state = GameState.lost - elif len(snake) == grid_size**2: - assign_grid_block_color(grid, snake[-1], "yellow") - new_game_state = GameState.won - - interval = use_interval(0.5) - - @reactpy.hooks.use_effect - async def animate(): - if new_game_state is not None: - await asyncio.sleep(1) - set_game_state(new_game_state) - return - - await interval - - new_snake_head = ( - # grid wraps due to mod op here - (snake[-1][0] + direction.current[0]) % grid_size, - (snake[-1][1] + direction.current[1]) % grid_size, - ) - - if snake[-1] == food: - set_food() - new_snake = [*snake, new_snake_head] - else: - new_snake = snake[1:] + [new_snake_head] - - set_snake(new_snake) - - return grid_wrapper - - -def use_snake_food(grid_size, current_snake): - grid_points = {(x, y) for x in range(grid_size) for y in range(grid_size)} - points_not_in_snake = grid_points.difference(current_snake) - - food, _set_food = reactpy.hooks.use_state(current_snake[-1]) - - def set_food(): - _set_food(random.choice(list(points_not_in_snake))) - - return food, set_food - - -def use_interval(rate): - usage_time = reactpy.hooks.use_ref(time.time()) - - async def interval() -> None: - await asyncio.sleep(rate - (time.time() - usage_time.current)) - usage_time.current = time.time() - - return asyncio.ensure_future(interval()) - - -def create_grid(grid_size, block_scale): - return reactpy.html.div( - { - "style": { - "height": f"{block_scale * grid_size}px", - "width": f"{block_scale * grid_size}px", - "cursor": "pointer", - "display": "grid", - "grid-gap": 0, - "grid-template-columns": f"repeat({grid_size}, {block_scale}px)", - "grid-template-rows": f"repeat({grid_size}, {block_scale}px)", - }, - "tab_index": -1, - }, - [ - reactpy.html.div( - {"style": {"height": f"{block_scale}px"}, "key": i}, - [ - create_grid_block("black", block_scale, key=i) - for i in range(grid_size) - ], - ) - for i in range(grid_size) - ], - ) - - -def create_grid_block(color, block_scale, key): - return reactpy.html.div( - { - "style": { - "height": f"{block_scale}px", - "width": f"{block_scale}px", - "background_color": color, - "outline": "1px solid grey", - }, - "key": key, - } - ) - - -def assign_grid_block_color(grid, point, color): - x, y = point - block = grid["children"][x]["children"][y] - block["attributes"]["style"]["backgroundColor"] = color - - -reactpy.run(GameView) diff --git a/docs/source/reference/_examples/todo.py b/docs/source/reference/_examples/todo.py deleted file mode 100644 index 104ea59a9..000000000 --- a/docs/source/reference/_examples/todo.py +++ /dev/null @@ -1,35 +0,0 @@ -import reactpy - - -@reactpy.component -def Todo(): - items, set_items = reactpy.hooks.use_state([]) - - async def add_new_task(event): - if event["key"] == "Enter": - set_items([*items, event["target"]["value"]]) - - tasks = [] - - for index, text in enumerate(items): - - async def remove_task(event, index=index): - set_items(items[:index] + items[index + 1 :]) - - task_text = reactpy.html.td(reactpy.html.p(text)) - delete_button = reactpy.html.td( - {"on_click": remove_task}, reactpy.html.button(["x"]) - ) - tasks.append(reactpy.html.tr(task_text, delete_button)) - - task_input = reactpy.html.input({"on_key_down": add_new_task}) - task_table = reactpy.html.table(tasks) - - return reactpy.html.div( - reactpy.html.p("press enter to add a task:"), - task_input, - task_table, - ) - - -reactpy.run(Todo) diff --git a/docs/source/reference/_examples/use_reducer_counter.py b/docs/source/reference/_examples/use_reducer_counter.py deleted file mode 100644 index 6f9581dfd..000000000 --- a/docs/source/reference/_examples/use_reducer_counter.py +++ /dev/null @@ -1,27 +0,0 @@ -import reactpy - - -def reducer(count, action): - if action == "increment": - return count + 1 - elif action == "decrement": - return count - 1 - elif action == "reset": - return 0 - else: - msg = f"Unknown action '{action}'" - raise ValueError(msg) - - -@reactpy.component -def Counter(): - count, dispatch = reactpy.hooks.use_reducer(reducer, 0) - return reactpy.html.div( - f"Count: {count}", - reactpy.html.button({"on_click": lambda event: dispatch("reset")}, "Reset"), - reactpy.html.button({"on_click": lambda event: dispatch("increment")}, "+"), - reactpy.html.button({"on_click": lambda event: dispatch("decrement")}, "-"), - ) - - -reactpy.run(Counter) diff --git a/docs/source/reference/_examples/use_state_counter.py b/docs/source/reference/_examples/use_state_counter.py deleted file mode 100644 index b2d8c84a9..000000000 --- a/docs/source/reference/_examples/use_state_counter.py +++ /dev/null @@ -1,26 +0,0 @@ -import reactpy - - -def increment(last_count): - return last_count + 1 - - -def decrement(last_count): - return last_count - 1 - - -@reactpy.component -def Counter(): - initial_count = 0 - count, set_count = reactpy.hooks.use_state(initial_count) - return reactpy.html.div( - f"Count: {count}", - reactpy.html.button( - {"on_click": lambda event: set_count(initial_count)}, "Reset" - ), - reactpy.html.button({"on_click": lambda event: set_count(increment)}, "+"), - reactpy.html.button({"on_click": lambda event: set_count(decrement)}, "-"), - ) - - -reactpy.run(Counter) diff --git a/docs/source/reference/_examples/victory_chart.py b/docs/source/reference/_examples/victory_chart.py deleted file mode 100644 index ce37c522f..000000000 --- a/docs/source/reference/_examples/victory_chart.py +++ /dev/null @@ -1,7 +0,0 @@ -import reactpy - -victory = reactpy.web.module_from_template("react", "victory-bar", fallback="⌛") -VictoryBar = reactpy.web.export(victory, "VictoryBar") - -bar_style = {"parent": {"width": "500px"}, "data": {"fill": "royalblue"}} -reactpy.run(reactpy.component(lambda: VictoryBar({"style": bar_style}))) diff --git a/docs/source/reference/_static/vdom-json-schema.json b/docs/source/reference/_static/vdom-json-schema.json deleted file mode 100644 index b1005d2ed..000000000 --- a/docs/source/reference/_static/vdom-json-schema.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "$ref": "#/definitions/element", - "$schema": "http://json-schema.org/draft-07/schema", - "definitions": { - "element": { - "dependentSchemas": { - "error": { - "properties": { - "tagName": { - "maxLength": 0 - } - } - } - }, - "properties": { - "attributes": { - "type": "object" - }, - "children": { - "$ref": "#/definitions/elementChildren" - }, - "error": { - "type": "string" - }, - "eventHandlers": { - "$ref": "#/definitions/elementEventHandlers" - }, - "importSource": { - "$ref": "#/definitions/importSource" - }, - "key": { - "type": "string" - }, - "tagName": { - "type": "string" - } - }, - "required": ["tagName"], - "type": "object" - }, - "elementChildren": { - "items": { - "$ref": "#/definitions/elementOrString" - }, - "type": "array" - }, - "elementEventHandlers": { - "patternProperties": { - ".*": { - "$ref": "#/definitions/eventHander" - } - }, - "type": "object" - }, - "elementOrString": { - "if": { - "type": "object" - }, - "then": { - "$ref": "#/definitions/element" - }, - "type": ["object", "string"] - }, - "eventHandler": { - "properties": { - "preventDefault": { - "type": "boolean" - }, - "stopPropagation": { - "type": "boolean" - }, - "target": { - "type": "string" - } - }, - "required": ["target"], - "type": "object" - }, - "importSource": { - "properties": { - "fallback": { - "if": { - "not": { - "type": "null" - } - }, - "then": { - "$ref": "#/definitions/elementOrString" - }, - "type": ["object", "string", "null"] - }, - "source": { - "type": "string" - }, - "sourceType": { - "enum": ["URL", "NAME"] - }, - "unmountBeforeUpdate": { - "type": "boolean" - } - }, - "required": ["source"], - "type": "object" - } - } -} diff --git a/docs/source/reference/browser-events.rst b/docs/source/reference/browser-events.rst deleted file mode 100644 index 632be410a..000000000 --- a/docs/source/reference/browser-events.rst +++ /dev/null @@ -1,65 +0,0 @@ -.. _Browser Events: - -Browser Events 🚧 -================= - -The event types below are triggered by an event in the bubbling phase. To register an -event handler for the capture phase, append Capture to the event name; for example, -instead of using ``onClick``, you would use ``onClickCapture`` to handle the click event -in the capture phase. - -.. note:: - - Under construction 🚧 - - -Clipboard Events ----------------- - -Composition Events ------------------- - -Keyboard Events ---------------- - -Focus Events ------------- - -Form Events ------------ - -Generic Events --------------- - -Mouse Events ------------- - -Pointer Events --------------- - -Selection Events ----------------- - -Touch Events ------------- - -UI Events ---------- - -Wheel Events ------------- - -Media Events ------------- - -Image Events ------------- - -Animation Events ----------------- - -Transition Events ------------------ - -Other Events ------------- diff --git a/docs/source/reference/hooks-api.rst b/docs/source/reference/hooks-api.rst deleted file mode 100644 index ca8123e85..000000000 --- a/docs/source/reference/hooks-api.rst +++ /dev/null @@ -1,379 +0,0 @@ -========= -Hooks API -========= - -Hooks are functions that allow you to "hook into" the life cycle events and state of -Components. Their usage should always follow the :ref:`Rules of Hooks`. For most use -cases the :ref:`Basic Hooks` should be enough, however the remaining -:ref:`Supplementary Hooks` should fulfill less common scenarios. - - -Basic Hooks -=========== - - -Use State ---------- - -.. code-block:: - - state, set_state = use_state(initial_state) - -Returns a stateful value and a function to update it. - -During the first render the ``state`` will be identical to the ``initial_state`` passed -as the first argument. However in subsequent renders ``state`` will take on the value -passed to ``set_state``. - -.. code-block:: - - set_state(new_state) - -The ``set_state`` function accepts a ``new_state`` as its only argument and schedules a -re-render of the component where ``use_state`` was initially called. During these -subsequent re-renders the ``state`` returned by ``use_state`` will take on the value -of ``new_state``. - -.. note:: - - The identity of ``set_state`` is guaranteed to be preserved across renders. This - means it can safely be omitted from dependency lists in :ref:`Use Effect` or - :ref:`Use Callback`. - - -Functional Updates -.................. - -If the new state is computed from the previous state, you can pass a function which -accepts a single argument (the previous state) and returns the next state. Consider this -simply use case of a counter where we've pulled out logic for increment and -decremented the count: - -.. reactpy:: _examples/use_state_counter - -We use the functional form for the "+" and "-" buttons since the next ``count`` depends -on the previous value, while for the "Reset" button we simple assign the -``initial_count`` since it is independent of the prior ``count``. This is a trivial -example, but it demonstrates how complex state logic can be factored out into well -defined and potentially reusable functions. - - -Lazy Initial State -.................. - -In cases where it is costly to create the initial value for ``use_state``, you can pass -a constructor function that accepts no arguments instead - it will be called on the -first render of a component, but will be disregarded in all following renders: - -.. code-block:: - - state, set_state = use_state(lambda: some_expensive_computation(a, b, c)) - - -Skipping Updates -................ - -If you update a State Hook to the same value as the current state then the component which -owns that state will not be rendered again. We check ``if new_state is current_state`` -in order to determine whether there has been a change. Thus the following would not -result in a re-render: - -.. code-block:: - - state, set_state = use_state([]) - set_state(state) - - -Use Effect ----------- - -.. code-block:: - - use_effect(did_render) - -The ``use_effect`` hook accepts a function which may be imperative, or mutate state. The -function will be called immediately after the layout has fully updated. - -Asynchronous actions, mutations, subscriptions, and other `side effects`_ can cause -unexpected bugs if placed in the main body of a component's render function. Thus the -``use_effect`` hook provides a way to safely escape the purely functional world of -component render functions. - -.. note:: - - Normally in React the ``did_render`` function is called once an update has been - committed to the screen. Since no such action is performed by ReactPy, and the time - at which the update is displayed cannot be known we are unable to achieve parity - with this behavior. - - -Cleaning Up Effects -................... - -If the effect you wish to enact creates resources, you'll probably need to clean them -up. In such cases you may simply return a function that addresses this from the -``did_render`` function which created the resource. Consider the case of opening and -then closing a connection: - -.. code-block:: - - def establish_connection(): - connection = open_connection() - return lambda: close_connection(connection) - - use_effect(establish_connection) - -The clean-up function will be run before the component is unmounted or, before the next -effect is triggered when the component re-renders. You can -:ref:`conditionally fire events ` to avoid triggering them each -time a component renders. - - -Conditional Effects -................... - -By default, effects are triggered after every successful render to ensure that all state -referenced by the effect is up to date. However, when an effect function references -non-global variables, the effect will only if the value of that variable changes. For -example, imagine that we had an effect that connected to a ``url`` state variable: - -.. code-block:: - - url, set_url = use_state("https://example.com") - - def establish_connection(): - connection = open_connection(url) - return lambda: close_connection(connection) - - use_effect(establish_connection) - -Here, a new connection will be established whenever a new ``url`` is set. - - -Async Effects -............. - -A behavior unique to ReactPy's implementation of ``use_effect`` is that it natively -supports ``async`` functions: - -.. code-block:: - - async def non_blocking_effect(): - resource = await do_something_asynchronously() - return lambda: blocking_close(resource) - - use_effect(non_blocking_effect) - - -There are **three important subtleties** to note about using asynchronous effects: - -1. The cleanup function must be a normal synchronous function. - -2. Asynchronous effects which do not complete before the next effect is created - following a re-render will be cancelled. This means an - :class:`~asyncio.CancelledError` will be raised somewhere in the body of the effect. - -3. An asynchronous effect may occur any time after the update which added this effect - and before the next effect following a subsequent update. - - -Manual Effect Conditions -........................ - -In some cases, you may want to explicitly declare when an effect should be triggered. -You can do this by passing ``dependencies`` to ``use_effect``. Each of the following -values produce different effect behaviors: - -- ``use_effect(..., dependencies=None)`` - triggers and cleans up on every render. -- ``use_effect(..., dependencies=[])`` - only triggers on the first and cleans up after - the last render. -- ``use_effect(..., dependencies=[x, y])`` - triggers on the first render and on subsequent renders if - ``x`` or ``y`` have changed. - - -Use Context ------------ - -.. code-block:: - - value = use_context(MyContext) - -Accepts a context object (the value returned from -:func:`reactpy.core.hooks.create_context`) and returns the current context value for that -context. The current context value is determined by the ``value`` argument passed to the -nearest ``MyContext`` in the tree. - -When the nearest above the component updates, this Hook will -trigger a rerender with the latest context value passed to that MyContext provider. Even -if an ancestor uses React.memo or shouldComponentUpdate, a rerender will still happen -starting at the component itself using useContext. - - -Supplementary Hooks -=================== - - -Use Reducer ------------ - -.. code-block:: - - state, dispatch_action = use_reducer(reducer, initial_state) - -An alternative and derivative of :ref:`Use State` the ``use_reducer`` hook, instead of -directly assigning a new state, allows you to specify an action which will transition -the previous state into the next state. This transition is defined by a reducer function -of the form ``(current_state, action) -> new_state``. The ``use_reducer`` hook then -returns the current state and a ``dispatch_action`` function that accepts an ``action`` -and causes a transition to the next state via the ``reducer``. - -``use_reducer`` is generally preferred to ``use_state`` if logic for transitioning from -one state to the next is especially complex or involves nested data structures. -``use_reducer`` can also be used to collect several ``use_state`` calls together - this -may be slightly more performant as well as being preferable since there is only one -``dispatch_action`` callback versus the many ``set_state`` callbacks. - -We can rework the :ref:`Functional Updates` counter example to use ``use_reducer``: - -.. reactpy:: _examples/use_reducer_counter - -.. note:: - - The identity of the ``dispatch_action`` function is guaranteed to be preserved - across re-renders throughout the lifetime of the component. This means it can safely - be omitted from dependency lists in :ref:`Use Effect` or :ref:`Use Callback`. - - -Use Callback ------------- - -.. code-block:: - - memoized_callback = use_callback(lambda: do_something(a, b)) - -A derivative of :ref:`Use Memo`, the ``use_callback`` hook returns a -`memoized `_ callback. This is useful when passing callbacks to child -components which check reference equality to prevent unnecessary renders. The -``memoized_callback`` will only change when any local variables is references do. - -.. note:: - - You may manually specify what values the callback depends on in the :ref:`same way - as effects ` using the ``dependencies`` parameter. - - -Use Memo --------- - -.. code-block:: - - memoized_value = use_memo(lambda: compute_something_expensive(a, b)) - -Returns a `memoized `_ value. By passing a constructor function accepting -no arguments and an array of dependencies for that constructor, the ``use_callback`` -hook will return the value computed by the constructor. The ``memoized_value`` will only -be recomputed if a local variable referenced by the constructor changes (e.g. ``a`` or -``b`` here). This optimizes performance because you don't need to -``compute_something_expensive`` on every render. - -Unlike ``use_effect`` the constructor function is called during each render (instead of -after) and should not incur side effects. - -.. warning:: - - Remember that you shouldn't optimize something unless you know it's a performance - bottleneck. Write your code without ``use_memo`` first and then add it to targeted - sections that need a speed-up. - -.. note:: - - You may manually specify what values the callback depends on in the :ref:`same way - as effects ` using the ``dependencies`` parameter. - - -Use Ref -------- - -.. code-block:: - - ref_container = use_ref(initial_value) - -Returns a mutable :class:`~reactpy.utils.Ref` object that has a single -:attr:`~reactpy.utils.Ref.current` attribute that at first contains the ``initial_state``. -The identity of the ``Ref`` object will be preserved for the lifetime of the component. - -A ``Ref`` is most useful if you need to incur side effects since updating its -``.current`` attribute doesn't trigger a re-render of the component. You'll often use this -hook alongside :ref:`Use Effect` or in response to component event handlers. - - -.. links -.. ===== - -.. _React Hooks: https://reactjs.org/docs/hooks-reference.html -.. _side effects: https://en.wikipedia.org/wiki/Side_effect_(computer_science) -.. _memoization: https://en.wikipedia.org/wiki/Memoization - - -Rules of Hooks -============== - -Hooks are just normal Python functions, but there's a bit of magic to them, and in order -for that magic to work you've got to follow two rules. Thankfully we supply a -:ref:`Flake8 Plugin` to help enforce them. - - -Only call outside flow controls -------------------------------- - -**Don't call hooks inside loops, conditions, or nested functions.** Instead you must -always call hooks at the top level of your functions. By adhering to this rule you -ensure that hooks are always called in the exact same order. This fact is what allows -ReactPy to preserve the state of hooks between multiple calls to ``useState`` and -``useEffect`` calls. - - -Only call in render functions ------------------------------ - -**Don't call hooks from regular Python functions.** Instead you should: - -- ✅ Call Hooks from a component's render function. - -- ✅ Call Hooks from another custom hook - -Following this rule ensures stateful logic for ReactPy component is always clearly -separated from the rest of your codebase. - - -Flake8 Plugin -------------- - -We provide a Flake8 plugin called `flake8-reactpy-hooks `_ that helps -to enforce the two rules described above. You can ``pip`` install it directly, or with -the ``lint`` extra for ReactPy: - -.. code-block:: bash - - pip install flake8-reactpy-hooks - -Once installed running, ``flake8`` on your code will start catching errors. For example: - -.. code-block:: bash - - flake8 my_reactpy_components.py - -Might produce something like the following output: - -.. code-block:: text - - ./my_reactpy_components:10:8 ROH102 hook 'use_effect' used inside if statement - ./my_reactpy_components:23:4 ROH102 hook 'use_state' used outside component or hook definition - -See the Flake8 docs for -`more info `__. - -.. links -.. ===== - -.. _Flake8 Linter Plugin: https://github.com/reactive-python/flake8-reactpy-hooks diff --git a/docs/source/reference/html-attributes.rst b/docs/source/reference/html-attributes.rst deleted file mode 100644 index 91813c355..000000000 --- a/docs/source/reference/html-attributes.rst +++ /dev/null @@ -1,197 +0,0 @@ -.. testcode:: - - from reactpy import html - - -HTML Attributes -=============== - -In ReactPy, HTML attributes are specified using snake_case instead of dash-separated -words. For example, ``tabindex`` and ``margin-left`` become ``tab_index`` and -``margin_left`` respectively. - - -Notable Attributes -------------------- - -Some attributes in ReactPy are renamed, have special meaning, or are used differently -than in HTML. - -``style`` -......... - -As mentioned above, instead of using a string to specify the ``style`` attribute, we use -a dictionary to describe the CSS properties we want to apply to an element. For example, -the following HTML: - -.. code-block:: html - -
-

My Todo List

-
    -
  • Build a cool new app
  • -
  • Share it with the world!
  • -
-
- -Would be written in ReactPy as: - -.. testcode:: - - html.div( - { - "style": { - "width": "50%", - "margin_left": "25%", - }, - }, - html.h1( - { - "style": { - "margin_top": "0px", - }, - }, - "My Todo List", - ), - html.ul( - html.li("Build a cool new app"), - html.li("Share it with the world!"), - ), - ) - -``class`` vs ``class_name`` -........................... - -In HTML, the ``class`` attribute is used to specify a CSS class for an element. In -ReactPy, this attribute is renamed to ``class_name`` to avoid conflicting with the -``class`` keyword in Python. For example, the following HTML: - -.. code-block:: html - -
-

My Todo List

-
    -
  • Build a cool new app
  • -
  • Share it with the world!
  • -
-
- -Would be written in ReactPy as: - -.. testcode:: - - html.div( - {"class_name": "container"}, - html.h1({"class_name": "title"}, "My Todo List"), - html.ul( - {"class_name": "list"}, - html.li({"class_name": "item"}, "Build a cool new app"), - html.li({"class_name": "item"}, "Share it with the world!"), - ), - ) - -``for`` vs ``html_for`` -....................... - -In HTML, the ``for`` attribute is used to specify the ``id`` of the element it's -associated with. In ReactPy, this attribute is renamed to ``html_for`` to avoid -conflicting with the ``for`` keyword in Python. For example, the following HTML: - -.. code-block:: html - -
- - -
- -Would be written in ReactPy as: - -.. testcode:: - - html.div( - html.label({"html_for": "todo"}, "Todo:"), - html.input({"id": "todo", "type": "text"}), - ) - -``dangerously_set_inner_HTML`` -.............................. - -This is used to set the ``innerHTML`` property of an element and should be provided a -dictionary with a single key ``__html`` whose value is the HTML to be set. It should be -used with **extreme caution** as it can lead to XSS attacks if the HTML inside isn't -trusted (for example if it comes from user input). - - -All Attributes --------------- - -`access_key `__ - A string. Specifies a keyboard shortcut for the element. Not generally recommended. - -`aria_* `__ - ARIA attributes let you specify the accessibility tree information for this element. - See ARIA attributes for a complete reference. In ReactPy, all ARIA attribute names are - exactly the same as in HTML. - -`auto_capitalize `__ - A string. Specifies whether and how the user input should be capitalized. - -`content_editable `__ - A boolean. If true, the browser lets the user edit the rendered element directly. This - is used to implement rich text input libraries like Lexical. ReactPy warns if you try - to pass children to an element with ``content_editable = True`` because ReactPy will - not be able to update its content after user edits. - -`data_* `__ - Data attributes let you attach some string data to the element, for example - data-fruit="banana". In ReactPy, they are not commonly used because you would usually - read data from props or state instead. - -`dir `__ - Either ``"ltr"`` or ``"rtl"``. Specifies the text direction of the element. - -`draggable `__ - A boolean. Specifies whether the element is draggable. Part of HTML Drag and Drop API. - -`enter_key_hint `__ - A string. Specifies which action to present for the enter key on virtual keyboards. - -`hidden