diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c12aea32..8e977ba6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,12 +3,12 @@ name: Run CI on: [push, pull_request] permissions: - contents: read + contents: write + packages: write jobs: - build: + unit-tests: runs-on: ${{ matrix.os }} - timeout-minutes: 10 strategy: fail-fast: false matrix: @@ -16,9 +16,9 @@ jobs: os: [ubuntu-22.04, macOS-latest, windows-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} # from https://github.com/actions/cache/blob/main/examples.md#python---pip @@ -36,10 +36,93 @@ jobs: key: ${{ runner.os }}-${{ matrix.python-version }}-pip-${{ github.sha }} restore-keys: | ${{ runner.os }}-${{ matrix.python-version }}-pip- - - name: Install dependencies + - name: Set up environment & install dependencies run: | - python -m pip install . - python -m pip install -r test-requirements.txt + python -m pip install pip-tools + pip-compile --quiet --generate-hashes --extra mainapp > requirements.txt + python -m pip install --requirement requirements.txt + python -m pip install .[test] - name: Run tests - run: | - python -m pytest tests + run: tox + - name: Create GitHub Release + if: startsWith(github.ref, 'refs/tags/release-') && github.event_name == 'push' + uses: softprops/action-gh-release@v1 + with: + files: | + requirements.txt + Dockerfile + - name: Store tested requirements.txt file as artifact + uses: actions/upload-artifact@v3 + with: + name: requirements.txt + path: | + requirements.txt + + publish-docker-image: + runs-on: ubuntu-latest + needs: [unit-tests] + steps: + - name: System Dependencies for Packaging + run: | + sudo apt-get update + sudo apt-get install -y python3-pip python3-venv + python3 -m venv /tmp/tomlq + /tmp/tomlq/bin/pip install --upgrade pip + /tmp/tomlq/bin/pip install yq + - name: Checkout + uses: actions/checkout@v3 + - name: Set Environment + run: | + echo "APP_VERSION=$(/tmp/tomlq/bin/tomlq -r .project.version pyproject.toml)" >> $GITHUB_ENV + echo "APP_DESC=$(/tmp/tomlq/bin/tomlq -r .project.description pyproject.toml)" >> $GITHUB_ENV + - name: Retrieve tested requirements file + uses: actions/download-artifact@v3 + with: + name: requirements.txt + - name: Build Image + run: > + docker build + --build-arg "APP_VERSION=${APP_VERSION}" + --build-arg "APP_DESC=${APP_DESC}" + -t "ghcr.io/${GITHUB_REPOSITORY}:${APP_VERSION}" + -t "ghcr.io/${GITHUB_REPOSITORY}:latest" + . + + # - name: Login to Docker Hub + # if: github.event_name == 'push' + # uses: docker/login-action@v2 + # with: + # username: ${{ secrets.DOCKERHUB_USERNAME }} + # password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GHCR + if: startsWith(github.ref, 'refs/tags/release-') && github.event_name == 'push' + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Push Docker Image + if: startsWith(github.ref, 'refs/tags/release-') && github.event_name == 'push' + run: | + docker push "ghcr.io/${GITHUB_REPOSITORY}:${APP_VERSION}" + + pypi-publish: + needs: [unit-tests] + if: startsWith(github.ref, 'refs/tags/release-') && github.event_name == 'push' + name: Upload release to PyPI + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/httpbin + permissions: + id-token: write + steps: + - uses: actions/checkout@v3 + - name: Build distribution + run: | + python -m pip install --upgrade pip build + pyproject-build + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.gitignore b/.gitignore index eac3867b..f75d9509 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,8 @@ dist/ .eggs/ .workon .epio-app -*.pyc .tox +*.pyc *.egg-info *.swp .vscode/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index dfad587e..00000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -dist: trusty -language: python - -sudo: false -matrix: - include: - - python: 2.7 - env: TOXENV=py27 - - python: 3.6 - env: TOXENV=py36 - - python: 3.7 - env: TOXENV=py37 - dist: xenial - sudo: true - -install: - - travis_retry pip install tox - -script: - - tox diff --git a/Dockerfile b/Dockerfile index 4a783e35..89aa5f99 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,48 @@ -FROM python:3.10-slim - -LABEL name="httpbin" -LABEL version="0.9.2" -LABEL description="A simple HTTP service." -LABEL org.kennethreitz.vendor="Kenneth Reitz" +FROM python:3.10-slim AS build ENV LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive -RUN apt update -y && apt install python3-pip git -y && pip3 install --no-cache-dir pipenv +RUN apt-get -y update +RUN apt-get install -y \ + python3-pip \ + python3-venv -ADD Pipfile Pipfile.lock /httpbin/ -WORKDIR /httpbin -RUN /bin/bash -c "pip3 install --no-cache-dir -r <(pipenv requirements)" +RUN python3 -m venv /opt/httpbin +RUN /opt/httpbin/bin/pip install -U pip + +ADD requirements.txt /requirements.txt +RUN /opt/httpbin/bin/pip install --no-deps --requirement /requirements.txt ADD . /httpbin -RUN pip3 install --no-cache-dir /httpbin -RUN chmod +x /httpbin/httpbin.bash +RUN /opt/httpbin/bin/pip install --no-deps /httpbin + + +# ---------------------------------------------------------------------------- + +FROM python:3.10-slim AS prod + +ARG APP_VERSION +LABEL name="httpbin" +LABEL version=${APP_VERSION} +LABEL description="A simple HTTP service." +LABEL org.kennethreitz.vendor="Kenneth Reitz" + +RUN useradd \ + --system \ + --shell /bin/nologin \ + --no-create-home \ + --home /opt/httpbin \ + httpbin + +COPY --from=build /opt/httpbin /opt/httpbin +WORKDIR /opt/httpbin -EXPOSE 80 +ADD httpbin.bash /opt/httpbin/bin +RUN chmod +x /opt/httpbin/bin/httpbin.bash +RUN chown --recursive httpbin /opt/httpbin +EXPOSE 8080 +CMD ["/opt/httpbin/bin/httpbin.bash"] -CMD ["/httpbin/httpbin.bash"] +USER httpbin diff --git a/LICENSE b/LICENSE index 885f52d8..a609ede2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,15 +1,3 @@ -ISC License - -Copyright (c) 2017 Kenneth Reitz. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +This software is made available under the terms of *either* of the licenses +found in LICENSE.ISC or LICENSE.MIT. Contributions to httpbin are made +under the terms of *both* these licenses. diff --git a/LICENSE.ISC b/LICENSE.ISC new file mode 100644 index 00000000..885f52d8 --- /dev/null +++ b/LICENSE.ISC @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2017 Kenneth Reitz. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/LICENSE.MIT b/LICENSE.MIT new file mode 100644 index 00000000..d01ec46c --- /dev/null +++ b/LICENSE.MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright 2017 Kenneth Reitz + +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/MANIFEST.in b/MANIFEST.in index 894af4cc..80361cea 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,3 @@ -include httpbin/VERSION README.md LICENSE AUTHORS test_httpbin.py +include README.md LICENSE.ISC LICENSE.MIT AUTHORS test_httpbin.py recursive-include httpbin/templates * recursive-include httpbin/static * diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 430f105e..00000000 --- a/Pipfile +++ /dev/null @@ -1,19 +0,0 @@ -[[source]] -url = "https://pypi.python.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -gunicorn = "*" -decorator = "*" -brotlicffi = "*" -gevent = "*" -Flask = "*" -meinheld = "*" -werkzeug = ">=0.14.1" -six = "*" -flasgger = "*" -pyyaml = "*" - -[dev-packages] -rope = "*" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 16c5799c..00000000 --- a/Pipfile.lock +++ /dev/null @@ -1,700 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "511d2ef8cf9b33f2f1e96454c00ac103df3ad036fb342e668a97399eb91720e0" - }, - "pipfile-spec": 6, - "requires": {}, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.python.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "attrs": { - "hashes": [ - "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", - "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015" - ], - "markers": "python_version >= '3.7'", - "version": "==23.1.0" - }, - "blinker": { - "hashes": [ - "sha256:4afd3de66ef3a9f8067559fb7a1cbe555c17dcbe15971b05d1b625c3e7abe213", - "sha256:c3d739772abb7bc2860abf5f2ec284223d9ad5c76da018234f6f50d6f31ab1f0" - ], - "markers": "python_version >= '3.7'", - "version": "==1.6.2" - }, - "brotlicffi": { - "hashes": [ - "sha256:0c248a68129d8fc6a217767406c731e498c3e19a7be05ea0a90c3c86637b7d96", - "sha256:137c4635edcdf593de5ce9d0daa596bf499591b16b8fca5fd72a490deb54b2ee", - "sha256:15e0db52c56056be6310fc116b3d7c6f34185594e261f23790b2fb6489998363", - "sha256:16a0c9392a1059e2e62839fbd037d2e7e03c8ae5da65e9746f582464f7fab1bb", - "sha256:1e27c43ef72a278f9739b12b2df80ee72048cd4cbe498f8bbe08aaaa67a5d5c8", - "sha256:21cd400d24b344c218d8e32b394849e31b7c15784667575dbda9f65c46a64b0a", - "sha256:2be4fb8a7cb482f226af686cd06d2a2cab164ccdf99e460f8e3a5ec9a5337da2", - "sha256:2e4629f7690ded66c8818715c6d4dd6a7ff6a4f10fad6186fe99850f781ce210", - "sha256:408c810c599786fb806556ff17e844a903884e6370ca400bcec7fa286149f39c", - "sha256:408ec4359f9763280d5c4e0ad29c51d1240b25fdd18719067e972163b4125b98", - "sha256:4454c3baedc277fd6e65f983e3eb8e77f4bc15060f69370a0201746e2edeca81", - "sha256:52c1c12dad6eb1d44213a0a76acf5f18f64653bd801300bef5e2f983405bdde5", - "sha256:551305703d12a2dd1ae43d3dde35dee20b1cb49b5796279d4d34e2c6aec6be4d", - "sha256:586f0ea3c2eed455d5f2330b9ab4a591514c8de0ee53d445645efcfbf053c69f", - "sha256:71061f8bc86335b652e442260c4367b782a92c6e295cf5a10eff84c7d19d8cf5", - "sha256:75a46bc5ed2753e1648cc211dcb2c1ac66116038766822dc104023f67ff4dfd8", - "sha256:7bb913d5bf3b4ce2ec59872711dc9faaff5f320c3c3827cada2d8a7b793a7753", - "sha256:7e72978f4090a161885b114f87b784f538dcb77dafc6602592c1cf39ae8d243d", - "sha256:8e7221d8a084d32d15c7b58e0ce0573972375c5038423dbe83f217cfe512e680", - "sha256:9030cd5099252d16bfa4e22659c84a89c102e94f8e81d30764788b72e2d7cfb7", - "sha256:9078432af4785f35ab3840587eed7fb131e3fc77eb2a739282b649b343c584dd", - "sha256:916b790f967a18a595e61f218c252f83718ac91f24157d622cf0fa710cd26ab7", - "sha256:94d2810efc5723f1447b332223b197466190518a3eeca93b9f357efb5b22c6dc", - "sha256:9e70f3e20f317d70912b10dbec48b29114d3dbd0e9d88475cb328e6c086f0546", - "sha256:a6208d82c3172eeeb3be83ed4efd5831552c7cd47576468e50fcf0fb23fcf97f", - "sha256:a73099858ee343e8801710a08be8d194f47715ff21e98d92a19ac461058f52d1", - "sha256:af8a1b7bcfccf9c41a3c8654994d6a81821fdfe4caddcfe5045bfda936546ca3", - "sha256:ba4a00263af40e875ec3d6c7f623cbf8c795b55705da18c64ec36b6bf0848bc5", - "sha256:df78aa47741122b0d5463f1208b7bb18bc9706dee5152d9f56e0ead4865015cd", - "sha256:feb942814285bdc5e97efc77a04e48283c17dfab9ea082d79c0a7b9e53ef1eab" - ], - "index": "pypi", - "version": "==1.0.9.2" - }, - "cffi": { - "hashes": [ - "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", - "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef", - "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104", - "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426", - "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405", - "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375", - "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a", - "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e", - "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc", - "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf", - "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185", - "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497", - "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3", - "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35", - "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c", - "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83", - "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21", - "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca", - "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984", - "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac", - "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd", - "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee", - "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a", - "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2", - "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192", - "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7", - "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585", - "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f", - "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e", - "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27", - "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b", - "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e", - "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e", - "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d", - "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c", - "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415", - "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82", - "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02", - "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314", - "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325", - "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c", - "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3", - "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914", - "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045", - "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d", - "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9", - "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5", - "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2", - "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c", - "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3", - "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2", - "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8", - "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d", - "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d", - "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9", - "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162", - "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76", - "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4", - "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e", - "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9", - "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6", - "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b", - "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", - "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0" - ], - "version": "==1.15.1" - }, - "click": { - "hashes": [ - "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd", - "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5" - ], - "markers": "python_version >= '3.7'", - "version": "==8.1.6" - }, - "decorator": { - "hashes": [ - "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", - "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" - ], - "index": "pypi", - "version": "==5.1.1" - }, - "flasgger": { - "hashes": [ - "sha256:ca098e10bfbb12f047acc6299cc70a33851943a746e550d86e65e60d4df245fb" - ], - "index": "pypi", - "version": "==0.9.7.1" - }, - "flask": { - "hashes": [ - "sha256:77fd4e1249d8c9923de34907236b747ced06e5467ecac1a7bb7115ae0e9670b0", - "sha256:8c2f9abd47a9e8df7f0c3f091ce9497d011dc3b31effcf4c85a6e2b50f4114ef" - ], - "index": "pypi", - "version": "==2.3.2" - }, - "gevent": { - "hashes": [ - "sha256:11b9bb0bce45170ff992760385a86e6955ccb88dba4a82a64d5ce9459290d8d6", - "sha256:1234849b0bc4df560924aa92f7c01ca3f310677735fb508a2b0d7a61bb946916", - "sha256:34086bcc1252ae41e1cb81cf13c4a7678031595c12f4e9a1c3d0ab433f20826a", - "sha256:369241d1a6a3fe3ef4eba454b71e0168026560c5344fc4bc37196867041982ac", - "sha256:3e0d76a7848726e0646324a1adc011355dcd91875e7913badd1ada2e5eeb8a6e", - "sha256:5b230007a665d2cf5cf8878c9f56a2b8bacbdc4fe0235afc5269b71cd00528e5", - "sha256:5da07d65dfa23fe419c37cea110bf951b42af6bf3a1fff244043a75c9185dbd5", - "sha256:6a51a8e3cdaa6901e47d56f84cb5f92b1bf3deea920bce69cf7a245df16159ac", - "sha256:6b3dd449c80814357f6568eb095a2be2421b805d59fa97c65094707e04a181f9", - "sha256:6bd9ea1b5fbdc7e5921a9e515f34a450eb3927a902253a33caedcce2d19d7d96", - "sha256:746a1e12f280dab07389e6709164b1e1a6caaf50493ea5b1dcaa73cff005174c", - "sha256:769e8811ded08fe7d8b09ad8ebb72d47aecc112411e0726e7296b7ed187ed629", - "sha256:76ca6f893953ab898ebbff5d772103318a85044e55d0bad401d6b49d71bb76e7", - "sha256:83b6d61a8e9da25edb304ca7fba19ee57bb1ffa801f9df3e668bfed7bb8386cb", - "sha256:8c284390f0f6d0b5be3bf805fa8e0ae1329065f2b0ac5af5423c67183197deb8", - "sha256:919423e803939726c99ab2d29ea46b8676af549cee72d263f2b24758ec607b2c", - "sha256:94b013587f7c4697d620c129627f7b12d7d9f6e40ab198635891ca2098cd8556", - "sha256:9c7c349aa23d67cf5cc3b2c87aaedcfead976d0577b1cfcd07ffeba63baba79c", - "sha256:a1d2f1e67d04fde47ca2deac89733df28ef3a7ec1d7359a79f57d4778cced16d", - "sha256:a226b42cb9a49580ca7729572a4f8289d1fa28cd2529c9f4eed3e14b995d1c9c", - "sha256:a8f62e8d37913512823923e05607a296389aeb50ccca8a271ae7cedb5b17faeb", - "sha256:add904a7ef960cd4e133e61eb7413982c5e4203928160be1c09752ac06a25e71", - "sha256:aeb1511cf0786152af741c47ee462dac81b57bbd1fbbe08ab562b6c8c9ad75ed", - "sha256:c1dba07207b15b371e50372369edf256a142cb5cdf8599849cbf8660327efa06", - "sha256:c92b837b60e850c50fc6d723d1e363e786d37fd9d51e564e07df52ad5e8a86d4", - "sha256:cea93f4f77badbddc711620cca164ad75c74056603908e621a5ba1b97adbc39c", - "sha256:d0d3630674c1b344b256a298ab1ff43220f840b12af768131b5d74e485924237", - "sha256:debc177e88a8c876cb1a4d974f985d03670177bdc61e1c084a8d525f1a50b12d", - "sha256:dec7b08daf08385fb281b81ec2e7e703243975d867f40ae0a8a3e30b380eb9ea", - "sha256:df4d7be3352126458cc818309ca6a3b678c209b1ae33e56b6975c6a8309f2068", - "sha256:f522b6b015f1bfa9d8d3716ddffb23e3d4a8933df3e4ebf0a29a65a9fa74382b" - ], - "index": "pypi", - "version": "==23.7.0" - }, - "greenlet": { - "hashes": [ - "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a", - "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a", - "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43", - "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33", - "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8", - "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088", - "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca", - "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343", - "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645", - "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db", - "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df", - "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3", - "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86", - "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2", - "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a", - "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf", - "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7", - "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394", - "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40", - "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3", - "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6", - "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74", - "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0", - "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3", - "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91", - "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5", - "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9", - "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8", - "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b", - "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6", - "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb", - "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73", - "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b", - "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df", - "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9", - "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f", - "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0", - "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857", - "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a", - "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249", - "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30", - "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292", - "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b", - "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d", - "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b", - "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c", - "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca", - "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7", - "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75", - "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae", - "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b", - "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470", - "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564", - "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9", - "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099", - "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0", - "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5", - "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19", - "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1", - "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526" - ], - "markers": "python_version < '3.12' and platform_python_implementation == 'CPython'", - "version": "==2.0.2" - }, - "gunicorn": { - "hashes": [ - "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0", - "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033" - ], - "index": "pypi", - "version": "==21.2.0" - }, - "importlib-metadata": { - "hashes": [ - "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb", - "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743" - ], - "markers": "python_version < '3.10'", - "version": "==6.8.0" - }, - "importlib-resources": { - "hashes": [ - "sha256:134832a506243891221b88b4ae1213327eea96ceb4e407a00d790bb0626f45cf", - "sha256:4359457e42708462b9626a04657c6208ad799ceb41e5c58c57ffa0e6a098a5d4" - ], - "markers": "python_version < '3.9'", - "version": "==6.0.1" - }, - "itsdangerous": { - "hashes": [ - "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", - "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a" - ], - "markers": "python_version >= '3.7'", - "version": "==2.1.2" - }, - "jinja2": { - "hashes": [ - "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", - "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" - ], - "markers": "python_version >= '3.7'", - "version": "==3.1.2" - }, - "jsonschema": { - "hashes": [ - "sha256:043dc26a3845ff09d20e4420d6012a9c91c9aa8999fa184e7efcfeccb41e32cb", - "sha256:6e1e7569ac13be8139b2dd2c21a55d350066ee3f80df06c608b398cdc6f30e8f" - ], - "markers": "python_version >= '3.8'", - "version": "==4.19.0" - }, - "jsonschema-specifications": { - "hashes": [ - "sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1", - "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb" - ], - "markers": "python_version >= '3.8'", - "version": "==2023.7.1" - }, - "markupsafe": { - "hashes": [ - "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e", - "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e", - "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431", - "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686", - "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559", - "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc", - "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c", - "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0", - "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4", - "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9", - "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575", - "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba", - "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d", - "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3", - "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00", - "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155", - "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac", - "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52", - "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f", - "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8", - "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b", - "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24", - "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea", - "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198", - "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0", - "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee", - "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be", - "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2", - "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707", - "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6", - "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58", - "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779", - "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636", - "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c", - "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad", - "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee", - "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc", - "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2", - "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48", - "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7", - "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e", - "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b", - "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa", - "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5", - "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e", - "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb", - "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9", - "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57", - "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc", - "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2" - ], - "markers": "python_version >= '3.7'", - "version": "==2.1.3" - }, - "meinheld": { - "hashes": [ - "sha256:1777b9ea8f2af6833baaaef122968ca67b61af17665df2adf2e24ccdbf209471" - ], - "index": "pypi", - "version": "==0.5" - }, - "mistune": { - "hashes": [ - "sha256:b9b3e438efbb57c62b5beb5e134dab664800bdf1284a7ee09e8b12b13eb1aac6", - "sha256:e912116c13aa0944f9dc530db38eb88f6a77087ab128f49f84a48f4c05ea163c" - ], - "markers": "python_version >= '3.7'", - "version": "==3.0.1" - }, - "packaging": { - "hashes": [ - "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", - "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" - ], - "markers": "python_version >= '3.7'", - "version": "==23.1" - }, - "pkgutil-resolve-name": { - "hashes": [ - "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174", - "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e" - ], - "markers": "python_version < '3.9'", - "version": "==1.3.10" - }, - "pycparser": { - "hashes": [ - "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", - "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" - ], - "version": "==2.21" - }, - "pyyaml": { - "hashes": [ - "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", - "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", - "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", - "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", - "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", - "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", - "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", - "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", - "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", - "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", - "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", - "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", - "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", - "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", - "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", - "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", - "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", - "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", - "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", - "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", - "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", - "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", - "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", - "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", - "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", - "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", - "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", - "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", - "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", - "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", - "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", - "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", - "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", - "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", - "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", - "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", - "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", - "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", - "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", - "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" - ], - "index": "pypi", - "version": "==6.0.1" - }, - "referencing": { - "hashes": [ - "sha256:449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf", - "sha256:794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0" - ], - "markers": "python_version >= '3.8'", - "version": "==0.30.2" - }, - "rpds-py": { - "hashes": [ - "sha256:0173c0444bec0a3d7d848eaeca2d8bd32a1b43f3d3fde6617aac3731fa4be05f", - "sha256:01899794b654e616c8625b194ddd1e5b51ef5b60ed61baa7a2d9c2ad7b2a4238", - "sha256:02938432352359805b6da099c9c95c8a0547fe4b274ce8f1a91677401bb9a45f", - "sha256:03421628f0dc10a4119d714a17f646e2837126a25ac7a256bdf7c3943400f67f", - "sha256:03975db5f103997904c37e804e5f340c8fdabbb5883f26ee50a255d664eed58c", - "sha256:0766babfcf941db8607bdaf82569ec38107dbb03c7f0b72604a0b346b6eb3298", - "sha256:07e2c54bef6838fa44c48dfbc8234e8e2466d851124b551fc4e07a1cfeb37260", - "sha256:0836d71ca19071090d524739420a61580f3f894618d10b666cf3d9a1688355b1", - "sha256:095b460e117685867d45548fbd8598a8d9999227e9061ee7f012d9d264e6048d", - "sha256:0e7521f5af0233e89939ad626b15278c71b69dc1dfccaa7b97bd4cdf96536bb7", - "sha256:0f2996fbac8e0b77fd67102becb9229986396e051f33dbceada3debaacc7033f", - "sha256:1054a08e818f8e18910f1bee731583fe8f899b0a0a5044c6e680ceea34f93876", - "sha256:13b602dc3e8dff3063734f02dcf05111e887f301fdda74151a93dbbc249930fe", - "sha256:141acb9d4ccc04e704e5992d35472f78c35af047fa0cfae2923835d153f091be", - "sha256:14c408e9d1a80dcb45c05a5149e5961aadb912fff42ca1dd9b68c0044904eb32", - "sha256:159fba751a1e6b1c69244e23ba6c28f879a8758a3e992ed056d86d74a194a0f3", - "sha256:190ca6f55042ea4649ed19c9093a9be9d63cd8a97880106747d7147f88a49d18", - "sha256:196cb208825a8b9c8fc360dc0f87993b8b260038615230242bf18ec84447c08d", - "sha256:1fcdee18fea97238ed17ab6478c66b2095e4ae7177e35fb71fbe561a27adf620", - "sha256:207f57c402d1f8712618f737356e4b6f35253b6d20a324d9a47cb9f38ee43a6b", - "sha256:24a81c177379300220e907e9b864107614b144f6c2a15ed5c3450e19cf536fae", - "sha256:29cd8bfb2d716366a035913ced99188a79b623a3512292963d84d3e06e63b496", - "sha256:2d8b3b3a2ce0eaa00c5bbbb60b6713e94e7e0becab7b3db6c5c77f979e8ed1f1", - "sha256:35da5cc5cb37c04c4ee03128ad59b8c3941a1e5cd398d78c37f716f32a9b7f67", - "sha256:44659b1f326214950a8204a248ca6199535e73a694be8d3e0e869f820767f12f", - "sha256:47c5f58a8e0c2c920cc7783113df2fc4ff12bf3a411d985012f145e9242a2764", - "sha256:4bd4dc3602370679c2dfb818d9c97b1137d4dd412230cfecd3c66a1bf388a196", - "sha256:4ea6b73c22d8182dff91155af018b11aac9ff7eca085750455c5990cb1cfae6e", - "sha256:50025635ba8b629a86d9d5474e650da304cb46bbb4d18690532dd79341467846", - "sha256:517cbf6e67ae3623c5127206489d69eb2bdb27239a3c3cc559350ef52a3bbf0b", - "sha256:5855c85eb8b8a968a74dc7fb014c9166a05e7e7a8377fb91d78512900aadd13d", - "sha256:5a46859d7f947061b4010e554ccd1791467d1b1759f2dc2ec9055fa239f1bc26", - "sha256:65a0583c43d9f22cb2130c7b110e695fff834fd5e832a776a107197e59a1898e", - "sha256:674c704605092e3ebbbd13687b09c9f78c362a4bc710343efe37a91457123044", - "sha256:682726178138ea45a0766907957b60f3a1bf3acdf212436be9733f28b6c5af3c", - "sha256:686ba516e02db6d6f8c279d1641f7067ebb5dc58b1d0536c4aaebb7bf01cdc5d", - "sha256:6a5d3fbd02efd9cf6a8ffc2f17b53a33542f6b154e88dd7b42ef4a4c0700fdad", - "sha256:6aa8326a4a608e1c28da191edd7c924dff445251b94653988efb059b16577a4d", - "sha256:700375326ed641f3d9d32060a91513ad668bcb7e2cffb18415c399acb25de2ab", - "sha256:71f2f7715935a61fa3e4ae91d91b67e571aeb5cb5d10331ab681256bda2ad920", - "sha256:745f5a43fdd7d6d25a53ab1a99979e7f8ea419dfefebcab0a5a1e9095490ee5e", - "sha256:79f594919d2c1a0cc17d1988a6adaf9a2f000d2e1048f71f298b056b1018e872", - "sha256:7d68dc8acded354c972116f59b5eb2e5864432948e098c19fe6994926d8e15c3", - "sha256:7f67da97f5b9eac838b6980fc6da268622e91f8960e083a34533ca710bec8611", - "sha256:83b32f0940adec65099f3b1c215ef7f1d025d13ff947975a055989cb7fd019a4", - "sha256:876bf9ed62323bc7dcfc261dbc5572c996ef26fe6406b0ff985cbcf460fc8a4c", - "sha256:890ba852c16ace6ed9f90e8670f2c1c178d96510a21b06d2fa12d8783a905193", - "sha256:8b08605d248b974eb02f40bdcd1a35d3924c83a2a5e8f5d0fa5af852c4d960af", - "sha256:8b2eb034c94b0b96d5eddb290b7b5198460e2d5d0c421751713953a9c4e47d10", - "sha256:8b9ec12ad5f0a4625db34db7e0005be2632c1013b253a4a60e8302ad4d462afd", - "sha256:8c8d7594e38cf98d8a7df25b440f684b510cf4627fe038c297a87496d10a174f", - "sha256:8d3335c03100a073883857e91db9f2e0ef8a1cf42dc0369cbb9151c149dbbc1b", - "sha256:8d70e8f14900f2657c249ea4def963bed86a29b81f81f5b76b5a9215680de945", - "sha256:9039a11bca3c41be5a58282ed81ae422fa680409022b996032a43badef2a3752", - "sha256:91378d9f4151adc223d584489591dbb79f78814c0734a7c3bfa9c9e09978121c", - "sha256:9251eb8aa82e6cf88510530b29eef4fac825a2b709baf5b94a6094894f252387", - "sha256:933a7d5cd4b84f959aedeb84f2030f0a01d63ae6cf256629af3081cf3e3426e8", - "sha256:978fa96dbb005d599ec4fd9ed301b1cc45f1a8f7982d4793faf20b404b56677d", - "sha256:987b06d1cdb28f88a42e4fb8a87f094e43f3c435ed8e486533aea0bf2e53d931", - "sha256:99b1c16f732b3a9971406fbfe18468592c5a3529585a45a35adbc1389a529a03", - "sha256:99e7c4bb27ff1aab90dcc3e9d37ee5af0231ed98d99cb6f5250de28889a3d502", - "sha256:9c439fd54b2b9053717cca3de9583be6584b384d88d045f97d409f0ca867d80f", - "sha256:9ea4d00850ef1e917815e59b078ecb338f6a8efda23369677c54a5825dbebb55", - "sha256:9f30d205755566a25f2ae0382944fcae2f350500ae4df4e795efa9e850821d82", - "sha256:a06418fe1155e72e16dddc68bb3780ae44cebb2912fbd8bb6ff9161de56e1798", - "sha256:a0805911caedfe2736935250be5008b261f10a729a303f676d3d5fea6900c96a", - "sha256:a1f044792e1adcea82468a72310c66a7f08728d72a244730d14880cd1dabe36b", - "sha256:a216b26e5af0a8e265d4efd65d3bcec5fba6b26909014effe20cd302fd1138fa", - "sha256:a987578ac5214f18b99d1f2a3851cba5b09f4a689818a106c23dbad0dfeb760f", - "sha256:aad51239bee6bff6823bbbdc8ad85136c6125542bbc609e035ab98ca1e32a192", - "sha256:ab2299e3f92aa5417d5e16bb45bb4586171c1327568f638e8453c9f8d9e0f020", - "sha256:ab6919a09c055c9b092798ce18c6c4adf49d24d4d9e43a92b257e3f2548231e7", - "sha256:b0c43f8ae8f6be1d605b0465671124aa8d6a0e40f1fb81dcea28b7e3d87ca1e1", - "sha256:b1440c291db3f98a914e1afd9d6541e8fc60b4c3aab1a9008d03da4651e67386", - "sha256:b52e7c5ae35b00566d244ffefba0f46bb6bec749a50412acf42b1c3f402e2c90", - "sha256:bf4151acb541b6e895354f6ff9ac06995ad9e4175cbc6d30aaed08856558201f", - "sha256:c27ee01a6c3223025f4badd533bea5e87c988cb0ba2811b690395dfe16088cfe", - "sha256:c545d9d14d47be716495076b659db179206e3fd997769bc01e2d550eeb685596", - "sha256:c5934e2833afeaf36bd1eadb57256239785f5af0220ed8d21c2896ec4d3a765f", - "sha256:c7671d45530fcb6d5e22fd40c97e1e1e01965fc298cbda523bb640f3d923b387", - "sha256:c861a7e4aef15ff91233751619ce3a3d2b9e5877e0fcd76f9ea4f6847183aa16", - "sha256:d25b1c1096ef0447355f7293fbe9ad740f7c47ae032c2884113f8e87660d8f6e", - "sha256:d55777a80f78dd09410bd84ff8c95ee05519f41113b2df90a69622f5540c4f8b", - "sha256:d576c3ef8c7b2d560e301eb33891d1944d965a4d7a2eacb6332eee8a71827db6", - "sha256:dd9da77c6ec1f258387957b754f0df60766ac23ed698b61941ba9acccd3284d1", - "sha256:de0b6eceb46141984671802d412568d22c6bacc9b230174f9e55fc72ef4f57de", - "sha256:e07e5dbf8a83c66783a9fe2d4566968ea8c161199680e8ad38d53e075df5f0d0", - "sha256:e564d2238512c5ef5e9d79338ab77f1cbbda6c2d541ad41b2af445fb200385e3", - "sha256:ed89861ee8c8c47d6beb742a602f912b1bb64f598b1e2f3d758948721d44d468", - "sha256:ef1f08f2a924837e112cba2953e15aacfccbbfcd773b4b9b4723f8f2ddded08e", - "sha256:f411330a6376fb50e5b7a3e66894e4a39e60ca2e17dce258d53768fea06a37bd", - "sha256:f68996a3b3dc9335037f82754f9cdbe3a95db42bde571d8c3be26cc6245f2324", - "sha256:f7fdf55283ad38c33e35e2855565361f4bf0abd02470b8ab28d499c663bc5d7c", - "sha256:f963c6b1218b96db85fc37a9f0851eaf8b9040aa46dec112611697a7023da535", - "sha256:fa2818759aba55df50592ecbc95ebcdc99917fa7b55cc6796235b04193eb3c55", - "sha256:fae5cb554b604b3f9e2c608241b5d8d303e410d7dfb6d397c335f983495ce7f6", - "sha256:fb39aca7a64ad0c9490adfa719dbeeb87d13be137ca189d2564e596f8ba32c07" - ], - "markers": "python_version >= '3.8'", - "version": "==0.9.2" - }, - "setuptools": { - "hashes": [ - "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f", - "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235" - ], - "markers": "python_version >= '3.7'", - "version": "==68.0.0" - }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "index": "pypi", - "version": "==1.16.0" - }, - "werkzeug": { - "hashes": [ - "sha256:935539fa1413afbb9195b24880778422ed620c0fc09670945185cce4d91a8890", - "sha256:98c774df2f91b05550078891dee5f0eb0cb797a522c757a2452b9cee5b202330" - ], - "index": "pypi", - "version": "==2.3.6" - }, - "zipp": { - "hashes": [ - "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0", - "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147" - ], - "markers": "python_version >= '3.8'", - "version": "==3.16.2" - }, - "zope.event": { - "hashes": [ - "sha256:2832e95014f4db26c47a13fdaef84cef2f4df37e66b59d8f1f4a8f319a632c26", - "sha256:bac440d8d9891b4068e2b5a2c5e2c9765a9df762944bda6955f96bb9b91e67cd" - ], - "markers": "python_version >= '3.7'", - "version": "==5.0" - }, - "zope.interface": { - "hashes": [ - "sha256:042f2381118b093714081fd82c98e3b189b68db38ee7d35b63c327c470ef8373", - "sha256:0ec9653825f837fbddc4e4b603d90269b501486c11800d7c761eee7ce46d1bbb", - "sha256:12175ca6b4db7621aedd7c30aa7cfa0a2d65ea3a0105393e05482d7a2d367446", - "sha256:1592f68ae11e557b9ff2bc96ac8fc30b187e77c45a3c9cd876e3368c53dc5ba8", - "sha256:23ac41d52fd15dd8be77e3257bc51bbb82469cf7f5e9a30b75e903e21439d16c", - "sha256:424d23b97fa1542d7be882eae0c0fc3d6827784105264a8169a26ce16db260d8", - "sha256:4407b1435572e3e1610797c9203ad2753666c62883b921318c5403fb7139dec2", - "sha256:48f4d38cf4b462e75fac78b6f11ad47b06b1c568eb59896db5b6ec1094eb467f", - "sha256:4c3d7dfd897a588ec27e391edbe3dd320a03684457470415870254e714126b1f", - "sha256:5171eb073474a5038321409a630904fd61f12dd1856dd7e9d19cd6fe092cbbc5", - "sha256:5a158846d0fca0a908c1afb281ddba88744d403f2550dc34405c3691769cdd85", - "sha256:6ee934f023f875ec2cfd2b05a937bd817efcc6c4c3f55c5778cbf78e58362ddc", - "sha256:790c1d9d8f9c92819c31ea660cd43c3d5451df1df61e2e814a6f99cebb292788", - "sha256:809fe3bf1a91393abc7e92d607976bbb8586512913a79f2bf7d7ec15bd8ea518", - "sha256:87b690bbee9876163210fd3f500ee59f5803e4a6607d1b1238833b8885ebd410", - "sha256:89086c9d3490a0f265a3c4b794037a84541ff5ffa28bb9c24cc9f66566968464", - "sha256:99856d6c98a326abbcc2363827e16bd6044f70f2ef42f453c0bd5440c4ce24e5", - "sha256:aab584725afd10c710b8f1e6e208dbee2d0ad009f57d674cb9d1b3964037275d", - "sha256:af169ba897692e9cd984a81cb0f02e46dacdc07d6cf9fd5c91e81f8efaf93d52", - "sha256:b39b8711578dcfd45fc0140993403b8a81e879ec25d53189f3faa1f006087dca", - "sha256:b3f543ae9d3408549a9900720f18c0194ac0fe810cecda2a584fd4dca2eb3bb8", - "sha256:d0583b75f2e70ec93f100931660328965bb9ff65ae54695fb3fa0a1255daa6f2", - "sha256:dfbbbf0809a3606046a41f8561c3eada9db811be94138f42d9135a5c47e75f6f", - "sha256:e538f2d4a6ffb6edfb303ce70ae7e88629ac6e5581870e66c306d9ad7b564a58", - "sha256:eba51599370c87088d8882ab74f637de0c4f04a6d08a312dce49368ba9ed5c2a", - "sha256:ee4b43f35f5dc15e1fec55ccb53c130adb1d11e8ad8263d68b1284b66a04190d", - "sha256:f2363e5fd81afb650085c6686f2ee3706975c54f331b426800b53531191fdf28", - "sha256:f299c020c6679cb389814a3b81200fe55d428012c5e76da7e722491f5d205990", - "sha256:f72f23bab1848edb7472309e9898603141644faec9fd57a823ea6b4d1c4c8995", - "sha256:fa90bac61c9dc3e1a563e5babb3fd2c0c1c80567e815442ddbe561eadc803b30" - ], - "markers": "python_version >= '3.7'", - "version": "==6.0" - } - }, - "develop": { - "packaging": { - "hashes": [ - "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", - "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" - ], - "markers": "python_version >= '3.7'", - "version": "==23.1" - }, - "platformdirs": { - "hashes": [ - "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d", - "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d" - ], - "version": "==3.10.0" - }, - "pytoolconfig": { - "extras": [ - "global" - ], - "hashes": [ - "sha256:239ba9d3e537b91d0243275a497700ea39a5e259ddb80421c366e3b288bf30fe", - "sha256:a50f9dfe23b03a9d40414c1fdf902fefbeae12f2ac75a3c8f915944d6ffac279" - ], - "markers": "python_version >= '3.7'", - "version": "==1.2.5" - }, - "rope": { - "hashes": [ - "sha256:2ed32d72cd2c4395bb1d569e38fd4f15d6080cfadd61b6e5c565fd39e3f677aa", - "sha256:f48d708132c0e062b411308732ca13933b976486b4b53d1e804f94ed08d69503" - ], - "index": "pypi", - "version": "==1.9.0" - }, - "tomli": { - "hashes": [ - "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" - ], - "markers": "python_version < '3.11'", - "version": "==2.0.1" - } - } -} diff --git a/README.md b/README.md index 3dc3b68b..292f3196 100644 --- a/README.md +++ b/README.md @@ -7,19 +7,73 @@ Why fork? we were unable to get ahold of the folks at postmanlabs to maintain t httpbin is a [Kenneth Reitz](http://kennethreitz.org/bitcoin) Project. ![ice cream](http://farm1.staticflickr.com/572/32514669683_4daf2ab7bc_k_d.jpg) -Run locally: +## Downloading and Running + ```sh -docker pull kennethreitz/httpbin -docker run -p 80:80 kennethreitz/httpbin +docker pull ghcr.io/psf/httpbin +docker run -p 80:8080 ghcr.io/psf/httpbin ``` -Some enviroments do not allow to bind to a privileged port. To run it on a -different port instead of port 80, set the environment variables as follows: +## Using `httpbin` as a Library + +`httpbin` can be used as a dependency in your own projects by simply adding +`httpbin` as a dependency. + +## Manually Building the Latest Docker Image + +To build the Docker image yourself, download the latest `Dockerfile` and +`requirements.txt` files from the [release page][release-page]. Store both file +in the same folder and run: ```sh -docker run -e HTTPIN_PORT=8000 -p 8000:8000 kennethreitz/httpbin +docker build --build-arg APP_VERSION= [other docker args] . ``` +Alternatively, you can re-generate a new `requirements.txt` file using +[pip-compile][pip-compile]. In that case, be aware that the code has not been +tested against those dependencies and we cannot guarantee that such an image +will run without errors. + +Where `APP_VERSION` will be stored in a docker-label. The default value is an +empty-string. + +[release-page]: https://github.com/psf/httpbin/releases +[pip-compile]: https://pip-tools.readthedocs.io/en/latest/ + +## Maintenance + +### "Extra" Dependencies + +The project provides two "extras" which contain dependencies that should only +be installed for specific use-cases. They will not be included when using +`httpbin` as a dependency, unless they are *explicitly* requested like +`httpbin[mainapp]`. + +* `mainapp`: Includes everything needed to run `httpbin` as a standalone app. + This is used by the docker image. +* `test`: Includes additional dependencies for unit-testing. This is only used + during development. + +### Publishing a new Release + +Releases (both docker and pypi) are automated via GitHub Actions (See #17). + +For *pypi* releases, the project uses [trusted-publishing][tp] via [the official +GitHub action][pypi-action]. + +For releases on *docker-hub* (when enabled in the CI), the following two +secrets are required: + +* `DOCKERHUB_USERNAME` +* `DOCKERHUB_TOKEN` + +Releases are triggered on commits tagged with `release-` (for example +`release-0.10.0`). + +[tp]: https://docs.pypi.org/trusted-publishers/ +[pypi-action]: https://github.com/pypa/gh-action-pypi-publish + + ## Changelog * 0.10.0: - Override docker image port with HTTPBIN_PORT diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index a7765f7b..00000000 --- a/docker-compose.yml +++ /dev/null @@ -1,6 +0,0 @@ -version: '2' -services: - httpbin: - build: '.' - ports: - - '80:80' \ No newline at end of file diff --git a/httpbin.bash b/httpbin.bash index 6fe976d1..e9ee1520 100644 --- a/httpbin.bash +++ b/httpbin.bash @@ -1,5 +1,5 @@ #!/bin/bash -exec gunicorn \ - -b ${HTTPBIN_HOST:-0.0.0.0}:${HTTPBIN_PORT:-80} \ +exec /opt/httpbin/bin/gunicorn \ + -b ${HTTPBIN_HOST:-0.0.0.0}:${HTTPBIN_PORT:-8080} \ -k gevent \ httpbin:app diff --git a/httpbin/core.py b/httpbin/core.py index 098620fd..a1afb425 100644 --- a/httpbin/core.py +++ b/httpbin/core.py @@ -54,10 +54,12 @@ from .utils import weighted_choice from .structures import CaseInsensitiveDict -with open( - os.path.join(os.path.realpath(os.path.dirname(__file__)), "VERSION") -) as version_file: - version = version_file.read().strip() +try: + from importlib.metadata import version as get_version +except ImportError: + from importlib_metadata import version as get_version + +version = get_version("httpbin") ENV_COOKIES = ( "_gauges_unique", diff --git a/pyproject.toml b/pyproject.toml index fed528d4..73f3f41c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,54 @@ [build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" + +[project.urls] +pypi = "https://pypi.org/project/httpbin/" +Repository = "https://github.com/psf/httpbin" + +[project] +name = "httpbin" +version = "0.10.0" +requires-python = ">=3.7" +description = "HTTP Request and Response Service" +readme = "README.md" +license = {text = "MIT or ISC"} +authors = [ + {name = "Kenneth Reitz", email = "me@kennethreitz.org"}, +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Natural Language :: English", + "License :: OSI Approved :: ISC License (ISCL)", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] +dependencies = [ + "Flask", + "brotlicffi", + "decorator", + "flasgger", + 'greenlet < 3.0; python_version<"3.12"', + 'greenlet >= 3.0.0a1; python_version>="3.12.0rc0"', + 'importlib-metadata; python_version<"3.8"', + "werkzeug >= 0.14.1", + "six", +] + +[project.optional-dependencies] +test = ["pytest", "tox"] +mainapp = [ + "gunicorn", + "gevent", +] + +[tool.setuptools.packages.find] +where = ["."] +include = ["httpbin*"] diff --git a/setup.py b/setup.py deleted file mode 100644 index 34a21785..00000000 --- a/setup.py +++ /dev/null @@ -1,41 +0,0 @@ -from setuptools import setup, find_packages -import os -import io - - -with open(os.path.join(os.path.realpath(os.path.dirname(__file__)), 'httpbin', 'VERSION')) as version_file: - version = version_file.read().strip() - -setup( - name="httpbin", - version=version, - description="HTTP Request and Response Service", - long_description="A simple HTTP Request & Response Service, written in Python + Flask.", - - # The project URL. - url='https://pypi.org/project/httpbin/', - - # Author details - author='Kenneth Reitz', - author_email='me@kennethreitz.org', - - # Choose your license - license='MIT', - - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Natural Language :: English', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.6', - ], - test_suite="test_httpbin", - packages=find_packages(exclude=["tests"]), - include_package_data = True, # include files listed in MANIFEST.in - install_requires=[ - 'Flask', 'MarkupSafe', 'decorator', 'itsdangerous', 'brotlicffi', - 'werkzeug', 'flasgger', 'jinja2' - ], -) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 70613be0..00000000 --- a/test-requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pytest==7.4.0 diff --git a/tests/test_httpbin.py b/tests/test_httpbin.py index db8d9ab7..54d72b1b 100755 --- a/tests/test_httpbin.py +++ b/tests/test_httpbin.py @@ -178,8 +178,8 @@ def test_post_binary(self): self.assertEqual(response.status_code, 200) def test_post_body_text(self): - with open('httpbin/core.py') as f: - response = self.app.post('/post', data={"file": f.read()}) + fake_contents = "this is some fake payload" + response = self.app.post('/post', data={"file": fake_contents}) self.assertEqual(response.status_code, 200) def test_post_body_binary(self): diff --git a/tox.ini b/tox.ini index 9a782253..519d325e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,16 +1,7 @@ [tox] -envlist = py27,py36,py37,py38,py39,py310,py311,py312,pypy3 +envlist = py37,py38,py39,py310,py311,py312,pypy3 [testenv] +extras = test commands = - python -m unittest -v tests/test_httpbin.py - -[testenv:release] -skipdist = true -usedevelop = false -deps = - twine>=1.6.0 - wheel -commands = - python setup.py sdist bdist_wheel - twine upload --skip-existing dist/* + pytest tests