├── .gimlet └── electric-paper-taxi-data-api-python.yaml ├── .github └── workflows │ └── ci_cd.yml ├── .gitignore ├── Dockerfile.1stage ├── Dockerfile.2stage ├── Dockerfile.naive ├── Makefile ├── README.md ├── docker-compose.yml ├── media ├── kibana.gif ├── kubernetes_cluster.gif └── yt_cover.png ├── poetry.lock ├── pyproject.toml ├── src ├── __init__.py ├── api.py ├── backend.py ├── config.py ├── middleware.py └── utils.py ├── taxi-data-api-rust ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── Makefile ├── README.md └── src │ ├── backend.rs │ └── main.rs └── tests ├── __init__.py └── test_read_parquet.py /.gimlet/electric-paper-taxi-data-api-python.yaml: -------------------------------------------------------------------------------- 1 | app: taxi-data-api-python 2 | env: electric-paper 3 | namespace: default 4 | chart: 5 | repository: https://chart.onechart.dev 6 | name: onechart 7 | version: 0.70.0 8 | values: 9 | containerPort: 8000 10 | gitRepository: Paulescu/taxi-data-api-python 11 | gitSha: '{{ .SHA }}' 12 | image: 13 | context: . 14 | dockerfile: "" 15 | registry: public 16 | repository: ghcr.io/paulescu/taxi-data-api-python 17 | strategy: dynamic 18 | tag: '{{ .SHA }}' 19 | ingress: 20 | annotations: 21 | cert-manager.io/cluster-issuer: letsencrypt 22 | kubernetes.io/ingress.class: nginx 23 | host: paulescu-taxi-data-api-python-ayolbhnl.gimlet.app 24 | tlsEnabled: true 25 | resources: 26 | ignoreLimits: true 27 | -------------------------------------------------------------------------------- /.github/workflows/ci_cd.yml: -------------------------------------------------------------------------------- 1 | name: CI/CD 2 | on: 3 | push: 4 | branches: 5 | - '*' 6 | paths-ignore: 7 | - 'README.md' 8 | jobs: 9 | cancel-previous-runs: 10 | name: 🧹 Cancel previous runs 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: 🛑 Cancel Previous Runs 14 | uses: styfle/cancel-workflow-action@0.10.1 15 | with: 16 | access_token: ${{ secrets.GITHUB_TOKEN }} 17 | - name: ⬇️ Check out 18 | uses: actions/checkout@v3 19 | - run: echo "Building" 20 | 21 | tests: 22 | name: 🧪 Run tests 23 | runs-on: ubuntu-latest 24 | needs: 25 | - "cancel-previous-runs" 26 | steps: 27 | - name: ⬇️ Check out 28 | uses: actions/checkout@v4 29 | - name: 🐍 Set up Python 3.10 30 | uses: actions/setup-python@v4 31 | with: 32 | python-version: '3.10' 33 | - name: 📦 Install Poetry 34 | uses: snok/install-poetry@v1 35 | - name: 📦 Install dependencies 36 | run: poetry install 37 | - name: 🧪 Run tests 38 | run: poetry run pytest tests/ 39 | 40 | docker-build: 41 | name: 📦 Docker build 42 | runs-on: ubuntu-latest 43 | needs: 44 | - "tests" 45 | steps: 46 | - name: ⬇️ Check out 47 | uses: actions/checkout@v4 48 | - name: 🐋 Set up Docker Buildx 49 | uses: docker/setup-buildx-action@v3 50 | - name: Login to GitHub Container Registry 51 | uses: docker/login-action@v3 52 | with: 53 | registry: ghcr.io 54 | username: ${{ github.repository_owner }} 55 | password: ${{ secrets.PAT }} # `PAT` is a secret that contains your Personal Access Token with `write:packages` scope 56 | - name: 🐋 Build and push docker image 57 | uses: docker/build-push-action@v6 58 | with: 59 | context: . 60 | file: Dockerfile.2stage 61 | platforms: linux/amd64 62 | push: true 63 | tags: ghcr.io/paulescu/taxi-data-api-python:${{ github.sha }} 64 | 65 | deploy: 66 | name: 🧑‍🚀 Deploy 67 | runs-on: ubuntu-latest 68 | needs: 69 | - "docker-build" 70 | if: github.ref == 'refs/heads/main' 71 | environment: production 72 | steps: 73 | - name: ⬇️ Check out 74 | uses: actions/checkout@v4 75 | - name: 🚀 Deploy / Production 76 | uses: gimlet-io/gimlet-artifact-shipper-action@v0.9.0 77 | with: 78 | DEPLOY: "true" 79 | ENV: "electric-paper" 80 | APP: "taxi-data-api-python" 81 | env: 82 | GIMLET_SERVER: ${{ secrets.GIMLET_SERVER }} 83 | GIMLET_TOKEN: ${{ secrets.GIMLET_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | .ruff_cache/ 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | #build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | cover/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff:import comet_ml 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | .pybuilder/ 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # poetry 99 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 100 | # This is especially recommended for binary packages to ensure reproducibility, and is more 101 | # commonly ignored for libraries. 102 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 103 | #poetry.lock 104 | 105 | # pdm 106 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 107 | #pdm.lock 108 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 109 | # in version control. 110 | # https://pdm.fming.dev/#use-with-ide 111 | .pdm.toml 112 | 113 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 114 | __pypackages__/ 115 | 116 | # Celery stuff 117 | celerybeat-schedule 118 | celerybeat.pid 119 | 120 | # SageMath parsed files 121 | *.sage.py 122 | 123 | # Environments 124 | .env 125 | .venv 126 | env/ 127 | venv/ 128 | ENV/ 129 | env.bak/ 130 | venv.bak/ 131 | 132 | # Spyder project settings 133 | .spyderproject 134 | .spyproject 135 | 136 | # Rope project settings 137 | .ropeproject 138 | 139 | # mkdocs documentation 140 | /site 141 | 142 | # mypy 143 | .mypy_cache/ 144 | .dmypy.json 145 | dmypy.json 146 | 147 | # Pyre type checker 148 | .pyre/ 149 | 150 | # pytype static type analyzer 151 | .pytype/ 152 | 153 | # Cython debug symbols 154 | cython_debug/ 155 | 156 | # PyCharm 157 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 158 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 159 | # and can be added to the global gitignore or merged into this file. For a more nuclear 160 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 161 | #.idea/ 162 | 163 | # VSCode 164 | .vscode/* 165 | !.vscode/settings.json 166 | !.vscode/tasks.json 167 | !.vscode/launch.json 168 | !.vscode/extensions.json 169 | !.vscode/*.code-snippets 170 | 171 | # Local History for Visual Studio Code 172 | .history/ 173 | 174 | # Built Visual Studio Code Extensions 175 | *.vsix 176 | 177 | # Artifacts 178 | results/ 179 | output*/ 180 | model_cache/ 181 | output* 182 | user_data.sh 183 | 184 | set_env_variables.sh 185 | logs/ 186 | .DS_Store 187 | gradio_cached_examples 188 | trust_policy.json 189 | 190 | .TODOS 191 | ca.cert 192 | *.pkl 193 | **/state 194 | **/setup_credentials.sh 195 | *.csv 196 | **/credentials.env 197 | .venv/ 198 | certificates/ 199 | **.parquet -------------------------------------------------------------------------------- /Dockerfile.1stage: -------------------------------------------------------------------------------- 1 | # Use the official Python image from the Docker Hub 2 | FROM python:3.10-slim 3 | 4 | # Set environment variables 5 | ENV PYTHONDONTWRITEBYTECODE=1 6 | ENV PYTHONUNBUFFERED=1 7 | 8 | # Set the working directory 9 | WORKDIR /app 10 | 11 | # Install Poetry 12 | RUN pip install poetry 13 | 14 | # Copy only the pyproject.toml and poetry.lock files to leverage Docker cache 15 | COPY pyproject.toml poetry.lock README.md /app/ 16 | 17 | # Install dependencies 18 | RUN poetry install --no-root 19 | 20 | # Copy the rest of the application code 21 | COPY . /app 22 | 23 | # Expose the port the app runs on 24 | EXPOSE 8000 25 | 26 | # Run the application 27 | CMD ["poetry", "run", "uvicorn", "src.api:app", "--host", "0.0.0.0", "--port", "8000"] 28 | -------------------------------------------------------------------------------- /Dockerfile.2stage: -------------------------------------------------------------------------------- 1 | # Stage 1: Build stage 2 | FROM python:3.10-slim AS builder 3 | 4 | # Set environment variables 5 | ENV PYTHONDONTWRITEBYTECODE=1 6 | ENV PYTHONUNBUFFERED=1 7 | 8 | # Set the working directory 9 | WORKDIR /app 10 | 11 | # Install Poetry 12 | RUN pip install poetry 13 | 14 | # Copy only the pyproject.toml and poetry.lock files to leverage Docker cache 15 | COPY pyproject.toml poetry.lock README.md /app/ 16 | 17 | # Install dependencies 18 | RUN poetry config virtualenvs.create false \ 19 | && poetry install --no-dev --no-root 20 | 21 | # Copy the rest of the application code 22 | COPY . /app 23 | 24 | # Stage 2: Runtime stage 25 | FROM python:3.10-slim 26 | 27 | # Set environment variables 28 | ENV PYTHONDONTWRITEBYTECODE=1 29 | ENV PYTHONUNBUFFERED=1 30 | 31 | # Set the working directory 32 | WORKDIR /app 33 | 34 | # Copy only the necessary files from the builder stage 35 | COPY --from=builder /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages 36 | COPY --from=builder /usr/local/bin /usr/local/bin 37 | COPY --from=builder /app /app 38 | 39 | # Expose the port the app runs on 40 | EXPOSE 8000 41 | 42 | # Run the application 43 | CMD ["uvicorn", "src.api:app", "--host", "0.0.0.0", "--port", "8000"] -------------------------------------------------------------------------------- /Dockerfile.naive: -------------------------------------------------------------------------------- 1 | # Use the official Python image from the Docker Hub 2 | FROM python:3.10-slim 3 | 4 | # Set environment variables 5 | ENV PYTHONDONTWRITEBYTECODE=1 6 | ENV PYTHONUNBUFFERED=1 7 | 8 | # Set the working directory 9 | WORKDIR /app 10 | 11 | # Install Poetry 12 | RUN pip install poetry 13 | 14 | # Copy application code into the image 15 | COPY . /app 16 | 17 | # Install dependencies 18 | RUN poetry install --no-root 19 | 20 | # Expose the port the app runs on 21 | EXPOSE 8000 22 | 23 | # Run the application 24 | CMD ["poetry", "run", "uvicorn", "src.api:app", "--host", "0.0.0.0", "--port", "8000"] 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # feel free to change the PORT value if you have another service running on port 8092 2 | export PORT=8095 3 | 4 | install: 5 | @echo "Downloading and installing Python Poetry" 6 | curl -sSL https://install.python-poetry.org | python3 - 7 | poetry env use $(shell which python3.10) 8 | poetry install 9 | 10 | run-dev: 11 | poetry run uvicorn src.api:app --reload --port $(PORT) 12 | 13 | build-naive: 14 | @echo "Building naive image" 15 | @time docker build -f Dockerfile.naive -t taxi-data-api-python:naive-build . 16 | 17 | @echo "Naive image size" 18 | @docker images --format "{{.Size}}" taxi-data-api-python:naive-build 19 | 20 | build-single-stage: 21 | @echo "Building single-stage image" 22 | @time docker build -f Dockerfile.1stage -t taxi-data-api-python:single-stage-build . 23 | 24 | @echo "Single-stage image size" 25 | @docker images --format "{{.Size}}" taxi-data-api-python:single-stage-build 26 | 27 | build-multi-stage: 28 | @echo "Building multi-stage image" 29 | @time docker build -f Dockerfile.2stage -t taxi-data-api-python:multi-stage-build . 30 | 31 | @echo "Multi-stage image size" 32 | @docker images --format "{{.Size}}" taxi-data-api-python:multi-stage-build 33 | 34 | build: build-multi-stage 35 | 36 | run: build 37 | docker run \ 38 | -e ELASTICSEARCH_HOST=http://elasticsearch:9200 \ 39 | -e ELASTICSEARCH_INDEX=taxi_data_api \ 40 | --network elasticsearch \ 41 | -p $(PORT):8000 \ 42 | taxi-data-api-python:multi-stage-build 43 | 44 | test: 45 | poetry run pytest tests/ 46 | 47 | lint: 48 | poetry run ruff check --fix . 49 | 50 | format: 51 | poetry run ruff format . 52 | 53 | all: lint format test build run 54 | 55 | # Commands to check the API works as expected when running locally 56 | health-check-local: 57 | curl -X GET "http://localhost:$(PORT)/health" 58 | 59 | sample-request-local: 60 | curl -X GET "http://localhost:$(PORT)/trips?from_ms=1674561748000&n_results=100" 61 | 62 | sample-request-no-results-local: 63 | curl -X GET "http://localhost:$(PORT)/trips?from_ms=1727430298000&n_results=100" 64 | 65 | many-requests-local: 66 | @N=$${N:-10}; \ 67 | for i in $$(seq 1 $$N); do \ 68 | echo "Request $$i:"; \ 69 | $(MAKE) sample-request-local; \ 70 | echo; \ 71 | done 72 | 73 | # Commands to check the API from the production environment works as expected 74 | health-check-production: 75 | curl -X GET "https://paulescu-taxi-data-api-python-ayolbhnl.gimlet.app/health" 76 | 77 | sample-request-production: 78 | curl -X GET "https://paulescu-taxi-data-api-python-ayolbhnl.gimlet.app/trips?from_ms=1674561748000&n_results=100" 79 | 80 | sample-request-no-results-production: 81 | curl -X GET "https://paulescu-taxi-data-api-python-ayolbhnl.gimlet.app/trips?from_ms=1727430298000&n_results=100" 82 | 83 | # Command to check the size of the local Docker images 84 | check-image-sizes: build-naive build-single-stage build-multi-stage 85 | @echo "Naive image size" 86 | @docker images --format "{{.Size}}" taxi-data-api-python:naive-build 87 | 88 | @echo "Single-stage image size" 89 | @docker images --format "{{.Size}}" taxi-data-api-python:single-stage-build 90 | 91 | @echo "Multi-stage image size" 92 | @docker images --format "{{.Size}}" taxi-data-api-python:multi-stage-build 93 | 94 | # Commands to start and stop the Elasticsearch and Kibana containers 95 | start-infra: 96 | docker compose up -d 97 | 98 | stop-infra: 99 | docker compose down -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

Real-World ML

3 |

Build and deploy a professional REST API to Kubernetes with Gimlet 🚀

4 | 5 |
6 | 7 |
8 | 9 | Deploy to Kubernetes with Gimlet 10 |

Click here to watch the video 🎬

