From 0b385b2d135baa12e8eda1eac9f406c8b59d10a1 Mon Sep 17 00:00:00 2001 From: devsjc <47188100+devsjc@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:10:42 +0000 Subject: [PATCH] Add ci pipeline --- .github/workflows/ci.yml | 170 ++++++++++++++++++ .gitignore | 160 +++++++++++++++++ Containerfile | 15 +- pyproject.toml | 8 +- src/fake_api.egg-info/PKG-INFO | 35 ---- src/fake_api.egg-info/SOURCES.txt | 18 -- src/fake_api.egg-info/dependency_links.txt | 1 - src/fake_api.egg-info/entry_points.txt | 2 - src/fake_api.egg-info/requires.txt | 15 -- src/fake_api.egg-info/top_level.txt | 1 - .../__pycache__/__init__.cpython-312.pyc | Bin 2234 -> 0 bytes .../cmd/__pycache__/__init__.cpython-312.pyc | Bin 156 -> 0 bytes .../cmd/__pycache__/main.cpython-312.pyc | Bin 701 -> 0 bytes src/fake_api/cmd/main.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 362 -> 0 bytes .../__pycache__/models.cpython-312.pyc | Bin 2676 -> 0 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 298 -> 0 bytes .../__pycache__/dummydb.cpython-312.pyc | Bin 8938 -> 0 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 228 -> 0 bytes .../__pycache__/server.cpython-312.pyc | Bin 3236 -> 0 bytes 20 files changed, 341 insertions(+), 85 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore delete mode 100644 src/fake_api.egg-info/PKG-INFO delete mode 100644 src/fake_api.egg-info/SOURCES.txt delete mode 100644 src/fake_api.egg-info/dependency_links.txt delete mode 100644 src/fake_api.egg-info/entry_points.txt delete mode 100644 src/fake_api.egg-info/requires.txt delete mode 100644 src/fake_api.egg-info/top_level.txt delete mode 100644 src/fake_api/__pycache__/__init__.cpython-312.pyc delete mode 100644 src/fake_api/cmd/__pycache__/__init__.cpython-312.pyc delete mode 100644 src/fake_api/cmd/__pycache__/main.cpython-312.pyc delete mode 100644 src/fake_api/internal/__pycache__/__init__.cpython-312.pyc delete mode 100644 src/fake_api/internal/__pycache__/models.cpython-312.pyc delete mode 100644 src/fake_api/internal/inputs/__pycache__/__init__.cpython-312.pyc delete mode 100644 src/fake_api/internal/inputs/__pycache__/dummydb.cpython-312.pyc delete mode 100644 src/fake_api/internal/service/__pycache__/__init__.cpython-312.pyc delete mode 100644 src/fake_api/internal/service/__pycache__/server.cpython-312.pyc diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2531c18 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,170 @@ +name: Python CI + +on: + push: + branches: [] + paths-ignore: + - 'README.md' + tags: + - 'v*' + pull_request: + branches: [] + paths-ignore: + - 'README.md' + workflow_dispatch: + +# Specify concurrency such that only one workflow can run at a time +# * Different workflow files are not affected +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# Registry for storing Container images +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +# Ensure the GitHub token can remove packages +permissions: + packages: write + + +jobs: + + # Define a dependencies job that runs on all branches and PRs + # * Installs dependencies and caches them + build-venv: + runs-on: ubuntu-latest + container: debian:12-slim + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Restore cached virtualenv, if available + # * The pyproject.toml hash is part of the cache key, invalidating + # the cache if the file changes + - name: Restore cached virtualenv + id: restore-cache + uses: actions/cache/restore@v3 + with: + path: .venv + key: ${{ runner.os }}-venv-${{ hashFiles('**/pyproject.toml') }} + + # Should mirror the build-venv stage in the Containerfile + - name: Build venv + run: | + apt -qq update && apt -qq install -y python3-venv gcc libpython3-dev + python3 -m venv .venv + .venv/bin/python -m pip install --upgrade -q pip wheel setuptools + if: steps.restore-cache.outputs.cache-hit != 'true' + + # Should mirror the build-reqs stage in the Containerfile + # * Except this installs the dev dependencies and binaries as well + - name: Install all dependencies + run: .venv/bin/python -m pip install .[test] + if: steps.restore-cache.outputs.cache-hit != 'true' + + # Cache the virtualenv for future runs + - name: Cache virtualenv + uses: actions/cache/save@v3 + with: + path: .venv + key: ${{ steps.restore-cache.outputs.cache-primary-key }} + if: steps.restore-cache.outputs.cache-hit != 'true' + + # Define a unittest job that runs on all branches and PRs + test-unit: + runs-on: ubuntu-latest + container: debian:12-slim + needs: build-venv + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install libpython3-dev + run: apt -qq update && apt -qq install -y python3-venv libpython3-dev + + # Restore cached virtualenv, if available + - name: Restore cached virtualenv + id: restore-cache + uses: actions/cache/restore@v3 + with: + path: .venv + key: ${{ runner.os }}-venv-${{ hashFiles('**/pyproject.toml') }} + fail-on-cache-miss: true + + # Run unittests + # * Produce JUnit XML report + - name: Run unit tests + run: | + .venv/bin/python3 -m xmlrunner discover -s src/fake_api -p "test_*.py" --output-file ut-report.xml + + # Create test summary to be visualised on the job summary screen on GitHub + # * Runs even if previous steps fail + - name: Create test summary + uses: test-summary/action@v2 + with: + paths: "*t-report.xml" + show: "fail, skip" + if: always() + + # Define a "build-container" job that runs on branch commits only + # * Builds and pushes an OCI Container image to the registry defined in the environment variables + # * Only runs if test job passes + build-container: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + needs: test-unit + if: github.event_name != 'pull_request' + + steps: + # Do a non-shallow clone of the repo to ensure tags are present + # * This allows setuptools-git-versioning to automatically set the version + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Buildx + uses: docker/setup-buildx-action@v2 + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Tag the built image according to the event type + # * If the event is a valid version tag, use the tag name + # * If the event is a branch commit, use the commit sha + - name: Extract metadata (tags, labels) for Container + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=semver,pattern={{version}} + + # Build and push the Container image to the registry + # * Creates a multiplatform-aware image + # * Semantic versioning is handled via the meta action + # * The image layers are cached between action runs + - name: Build and push Container image + uses: docker/build-push-action@v4 + with: + context: . + file: Containerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64,linux/arm64 + cache-from: type=gha + cache-to: type=gha,mode=max + key: ${{ runner.os }}-venv-${{ hashFiles('**/pyproject.toml') }} + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..925f070 --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifestutoPairsReturnutoPairsReturnutoPairsReturnutoPairsReturn +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ diff --git a/Containerfile b/Containerfile index 040f36a..839b4a7 100644 --- a/Containerfile +++ b/Containerfile @@ -1,13 +1,13 @@ # Build a virtualenv using venv # * Install required compilation tools for wheels via apt -FROM python:3.11-slim AS build-venv -RUN apt -qq update && apt -qq install -y build-essential -RUN python3 -m venv /venv -RUN /venv/bin/pip install --upgrade -q pip wheel setuptools +FROM debian:12-slim AS build +RUN apt -qq update && apt -qq install -y python3-venv gcc libpython3-dev && \ + python3 -m venv /venv && \ + /venv/bin/pip install --upgrade -q pip setuptools wheel # Install packages into the virtualenv as a separate step # * Only re-execute this step when the requirements files change -FROM build-venv AS install-deps +FROM build AS install-deps WORKDIR /app COPY pyproject.toml pyproject.toml RUN /venv/bin/pip install -q . --no-cache-dir --no-binary=fake_api @@ -21,12 +21,13 @@ COPY src src COPY .git .git COPY README.md README.md RUN /venv/bin/pip install . +RUN ls /venv/bin # Copy the virtualenv into a distroless image # * These are small images that only contain the runtime dependencies -FROM gcr.io/distroless/python3-debian11 -WORKDIR /app +FROM gcr.io/distroless/python3-debian12 COPY --from=build-app /venv /venv +WORKDIR /app HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8000/health || exit 1 ENTRYPOINT ["/venv/bin/fake-api"] diff --git a/pyproject.toml b/pyproject.toml index 8be70af..b4a4d50 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ # --- PROJECT CONFIGURATION --- # [build-system] -requires = ["setuptools>=67", "wheel", "setuptools-git-versioning>=1.13.3"] +requires = ["setuptools>=69", "wheel", "setuptools-git-versioning>=1.13.3"] build-backend = "setuptools.build_meta" # Metadata (see https://peps.python.org/pep-0621/) @@ -18,7 +18,6 @@ authors = [ classifiers = ["Programming Language :: Python :: 3"] dependencies = [ "fastapi >= 0.105.0", - "numpy >= 1.23.2", "structlog >= 23.2.0", "uvicorn >= 0.24.0", ] @@ -53,12 +52,9 @@ enabled = true # MyPy configuration # * See https://mypy.readthedocs.io/en/stable/index.html [tool.mypy] -python_version = "3.12" +python_version = "3.11" warn_return_any = true disallow_untyped_defs = true -plugins = [ - 'numpy.typing.mypy_plugin' -] # Ruff configuration # * See https://beta.ruff.rs/docs/ diff --git a/src/fake_api.egg-info/PKG-INFO b/src/fake_api.egg-info/PKG-INFO deleted file mode 100644 index 3c2fe88..0000000 --- a/src/fake_api.egg-info/PKG-INFO +++ /dev/null @@ -1,35 +0,0 @@ -Metadata-Version: 2.1 -Name: fake-api -Version: 0.0.1 -Summary: Fake API for wind and solar data -Author-email: Sol Cotton -License: MIT License -Project-URL: repository, https://github.com/openclimatefix/fake-api -Classifier: Programming Language :: Python :: 3 -Requires-Python: >=3.11.0 -Description-Content-Type: text/markdown -Requires-Dist: fastapi>=0.105.0 -Requires-Dist: numpy>=1.23.2 -Requires-Dist: structlog>=23.2.0 -Requires-Dist: uvicorn>=0.24.0 -Provides-Extra: test -Requires-Dist: unittest-xml-reporting==3.2.0; extra == "test" -Provides-Extra: lint -Requires-Dist: mypy>=1.7.1; extra == "lint" -Requires-Dist: python-lsp-server>=1.9.0; extra == "lint" -Requires-Dist: ruff>=0.1.7; extra == "lint" -Provides-Extra: dev -Requires-Dist: fake-api[lint,test]; extra == "dev" - -# Fake API - -Defines a fake API to help with building frontends. - -## Running the service - -Clone the repository, -and create a new virtual environment with your favorite environment manager. -Install the dependencies with -``` - -``` diff --git a/src/fake_api.egg-info/SOURCES.txt b/src/fake_api.egg-info/SOURCES.txt deleted file mode 100644 index efedbb0..0000000 --- a/src/fake_api.egg-info/SOURCES.txt +++ /dev/null @@ -1,18 +0,0 @@ -README.md -pyproject.toml -src/fake_api/__init__.py -src/fake_api.egg-info/PKG-INFO -src/fake_api.egg-info/SOURCES.txt -src/fake_api.egg-info/dependency_links.txt -src/fake_api.egg-info/entry_points.txt -src/fake_api.egg-info/requires.txt -src/fake_api.egg-info/top_level.txt -src/fake_api/cmd/__init__.py -src/fake_api/cmd/main.py -src/fake_api/internal/__init__.py -src/fake_api/internal/models.py -src/fake_api/internal/inputs/__init__.py -src/fake_api/internal/inputs/dummydb.py -src/fake_api/internal/inputs/test_dummydb.py -src/fake_api/internal/service/__init__.py -src/fake_api/internal/service/server.py \ No newline at end of file diff --git a/src/fake_api.egg-info/dependency_links.txt b/src/fake_api.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/src/fake_api.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/fake_api.egg-info/entry_points.txt b/src/fake_api.egg-info/entry_points.txt deleted file mode 100644 index 169f356..0000000 --- a/src/fake_api.egg-info/entry_points.txt +++ /dev/null @@ -1,2 +0,0 @@ -[console_scripts] -run-api = fake_api.cmd.main:run diff --git a/src/fake_api.egg-info/requires.txt b/src/fake_api.egg-info/requires.txt deleted file mode 100644 index b964a72..0000000 --- a/src/fake_api.egg-info/requires.txt +++ /dev/null @@ -1,15 +0,0 @@ -fastapi>=0.105.0 -numpy>=1.23.2 -structlog>=23.2.0 -uvicorn>=0.24.0 - -[dev] -fake-api[lint,test] - -[lint] -mypy>=1.7.1 -python-lsp-server>=1.9.0 -ruff>=0.1.7 - -[test] -unittest-xml-reporting==3.2.0 diff --git a/src/fake_api.egg-info/top_level.txt b/src/fake_api.egg-info/top_level.txt deleted file mode 100644 index ce2c741..0000000 --- a/src/fake_api.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -fake_api diff --git a/src/fake_api/__pycache__/__init__.cpython-312.pyc b/src/fake_api/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index e1174494096f32958a5ecf2207f7839fdeca2e88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2234 zcmb7EJ#5=n5Ptj>Wl^>)%dX=ZsE|5HWVlx10Cny3&$VSkfhq;I(iQ>&f)<|@Dimov z(ka{}PM21blc`Hl6rEDoL&r`*_I5C#0#sj?0GYb62+$!z(W4xuZYdAp@Q(N0eRtoT zsP{`UIe_5#?%|hsRYd4%;Dk^7#mlq5IfTAJ8mb|U(O842F+I!H*q-HTT+i|~o<*2# z_9})&j;+RN`~iFX-c0^C7I+6Qpjr$w%~UiFXu2<&>5GoN0y^F|ccL#k8AUbWTd6jL z`DQj6YrYx9!byQK6^%B}N3l~fFGMq&(^2dd*fUXfgFRr5(NiXzjdD)ucqy8xiHETh z_51DPa+DQrup!hYFxPxLn$cW{Vj+vX(Li|O2L@CwMzfmlMX`{1pQ)wIjhF0xYCnjw zHA#yf4us$S{h)6@=7&+{skzJ1TrF`Zhnoy^!vBzOu0->C_-Yi#LpXK@;IIZxA0|W1 z4BBOLgI`RStVTmO8`-*LZt0C3qB^=|X16Sob#CIUy1i}a^&U3+N6?^5rBY?BRQRM& zqI|KuTFFUNT3#j>(e*VdmMhhb zLX~p5ZRHrsZM7U4Yhl|~8<>g;zKu->@BxCi4YiJy&D|=vaoZw}atrU;IhH0rC!h`! zrEaLUO$WA#Rfhr=v2#;2rYM?KR}>mEj_0GSWmC@HwV{YZcIpn`RBT`eo42X36BHtF zA0i?I2i%#6#DXKZEqlsIaQ~4698^|JwS}uz31k{nv>naRH|gXx%hrSCsm2m%?6hD4 zd(|Q>)p4NqNI)E0Rt*D^@HLe{1;Cdy4HG&X!Kt)bEEUR29~Y=tDwYf73Qek-rhsb2 z=(SB$^%mZ6)D|eG!|+nSRW!G(b!hJivZWg^7JN|3rnO`C z1UE4G5j}(X(ewHIbsG~q4-M=2m0%7F+)w$)SPnpsRyG+{8Wd}pMa-be!9cY_@jwY_6QC86Nry} zwRm^Y<1#Ln`HdU%MJ_FN;}bpy_K7sSpKK>R>6|N_>qzIJby~c8)lUg8a==24Cr!H2 zq$lNEDfb}vNIH^o9jWLG5QV+Q(_wtZm1g`{fJ!IOfc4W#kF(&%A-V?*5R=)9duYT( kBi;1;y_}bxchmDf%a1;D-zj&}u=F#32^_LriN$F_FkS)Hw|Ov zQYOVT<1v%2BE=F_Rey%%vR)tP@E-RFAAuCJJgomVRCVYewI-yBrzvE&|MP7B2IE^Ka zIExA)D2t{8&#dfq!^#u|6MDq&V5wZ^AL%53@MPMN|h^ z2T@7_y< None: if __name__ == "__main__": run() + diff --git a/src/fake_api/internal/__pycache__/__init__.cpython-312.pyc b/src/fake_api/internal/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index cdd7b2c67495e7bf778522e61a679bbc126d5685..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 362 zcmXv~Jx{|h5Vd2cMbJnvvIPkVWuW;32tk#F1$AK{i)HL=7+|3@uOc3%`oZZLLLKzzlRf0h15-2oCu~<<^K5VS%iV$Qe^(pENWF`LG25mQbJHuLtBwp2pY9ml+|W;oNUX`5W`6Hu)<5QQ zLkLD|auZh+gdVd+GGNU|=R26Tk&UXz7HrWKssf+Is)VIAE!Ij+BD#)jX$#r%t{83a z#?q>Cf`tMWYLA7=y=6eAVPP$wIwod!rHH9&4Y81I7R$Kic$n(JD%Q<<-E}N8aC}c+ z_igM_-SlkT@d8Y0riE$ocV=9%VqbiU{h`hkSZ*VX057VFOMo5_%UH3+S&(o}>T+_I zQyAA!3z=}NJpUfSwqpg@{?Ng$-Fz#3JKGFQ%QY$0Yd+EIiKgCQs(O9Hb+N72h`+9z zI`ub*g^OW^`+4_vsNHhb@sj6!7Uq{c3zNVERE-7yemI(1-*8q|D?4ha8HQ)BW5WoC z32Fh1Qd-B^+_4BNM0TLMqvs9~6%=LbA^)G&5XhehYfTxp47LQB+ltx_4^ z!>(V)q*OCM!I#XsQ=-J;3xh3qpgq$qMZquD8$<>toMeEZ&jI-o{U+Z$$c=3-?B~Zf z7x&Lh{UlHAPfq_VPm}RPyMKl*g7`EUYRCm8%$4V_S^?mVQZajcDon0+QXU9v4x$37 zkSt@z7~!{_VBDF6uq`?YgrR&VLAkXU=`yt=$e2eqItM@wkwula#(R~C4~H#c)s}Du zYiD7zCfo9s-0ik3mQS=9ifxpX&F}!5HXJWQ4=kG$-%MJv zc{!aIUO=ogHK2%-*!Q+A}T z6IKP`iz_%Vx_xbMhX(I%YCy{yiKFK0Jz*%G(sTyS>9AJ%9JN)H&GEV#i2IFR+;PpH z7BqPl&O8G40=seKfXbM_xlUg<>{XYqeSJfBM9akp%~+8!{f|eIs&dz$P@OQ zkzqzg7|8(%C3D#d^X4)Q2>4sa!K!bE60Aa*b!hbYU_~E2vClJ(7sq+VJ@pDd!}b_q z?;QOB$QF7e&mSn-FUnL)nQDuol6xSv5lnmX!^OL;8z2A4799zx(_GrtkeW?tfBym3 zesF8=QtRzIgOq8c96Vh3sCE7BAnj|Bc6skyt9<)V`44u>=zGDi6tX;08es&KZAfIxi2e48&PxD$aVnZFUR9K^p)O{#VP diff --git a/src/fake_api/internal/inputs/__pycache__/__init__.cpython-312.pyc b/src/fake_api/internal/inputs/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index fdf4272bb63c05691472c99c13cce0fe2a6d0903..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 298 zcmXv~y-LJD5Z+Bra-0MNyR!*m6T#aT5J3otjo8?v8TPUh4Q{ewHxXhdK7`NUv)I_0 zN)QXJgzK(y_Rz1G`F@yTn3p)7F~axGBWmg&Ui>5YBda-)C#G1=6jy=fb&v;~sqmWT z;V?ClGcUZj&T z0#K#^7$fC#wcI4$mRbWmvz0$*eI~AG$O&h3Au_x}ZCbRVl(%>!+e$cFYy@~wH67YU zY9ejlIRQ{LRR^$WhxPQhHmcWnV*LmFZEly!PsllcV~3w?|9yM@I@^1Q?3Dap(Iiu+ diff --git a/src/fake_api/internal/inputs/__pycache__/dummydb.cpython-312.pyc b/src/fake_api/internal/inputs/__pycache__/dummydb.cpython-312.pyc deleted file mode 100644 index 9d69cc8a649aa0ef4059584616f74052a710bc52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8938 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 j3 diff --git a/src/fake_api/internal/service/__pycache__/__init__.cpython-312.pyc b/src/fake_api/internal/service/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index a54ebae5d925e2f56030a2de49b850c5d71245b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 228 zcmX@j%ge<81m+UWsfIxMF^B^LOi;#WF(6|)LkdF*V-7*H4oPOy6RUk5A0WiH~2&@EK&*FAx1tpt559;{2RseV5d- z)SUc+)FS<~#Ozev#DYxy;-X|QCmzJf%qvMP%1g}A2br9ioT?umpP83g5+AQuQ2C3) pCO1E&G$+-rhy!Ra$PLB(K;i>4BO~Ko2B`_u!qF#xh%ImG|~ diff --git a/src/fake_api/internal/service/__pycache__/server.cpython-312.pyc b/src/fake_api/internal/service/__pycache__/server.cpython-312.pyc deleted file mode 100644 index 1439df468f9b550085a43755e35fa488710330db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3236 zcmeHJU2GFa5Z=49&p(NAoF9{f1PnwWb|Ho+B@rN`K!^zRCy=DH=I3Q{%_LQ&=B1rI$BAo_ikG%8 z9cgE8c4zi>c6Ppd&dLb?( zEFnw68nSY1+!7ZPwva7h57`rrkb^@!!j_whi-epYIbz;Lv7lShD8)AHQmlJm4m)G@ z1uBc5ig*)t!bq`UcZ65$A1|+8wu+6T$i`V<<5|U~WXYx!mn$x4?0=%Nrogsh6oUHd|K9Vw`yP#k;9mlb?)mSSc!%Wtb7o~afOOebvSA0lvhqKa6u{(Y$S;qX3OS@ zhYtbTJi7%~%-}}3UgQ@>YmaK0;lrvjtVLDB7tzSl#;Elmj>k1>J*JVkGL6U@wgNP? z&=u_0G0}s%77qtI@fjS~hA|07{AY!z0u| zu&hV~wm>|vt{a-p*d)q|$W=LYELBpUveXkcHfjqFVmWRMuIyPOs4&kA=yMcfUKf$+ zH9uN+&|GO{zljBm{Jh!Gl7oGHJyOf|?b5r4%>yv^LdrmemJMJ-%Iyh!fVh%M7_Ne* zGnR9r>hs8qw<+yyN|pFi7Jtr_#^7L7H#8CrOGY$-;b5Xz502?tl7#U@aE#!AsHRT9 zO)y7TOxZxV&?A<%W=yY|X*+->_;K)ms0ksmw%`<)P7#fBxA^?^o#53LuoGUfvlbbF zSY+o_EaT`4^d)bIdEJ;j|FzsJ)@yt(8s|IFWg*NDpfG>(eS{{2aUo`c(y}J|GD`Du zjNP{)im_`_L>}_ z3+{e(NY&1&zTA!QP4m=>3DJmoO~HaUMk$&Ws5rtvK{toVdf3#oi?E>3Ms{0=^Uxu& zA4xe~39?>V`r($p>Y2Y^Nimlnm1cglLVoP)=#-8gIMRQhw~yNU;8ypm(GLNX3~E4W<0yno?Q>SQl4EI&*6*WtiwIk_S8{p zPVG*6c0YVC<=LI_yme6o7^>cK{mk{jR8{bqw{FI}BkkSs(khfWvq*3_v!!U`mfr-v z!a2LH?#9Ni0@H!7$=$I#V|UNpIrn(elg3Alx6ftTj?Ar{3<{9