11 |
12 |
13 | 14 | 15 | #### Table of contents 16 | * [Our goal 🎯](#our-goal) 17 | * [How to run the API locally? 🏃](#how-to-run-the-api-locally) 18 | * [How to deploy the API to Kubernetes with Gimlet? 🚀](#how-to-deploy-the-api-to-kubernetes-with-gimlet) 19 | * [How to monitor our API with Elasticsearch and Kibana? 🔎](#how-to-monitor-our-api-with-elasticsearch-and-kibana) 20 | * [See it in action 🎬](#see-it-in-action) 21 | * [Wanna learn more real-world ML? 🧠](#wanna-learn-more-real-world-ml) 22 | 23 | ## Our goal 24 | 25 | Let’s **build** and **deploy** a production-ready REST API that can serve data on historical taxi rides in NYC. 26 | 27 | The original data is stored in one-month parquet files [on this website](https://www.nyc.gov/site/tlc/about/tlc-trip-record-data.page), and our goal is to make it easily accessible to the WORLD through a REST API. 28 | 29 | 30 | ## How to run the API locally? 31 | 32 | Git clone this repository, cd into the root directory of the project and then run the following commands using make. 33 | 34 | 1. Install [Python Poetry](https://python-poetry.org/docs/#installation) (if necessary) 35 | and create an isolated virtual environmnet for development purposes. 36 | ``` 37 | $ make install 38 | ``` 39 | 40 | 2. Test, build and run the dockerized REST API with 41 | ``` 42 | $ make all 43 | ``` 44 | 45 | 3. Check the API is up and running locally, and that you can connect to it 46 | ``` 47 | $ make health-check-local 48 | ``` 49 | 50 | 4. Send a sample request to the local API 51 | ``` 52 | $ make sample-request-local 53 | ``` 54 | 55 | Good job. The API is up and running locally. However, until you don’t deploy it to a production environment, and make it accessible to 56 | 57 | * your clients 💁🏻‍♀️ 58 | * your colleagues 👨🏻‍💼 59 | * or the whole world 🌏 60 | 61 | your real-world impact is **ZERO**. 62 | 63 | Let me show you how to deploy this API to a production Kubernetes cluster. 64 | 65 | 66 | > **What is Kubernetes? ☸📦** 67 | > 68 | > Kubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of your Dockerized apps 69 | > 70 | > It is currently the most widely used container orchestration platform in the world, and it has become the de facto standard due to its robust features, large community support, and backing from major tech companies. 71 | 72 | ## How to deploy the API to Kubernetes with Gimlet? 73 | 74 | [Gimlet](https://gimlet.io/) is a tool that helps you quickly deploy your apps to ANY Kubernetes cluster. 75 | 76 | - You can do it entirely from the Gimlet UI, as explained in this article. 77 | 78 | or 79 | 80 | - You can adjust the [gimlet manifest in this repository](https://github.com/Paulescu/taxi-data-api-python/blob/main/.gimlet/electric-paper-taxi-data-api-python.yaml), to automatically deploy your code changes to the main branch. 81 | 82 | ## How to monitor our API with Elasticsearch and Kibana? 83 | 84 | These are the steps: 85 | 86 | 1. Spin up Elasticsearch and Kibana with the docker compose 87 | 2. Add middleware to FastAPI app 88 | 3. Build a dashboard with Kibana 89 | 90 | 91 | 92 | ## See it in action 93 | 94 | [👉🏽 Click here to try the API](https://paulescu-taxi-data-api-python-ayolbhnl.gimlet.app/trips?from_ms=1674561817000&n_results=100) 95 | 96 | 97 | ## Wanna learn more real-world ML? 98 | 99 | Join more than 19k builders to the [**Real-World ML Newsletter**](https://www.realworldml.net/subscribe). Every Saturday morning. 100 | 101 | ### [👉🏽 Click here to subscribe for FREE](https://www.realworldml.net/subscribe) 102 | 103 | ### [**👉🏽 My live courses on Real World ML**](https://www.realworldml.net/courses) 104 | 105 | 106 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | name: elastic_search_and_kibana 2 | 3 | services: 4 | elasticsearch: 5 | image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0 6 | container_name: elasticsearch 7 | environment: 8 | - discovery.type=single-node 9 | - ES_JAVA_OPTS=-Xms512m -Xmx512m 10 | ports: 11 | - "9200:9200" 12 | - "9300:9300" 13 | volumes: 14 | - elasticsearch_data:/usr/share/elasticsearch/data 15 | networks: 16 | - elasticsearch 17 | 18 | kibana: 19 | image: docker.elastic.co/kibana/kibana:7.14.0 20 | container_name: kibana 21 | ports: 22 | - "5601:5601" 23 | environment: 24 | - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 25 | depends_on: 26 | - elasticsearch 27 | volumes: 28 | - kibana_data:/usr/share/kibana/data 29 | networks: 30 | - elasticsearch 31 | 32 | networks: 33 | elasticsearch: 34 | driver: bridge 35 | name: elasticsearch 36 | 37 | volumes: 38 | elasticsearch_data: 39 | kibana_data: 40 | -------------------------------------------------------------------------------- /media/kibana.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paulescu/taxi-data-api-python/1ec743d2626c26a785ea624a8d231f6c84f245ae/media/kibana.gif -------------------------------------------------------------------------------- /media/kubernetes_cluster.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paulescu/taxi-data-api-python/1ec743d2626c26a785ea624a8d231f6c84f245ae/media/kubernetes_cluster.gif -------------------------------------------------------------------------------- /media/yt_cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paulescu/taxi-data-api-python/1ec743d2626c26a785ea624a8d231f6c84f245ae/media/yt_cover.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "src" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Paulescu "] 6 | readme = "README.md" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.10" 10 | fastapi = {extras = ["all"], version = "^0.115.2"} 11 | uvicorn = "^0.30.6" 12 | loguru = "^0.7.2" 13 | pandas = "^2.2.3" 14 | requests = "^2.32.3" 15 | fastparquet = "^2024.5.0" 16 | fire = "^0.6.0" 17 | pyarrow = "^17.0.0" 18 | elasticsearch = "^8.15.1" 19 | 20 | 21 | [tool.poetry.group.dev.dependencies] 22 | ruff = "^0.6.8" 23 | pytest = "^8.3.3" 24 | 25 | [build-system] 26 | requires = ["poetry-core"] 27 | build-backend = "poetry.core.masonry.api" 28 | 29 | [tool.ruff] 30 | line-length = 88 31 | 32 | [tool.ruff.format] 33 | quote-style = "single" 34 | indent-style = "space" 35 | docstring-code-format = true 36 | 37 | [tool.ruff.lint] 38 | extend-select = ["I"] -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paulescu/taxi-data-api-python/1ec743d2626c26a785ea624a8d231f6c84f245ae/src/__init__.py -------------------------------------------------------------------------------- /src/api.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from fastapi import FastAPI, Query 4 | from loguru import logger 5 | from pydantic import BaseModel 6 | 7 | from src.backend import Trip, get_trips 8 | from src.middleware import TimingMiddleware 9 | 10 | app = FastAPI() 11 | 12 | app.add_middleware(TimingMiddleware) 13 | 14 | 15 | class TripsResponse(BaseModel): 16 | trips: Optional[list[Trip]] = None 17 | next_from_ms: Optional[int] = None 18 | message: Optional[str] = None 19 | 20 | 21 | @app.get('/trips', response_model=TripsResponse) 22 | def get_trip( 23 | from_ms: int = Query(..., description='Unix milliseconds'), 24 | n_results: int = Query(100, description='Number of results to output'), 25 | ): 26 | # Log the received parameters 27 | logger.info( 28 | f'Received request with params from_ms: {from_ms}, n_results: {n_results}' 29 | ) 30 | 31 | # get the trips from the backend 32 | trips: list[Trip] = get_trips(from_ms, n_results) 33 | 34 | # format the response object TripsResponse 35 | if len(trips) > 0: 36 | return TripsResponse( 37 | trips=trips, 38 | next_from_ms=trips[-1].tpep_pickup_datetime_ms, 39 | message=f'Success. Returned {len(trips)} trips.', 40 | ) 41 | else: 42 | return TripsResponse(message='No trips found for the given time range.') 43 | 44 | 45 | @app.get('/health') 46 | def health_check(): 47 | return {'status': 'Healthy!!!'} 48 | -------------------------------------------------------------------------------- /src/backend.py: -------------------------------------------------------------------------------- 1 | import os 2 | from datetime import datetime 3 | from typing import Optional 4 | 5 | import pandas as pd 6 | import requests 7 | from loguru import logger 8 | from pydantic import BaseModel 9 | 10 | CACHE_DIR = os.getenv('CACHE_DIR', '/tmp/taxi-data-api-python/') 11 | if not os.path.exists(CACHE_DIR): 12 | os.makedirs(CACHE_DIR) 13 | 14 | 15 | class Trip(BaseModel): 16 | tpep_pickup_datetime: datetime 17 | tpep_dropoff_datetime: datetime 18 | trip_distance: float 19 | fare_amount: float 20 | 21 | @property 22 | def tpep_pickup_datetime_ms(self) -> int: 23 | return int(self.tpep_pickup_datetime.timestamp() * 1000) 24 | 25 | 26 | def get_trips(from_ms: int, n_results: int) -> list[Trip]: 27 | """ 28 | Returns a list of sorted trips from the given from_ms timestamp, with a maximum of n_results. 29 | The trips are returned in chronological order. 30 | 31 | Args: 32 | from_ms: The timestamp in milliseconds to start the search from. 33 | n_results: The maximum number of results to return. 34 | 35 | Returns: 36 | A list of trips. 37 | """ 38 | from src.utils import get_year_and_month 39 | 40 | year, month = get_year_and_month(from_ms) 41 | logger.info(f'Extracted year: {year}, month: {month}') 42 | 43 | # load parquet file with the data 44 | df: Optional[pd.DataFrame] = read_parquet_file(year, month) 45 | 46 | if df is None: 47 | logger.info(f'No trips found for the given year: {year}, month: {month}') 48 | return [] 49 | 50 | # Convert datetime to Unix timestamp in milliseconds 51 | df['tpep_pickup_datetime_ms'] = ( 52 | df['tpep_pickup_datetime'].astype(int) / 10**3 53 | ).astype(int) 54 | 55 | # filter df to only include rows where tpep_pickup_datetime_ms is greater than from_ms 56 | df = df[df['tpep_pickup_datetime_ms'] > from_ms] 57 | 58 | # get the first n_results rows 59 | df = df.head(n_results) 60 | 61 | # convert df to list of Trip 62 | trips = df.to_dict(orient='records') 63 | trips = [Trip(**trip) for trip in trips] 64 | 65 | # Uncomment to test the API with a delay 66 | # from time import sleep 67 | # sleep(0.3) 68 | 69 | return trips 70 | 71 | 72 | def download_parquet_file(year: int, month: int): 73 | """ 74 | Download the parquet file for the given year and month from the NYC Taxi and Limousine Commission. 75 | 76 | https://www.nyc.gov/site/tlc/about/tlc-trip-record-data.page 77 | 78 | Args: 79 | year: The year to download the file for. 80 | month: The month to download the file for. 81 | """ 82 | # URL to download the file from 83 | url = f'https://d37ci6vzurychx.cloudfront.net/trip-data/yellow_tripdata_{year}-{month:02d}.parquet' 84 | 85 | # Download the file 86 | response = requests.get(url) 87 | if response.status_code == 200: 88 | with open(f'{CACHE_DIR}/yellow_tripdata_{year}-{month:02d}.parquet', 'wb') as f: 89 | f.write(response.content) 90 | logger.info(f'Downloaded file: yellow_tripdata_{year}-{month:02d}.parquet') 91 | else: 92 | logger.info(f'Failed to download file: {response.status_code}') 93 | 94 | 95 | def read_parquet_file(year: int, month: int) -> Optional[pd.DataFrame]: 96 | """ 97 | Read the parquet file for the given year and month. 98 | 99 | Args: 100 | year: The year to read the file for. 101 | month: The month to read the file for. 102 | 103 | Returns: 104 | A pandas DataFrame with the data, or None if the file couldn't be read. 105 | """ 106 | # check if the file exists 107 | if not os.path.exists(f'{CACHE_DIR}/yellow_tripdata_{year}-{month:02d}.parquet'): 108 | logger.info(f'File not found: yellow_tripdata_{year}-{month:02d}.parquet') 109 | logger.info(f'Downloading file: yellow_tripdata_{year}-{month:02d}.parquet') 110 | download_parquet_file(year, month) 111 | 112 | logger.info(f'Reading file: yellow_tripdata_{year}-{month:02d}.parquet') 113 | try: 114 | df = pd.read_parquet( 115 | f'{CACHE_DIR}/yellow_tripdata_{year}-{month:02d}.parquet', engine='pyarrow' 116 | ) 117 | except Exception as e: 118 | logger.info(f'Failed to read file: {e}') 119 | return None 120 | 121 | # filter the df to only include the columns we need 122 | df = df[ 123 | [ 124 | 'tpep_pickup_datetime', 125 | 'tpep_dropoff_datetime', 126 | 'trip_distance', 127 | 'fare_amount', 128 | ] 129 | ] 130 | 131 | # filter rows where tpep_pickup_datetime is in that year and month 132 | df = df[df['tpep_pickup_datetime'].dt.year == year] 133 | df = df[df['tpep_pickup_datetime'].dt.month == month] 134 | 135 | # sort the df by tpep_pickup_datetime 136 | df = df.sort_values(by='tpep_pickup_datetime') 137 | 138 | return df 139 | 140 | 141 | if __name__ == '__main__': 142 | # used for debugging purposes 143 | # import argparse 144 | 145 | # # argparse 146 | # parser = argparse.ArgumentParser() 147 | # parser.add_argument("--year", type=int, required=True) 148 | # parser.add_argument("--month", type=int, required=True) 149 | # args = parser.parse_args() 150 | 151 | # df = read_parquet_file(args.year, args.month) 152 | 153 | # # df = read_parquet_file(2023, 2) 154 | # print(df.head()) 155 | # print(df.tail()) 156 | 157 | trips = get_trips(from_ms=1674561748000, n_results=100) 158 | -------------------------------------------------------------------------------- /src/config.py: -------------------------------------------------------------------------------- 1 | from pydantic import Field 2 | from pydantic_settings import BaseSettings 3 | 4 | 5 | class ElasticsearchConfig(BaseSettings): 6 | host: str = Field(default='http://localhost:9200', alias='ELASTICSEARCH_HOST') 7 | index: str = Field(default='taxi_data_api', alias='ELASTICSEARCH_INDEX') 8 | 9 | 10 | elasticsearch_config = ElasticsearchConfig() 11 | -------------------------------------------------------------------------------- /src/middleware.py: -------------------------------------------------------------------------------- 1 | import time 2 | from datetime import datetime 3 | 4 | from elasticsearch import Elasticsearch 5 | from fastapi import Request 6 | from loguru import logger 7 | from starlette.middleware.base import BaseHTTPMiddleware 8 | 9 | from src.config import elasticsearch_config 10 | 11 | # Initialize Elasticsearch client 12 | es = Elasticsearch([elasticsearch_config.host]) 13 | 14 | 15 | class TimingMiddleware(BaseHTTPMiddleware): 16 | async def dispatch(self, request: Request, call_next): 17 | if request.url.path == '/trips': 18 | start_time = time.time() 19 | response = await call_next(request) 20 | process_time = time.time() - start_time 21 | 22 | # Log to Elasticsearch 23 | try: 24 | es.index( 25 | index=elasticsearch_config.index, 26 | body={ 27 | 'endpoint': '/trips', 28 | 'method': request.method, 29 | 'process_time': process_time, 30 | 'timestamp': datetime.utcnow().isoformat(), 31 | }, 32 | ) 33 | except Exception as e: 34 | logger.error(f'Error logging to Elasticsearch: {e}') 35 | 36 | return response 37 | 38 | return await call_next(request) 39 | -------------------------------------------------------------------------------- /src/utils.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Tuple 3 | 4 | 5 | def get_year_and_month(from_ms: int) -> Tuple[int, int]: 6 | """ 7 | Get the year and month from a given Unix milliseconds timestamp. 8 | 9 | Args: 10 | from_ms (int): Unix milliseconds timestamp. 11 | 12 | Returns: 13 | Tuple[int, int]: Year and month. 14 | """ 15 | # Convert from_ms to a datetime object 16 | dt = datetime.fromtimestamp(from_ms / 1000) 17 | 18 | # Extract year and month 19 | year = dt.year 20 | month = dt.month 21 | 22 | return year, month 23 | -------------------------------------------------------------------------------- /taxi-data-api-rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "actix-codec" 7 | version = "0.5.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" 10 | dependencies = [ 11 | "bitflags", 12 | "bytes", 13 | "futures-core", 14 | "futures-sink", 15 | "memchr", 16 | "pin-project-lite", 17 | "tokio", 18 | "tokio-util", 19 | "tracing", 20 | ] 21 | 22 | [[package]] 23 | name = "actix-http" 24 | version = "3.9.0" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "d48f96fc3003717aeb9856ca3d02a8c7de502667ad76eeacd830b48d2e91fac4" 27 | dependencies = [ 28 | "actix-codec", 29 | "actix-rt", 30 | "actix-service", 31 | "actix-utils", 32 | "ahash", 33 | "base64 0.22.1", 34 | "bitflags", 35 | "brotli 6.0.0", 36 | "bytes", 37 | "bytestring", 38 | "derive_more", 39 | "encoding_rs", 40 | "flate2", 41 | "futures-core", 42 | "h2 0.3.26", 43 | "http 0.2.12", 44 | "httparse", 45 | "httpdate", 46 | "itoa", 47 | "language-tags", 48 | "local-channel", 49 | "mime", 50 | "percent-encoding", 51 | "pin-project-lite", 52 | "rand", 53 | "sha1", 54 | "smallvec", 55 | "tokio", 56 | "tokio-util", 57 | "tracing", 58 | "zstd", 59 | ] 60 | 61 | [[package]] 62 | name = "actix-macros" 63 | version = "0.2.4" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" 66 | dependencies = [ 67 | "quote", 68 | "syn 2.0.85", 69 | ] 70 | 71 | [[package]] 72 | name = "actix-router" 73 | version = "0.5.3" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" 76 | dependencies = [ 77 | "bytestring", 78 | "cfg-if", 79 | "http 0.2.12", 80 | "regex", 81 | "regex-lite", 82 | "serde", 83 | "tracing", 84 | ] 85 | 86 | [[package]] 87 | name = "actix-rt" 88 | version = "2.10.0" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" 91 | dependencies = [ 92 | "futures-core", 93 | "tokio", 94 | ] 95 | 96 | [[package]] 97 | name = "actix-server" 98 | version = "2.5.0" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "7ca2549781d8dd6d75c40cf6b6051260a2cc2f3c62343d761a969a0640646894" 101 | dependencies = [ 102 | "actix-rt", 103 | "actix-service", 104 | "actix-utils", 105 | "futures-core", 106 | "futures-util", 107 | "mio", 108 | "socket2", 109 | "tokio", 110 | "tracing", 111 | ] 112 | 113 | [[package]] 114 | name = "actix-service" 115 | version = "2.0.2" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" 118 | dependencies = [ 119 | "futures-core", 120 | "paste", 121 | "pin-project-lite", 122 | ] 123 | 124 | [[package]] 125 | name = "actix-utils" 126 | version = "3.0.1" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" 129 | dependencies = [ 130 | "local-waker", 131 | "pin-project-lite", 132 | ] 133 | 134 | [[package]] 135 | name = "actix-web" 136 | version = "4.9.0" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "9180d76e5cc7ccbc4d60a506f2c727730b154010262df5b910eb17dbe4b8cb38" 139 | dependencies = [ 140 | "actix-codec", 141 | "actix-http", 142 | "actix-macros", 143 | "actix-router", 144 | "actix-rt", 145 | "actix-server", 146 | "actix-service", 147 | "actix-utils", 148 | "actix-web-codegen", 149 | "ahash", 150 | "bytes", 151 | "bytestring", 152 | "cfg-if", 153 | "cookie", 154 | "derive_more", 155 | "encoding_rs", 156 | "futures-core", 157 | "futures-util", 158 | "impl-more", 159 | "itoa", 160 | "language-tags", 161 | "log", 162 | "mime", 163 | "once_cell", 164 | "pin-project-lite", 165 | "regex", 166 | "regex-lite", 167 | "serde", 168 | "serde_json", 169 | "serde_urlencoded", 170 | "smallvec", 171 | "socket2", 172 | "time", 173 | "url", 174 | ] 175 | 176 | [[package]] 177 | name = "actix-web-codegen" 178 | version = "4.3.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" 181 | dependencies = [ 182 | "actix-router", 183 | "proc-macro2", 184 | "quote", 185 | "syn 2.0.85", 186 | ] 187 | 188 | [[package]] 189 | name = "addr2line" 190 | version = "0.24.2" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 193 | dependencies = [ 194 | "gimli", 195 | ] 196 | 197 | [[package]] 198 | name = "adler2" 199 | version = "2.0.0" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 202 | 203 | [[package]] 204 | name = "ahash" 205 | version = "0.8.11" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 208 | dependencies = [ 209 | "cfg-if", 210 | "getrandom", 211 | "once_cell", 212 | "version_check", 213 | "zerocopy", 214 | ] 215 | 216 | [[package]] 217 | name = "aho-corasick" 218 | version = "1.1.3" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 221 | dependencies = [ 222 | "memchr", 223 | ] 224 | 225 | [[package]] 226 | name = "alloc-no-stdlib" 227 | version = "2.0.4" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" 230 | 231 | [[package]] 232 | name = "alloc-stdlib" 233 | version = "0.2.2" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" 236 | dependencies = [ 237 | "alloc-no-stdlib", 238 | ] 239 | 240 | [[package]] 241 | name = "allocator-api2" 242 | version = "0.2.18" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" 245 | 246 | [[package]] 247 | name = "android-tzdata" 248 | version = "0.1.1" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 251 | 252 | [[package]] 253 | name = "android_system_properties" 254 | version = "0.1.5" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 257 | dependencies = [ 258 | "libc", 259 | ] 260 | 261 | [[package]] 262 | name = "anstream" 263 | version = "0.6.17" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" 266 | dependencies = [ 267 | "anstyle", 268 | "anstyle-parse", 269 | "anstyle-query", 270 | "anstyle-wincon", 271 | "colorchoice", 272 | "is_terminal_polyfill", 273 | "utf8parse", 274 | ] 275 | 276 | [[package]] 277 | name = "anstyle" 278 | version = "1.0.9" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" 281 | 282 | [[package]] 283 | name = "anstyle-parse" 284 | version = "0.2.6" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 287 | dependencies = [ 288 | "utf8parse", 289 | ] 290 | 291 | [[package]] 292 | name = "anstyle-query" 293 | version = "1.1.2" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 296 | dependencies = [ 297 | "windows-sys 0.59.0", 298 | ] 299 | 300 | [[package]] 301 | name = "anstyle-wincon" 302 | version = "3.0.6" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" 305 | dependencies = [ 306 | "anstyle", 307 | "windows-sys 0.59.0", 308 | ] 309 | 310 | [[package]] 311 | name = "anyhow" 312 | version = "1.0.91" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" 315 | 316 | [[package]] 317 | name = "argminmax" 318 | version = "0.6.2" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "52424b59d69d69d5056d508b260553afd91c57e21849579cd1f50ee8b8b88eaa" 321 | dependencies = [ 322 | "num-traits", 323 | ] 324 | 325 | [[package]] 326 | name = "array-init-cursor" 327 | version = "0.2.0" 328 | source = "registry+https://github.com/rust-lang/crates.io-index" 329 | checksum = "bf7d0a018de4f6aa429b9d33d69edf69072b1c5b1cb8d3e4a5f7ef898fc3eb76" 330 | 331 | [[package]] 332 | name = "arrow-format" 333 | version = "0.8.1" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "07884ea216994cdc32a2d5f8274a8bee979cfe90274b83f86f440866ee3132c7" 336 | dependencies = [ 337 | "planus", 338 | "serde", 339 | ] 340 | 341 | [[package]] 342 | name = "async-stream" 343 | version = "0.3.6" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" 346 | dependencies = [ 347 | "async-stream-impl", 348 | "futures-core", 349 | "pin-project-lite", 350 | ] 351 | 352 | [[package]] 353 | name = "async-stream-impl" 354 | version = "0.3.6" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" 357 | dependencies = [ 358 | "proc-macro2", 359 | "quote", 360 | "syn 2.0.85", 361 | ] 362 | 363 | [[package]] 364 | name = "async-trait" 365 | version = "0.1.83" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" 368 | dependencies = [ 369 | "proc-macro2", 370 | "quote", 371 | "syn 2.0.85", 372 | ] 373 | 374 | [[package]] 375 | name = "atoi" 376 | version = "2.0.0" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" 379 | dependencies = [ 380 | "num-traits", 381 | ] 382 | 383 | [[package]] 384 | name = "atoi_simd" 385 | version = "0.15.6" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "9ae037714f313c1353189ead58ef9eec30a8e8dc101b2622d461418fd59e28a9" 388 | 389 | [[package]] 390 | name = "atomic-waker" 391 | version = "1.1.2" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 394 | 395 | [[package]] 396 | name = "autocfg" 397 | version = "1.4.0" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 400 | 401 | [[package]] 402 | name = "backtrace" 403 | version = "0.3.74" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 406 | dependencies = [ 407 | "addr2line", 408 | "cfg-if", 409 | "libc", 410 | "miniz_oxide", 411 | "object", 412 | "rustc-demangle", 413 | "windows-targets", 414 | ] 415 | 416 | [[package]] 417 | name = "base64" 418 | version = "0.21.7" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 421 | 422 | [[package]] 423 | name = "base64" 424 | version = "0.22.1" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 427 | 428 | [[package]] 429 | name = "bitflags" 430 | version = "2.6.0" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 433 | 434 | [[package]] 435 | name = "block-buffer" 436 | version = "0.10.4" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 439 | dependencies = [ 440 | "generic-array", 441 | ] 442 | 443 | [[package]] 444 | name = "brotli" 445 | version = "3.5.0" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" 448 | dependencies = [ 449 | "alloc-no-stdlib", 450 | "alloc-stdlib", 451 | "brotli-decompressor 2.5.1", 452 | ] 453 | 454 | [[package]] 455 | name = "brotli" 456 | version = "6.0.0" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" 459 | dependencies = [ 460 | "alloc-no-stdlib", 461 | "alloc-stdlib", 462 | "brotli-decompressor 4.0.1", 463 | ] 464 | 465 | [[package]] 466 | name = "brotli-decompressor" 467 | version = "2.5.1" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" 470 | dependencies = [ 471 | "alloc-no-stdlib", 472 | "alloc-stdlib", 473 | ] 474 | 475 | [[package]] 476 | name = "brotli-decompressor" 477 | version = "4.0.1" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" 480 | dependencies = [ 481 | "alloc-no-stdlib", 482 | "alloc-stdlib", 483 | ] 484 | 485 | [[package]] 486 | name = "bumpalo" 487 | version = "3.16.0" 488 | source = "registry+https://github.com/rust-lang/crates.io-index" 489 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 490 | 491 | [[package]] 492 | name = "bytemuck" 493 | version = "1.19.0" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" 496 | dependencies = [ 497 | "bytemuck_derive", 498 | ] 499 | 500 | [[package]] 501 | name = "bytemuck_derive" 502 | version = "1.8.0" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" 505 | dependencies = [ 506 | "proc-macro2", 507 | "quote", 508 | "syn 2.0.85", 509 | ] 510 | 511 | [[package]] 512 | name = "byteorder" 513 | version = "1.5.0" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 516 | 517 | [[package]] 518 | name = "bytes" 519 | version = "1.8.0" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" 522 | 523 | [[package]] 524 | name = "bytestring" 525 | version = "1.3.1" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" 528 | dependencies = [ 529 | "bytes", 530 | ] 531 | 532 | [[package]] 533 | name = "cc" 534 | version = "1.1.31" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" 537 | dependencies = [ 538 | "jobserver", 539 | "libc", 540 | "shlex", 541 | ] 542 | 543 | [[package]] 544 | name = "cfg-if" 545 | version = "1.0.0" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 548 | 549 | [[package]] 550 | name = "chrono" 551 | version = "0.4.38" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" 554 | dependencies = [ 555 | "android-tzdata", 556 | "iana-time-zone", 557 | "js-sys", 558 | "num-traits", 559 | "serde", 560 | "wasm-bindgen", 561 | "windows-targets", 562 | ] 563 | 564 | [[package]] 565 | name = "colorchoice" 566 | version = "1.0.3" 567 | source = "registry+https://github.com/rust-lang/crates.io-index" 568 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 569 | 570 | [[package]] 571 | name = "comfy-table" 572 | version = "7.1.1" 573 | source = "registry+https://github.com/rust-lang/crates.io-index" 574 | checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" 575 | dependencies = [ 576 | "crossterm", 577 | "strum", 578 | "strum_macros 0.26.4", 579 | "unicode-width", 580 | ] 581 | 582 | [[package]] 583 | name = "convert_case" 584 | version = "0.4.0" 585 | source = "registry+https://github.com/rust-lang/crates.io-index" 586 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 587 | 588 | [[package]] 589 | name = "cookie" 590 | version = "0.16.2" 591 | source = "registry+https://github.com/rust-lang/crates.io-index" 592 | checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" 593 | dependencies = [ 594 | "percent-encoding", 595 | "time", 596 | "version_check", 597 | ] 598 | 599 | [[package]] 600 | name = "core-foundation" 601 | version = "0.9.4" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 604 | dependencies = [ 605 | "core-foundation-sys", 606 | "libc", 607 | ] 608 | 609 | [[package]] 610 | name = "core-foundation-sys" 611 | version = "0.8.7" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 614 | 615 | [[package]] 616 | name = "cpufeatures" 617 | version = "0.2.14" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" 620 | dependencies = [ 621 | "libc", 622 | ] 623 | 624 | [[package]] 625 | name = "crc32fast" 626 | version = "1.4.2" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 629 | dependencies = [ 630 | "cfg-if", 631 | ] 632 | 633 | [[package]] 634 | name = "crossbeam-channel" 635 | version = "0.5.13" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" 638 | dependencies = [ 639 | "crossbeam-utils", 640 | ] 641 | 642 | [[package]] 643 | name = "crossbeam-deque" 644 | version = "0.8.5" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" 647 | dependencies = [ 648 | "crossbeam-epoch", 649 | "crossbeam-utils", 650 | ] 651 | 652 | [[package]] 653 | name = "crossbeam-epoch" 654 | version = "0.9.18" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 657 | dependencies = [ 658 | "crossbeam-utils", 659 | ] 660 | 661 | [[package]] 662 | name = "crossbeam-queue" 663 | version = "0.3.11" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" 666 | dependencies = [ 667 | "crossbeam-utils", 668 | ] 669 | 670 | [[package]] 671 | name = "crossbeam-utils" 672 | version = "0.8.20" 673 | source = "registry+https://github.com/rust-lang/crates.io-index" 674 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 675 | 676 | [[package]] 677 | name = "crossterm" 678 | version = "0.27.0" 679 | source = "registry+https://github.com/rust-lang/crates.io-index" 680 | checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" 681 | dependencies = [ 682 | "bitflags", 683 | "crossterm_winapi", 684 | "libc", 685 | "parking_lot", 686 | "winapi", 687 | ] 688 | 689 | [[package]] 690 | name = "crossterm_winapi" 691 | version = "0.9.1" 692 | source = "registry+https://github.com/rust-lang/crates.io-index" 693 | checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" 694 | dependencies = [ 695 | "winapi", 696 | ] 697 | 698 | [[package]] 699 | name = "crypto-common" 700 | version = "0.1.6" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 703 | dependencies = [ 704 | "generic-array", 705 | "typenum", 706 | ] 707 | 708 | [[package]] 709 | name = "deranged" 710 | version = "0.3.11" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 713 | dependencies = [ 714 | "powerfmt", 715 | ] 716 | 717 | [[package]] 718 | name = "derive_more" 719 | version = "0.99.18" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" 722 | dependencies = [ 723 | "convert_case", 724 | "proc-macro2", 725 | "quote", 726 | "rustc_version", 727 | "syn 2.0.85", 728 | ] 729 | 730 | [[package]] 731 | name = "digest" 732 | version = "0.10.7" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 735 | dependencies = [ 736 | "block-buffer", 737 | "crypto-common", 738 | ] 739 | 740 | [[package]] 741 | name = "dyn-clone" 742 | version = "1.0.17" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" 745 | 746 | [[package]] 747 | name = "either" 748 | version = "1.13.0" 749 | source = "registry+https://github.com/rust-lang/crates.io-index" 750 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 751 | 752 | [[package]] 753 | name = "encoding_rs" 754 | version = "0.8.35" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 757 | dependencies = [ 758 | "cfg-if", 759 | ] 760 | 761 | [[package]] 762 | name = "enum_dispatch" 763 | version = "0.3.13" 764 | source = "registry+https://github.com/rust-lang/crates.io-index" 765 | checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" 766 | dependencies = [ 767 | "once_cell", 768 | "proc-macro2", 769 | "quote", 770 | "syn 2.0.85", 771 | ] 772 | 773 | [[package]] 774 | name = "env_filter" 775 | version = "0.1.2" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" 778 | dependencies = [ 779 | "log", 780 | "regex", 781 | ] 782 | 783 | [[package]] 784 | name = "env_logger" 785 | version = "0.11.5" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" 788 | dependencies = [ 789 | "anstream", 790 | "anstyle", 791 | "env_filter", 792 | "humantime", 793 | "log", 794 | ] 795 | 796 | [[package]] 797 | name = "equivalent" 798 | version = "1.0.1" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 801 | 802 | [[package]] 803 | name = "errno" 804 | version = "0.3.9" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 807 | dependencies = [ 808 | "libc", 809 | "windows-sys 0.52.0", 810 | ] 811 | 812 | [[package]] 813 | name = "ethnum" 814 | version = "1.5.0" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" 817 | 818 | [[package]] 819 | name = "fallible-streaming-iterator" 820 | version = "0.1.9" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" 823 | 824 | [[package]] 825 | name = "fast-float" 826 | version = "0.2.0" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" 829 | 830 | [[package]] 831 | name = "fastrand" 832 | version = "2.1.1" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" 835 | 836 | [[package]] 837 | name = "flate2" 838 | version = "1.0.34" 839 | source = "registry+https://github.com/rust-lang/crates.io-index" 840 | checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" 841 | dependencies = [ 842 | "crc32fast", 843 | "miniz_oxide", 844 | ] 845 | 846 | [[package]] 847 | name = "fnv" 848 | version = "1.0.7" 849 | source = "registry+https://github.com/rust-lang/crates.io-index" 850 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 851 | 852 | [[package]] 853 | name = "foreign-types" 854 | version = "0.3.2" 855 | source = "registry+https://github.com/rust-lang/crates.io-index" 856 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 857 | dependencies = [ 858 | "foreign-types-shared", 859 | ] 860 | 861 | [[package]] 862 | name = "foreign-types-shared" 863 | version = "0.1.1" 864 | source = "registry+https://github.com/rust-lang/crates.io-index" 865 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 866 | 867 | [[package]] 868 | name = "foreign_vec" 869 | version = "0.1.0" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "ee1b05cbd864bcaecbd3455d6d967862d446e4ebfc3c2e5e5b9841e53cba6673" 872 | 873 | [[package]] 874 | name = "form_urlencoded" 875 | version = "1.2.1" 876 | source = "registry+https://github.com/rust-lang/crates.io-index" 877 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 878 | dependencies = [ 879 | "percent-encoding", 880 | ] 881 | 882 | [[package]] 883 | name = "futures" 884 | version = "0.3.31" 885 | source = "registry+https://github.com/rust-lang/crates.io-index" 886 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 887 | dependencies = [ 888 | "futures-channel", 889 | "futures-core", 890 | "futures-executor", 891 | "futures-io", 892 | "futures-sink", 893 | "futures-task", 894 | "futures-util", 895 | ] 896 | 897 | [[package]] 898 | name = "futures-channel" 899 | version = "0.3.31" 900 | source = "registry+https://github.com/rust-lang/crates.io-index" 901 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 902 | dependencies = [ 903 | "futures-core", 904 | "futures-sink", 905 | ] 906 | 907 | [[package]] 908 | name = "futures-core" 909 | version = "0.3.31" 910 | source = "registry+https://github.com/rust-lang/crates.io-index" 911 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 912 | 913 | [[package]] 914 | name = "futures-executor" 915 | version = "0.3.31" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 918 | dependencies = [ 919 | "futures-core", 920 | "futures-task", 921 | "futures-util", 922 | ] 923 | 924 | [[package]] 925 | name = "futures-io" 926 | version = "0.3.31" 927 | source = "registry+https://github.com/rust-lang/crates.io-index" 928 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 929 | 930 | [[package]] 931 | name = "futures-macro" 932 | version = "0.3.31" 933 | source = "registry+https://github.com/rust-lang/crates.io-index" 934 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 935 | dependencies = [ 936 | "proc-macro2", 937 | "quote", 938 | "syn 2.0.85", 939 | ] 940 | 941 | [[package]] 942 | name = "futures-sink" 943 | version = "0.3.31" 944 | source = "registry+https://github.com/rust-lang/crates.io-index" 945 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 946 | 947 | [[package]] 948 | name = "futures-task" 949 | version = "0.3.31" 950 | source = "registry+https://github.com/rust-lang/crates.io-index" 951 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 952 | 953 | [[package]] 954 | name = "futures-util" 955 | version = "0.3.31" 956 | source = "registry+https://github.com/rust-lang/crates.io-index" 957 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 958 | dependencies = [ 959 | "futures-channel", 960 | "futures-core", 961 | "futures-io", 962 | "futures-macro", 963 | "futures-sink", 964 | "futures-task", 965 | "memchr", 966 | "pin-project-lite", 967 | "pin-utils", 968 | "slab", 969 | ] 970 | 971 | [[package]] 972 | name = "generic-array" 973 | version = "0.14.7" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 976 | dependencies = [ 977 | "typenum", 978 | "version_check", 979 | ] 980 | 981 | [[package]] 982 | name = "getrandom" 983 | version = "0.2.15" 984 | source = "registry+https://github.com/rust-lang/crates.io-index" 985 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 986 | dependencies = [ 987 | "cfg-if", 988 | "js-sys", 989 | "libc", 990 | "wasi", 991 | "wasm-bindgen", 992 | ] 993 | 994 | [[package]] 995 | name = "gimli" 996 | version = "0.31.1" 997 | source = "registry+https://github.com/rust-lang/crates.io-index" 998 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 999 | 1000 | [[package]] 1001 | name = "glob" 1002 | version = "0.3.1" 1003 | source = "registry+https://github.com/rust-lang/crates.io-index" 1004 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" 1005 | 1006 | [[package]] 1007 | name = "h2" 1008 | version = "0.3.26" 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" 1010 | checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" 1011 | dependencies = [ 1012 | "bytes", 1013 | "fnv", 1014 | "futures-core", 1015 | "futures-sink", 1016 | "futures-util", 1017 | "http 0.2.12", 1018 | "indexmap", 1019 | "slab", 1020 | "tokio", 1021 | "tokio-util", 1022 | "tracing", 1023 | ] 1024 | 1025 | [[package]] 1026 | name = "h2" 1027 | version = "0.4.6" 1028 | source = "registry+https://github.com/rust-lang/crates.io-index" 1029 | checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" 1030 | dependencies = [ 1031 | "atomic-waker", 1032 | "bytes", 1033 | "fnv", 1034 | "futures-core", 1035 | "futures-sink", 1036 | "http 1.1.0", 1037 | "indexmap", 1038 | "slab", 1039 | "tokio", 1040 | "tokio-util", 1041 | "tracing", 1042 | ] 1043 | 1044 | [[package]] 1045 | name = "hashbrown" 1046 | version = "0.14.5" 1047 | source = "registry+https://github.com/rust-lang/crates.io-index" 1048 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 1049 | dependencies = [ 1050 | "ahash", 1051 | "allocator-api2", 1052 | "rayon", 1053 | ] 1054 | 1055 | [[package]] 1056 | name = "hashbrown" 1057 | version = "0.15.0" 1058 | source = "registry+https://github.com/rust-lang/crates.io-index" 1059 | checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" 1060 | 1061 | [[package]] 1062 | name = "heck" 1063 | version = "0.4.1" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 1066 | 1067 | [[package]] 1068 | name = "heck" 1069 | version = "0.5.0" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 1072 | 1073 | [[package]] 1074 | name = "hermit-abi" 1075 | version = "0.3.9" 1076 | source = "registry+https://github.com/rust-lang/crates.io-index" 1077 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 1078 | 1079 | [[package]] 1080 | name = "home" 1081 | version = "0.5.9" 1082 | source = "registry+https://github.com/rust-lang/crates.io-index" 1083 | checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" 1084 | dependencies = [ 1085 | "windows-sys 0.52.0", 1086 | ] 1087 | 1088 | [[package]] 1089 | name = "http" 1090 | version = "0.2.12" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 1093 | dependencies = [ 1094 | "bytes", 1095 | "fnv", 1096 | "itoa", 1097 | ] 1098 | 1099 | [[package]] 1100 | name = "http" 1101 | version = "1.1.0" 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" 1103 | checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" 1104 | dependencies = [ 1105 | "bytes", 1106 | "fnv", 1107 | "itoa", 1108 | ] 1109 | 1110 | [[package]] 1111 | name = "http-body" 1112 | version = "1.0.1" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 1115 | dependencies = [ 1116 | "bytes", 1117 | "http 1.1.0", 1118 | ] 1119 | 1120 | [[package]] 1121 | name = "http-body-util" 1122 | version = "0.1.2" 1123 | source = "registry+https://github.com/rust-lang/crates.io-index" 1124 | checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" 1125 | dependencies = [ 1126 | "bytes", 1127 | "futures-util", 1128 | "http 1.1.0", 1129 | "http-body", 1130 | "pin-project-lite", 1131 | ] 1132 | 1133 | [[package]] 1134 | name = "httparse" 1135 | version = "1.9.5" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" 1138 | 1139 | [[package]] 1140 | name = "httpdate" 1141 | version = "1.0.3" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 1144 | 1145 | [[package]] 1146 | name = "humantime" 1147 | version = "2.1.0" 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" 1149 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 1150 | 1151 | [[package]] 1152 | name = "hyper" 1153 | version = "1.5.0" 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" 1155 | checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" 1156 | dependencies = [ 1157 | "bytes", 1158 | "futures-channel", 1159 | "futures-util", 1160 | "h2 0.4.6", 1161 | "http 1.1.0", 1162 | "http-body", 1163 | "httparse", 1164 | "itoa", 1165 | "pin-project-lite", 1166 | "smallvec", 1167 | "tokio", 1168 | "want", 1169 | ] 1170 | 1171 | [[package]] 1172 | name = "hyper-rustls" 1173 | version = "0.27.3" 1174 | source = "registry+https://github.com/rust-lang/crates.io-index" 1175 | checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" 1176 | dependencies = [ 1177 | "futures-util", 1178 | "http 1.1.0", 1179 | "hyper", 1180 | "hyper-util", 1181 | "rustls", 1182 | "rustls-pki-types", 1183 | "tokio", 1184 | "tokio-rustls", 1185 | "tower-service", 1186 | ] 1187 | 1188 | [[package]] 1189 | name = "hyper-tls" 1190 | version = "0.6.0" 1191 | source = "registry+https://github.com/rust-lang/crates.io-index" 1192 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 1193 | dependencies = [ 1194 | "bytes", 1195 | "http-body-util", 1196 | "hyper", 1197 | "hyper-util", 1198 | "native-tls", 1199 | "tokio", 1200 | "tokio-native-tls", 1201 | "tower-service", 1202 | ] 1203 | 1204 | [[package]] 1205 | name = "hyper-util" 1206 | version = "0.1.10" 1207 | source = "registry+https://github.com/rust-lang/crates.io-index" 1208 | checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" 1209 | dependencies = [ 1210 | "bytes", 1211 | "futures-channel", 1212 | "futures-util", 1213 | "http 1.1.0", 1214 | "http-body", 1215 | "hyper", 1216 | "pin-project-lite", 1217 | "socket2", 1218 | "tokio", 1219 | "tower-service", 1220 | "tracing", 1221 | ] 1222 | 1223 | [[package]] 1224 | name = "iana-time-zone" 1225 | version = "0.1.61" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 1228 | dependencies = [ 1229 | "android_system_properties", 1230 | "core-foundation-sys", 1231 | "iana-time-zone-haiku", 1232 | "js-sys", 1233 | "wasm-bindgen", 1234 | "windows-core", 1235 | ] 1236 | 1237 | [[package]] 1238 | name = "iana-time-zone-haiku" 1239 | version = "0.1.2" 1240 | source = "registry+https://github.com/rust-lang/crates.io-index" 1241 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 1242 | dependencies = [ 1243 | "cc", 1244 | ] 1245 | 1246 | [[package]] 1247 | name = "idna" 1248 | version = "0.5.0" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" 1251 | dependencies = [ 1252 | "unicode-bidi", 1253 | "unicode-normalization", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "impl-more" 1258 | version = "0.1.8" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "aae21c3177a27788957044151cc2800043d127acaa460a47ebb9b84dfa2c6aa0" 1261 | 1262 | [[package]] 1263 | name = "indexmap" 1264 | version = "2.6.0" 1265 | source = "registry+https://github.com/rust-lang/crates.io-index" 1266 | checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" 1267 | dependencies = [ 1268 | "equivalent", 1269 | "hashbrown 0.15.0", 1270 | ] 1271 | 1272 | [[package]] 1273 | name = "ipnet" 1274 | version = "2.10.1" 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" 1276 | checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" 1277 | 1278 | [[package]] 1279 | name = "is_terminal_polyfill" 1280 | version = "1.70.1" 1281 | source = "registry+https://github.com/rust-lang/crates.io-index" 1282 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 1283 | 1284 | [[package]] 1285 | name = "itoa" 1286 | version = "1.0.11" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 1289 | 1290 | [[package]] 1291 | name = "jobserver" 1292 | version = "0.1.32" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" 1295 | dependencies = [ 1296 | "libc", 1297 | ] 1298 | 1299 | [[package]] 1300 | name = "js-sys" 1301 | version = "0.3.72" 1302 | source = "registry+https://github.com/rust-lang/crates.io-index" 1303 | checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" 1304 | dependencies = [ 1305 | "wasm-bindgen", 1306 | ] 1307 | 1308 | [[package]] 1309 | name = "language-tags" 1310 | version = "0.3.2" 1311 | source = "registry+https://github.com/rust-lang/crates.io-index" 1312 | checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" 1313 | 1314 | [[package]] 1315 | name = "libc" 1316 | version = "0.2.161" 1317 | source = "registry+https://github.com/rust-lang/crates.io-index" 1318 | checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" 1319 | 1320 | [[package]] 1321 | name = "libm" 1322 | version = "0.2.11" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" 1325 | 1326 | [[package]] 1327 | name = "linux-raw-sys" 1328 | version = "0.4.14" 1329 | source = "registry+https://github.com/rust-lang/crates.io-index" 1330 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 1331 | 1332 | [[package]] 1333 | name = "local-channel" 1334 | version = "0.1.5" 1335 | source = "registry+https://github.com/rust-lang/crates.io-index" 1336 | checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" 1337 | dependencies = [ 1338 | "futures-core", 1339 | "futures-sink", 1340 | "local-waker", 1341 | ] 1342 | 1343 | [[package]] 1344 | name = "local-waker" 1345 | version = "0.1.4" 1346 | source = "registry+https://github.com/rust-lang/crates.io-index" 1347 | checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" 1348 | 1349 | [[package]] 1350 | name = "lock_api" 1351 | version = "0.4.12" 1352 | source = "registry+https://github.com/rust-lang/crates.io-index" 1353 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 1354 | dependencies = [ 1355 | "autocfg", 1356 | "scopeguard", 1357 | ] 1358 | 1359 | [[package]] 1360 | name = "log" 1361 | version = "0.4.22" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 1364 | 1365 | [[package]] 1366 | name = "lz4" 1367 | version = "1.28.0" 1368 | source = "registry+https://github.com/rust-lang/crates.io-index" 1369 | checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" 1370 | dependencies = [ 1371 | "lz4-sys", 1372 | ] 1373 | 1374 | [[package]] 1375 | name = "lz4-sys" 1376 | version = "1.11.1+lz4-1.10.0" 1377 | source = "registry+https://github.com/rust-lang/crates.io-index" 1378 | checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" 1379 | dependencies = [ 1380 | "cc", 1381 | "libc", 1382 | ] 1383 | 1384 | [[package]] 1385 | name = "memchr" 1386 | version = "2.7.4" 1387 | source = "registry+https://github.com/rust-lang/crates.io-index" 1388 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1389 | 1390 | [[package]] 1391 | name = "memmap2" 1392 | version = "0.7.1" 1393 | source = "registry+https://github.com/rust-lang/crates.io-index" 1394 | checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6" 1395 | dependencies = [ 1396 | "libc", 1397 | ] 1398 | 1399 | [[package]] 1400 | name = "mime" 1401 | version = "0.3.17" 1402 | source = "registry+https://github.com/rust-lang/crates.io-index" 1403 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1404 | 1405 | [[package]] 1406 | name = "miniz_oxide" 1407 | version = "0.8.0" 1408 | source = "registry+https://github.com/rust-lang/crates.io-index" 1409 | checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" 1410 | dependencies = [ 1411 | "adler2", 1412 | ] 1413 | 1414 | [[package]] 1415 | name = "mio" 1416 | version = "1.0.2" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" 1419 | dependencies = [ 1420 | "hermit-abi", 1421 | "libc", 1422 | "log", 1423 | "wasi", 1424 | "windows-sys 0.52.0", 1425 | ] 1426 | 1427 | [[package]] 1428 | name = "multiversion" 1429 | version = "0.7.4" 1430 | source = "registry+https://github.com/rust-lang/crates.io-index" 1431 | checksum = "c4851161a11d3ad0bf9402d90ffc3967bf231768bfd7aeb61755ad06dbf1a142" 1432 | dependencies = [ 1433 | "multiversion-macros", 1434 | "target-features", 1435 | ] 1436 | 1437 | [[package]] 1438 | name = "multiversion-macros" 1439 | version = "0.7.4" 1440 | source = "registry+https://github.com/rust-lang/crates.io-index" 1441 | checksum = "79a74ddee9e0c27d2578323c13905793e91622148f138ba29738f9dddb835e90" 1442 | dependencies = [ 1443 | "proc-macro2", 1444 | "quote", 1445 | "syn 1.0.109", 1446 | "target-features", 1447 | ] 1448 | 1449 | [[package]] 1450 | name = "native-tls" 1451 | version = "0.2.12" 1452 | source = "registry+https://github.com/rust-lang/crates.io-index" 1453 | checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" 1454 | dependencies = [ 1455 | "libc", 1456 | "log", 1457 | "openssl", 1458 | "openssl-probe", 1459 | "openssl-sys", 1460 | "schannel", 1461 | "security-framework", 1462 | "security-framework-sys", 1463 | "tempfile", 1464 | ] 1465 | 1466 | [[package]] 1467 | name = "now" 1468 | version = "0.1.3" 1469 | source = "registry+https://github.com/rust-lang/crates.io-index" 1470 | checksum = "6d89e9874397a1f0a52fc1f197a8effd9735223cb2390e9dcc83ac6cd02923d0" 1471 | dependencies = [ 1472 | "chrono", 1473 | ] 1474 | 1475 | [[package]] 1476 | name = "ntapi" 1477 | version = "0.4.1" 1478 | source = "registry+https://github.com/rust-lang/crates.io-index" 1479 | checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" 1480 | dependencies = [ 1481 | "winapi", 1482 | ] 1483 | 1484 | [[package]] 1485 | name = "num-conv" 1486 | version = "0.1.0" 1487 | source = "registry+https://github.com/rust-lang/crates.io-index" 1488 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 1489 | 1490 | [[package]] 1491 | name = "num-traits" 1492 | version = "0.2.19" 1493 | source = "registry+https://github.com/rust-lang/crates.io-index" 1494 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1495 | dependencies = [ 1496 | "autocfg", 1497 | "libm", 1498 | ] 1499 | 1500 | [[package]] 1501 | name = "object" 1502 | version = "0.36.5" 1503 | source = "registry+https://github.com/rust-lang/crates.io-index" 1504 | checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" 1505 | dependencies = [ 1506 | "memchr", 1507 | ] 1508 | 1509 | [[package]] 1510 | name = "once_cell" 1511 | version = "1.20.2" 1512 | source = "registry+https://github.com/rust-lang/crates.io-index" 1513 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 1514 | 1515 | [[package]] 1516 | name = "openssl" 1517 | version = "0.10.68" 1518 | source = "registry+https://github.com/rust-lang/crates.io-index" 1519 | checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" 1520 | dependencies = [ 1521 | "bitflags", 1522 | "cfg-if", 1523 | "foreign-types", 1524 | "libc", 1525 | "once_cell", 1526 | "openssl-macros", 1527 | "openssl-sys", 1528 | ] 1529 | 1530 | [[package]] 1531 | name = "openssl-macros" 1532 | version = "0.1.1" 1533 | source = "registry+https://github.com/rust-lang/crates.io-index" 1534 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1535 | dependencies = [ 1536 | "proc-macro2", 1537 | "quote", 1538 | "syn 2.0.85", 1539 | ] 1540 | 1541 | [[package]] 1542 | name = "openssl-probe" 1543 | version = "0.1.5" 1544 | source = "registry+https://github.com/rust-lang/crates.io-index" 1545 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 1546 | 1547 | [[package]] 1548 | name = "openssl-sys" 1549 | version = "0.9.104" 1550 | source = "registry+https://github.com/rust-lang/crates.io-index" 1551 | checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" 1552 | dependencies = [ 1553 | "cc", 1554 | "libc", 1555 | "pkg-config", 1556 | "vcpkg", 1557 | ] 1558 | 1559 | [[package]] 1560 | name = "parking_lot" 1561 | version = "0.12.3" 1562 | source = "registry+https://github.com/rust-lang/crates.io-index" 1563 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 1564 | dependencies = [ 1565 | "lock_api", 1566 | "parking_lot_core", 1567 | ] 1568 | 1569 | [[package]] 1570 | name = "parking_lot_core" 1571 | version = "0.9.10" 1572 | source = "registry+https://github.com/rust-lang/crates.io-index" 1573 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 1574 | dependencies = [ 1575 | "cfg-if", 1576 | "libc", 1577 | "redox_syscall", 1578 | "smallvec", 1579 | "windows-targets", 1580 | ] 1581 | 1582 | [[package]] 1583 | name = "parquet-format-safe" 1584 | version = "0.2.4" 1585 | source = "registry+https://github.com/rust-lang/crates.io-index" 1586 | checksum = "1131c54b167dd4e4799ce762e1ab01549ebb94d5bdd13e6ec1b467491c378e1f" 1587 | dependencies = [ 1588 | "async-trait", 1589 | "futures", 1590 | ] 1591 | 1592 | [[package]] 1593 | name = "paste" 1594 | version = "1.0.15" 1595 | source = "registry+https://github.com/rust-lang/crates.io-index" 1596 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 1597 | 1598 | [[package]] 1599 | name = "percent-encoding" 1600 | version = "2.3.1" 1601 | source = "registry+https://github.com/rust-lang/crates.io-index" 1602 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1603 | 1604 | [[package]] 1605 | name = "pin-project-lite" 1606 | version = "0.2.15" 1607 | source = "registry+https://github.com/rust-lang/crates.io-index" 1608 | checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" 1609 | 1610 | [[package]] 1611 | name = "pin-utils" 1612 | version = "0.1.0" 1613 | source = "registry+https://github.com/rust-lang/crates.io-index" 1614 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1615 | 1616 | [[package]] 1617 | name = "pkg-config" 1618 | version = "0.3.31" 1619 | source = "registry+https://github.com/rust-lang/crates.io-index" 1620 | checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" 1621 | 1622 | [[package]] 1623 | name = "planus" 1624 | version = "0.3.1" 1625 | source = "registry+https://github.com/rust-lang/crates.io-index" 1626 | checksum = "fc1691dd09e82f428ce8d6310bd6d5da2557c82ff17694d2a32cad7242aea89f" 1627 | dependencies = [ 1628 | "array-init-cursor", 1629 | ] 1630 | 1631 | [[package]] 1632 | name = "polars" 1633 | version = "0.35.4" 1634 | source = "registry+https://github.com/rust-lang/crates.io-index" 1635 | checksum = "df8e52f9236eb722da0990a70bbb1216dcc7a77bcb00c63439d2d982823e90d5" 1636 | dependencies = [ 1637 | "getrandom", 1638 | "polars-core", 1639 | "polars-io", 1640 | "polars-lazy", 1641 | "polars-ops", 1642 | "polars-sql", 1643 | "polars-time", 1644 | "version_check", 1645 | ] 1646 | 1647 | [[package]] 1648 | name = "polars-arrow" 1649 | version = "0.35.4" 1650 | source = "registry+https://github.com/rust-lang/crates.io-index" 1651 | checksum = "dd503430a6d9779b07915d858865fe998317ef3cfef8973881f578ac5d4baae7" 1652 | dependencies = [ 1653 | "ahash", 1654 | "arrow-format", 1655 | "atoi_simd", 1656 | "bytemuck", 1657 | "chrono", 1658 | "dyn-clone", 1659 | "either", 1660 | "ethnum", 1661 | "fast-float", 1662 | "foreign_vec", 1663 | "futures", 1664 | "getrandom", 1665 | "hashbrown 0.14.5", 1666 | "itoa", 1667 | "lz4", 1668 | "multiversion", 1669 | "num-traits", 1670 | "polars-error", 1671 | "polars-utils", 1672 | "rustc_version", 1673 | "ryu", 1674 | "simdutf8", 1675 | "streaming-iterator", 1676 | "strength_reduce", 1677 | "zstd", 1678 | ] 1679 | 1680 | [[package]] 1681 | name = "polars-core" 1682 | version = "0.35.4" 1683 | source = "registry+https://github.com/rust-lang/crates.io-index" 1684 | checksum = "ae73d5b8e55decde670caba1cc82b61f14bfb9a72503198f0997d657a98dcfd6" 1685 | dependencies = [ 1686 | "ahash", 1687 | "bitflags", 1688 | "bytemuck", 1689 | "chrono", 1690 | "comfy-table", 1691 | "either", 1692 | "hashbrown 0.14.5", 1693 | "indexmap", 1694 | "num-traits", 1695 | "once_cell", 1696 | "polars-arrow", 1697 | "polars-error", 1698 | "polars-row", 1699 | "polars-utils", 1700 | "rand", 1701 | "rand_distr", 1702 | "rayon", 1703 | "regex", 1704 | "smartstring", 1705 | "thiserror", 1706 | "version_check", 1707 | "xxhash-rust", 1708 | ] 1709 | 1710 | [[package]] 1711 | name = "polars-error" 1712 | version = "0.35.4" 1713 | source = "registry+https://github.com/rust-lang/crates.io-index" 1714 | checksum = "eb0520d68eaa9993ae0c741409d1526beff5b8f48e1d73e4381616f8152cf488" 1715 | dependencies = [ 1716 | "arrow-format", 1717 | "regex", 1718 | "simdutf8", 1719 | "thiserror", 1720 | ] 1721 | 1722 | [[package]] 1723 | name = "polars-io" 1724 | version = "0.35.4" 1725 | source = "registry+https://github.com/rust-lang/crates.io-index" 1726 | checksum = "96e10a0745acd6009db64bef0ceb9e23a70b1c27b26a0a6517c91f3e6363bc06" 1727 | dependencies = [ 1728 | "ahash", 1729 | "async-trait", 1730 | "atoi_simd", 1731 | "bytes", 1732 | "chrono", 1733 | "fast-float", 1734 | "futures", 1735 | "home", 1736 | "itoa", 1737 | "memchr", 1738 | "memmap2", 1739 | "num-traits", 1740 | "once_cell", 1741 | "percent-encoding", 1742 | "polars-arrow", 1743 | "polars-core", 1744 | "polars-error", 1745 | "polars-parquet", 1746 | "polars-time", 1747 | "polars-utils", 1748 | "rayon", 1749 | "regex", 1750 | "ryu", 1751 | "simdutf8", 1752 | "smartstring", 1753 | "tokio", 1754 | "tokio-util", 1755 | ] 1756 | 1757 | [[package]] 1758 | name = "polars-lazy" 1759 | version = "0.35.4" 1760 | source = "registry+https://github.com/rust-lang/crates.io-index" 1761 | checksum = "3555f759705be6dd0d3762d16a0b8787b2dc4da73b57465f3b2bf1a070ba8f20" 1762 | dependencies = [ 1763 | "ahash", 1764 | "bitflags", 1765 | "glob", 1766 | "once_cell", 1767 | "polars-arrow", 1768 | "polars-core", 1769 | "polars-io", 1770 | "polars-ops", 1771 | "polars-pipe", 1772 | "polars-plan", 1773 | "polars-time", 1774 | "polars-utils", 1775 | "rayon", 1776 | "smartstring", 1777 | "version_check", 1778 | ] 1779 | 1780 | [[package]] 1781 | name = "polars-ops" 1782 | version = "0.35.4" 1783 | source = "registry+https://github.com/rust-lang/crates.io-index" 1784 | checksum = "1a7eb218296aaa7f79945f08288ca32ca3cf25fa505649eeee689ec21eebf636" 1785 | dependencies = [ 1786 | "ahash", 1787 | "argminmax", 1788 | "bytemuck", 1789 | "either", 1790 | "hashbrown 0.14.5", 1791 | "indexmap", 1792 | "memchr", 1793 | "num-traits", 1794 | "polars-arrow", 1795 | "polars-core", 1796 | "polars-error", 1797 | "polars-utils", 1798 | "rayon", 1799 | "regex", 1800 | "smartstring", 1801 | "version_check", 1802 | ] 1803 | 1804 | [[package]] 1805 | name = "polars-parquet" 1806 | version = "0.35.4" 1807 | source = "registry+https://github.com/rust-lang/crates.io-index" 1808 | checksum = "146010e4b7dd4d2d0e58ddc762f6361f77d7a0385c54471199370c17164f67dd" 1809 | dependencies = [ 1810 | "ahash", 1811 | "async-stream", 1812 | "base64 0.21.7", 1813 | "brotli 3.5.0", 1814 | "ethnum", 1815 | "flate2", 1816 | "futures", 1817 | "lz4", 1818 | "num-traits", 1819 | "parquet-format-safe", 1820 | "polars-arrow", 1821 | "polars-error", 1822 | "polars-utils", 1823 | "seq-macro", 1824 | "simdutf8", 1825 | "snap", 1826 | "streaming-decompression", 1827 | "zstd", 1828 | ] 1829 | 1830 | [[package]] 1831 | name = "polars-pipe" 1832 | version = "0.35.4" 1833 | source = "registry+https://github.com/rust-lang/crates.io-index" 1834 | checksum = "66094e7df64c932a9a7bdfe7df0c65efdcb192096e11a6a765a9778f78b4bdec" 1835 | dependencies = [ 1836 | "crossbeam-channel", 1837 | "crossbeam-queue", 1838 | "enum_dispatch", 1839 | "hashbrown 0.14.5", 1840 | "num-traits", 1841 | "polars-arrow", 1842 | "polars-core", 1843 | "polars-io", 1844 | "polars-ops", 1845 | "polars-plan", 1846 | "polars-row", 1847 | "polars-utils", 1848 | "rayon", 1849 | "smartstring", 1850 | "version_check", 1851 | ] 1852 | 1853 | [[package]] 1854 | name = "polars-plan" 1855 | version = "0.35.4" 1856 | source = "registry+https://github.com/rust-lang/crates.io-index" 1857 | checksum = "10e32a0958ef854b132bad7f8369cb3237254635d5e864c99505bc0bc1035fbc" 1858 | dependencies = [ 1859 | "ahash", 1860 | "bytemuck", 1861 | "once_cell", 1862 | "percent-encoding", 1863 | "polars-arrow", 1864 | "polars-core", 1865 | "polars-io", 1866 | "polars-ops", 1867 | "polars-parquet", 1868 | "polars-time", 1869 | "polars-utils", 1870 | "rayon", 1871 | "regex", 1872 | "smartstring", 1873 | "strum_macros 0.25.3", 1874 | "version_check", 1875 | ] 1876 | 1877 | [[package]] 1878 | name = "polars-row" 1879 | version = "0.35.4" 1880 | source = "registry+https://github.com/rust-lang/crates.io-index" 1881 | checksum = "d135ab81cac2906ba74ea8984c7e6025d081ae5867615bcefb4d84dfdb456dac" 1882 | dependencies = [ 1883 | "polars-arrow", 1884 | "polars-error", 1885 | "polars-utils", 1886 | ] 1887 | 1888 | [[package]] 1889 | name = "polars-sql" 1890 | version = "0.35.4" 1891 | source = "registry+https://github.com/rust-lang/crates.io-index" 1892 | checksum = "b8dbd7786849a5e3ad1fde188bf38141632f626e3a57319b0bbf7a5f1d75519e" 1893 | dependencies = [ 1894 | "polars-arrow", 1895 | "polars-core", 1896 | "polars-error", 1897 | "polars-lazy", 1898 | "polars-plan", 1899 | "rand", 1900 | "serde", 1901 | "serde_json", 1902 | "sqlparser", 1903 | ] 1904 | 1905 | [[package]] 1906 | name = "polars-time" 1907 | version = "0.35.4" 1908 | source = "registry+https://github.com/rust-lang/crates.io-index" 1909 | checksum = "aae56f79e9cedd617773c1c8f5ca84a31a8b1d593714959d5f799e7bdd98fe51" 1910 | dependencies = [ 1911 | "atoi", 1912 | "chrono", 1913 | "now", 1914 | "once_cell", 1915 | "polars-arrow", 1916 | "polars-core", 1917 | "polars-error", 1918 | "polars-ops", 1919 | "polars-utils", 1920 | "regex", 1921 | "smartstring", 1922 | ] 1923 | 1924 | [[package]] 1925 | name = "polars-utils" 1926 | version = "0.35.4" 1927 | source = "registry+https://github.com/rust-lang/crates.io-index" 1928 | checksum = "da6ce68169fe61d46958c8eab7447360f30f2f23f6e24a0ce703a14b0a3cfbfc" 1929 | dependencies = [ 1930 | "ahash", 1931 | "bytemuck", 1932 | "hashbrown 0.14.5", 1933 | "indexmap", 1934 | "num-traits", 1935 | "once_cell", 1936 | "polars-error", 1937 | "rayon", 1938 | "smartstring", 1939 | "sysinfo", 1940 | "version_check", 1941 | ] 1942 | 1943 | [[package]] 1944 | name = "powerfmt" 1945 | version = "0.2.0" 1946 | source = "registry+https://github.com/rust-lang/crates.io-index" 1947 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 1948 | 1949 | [[package]] 1950 | name = "ppv-lite86" 1951 | version = "0.2.20" 1952 | source = "registry+https://github.com/rust-lang/crates.io-index" 1953 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 1954 | dependencies = [ 1955 | "zerocopy", 1956 | ] 1957 | 1958 | [[package]] 1959 | name = "proc-macro2" 1960 | version = "1.0.89" 1961 | source = "registry+https://github.com/rust-lang/crates.io-index" 1962 | checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" 1963 | dependencies = [ 1964 | "unicode-ident", 1965 | ] 1966 | 1967 | [[package]] 1968 | name = "quote" 1969 | version = "1.0.37" 1970 | source = "registry+https://github.com/rust-lang/crates.io-index" 1971 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 1972 | dependencies = [ 1973 | "proc-macro2", 1974 | ] 1975 | 1976 | [[package]] 1977 | name = "rand" 1978 | version = "0.8.5" 1979 | source = "registry+https://github.com/rust-lang/crates.io-index" 1980 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1981 | dependencies = [ 1982 | "libc", 1983 | "rand_chacha", 1984 | "rand_core", 1985 | ] 1986 | 1987 | [[package]] 1988 | name = "rand_chacha" 1989 | version = "0.3.1" 1990 | source = "registry+https://github.com/rust-lang/crates.io-index" 1991 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1992 | dependencies = [ 1993 | "ppv-lite86", 1994 | "rand_core", 1995 | ] 1996 | 1997 | [[package]] 1998 | name = "rand_core" 1999 | version = "0.6.4" 2000 | source = "registry+https://github.com/rust-lang/crates.io-index" 2001 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 2002 | dependencies = [ 2003 | "getrandom", 2004 | ] 2005 | 2006 | [[package]] 2007 | name = "rand_distr" 2008 | version = "0.4.3" 2009 | source = "registry+https://github.com/rust-lang/crates.io-index" 2010 | checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" 2011 | dependencies = [ 2012 | "num-traits", 2013 | "rand", 2014 | ] 2015 | 2016 | [[package]] 2017 | name = "rayon" 2018 | version = "1.10.0" 2019 | source = "registry+https://github.com/rust-lang/crates.io-index" 2020 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 2021 | dependencies = [ 2022 | "either", 2023 | "rayon-core", 2024 | ] 2025 | 2026 | [[package]] 2027 | name = "rayon-core" 2028 | version = "1.12.1" 2029 | source = "registry+https://github.com/rust-lang/crates.io-index" 2030 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 2031 | dependencies = [ 2032 | "crossbeam-deque", 2033 | "crossbeam-utils", 2034 | ] 2035 | 2036 | [[package]] 2037 | name = "redox_syscall" 2038 | version = "0.5.7" 2039 | source = "registry+https://github.com/rust-lang/crates.io-index" 2040 | checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" 2041 | dependencies = [ 2042 | "bitflags", 2043 | ] 2044 | 2045 | [[package]] 2046 | name = "regex" 2047 | version = "1.11.1" 2048 | source = "registry+https://github.com/rust-lang/crates.io-index" 2049 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 2050 | dependencies = [ 2051 | "aho-corasick", 2052 | "memchr", 2053 | "regex-automata", 2054 | "regex-syntax", 2055 | ] 2056 | 2057 | [[package]] 2058 | name = "regex-automata" 2059 | version = "0.4.8" 2060 | source = "registry+https://github.com/rust-lang/crates.io-index" 2061 | checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" 2062 | dependencies = [ 2063 | "aho-corasick", 2064 | "memchr", 2065 | "regex-syntax", 2066 | ] 2067 | 2068 | [[package]] 2069 | name = "regex-lite" 2070 | version = "0.1.6" 2071 | source = "registry+https://github.com/rust-lang/crates.io-index" 2072 | checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" 2073 | 2074 | [[package]] 2075 | name = "regex-syntax" 2076 | version = "0.8.5" 2077 | source = "registry+https://github.com/rust-lang/crates.io-index" 2078 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 2079 | 2080 | [[package]] 2081 | name = "reqwest" 2082 | version = "0.12.9" 2083 | source = "registry+https://github.com/rust-lang/crates.io-index" 2084 | checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" 2085 | dependencies = [ 2086 | "base64 0.22.1", 2087 | "bytes", 2088 | "encoding_rs", 2089 | "futures-core", 2090 | "futures-util", 2091 | "h2 0.4.6", 2092 | "http 1.1.0", 2093 | "http-body", 2094 | "http-body-util", 2095 | "hyper", 2096 | "hyper-rustls", 2097 | "hyper-tls", 2098 | "hyper-util", 2099 | "ipnet", 2100 | "js-sys", 2101 | "log", 2102 | "mime", 2103 | "native-tls", 2104 | "once_cell", 2105 | "percent-encoding", 2106 | "pin-project-lite", 2107 | "rustls-pemfile", 2108 | "serde", 2109 | "serde_json", 2110 | "serde_urlencoded", 2111 | "sync_wrapper", 2112 | "system-configuration", 2113 | "tokio", 2114 | "tokio-native-tls", 2115 | "tower-service", 2116 | "url", 2117 | "wasm-bindgen", 2118 | "wasm-bindgen-futures", 2119 | "web-sys", 2120 | "windows-registry", 2121 | ] 2122 | 2123 | [[package]] 2124 | name = "ring" 2125 | version = "0.17.8" 2126 | source = "registry+https://github.com/rust-lang/crates.io-index" 2127 | checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" 2128 | dependencies = [ 2129 | "cc", 2130 | "cfg-if", 2131 | "getrandom", 2132 | "libc", 2133 | "spin", 2134 | "untrusted", 2135 | "windows-sys 0.52.0", 2136 | ] 2137 | 2138 | [[package]] 2139 | name = "rustc-demangle" 2140 | version = "0.1.24" 2141 | source = "registry+https://github.com/rust-lang/crates.io-index" 2142 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 2143 | 2144 | [[package]] 2145 | name = "rustc_version" 2146 | version = "0.4.1" 2147 | source = "registry+https://github.com/rust-lang/crates.io-index" 2148 | checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" 2149 | dependencies = [ 2150 | "semver", 2151 | ] 2152 | 2153 | [[package]] 2154 | name = "rustix" 2155 | version = "0.38.38" 2156 | source = "registry+https://github.com/rust-lang/crates.io-index" 2157 | checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" 2158 | dependencies = [ 2159 | "bitflags", 2160 | "errno", 2161 | "libc", 2162 | "linux-raw-sys", 2163 | "windows-sys 0.52.0", 2164 | ] 2165 | 2166 | [[package]] 2167 | name = "rustls" 2168 | version = "0.23.16" 2169 | source = "registry+https://github.com/rust-lang/crates.io-index" 2170 | checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" 2171 | dependencies = [ 2172 | "once_cell", 2173 | "rustls-pki-types", 2174 | "rustls-webpki", 2175 | "subtle", 2176 | "zeroize", 2177 | ] 2178 | 2179 | [[package]] 2180 | name = "rustls-pemfile" 2181 | version = "2.2.0" 2182 | source = "registry+https://github.com/rust-lang/crates.io-index" 2183 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 2184 | dependencies = [ 2185 | "rustls-pki-types", 2186 | ] 2187 | 2188 | [[package]] 2189 | name = "rustls-pki-types" 2190 | version = "1.10.0" 2191 | source = "registry+https://github.com/rust-lang/crates.io-index" 2192 | checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" 2193 | 2194 | [[package]] 2195 | name = "rustls-webpki" 2196 | version = "0.102.8" 2197 | source = "registry+https://github.com/rust-lang/crates.io-index" 2198 | checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" 2199 | dependencies = [ 2200 | "ring", 2201 | "rustls-pki-types", 2202 | "untrusted", 2203 | ] 2204 | 2205 | [[package]] 2206 | name = "rustversion" 2207 | version = "1.0.18" 2208 | source = "registry+https://github.com/rust-lang/crates.io-index" 2209 | checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" 2210 | 2211 | [[package]] 2212 | name = "ryu" 2213 | version = "1.0.18" 2214 | source = "registry+https://github.com/rust-lang/crates.io-index" 2215 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 2216 | 2217 | [[package]] 2218 | name = "schannel" 2219 | version = "0.1.26" 2220 | source = "registry+https://github.com/rust-lang/crates.io-index" 2221 | checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" 2222 | dependencies = [ 2223 | "windows-sys 0.59.0", 2224 | ] 2225 | 2226 | [[package]] 2227 | name = "scopeguard" 2228 | version = "1.2.0" 2229 | source = "registry+https://github.com/rust-lang/crates.io-index" 2230 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 2231 | 2232 | [[package]] 2233 | name = "security-framework" 2234 | version = "2.11.1" 2235 | source = "registry+https://github.com/rust-lang/crates.io-index" 2236 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 2237 | dependencies = [ 2238 | "bitflags", 2239 | "core-foundation", 2240 | "core-foundation-sys", 2241 | "libc", 2242 | "security-framework-sys", 2243 | ] 2244 | 2245 | [[package]] 2246 | name = "security-framework-sys" 2247 | version = "2.12.0" 2248 | source = "registry+https://github.com/rust-lang/crates.io-index" 2249 | checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" 2250 | dependencies = [ 2251 | "core-foundation-sys", 2252 | "libc", 2253 | ] 2254 | 2255 | [[package]] 2256 | name = "semver" 2257 | version = "1.0.23" 2258 | source = "registry+https://github.com/rust-lang/crates.io-index" 2259 | checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" 2260 | 2261 | [[package]] 2262 | name = "seq-macro" 2263 | version = "0.3.5" 2264 | source = "registry+https://github.com/rust-lang/crates.io-index" 2265 | checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" 2266 | 2267 | [[package]] 2268 | name = "serde" 2269 | version = "1.0.214" 2270 | source = "registry+https://github.com/rust-lang/crates.io-index" 2271 | checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" 2272 | dependencies = [ 2273 | "serde_derive", 2274 | ] 2275 | 2276 | [[package]] 2277 | name = "serde_derive" 2278 | version = "1.0.214" 2279 | source = "registry+https://github.com/rust-lang/crates.io-index" 2280 | checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" 2281 | dependencies = [ 2282 | "proc-macro2", 2283 | "quote", 2284 | "syn 2.0.85", 2285 | ] 2286 | 2287 | [[package]] 2288 | name = "serde_json" 2289 | version = "1.0.132" 2290 | source = "registry+https://github.com/rust-lang/crates.io-index" 2291 | checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" 2292 | dependencies = [ 2293 | "itoa", 2294 | "memchr", 2295 | "ryu", 2296 | "serde", 2297 | ] 2298 | 2299 | [[package]] 2300 | name = "serde_urlencoded" 2301 | version = "0.7.1" 2302 | source = "registry+https://github.com/rust-lang/crates.io-index" 2303 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 2304 | dependencies = [ 2305 | "form_urlencoded", 2306 | "itoa", 2307 | "ryu", 2308 | "serde", 2309 | ] 2310 | 2311 | [[package]] 2312 | name = "sha1" 2313 | version = "0.10.6" 2314 | source = "registry+https://github.com/rust-lang/crates.io-index" 2315 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 2316 | dependencies = [ 2317 | "cfg-if", 2318 | "cpufeatures", 2319 | "digest", 2320 | ] 2321 | 2322 | [[package]] 2323 | name = "shlex" 2324 | version = "1.3.0" 2325 | source = "registry+https://github.com/rust-lang/crates.io-index" 2326 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 2327 | 2328 | [[package]] 2329 | name = "signal-hook-registry" 2330 | version = "1.4.2" 2331 | source = "registry+https://github.com/rust-lang/crates.io-index" 2332 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 2333 | dependencies = [ 2334 | "libc", 2335 | ] 2336 | 2337 | [[package]] 2338 | name = "simdutf8" 2339 | version = "0.1.5" 2340 | source = "registry+https://github.com/rust-lang/crates.io-index" 2341 | checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" 2342 | 2343 | [[package]] 2344 | name = "slab" 2345 | version = "0.4.9" 2346 | source = "registry+https://github.com/rust-lang/crates.io-index" 2347 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 2348 | dependencies = [ 2349 | "autocfg", 2350 | ] 2351 | 2352 | [[package]] 2353 | name = "smallvec" 2354 | version = "1.13.2" 2355 | source = "registry+https://github.com/rust-lang/crates.io-index" 2356 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 2357 | 2358 | [[package]] 2359 | name = "smartstring" 2360 | version = "1.0.1" 2361 | source = "registry+https://github.com/rust-lang/crates.io-index" 2362 | checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" 2363 | dependencies = [ 2364 | "autocfg", 2365 | "static_assertions", 2366 | "version_check", 2367 | ] 2368 | 2369 | [[package]] 2370 | name = "snap" 2371 | version = "1.1.1" 2372 | source = "registry+https://github.com/rust-lang/crates.io-index" 2373 | checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" 2374 | 2375 | [[package]] 2376 | name = "socket2" 2377 | version = "0.5.7" 2378 | source = "registry+https://github.com/rust-lang/crates.io-index" 2379 | checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" 2380 | dependencies = [ 2381 | "libc", 2382 | "windows-sys 0.52.0", 2383 | ] 2384 | 2385 | [[package]] 2386 | name = "spin" 2387 | version = "0.9.8" 2388 | source = "registry+https://github.com/rust-lang/crates.io-index" 2389 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 2390 | 2391 | [[package]] 2392 | name = "sqlparser" 2393 | version = "0.39.0" 2394 | source = "registry+https://github.com/rust-lang/crates.io-index" 2395 | checksum = "743b4dc2cbde11890ccb254a8fc9d537fa41b36da00de2a1c5e9848c9bc42bd7" 2396 | dependencies = [ 2397 | "log", 2398 | ] 2399 | 2400 | [[package]] 2401 | name = "static_assertions" 2402 | version = "1.1.0" 2403 | source = "registry+https://github.com/rust-lang/crates.io-index" 2404 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 2405 | 2406 | [[package]] 2407 | name = "streaming-decompression" 2408 | version = "0.1.2" 2409 | source = "registry+https://github.com/rust-lang/crates.io-index" 2410 | checksum = "bf6cc3b19bfb128a8ad11026086e31d3ce9ad23f8ea37354b31383a187c44cf3" 2411 | dependencies = [ 2412 | "fallible-streaming-iterator", 2413 | ] 2414 | 2415 | [[package]] 2416 | name = "streaming-iterator" 2417 | version = "0.1.9" 2418 | source = "registry+https://github.com/rust-lang/crates.io-index" 2419 | checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" 2420 | 2421 | [[package]] 2422 | name = "strength_reduce" 2423 | version = "0.2.4" 2424 | source = "registry+https://github.com/rust-lang/crates.io-index" 2425 | checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" 2426 | 2427 | [[package]] 2428 | name = "strum" 2429 | version = "0.26.3" 2430 | source = "registry+https://github.com/rust-lang/crates.io-index" 2431 | checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" 2432 | 2433 | [[package]] 2434 | name = "strum_macros" 2435 | version = "0.25.3" 2436 | source = "registry+https://github.com/rust-lang/crates.io-index" 2437 | checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" 2438 | dependencies = [ 2439 | "heck 0.4.1", 2440 | "proc-macro2", 2441 | "quote", 2442 | "rustversion", 2443 | "syn 2.0.85", 2444 | ] 2445 | 2446 | [[package]] 2447 | name = "strum_macros" 2448 | version = "0.26.4" 2449 | source = "registry+https://github.com/rust-lang/crates.io-index" 2450 | checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" 2451 | dependencies = [ 2452 | "heck 0.5.0", 2453 | "proc-macro2", 2454 | "quote", 2455 | "rustversion", 2456 | "syn 2.0.85", 2457 | ] 2458 | 2459 | [[package]] 2460 | name = "subtle" 2461 | version = "2.6.1" 2462 | source = "registry+https://github.com/rust-lang/crates.io-index" 2463 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 2464 | 2465 | [[package]] 2466 | name = "syn" 2467 | version = "1.0.109" 2468 | source = "registry+https://github.com/rust-lang/crates.io-index" 2469 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 2470 | dependencies = [ 2471 | "proc-macro2", 2472 | "quote", 2473 | "unicode-ident", 2474 | ] 2475 | 2476 | [[package]] 2477 | name = "syn" 2478 | version = "2.0.85" 2479 | source = "registry+https://github.com/rust-lang/crates.io-index" 2480 | checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" 2481 | dependencies = [ 2482 | "proc-macro2", 2483 | "quote", 2484 | "unicode-ident", 2485 | ] 2486 | 2487 | [[package]] 2488 | name = "sync_wrapper" 2489 | version = "1.0.1" 2490 | source = "registry+https://github.com/rust-lang/crates.io-index" 2491 | checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" 2492 | dependencies = [ 2493 | "futures-core", 2494 | ] 2495 | 2496 | [[package]] 2497 | name = "sysinfo" 2498 | version = "0.29.11" 2499 | source = "registry+https://github.com/rust-lang/crates.io-index" 2500 | checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" 2501 | dependencies = [ 2502 | "cfg-if", 2503 | "core-foundation-sys", 2504 | "libc", 2505 | "ntapi", 2506 | "once_cell", 2507 | "winapi", 2508 | ] 2509 | 2510 | [[package]] 2511 | name = "system-configuration" 2512 | version = "0.6.1" 2513 | source = "registry+https://github.com/rust-lang/crates.io-index" 2514 | checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 2515 | dependencies = [ 2516 | "bitflags", 2517 | "core-foundation", 2518 | "system-configuration-sys", 2519 | ] 2520 | 2521 | [[package]] 2522 | name = "system-configuration-sys" 2523 | version = "0.6.0" 2524 | source = "registry+https://github.com/rust-lang/crates.io-index" 2525 | checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" 2526 | dependencies = [ 2527 | "core-foundation-sys", 2528 | "libc", 2529 | ] 2530 | 2531 | [[package]] 2532 | name = "target-features" 2533 | version = "0.1.6" 2534 | source = "registry+https://github.com/rust-lang/crates.io-index" 2535 | checksum = "c1bbb9f3c5c463a01705937a24fdabc5047929ac764b2d5b9cf681c1f5041ed5" 2536 | 2537 | [[package]] 2538 | name = "taxi-data-api-rust" 2539 | version = "0.1.0" 2540 | dependencies = [ 2541 | "actix-web", 2542 | "anyhow", 2543 | "chrono", 2544 | "env_logger", 2545 | "log", 2546 | "polars", 2547 | "rand", 2548 | "reqwest", 2549 | "serde", 2550 | "serde_json", 2551 | "tokio", 2552 | ] 2553 | 2554 | [[package]] 2555 | name = "tempfile" 2556 | version = "3.13.0" 2557 | source = "registry+https://github.com/rust-lang/crates.io-index" 2558 | checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" 2559 | dependencies = [ 2560 | "cfg-if", 2561 | "fastrand", 2562 | "once_cell", 2563 | "rustix", 2564 | "windows-sys 0.59.0", 2565 | ] 2566 | 2567 | [[package]] 2568 | name = "thiserror" 2569 | version = "1.0.65" 2570 | source = "registry+https://github.com/rust-lang/crates.io-index" 2571 | checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" 2572 | dependencies = [ 2573 | "thiserror-impl", 2574 | ] 2575 | 2576 | [[package]] 2577 | name = "thiserror-impl" 2578 | version = "1.0.65" 2579 | source = "registry+https://github.com/rust-lang/crates.io-index" 2580 | checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" 2581 | dependencies = [ 2582 | "proc-macro2", 2583 | "quote", 2584 | "syn 2.0.85", 2585 | ] 2586 | 2587 | [[package]] 2588 | name = "time" 2589 | version = "0.3.36" 2590 | source = "registry+https://github.com/rust-lang/crates.io-index" 2591 | checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" 2592 | dependencies = [ 2593 | "deranged", 2594 | "itoa", 2595 | "num-conv", 2596 | "powerfmt", 2597 | "serde", 2598 | "time-core", 2599 | "time-macros", 2600 | ] 2601 | 2602 | [[package]] 2603 | name = "time-core" 2604 | version = "0.1.2" 2605 | source = "registry+https://github.com/rust-lang/crates.io-index" 2606 | checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" 2607 | 2608 | [[package]] 2609 | name = "time-macros" 2610 | version = "0.2.18" 2611 | source = "registry+https://github.com/rust-lang/crates.io-index" 2612 | checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" 2613 | dependencies = [ 2614 | "num-conv", 2615 | "time-core", 2616 | ] 2617 | 2618 | [[package]] 2619 | name = "tinyvec" 2620 | version = "1.8.0" 2621 | source = "registry+https://github.com/rust-lang/crates.io-index" 2622 | checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" 2623 | dependencies = [ 2624 | "tinyvec_macros", 2625 | ] 2626 | 2627 | [[package]] 2628 | name = "tinyvec_macros" 2629 | version = "0.1.1" 2630 | source = "registry+https://github.com/rust-lang/crates.io-index" 2631 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 2632 | 2633 | [[package]] 2634 | name = "tokio" 2635 | version = "1.41.0" 2636 | source = "registry+https://github.com/rust-lang/crates.io-index" 2637 | checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" 2638 | dependencies = [ 2639 | "backtrace", 2640 | "bytes", 2641 | "libc", 2642 | "mio", 2643 | "parking_lot", 2644 | "pin-project-lite", 2645 | "signal-hook-registry", 2646 | "socket2", 2647 | "tokio-macros", 2648 | "windows-sys 0.52.0", 2649 | ] 2650 | 2651 | [[package]] 2652 | name = "tokio-macros" 2653 | version = "2.4.0" 2654 | source = "registry+https://github.com/rust-lang/crates.io-index" 2655 | checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" 2656 | dependencies = [ 2657 | "proc-macro2", 2658 | "quote", 2659 | "syn 2.0.85", 2660 | ] 2661 | 2662 | [[package]] 2663 | name = "tokio-native-tls" 2664 | version = "0.3.1" 2665 | source = "registry+https://github.com/rust-lang/crates.io-index" 2666 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 2667 | dependencies = [ 2668 | "native-tls", 2669 | "tokio", 2670 | ] 2671 | 2672 | [[package]] 2673 | name = "tokio-rustls" 2674 | version = "0.26.0" 2675 | source = "registry+https://github.com/rust-lang/crates.io-index" 2676 | checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" 2677 | dependencies = [ 2678 | "rustls", 2679 | "rustls-pki-types", 2680 | "tokio", 2681 | ] 2682 | 2683 | [[package]] 2684 | name = "tokio-util" 2685 | version = "0.7.12" 2686 | source = "registry+https://github.com/rust-lang/crates.io-index" 2687 | checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" 2688 | dependencies = [ 2689 | "bytes", 2690 | "futures-core", 2691 | "futures-sink", 2692 | "pin-project-lite", 2693 | "tokio", 2694 | ] 2695 | 2696 | [[package]] 2697 | name = "tower-service" 2698 | version = "0.3.3" 2699 | source = "registry+https://github.com/rust-lang/crates.io-index" 2700 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 2701 | 2702 | [[package]] 2703 | name = "tracing" 2704 | version = "0.1.40" 2705 | source = "registry+https://github.com/rust-lang/crates.io-index" 2706 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 2707 | dependencies = [ 2708 | "log", 2709 | "pin-project-lite", 2710 | "tracing-core", 2711 | ] 2712 | 2713 | [[package]] 2714 | name = "tracing-core" 2715 | version = "0.1.32" 2716 | source = "registry+https://github.com/rust-lang/crates.io-index" 2717 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 2718 | dependencies = [ 2719 | "once_cell", 2720 | ] 2721 | 2722 | [[package]] 2723 | name = "try-lock" 2724 | version = "0.2.5" 2725 | source = "registry+https://github.com/rust-lang/crates.io-index" 2726 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 2727 | 2728 | [[package]] 2729 | name = "typenum" 2730 | version = "1.17.0" 2731 | source = "registry+https://github.com/rust-lang/crates.io-index" 2732 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 2733 | 2734 | [[package]] 2735 | name = "unicode-bidi" 2736 | version = "0.3.17" 2737 | source = "registry+https://github.com/rust-lang/crates.io-index" 2738 | checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" 2739 | 2740 | [[package]] 2741 | name = "unicode-ident" 2742 | version = "1.0.13" 2743 | source = "registry+https://github.com/rust-lang/crates.io-index" 2744 | checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" 2745 | 2746 | [[package]] 2747 | name = "unicode-normalization" 2748 | version = "0.1.24" 2749 | source = "registry+https://github.com/rust-lang/crates.io-index" 2750 | checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" 2751 | dependencies = [ 2752 | "tinyvec", 2753 | ] 2754 | 2755 | [[package]] 2756 | name = "unicode-width" 2757 | version = "0.1.14" 2758 | source = "registry+https://github.com/rust-lang/crates.io-index" 2759 | checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" 2760 | 2761 | [[package]] 2762 | name = "untrusted" 2763 | version = "0.9.0" 2764 | source = "registry+https://github.com/rust-lang/crates.io-index" 2765 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 2766 | 2767 | [[package]] 2768 | name = "url" 2769 | version = "2.5.2" 2770 | source = "registry+https://github.com/rust-lang/crates.io-index" 2771 | checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" 2772 | dependencies = [ 2773 | "form_urlencoded", 2774 | "idna", 2775 | "percent-encoding", 2776 | ] 2777 | 2778 | [[package]] 2779 | name = "utf8parse" 2780 | version = "0.2.2" 2781 | source = "registry+https://github.com/rust-lang/crates.io-index" 2782 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 2783 | 2784 | [[package]] 2785 | name = "vcpkg" 2786 | version = "0.2.15" 2787 | source = "registry+https://github.com/rust-lang/crates.io-index" 2788 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2789 | 2790 | [[package]] 2791 | name = "version_check" 2792 | version = "0.9.5" 2793 | source = "registry+https://github.com/rust-lang/crates.io-index" 2794 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 2795 | 2796 | [[package]] 2797 | name = "want" 2798 | version = "0.3.1" 2799 | source = "registry+https://github.com/rust-lang/crates.io-index" 2800 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 2801 | dependencies = [ 2802 | "try-lock", 2803 | ] 2804 | 2805 | [[package]] 2806 | name = "wasi" 2807 | version = "0.11.0+wasi-snapshot-preview1" 2808 | source = "registry+https://github.com/rust-lang/crates.io-index" 2809 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2810 | 2811 | [[package]] 2812 | name = "wasm-bindgen" 2813 | version = "0.2.95" 2814 | source = "registry+https://github.com/rust-lang/crates.io-index" 2815 | checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" 2816 | dependencies = [ 2817 | "cfg-if", 2818 | "once_cell", 2819 | "wasm-bindgen-macro", 2820 | ] 2821 | 2822 | [[package]] 2823 | name = "wasm-bindgen-backend" 2824 | version = "0.2.95" 2825 | source = "registry+https://github.com/rust-lang/crates.io-index" 2826 | checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" 2827 | dependencies = [ 2828 | "bumpalo", 2829 | "log", 2830 | "once_cell", 2831 | "proc-macro2", 2832 | "quote", 2833 | "syn 2.0.85", 2834 | "wasm-bindgen-shared", 2835 | ] 2836 | 2837 | [[package]] 2838 | name = "wasm-bindgen-futures" 2839 | version = "0.4.45" 2840 | source = "registry+https://github.com/rust-lang/crates.io-index" 2841 | checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" 2842 | dependencies = [ 2843 | "cfg-if", 2844 | "js-sys", 2845 | "wasm-bindgen", 2846 | "web-sys", 2847 | ] 2848 | 2849 | [[package]] 2850 | name = "wasm-bindgen-macro" 2851 | version = "0.2.95" 2852 | source = "registry+https://github.com/rust-lang/crates.io-index" 2853 | checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" 2854 | dependencies = [ 2855 | "quote", 2856 | "wasm-bindgen-macro-support", 2857 | ] 2858 | 2859 | [[package]] 2860 | name = "wasm-bindgen-macro-support" 2861 | version = "0.2.95" 2862 | source = "registry+https://github.com/rust-lang/crates.io-index" 2863 | checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" 2864 | dependencies = [ 2865 | "proc-macro2", 2866 | "quote", 2867 | "syn 2.0.85", 2868 | "wasm-bindgen-backend", 2869 | "wasm-bindgen-shared", 2870 | ] 2871 | 2872 | [[package]] 2873 | name = "wasm-bindgen-shared" 2874 | version = "0.2.95" 2875 | source = "registry+https://github.com/rust-lang/crates.io-index" 2876 | checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" 2877 | 2878 | [[package]] 2879 | name = "web-sys" 2880 | version = "0.3.72" 2881 | source = "registry+https://github.com/rust-lang/crates.io-index" 2882 | checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" 2883 | dependencies = [ 2884 | "js-sys", 2885 | "wasm-bindgen", 2886 | ] 2887 | 2888 | [[package]] 2889 | name = "winapi" 2890 | version = "0.3.9" 2891 | source = "registry+https://github.com/rust-lang/crates.io-index" 2892 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2893 | dependencies = [ 2894 | "winapi-i686-pc-windows-gnu", 2895 | "winapi-x86_64-pc-windows-gnu", 2896 | ] 2897 | 2898 | [[package]] 2899 | name = "winapi-i686-pc-windows-gnu" 2900 | version = "0.4.0" 2901 | source = "registry+https://github.com/rust-lang/crates.io-index" 2902 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2903 | 2904 | [[package]] 2905 | name = "winapi-x86_64-pc-windows-gnu" 2906 | version = "0.4.0" 2907 | source = "registry+https://github.com/rust-lang/crates.io-index" 2908 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2909 | 2910 | [[package]] 2911 | name = "windows-core" 2912 | version = "0.52.0" 2913 | source = "registry+https://github.com/rust-lang/crates.io-index" 2914 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 2915 | dependencies = [ 2916 | "windows-targets", 2917 | ] 2918 | 2919 | [[package]] 2920 | name = "windows-registry" 2921 | version = "0.2.0" 2922 | source = "registry+https://github.com/rust-lang/crates.io-index" 2923 | checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" 2924 | dependencies = [ 2925 | "windows-result", 2926 | "windows-strings", 2927 | "windows-targets", 2928 | ] 2929 | 2930 | [[package]] 2931 | name = "windows-result" 2932 | version = "0.2.0" 2933 | source = "registry+https://github.com/rust-lang/crates.io-index" 2934 | checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" 2935 | dependencies = [ 2936 | "windows-targets", 2937 | ] 2938 | 2939 | [[package]] 2940 | name = "windows-strings" 2941 | version = "0.1.0" 2942 | source = "registry+https://github.com/rust-lang/crates.io-index" 2943 | checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" 2944 | dependencies = [ 2945 | "windows-result", 2946 | "windows-targets", 2947 | ] 2948 | 2949 | [[package]] 2950 | name = "windows-sys" 2951 | version = "0.52.0" 2952 | source = "registry+https://github.com/rust-lang/crates.io-index" 2953 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2954 | dependencies = [ 2955 | "windows-targets", 2956 | ] 2957 | 2958 | [[package]] 2959 | name = "windows-sys" 2960 | version = "0.59.0" 2961 | source = "registry+https://github.com/rust-lang/crates.io-index" 2962 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 2963 | dependencies = [ 2964 | "windows-targets", 2965 | ] 2966 | 2967 | [[package]] 2968 | name = "windows-targets" 2969 | version = "0.52.6" 2970 | source = "registry+https://github.com/rust-lang/crates.io-index" 2971 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 2972 | dependencies = [ 2973 | "windows_aarch64_gnullvm", 2974 | "windows_aarch64_msvc", 2975 | "windows_i686_gnu", 2976 | "windows_i686_gnullvm", 2977 | "windows_i686_msvc", 2978 | "windows_x86_64_gnu", 2979 | "windows_x86_64_gnullvm", 2980 | "windows_x86_64_msvc", 2981 | ] 2982 | 2983 | [[package]] 2984 | name = "windows_aarch64_gnullvm" 2985 | version = "0.52.6" 2986 | source = "registry+https://github.com/rust-lang/crates.io-index" 2987 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2988 | 2989 | [[package]] 2990 | name = "windows_aarch64_msvc" 2991 | version = "0.52.6" 2992 | source = "registry+https://github.com/rust-lang/crates.io-index" 2993 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2994 | 2995 | [[package]] 2996 | name = "windows_i686_gnu" 2997 | version = "0.52.6" 2998 | source = "registry+https://github.com/rust-lang/crates.io-index" 2999 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 3000 | 3001 | [[package]] 3002 | name = "windows_i686_gnullvm" 3003 | version = "0.52.6" 3004 | source = "registry+https://github.com/rust-lang/crates.io-index" 3005 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 3006 | 3007 | [[package]] 3008 | name = "windows_i686_msvc" 3009 | version = "0.52.6" 3010 | source = "registry+https://github.com/rust-lang/crates.io-index" 3011 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 3012 | 3013 | [[package]] 3014 | name = "windows_x86_64_gnu" 3015 | version = "0.52.6" 3016 | source = "registry+https://github.com/rust-lang/crates.io-index" 3017 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 3018 | 3019 | [[package]] 3020 | name = "windows_x86_64_gnullvm" 3021 | version = "0.52.6" 3022 | source = "registry+https://github.com/rust-lang/crates.io-index" 3023 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 3024 | 3025 | [[package]] 3026 | name = "windows_x86_64_msvc" 3027 | version = "0.52.6" 3028 | source = "registry+https://github.com/rust-lang/crates.io-index" 3029 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 3030 | 3031 | [[package]] 3032 | name = "xxhash-rust" 3033 | version = "0.8.12" 3034 | source = "registry+https://github.com/rust-lang/crates.io-index" 3035 | checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" 3036 | 3037 | [[package]] 3038 | name = "zerocopy" 3039 | version = "0.7.35" 3040 | source = "registry+https://github.com/rust-lang/crates.io-index" 3041 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 3042 | dependencies = [ 3043 | "byteorder", 3044 | "zerocopy-derive", 3045 | ] 3046 | 3047 | [[package]] 3048 | name = "zerocopy-derive" 3049 | version = "0.7.35" 3050 | source = "registry+https://github.com/rust-lang/crates.io-index" 3051 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 3052 | dependencies = [ 3053 | "proc-macro2", 3054 | "quote", 3055 | "syn 2.0.85", 3056 | ] 3057 | 3058 | [[package]] 3059 | name = "zeroize" 3060 | version = "1.8.1" 3061 | source = "registry+https://github.com/rust-lang/crates.io-index" 3062 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 3063 | 3064 | [[package]] 3065 | name = "zstd" 3066 | version = "0.13.2" 3067 | source = "registry+https://github.com/rust-lang/crates.io-index" 3068 | checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" 3069 | dependencies = [ 3070 | "zstd-safe", 3071 | ] 3072 | 3073 | [[package]] 3074 | name = "zstd-safe" 3075 | version = "7.2.1" 3076 | source = "registry+https://github.com/rust-lang/crates.io-index" 3077 | checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" 3078 | dependencies = [ 3079 | "zstd-sys", 3080 | ] 3081 | 3082 | [[package]] 3083 | name = "zstd-sys" 3084 | version = "2.0.13+zstd.1.5.6" 3085 | source = "registry+https://github.com/rust-lang/crates.io-index" 3086 | checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" 3087 | dependencies = [ 3088 | "cc", 3089 | "pkg-config", 3090 | ] 3091 | -------------------------------------------------------------------------------- /taxi-data-api-rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "taxi-data-api-rust" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | actix-web = "4.9.0" 8 | anyhow = "1.0.91" 9 | chrono = { version = "0.4.38", features = ["serde"] } 10 | env_logger = "0.11.5" 11 | log = "0.4.22" 12 | rand = "0.8.5" 13 | reqwest = { version = "0.12.9", features = ["json"] } 14 | serde = { version = "1.0.214", features = ["derive"] } 15 | serde_json = "1.0.132" 16 | tokio = { version = "1.0", features = ["full"] } 17 | polars = { version = "0.35", features = ["parquet", "lazy"] } -------------------------------------------------------------------------------- /taxi-data-api-rust/Dockerfile: -------------------------------------------------------------------------------- 1 | ### Build stage 2 | FROM rust:1.76-slim as builder 3 | WORKDIR /usr/src/app 4 | # Install OpenSSL development packages for compilation 5 | RUN apt-get update && \ 6 | apt-get install -y pkg-config libssl-dev && \ 7 | rm -rf /var/lib/apt/lists/* 8 | 9 | # Copy only the necessary files for building 10 | COPY Cargo.toml Cargo.lock ./ 11 | COPY src src/ 12 | 13 | # Build the application 14 | RUN cargo build --release 15 | 16 | 17 | ### Runtime stage 18 | FROM debian:bookworm-slim 19 | WORKDIR /usr/local/bin 20 | COPY --from=builder /usr/src/app/target/release/taxi-data-api-rust . 21 | RUN apt-get update && apt-get install -y libssl-dev ca-certificates && rm -rf /var/lib/apt/lists/* 22 | 23 | # Run as non-root user for better security 24 | # RUN useradd -m myapp 25 | # USER myapp 26 | 27 | EXPOSE 8080 28 | CMD ["./taxi-data-api-rust"] -------------------------------------------------------------------------------- /taxi-data-api-rust/Makefile: -------------------------------------------------------------------------------- 1 | export PORT=8089 2 | 3 | # Runs the API locally 4 | run-dev: 5 | cargo run 6 | 7 | # Commands to check the API works as expected when running locally 8 | health-check-local: 9 | curl -X GET "http://localhost:$(PORT)/health" 10 | 11 | sample-request-local: 12 | curl -X GET "http://localhost:$(PORT)/trips?from_ms=1714204800000&n_results=100" 13 | 14 | sample-request-no-results-local: 15 | curl -X GET "http://localhost:$(PORT)/trips?from_ms=1727430298000&n_results=100" 16 | 17 | build: 18 | docker build -t taxi-data-api-rust . 19 | 20 | run: build 21 | docker run -p $(PORT):8080 taxi-data-api-rust -------------------------------------------------------------------------------- /taxi-data-api-rust/README.md: -------------------------------------------------------------------------------- 1 | # Steps 2 | 3 | - [ ] Create Rust project structure 4 | - [ ] Don't forget Rust analyzer 5 | - [ ] Add actix-web 6 | - [ ] Create the HttpServer 7 | - [ ] Add /health endpoint 8 | 9 | - [ ] Easy error handling with anyhow 10 | 11 | - [ ] Set port from env variable 12 | - [ ] Add middleware for logging 13 | - [ ] Add /trips endpoint 14 | - [ ] Create another module backend.rs with the get_trips function 15 | - [ ] Implement the get_trips function 16 | 17 | 18 | ## Notes 19 | 20 | `unwrap()` extracts the value from an `Option` or a `Result` type, but it does that in 21 | a dangerous way. It will Panic and crash the program if the valueis None or Err. 22 | 23 | Alternatives: 24 | * `expect()` with a meaningfull message 25 | * Patter matching with `match` 26 | * `unwrap_or()` to provide a default value 27 | * `ok_or()` to convert to a Result -------------------------------------------------------------------------------- /taxi-data-api-rust/src/backend.rs: -------------------------------------------------------------------------------- 1 | use chrono::{DateTime, Utc, Datelike}; 2 | use serde::Serialize; 3 | use log::{info, error}; 4 | use anyhow::Result; 5 | use polars::prelude::*; 6 | use rand::Rng; 7 | 8 | #[derive(Debug, Serialize, Clone)] 9 | pub struct Trip { 10 | tpep_pickup_datetime: DateTime, 11 | tpep_dropoff_datetime: DateTime, 12 | trip_distance: f64, 13 | fare_amount: f64, 14 | } 15 | 16 | pub async fn get_fake_trips(from_ms: i64, n_results: i64) -> Result> { 17 | // Create a random number generator 18 | let mut rng = rand::thread_rng(); 19 | 20 | // Create n_results fake trips 21 | let trips = (0..n_results).map(|_| { 22 | let random_seconds = rng.gen_range(0..60); 23 | let pickup_time = DateTime::::from_timestamp(from_ms / 1000 + random_seconds, 0).unwrap(); 24 | let dropoff_time = DateTime::::from_timestamp(from_ms / 1000 + random_seconds + rng.gen_range(300..3600), 0).unwrap(); 25 | 26 | Trip { 27 | tpep_pickup_datetime: pickup_time, 28 | tpep_dropoff_datetime: dropoff_time, 29 | trip_distance: rng.gen_range(0.5..20.0), 30 | fare_amount: rng.gen_range(2.5..100.0), 31 | } 32 | }).collect(); 33 | 34 | Ok(trips) 35 | } 36 | 37 | /// Reads taxi trip data from a parquet file and returns a vector of Trip structs 38 | /// 39 | /// # Arguments 40 | /// 41 | /// * `file_path` - Path to the parquet file containing taxi trip data 42 | /// * `from_ms` - Unix timestamp in milliseconds to filter trips after this time 43 | /// * `n_results` - Maximum number of trips to return 44 | /// 45 | /// # Returns 46 | /// 47 | /// Returns a Result containing a Vec of Trip structs if successful, or an error if the 48 | /// file cannot be read or the data is invalid 49 | fn get_trips_from_file( 50 | file_path: &str, 51 | from_ms: i64, 52 | n_results: i64 53 | ) -> Result> { 54 | 55 | let df = LazyFrame::scan_parquet(file_path, Default::default())? 56 | .select([ 57 | col("tpep_pickup_datetime"), 58 | col("tpep_dropoff_datetime"), 59 | col("trip_distance"), 60 | col("fare_amount"), 61 | ]) 62 | .filter(col("tpep_pickup_datetime").gt_eq(lit(from_ms * 1_000_000))) 63 | .sort("tpep_pickup_datetime", Default::default()) 64 | .limit(n_results as u32) 65 | .collect()?; 66 | 67 | let pickup_series = df 68 | .column("tpep_pickup_datetime")? 69 | .datetime() 70 | .expect("pickup datetime column should be datetime type"); 71 | 72 | let dropoff_series = df 73 | .column("tpep_dropoff_datetime")? 74 | .datetime() 75 | .expect("dropoff datetime column should be datetime type"); 76 | 77 | let distance_series = df 78 | .column("trip_distance")? 79 | .f64() 80 | .expect("distance column should be f64 type"); 81 | 82 | let fare_series = df 83 | .column("fare_amount")? 84 | .f64() 85 | .expect("fare column should be f64 type"); 86 | 87 | // Convert to Vec 88 | let trips: Vec = (0..df.height()).map(|i| { 89 | Trip { 90 | tpep_pickup_datetime: DateTime::::from_timestamp_nanos(pickup_series.get(i).unwrap()), 91 | tpep_dropoff_datetime: DateTime::::from_timestamp_nanos(dropoff_series.get(i).unwrap()), 92 | trip_distance: distance_series.get(i).unwrap(), 93 | fare_amount: fare_series.get(i).unwrap(), 94 | } 95 | }) 96 | .collect(); 97 | 98 | Ok(trips) 99 | } 100 | 101 | pub async fn get_trips(from_ms: i64, n_results: i64) -> Result> { 102 | 103 | let (year, month) = get_year_and_month(from_ms); 104 | info!("Extracted year: {}, month: {}", year, month); 105 | 106 | // Download the parquet file 107 | info!("Downloading parquet file for year: {}, month: {}", year, month); 108 | let file_path = download_parquet_file(year, month).await?; 109 | 110 | // Get the trips from the file 111 | let trips = get_trips_from_file(&file_path, from_ms, n_results)?; 112 | 113 | // TODO: Fake data for now 114 | // let trips = get_fake_trips(); 115 | 116 | info!("Returning {} trips", trips.len()); 117 | Ok(trips) 118 | } 119 | 120 | pub async fn download_parquet_file(year: i32, month: i32) -> Result { 121 | 122 | let url = format!( 123 | "https://d37ci6vzurychx.cloudfront.net/trip-data/yellow_tripdata_{}-{:02}.parquet", 124 | year, 125 | month 126 | ); 127 | let file_path = format!("yellow_tripdata_{}-{:02}.parquet", year, month); 128 | 129 | // Check if the file already exists. If it does, return the file path. 130 | if tokio::fs::try_exists(&file_path).await? { 131 | info!("File {} already exists", &file_path); 132 | return Ok(file_path); 133 | } 134 | 135 | info!("Downloading file from {}", &url); 136 | let response = reqwest::get(&url).await?; 137 | if response.status().is_success() { 138 | 139 | let bytes = response.bytes().await?; 140 | 141 | // async copy of bytes to file 142 | tokio::fs::write(&file_path, bytes).await?; 143 | 144 | info!("File {} downloaded successfully", &file_path); 145 | } else { 146 | error!("Failed to download file"); 147 | } 148 | Ok(file_path) 149 | } 150 | 151 | pub fn get_year_and_month(from_ms: i64) -> (i32, i32) { 152 | let datetime = DateTime::::from_timestamp(from_ms / 1000, 0).unwrap(); 153 | (datetime.year(), datetime.month() as i32) 154 | } 155 | -------------------------------------------------------------------------------- /taxi-data-api-rust/src/main.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{App, HttpServer, web, HttpResponse}; 2 | use log::{info, error}; 3 | use std::env; 4 | use serde::Deserialize; 5 | use env_logger::Env; 6 | 7 | mod backend; 8 | use crate::backend::{get_trips, get_fake_trips}; 9 | 10 | async fn health() -> HttpResponse { 11 | HttpResponse::Ok().json(serde_json::json!({ 12 | "status": "healthy", 13 | "timestamp": chrono::Utc::now().to_rfc3339() 14 | })) 15 | } 16 | 17 | #[derive(Deserialize)] 18 | struct TripsQuery { 19 | from_ms: i64, 20 | n_results: i64 21 | } 22 | 23 | async fn trips(query: web::Query) -> HttpResponse { 24 | match get_fake_trips(query.from_ms, query.n_results).await { 25 | Ok(trips) => HttpResponse::Ok().json(trips), 26 | Err(e) => HttpResponse::InternalServerError().body(e.to_string()) 27 | } 28 | } 29 | 30 | #[actix_web::main] 31 | async fn main() -> std::io::Result<()> { 32 | 33 | // Initialize the logger 34 | env_logger::init_from_env(Env::new().default_filter_or("info")); 35 | 36 | let port = env::var("PORT") 37 | .unwrap_or_else(|_| "8080".to_string()) 38 | .parse::() 39 | .expect("PORT must be a valid number"); 40 | 41 | info!("Starting server on port {}", port); 42 | 43 | HttpServer::new(|| { 44 | App::new() 45 | .wrap(actix_web::middleware::Logger::default()) 46 | .route("/health", web::get().to(health)) 47 | .route("/trips", web::get().to(trips)) 48 | }) 49 | .bind(("0.0.0.0", port))? 50 | .run() 51 | .await.map_err(|e| { 52 | error!("Error starting server: {}", e); 53 | e 54 | }) 55 | } -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paulescu/taxi-data-api-python/1ec743d2626c26a785ea624a8d231f6c84f245ae/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_read_parquet.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | from src.backend import read_parquet_file 4 | 5 | 6 | def test_read_parquet_file_returns_non_empty_dataframe(): 7 | # Arrange 8 | year = 2024 9 | month = 1 10 | 11 | # Act 12 | result = read_parquet_file(year, month) 13 | 14 | # Assert 15 | assert result is not None 16 | assert isinstance(result, pd.DataFrame) 17 | assert not result.empty 18 | --------------------------------------------------------------------------------