* Set up the web project dependencies

- Add linters, pre-commit, and GitHub Actions
- Add a Makefile
- Add a pyproject.toml

* Fix pyupgrade job

- Remove continue_on_error everywhere

* Remove old code

* Rename a GithubActions job

* Change README

* Adjust pre-commit and GitHub actions

* Add tables and set up alembic

* Set up tests

* Extend tests

* Add coverage config

* Adjust the GithubActions workflow

* Fix GithubActions workflow

* Try fixing pyproject-fmt config

* Fix formatting of pyproject.toml

* Fix formatting of pyproject.toml

* Add coverage report

* Test listing the repositories

* Add a working prototype of SourceGraph client

* Add parsing of the SourceGraph SSE data

* Fix tests

* Ged rid of packages replaced by ruff

* Fix waits in the SourceGraph client

* Refactor the models and add a mapper

- A new mapper allows to create database repositories from the SourceGraph data

* Add mypy

* Try fixing mypy action

* Remove redundant configs

* Exclude tests from type checking

* Fix mypy pre-commit and GitHub action

* Ignore factories

* Make upserting possible for source graph data

* Add logic for parsing the dependencies and populating the database

* Add a database and a cron GitHub Action job

* Try manually trigger a workflow

* Bring back the old config

* Add ReadTimeout for errors to retry for in SourceGraph client

* Add typer

* Adjust the docstrings

* Update the database

* Refactor and optimize scraping and dependencies parsing

* Make scraping run on push for now

* Add a unique constraint for the repo url and source graph repo id

* Change the index columns in on_conflict statement for repo creation

* Optimize dependencies parsing

- Do not parse dependencies for a repo  when revision did not change

* Scraped repositories from Source Graph

* Refactor scraping

* Set up frontend

* Scraped repositories from Source Graph

* Add TODOs

* Skip scraping when testing

* Fix a test with updating the repos

* Scraped repositories from Source Graph

* Add some more TODOs

* Scraped repositories from Source Graph

* Add some more TODO comments

* Add chadcn/ui

* Scraped repositories from Source Graph

* Create index.json

* Scraped repositories from Source Graph

* Add a draft of data table and display all the repos

* Scraped repositories from Source Graph

* Implement stars badges and description with overflow

* Format the links to Github repos

* Fix link clicking

* Scraped repositories from Source Graph

* Add simple pagination and stars column sorting

* Scraped repositories from Source Graph

* Implement basic searching

* Scraped repositories from Source Graph

* Implement a multiselect for dependencies

* Scraped repositories from Source Graph

* Implement actual filtering by dependencies

* Scraped repositories from Source Graph

* Add a workflow to deploy nextjs on github pages

* Try fixing the deployment job

* Enable static exports for app router

* Fix uploading arifacts for nextjs job

* Set base path to properly load JS and CSS

* Fix the base path

* Scraped repositories from Source Graph

* Add header

* Remove language version

* Scraped repositories from Source Graph

* Add some more TODOs

* Scraped repositories from Source Graph

* Adjust the pre-commit config

* Fix pipelines

* Scraped repositories from Source Graph

* Add a footer

* Create the indexes

* Scraped repositories from Source Graph

* Add more TODOs

* Introduce minor footer adjustments

* Adjust the scraping actions

* Scraped repositories from Source Graph, parsed the dependencies, and generated the indexes

* Implement query params state

* Scraped repositories from Source Graph, parsed the dependencies, and generated the indexes

* Do not commit query state on unmount

* Scraped repositories from Source Graph, parsed the dependencies, and generated the indexes

* Hopefully fix query states and multiselect input

* Scraped repositories from Source Graph, parsed the dependencies, and generated the indexes

* Extend the Makefile

* Resolve most of TODOs

* Resolve the conflicts with anyio version, bring back httpx

* Adjust the Makefile and README.md

* Fix a typo in README.md

* Adjust readme

* Fix the Makefile

* Fix some stuff

* Make some adjustments

* Possibly fix failing scraping jobs

* Load the repo project URL from env

---------

Co-authored-by: vladfedoriuk <vladfedoriuk@users.noreply.github.com>
Co-authored-by: Vladyslav Fedoriuk <vladyslav.fedoriuk@deployed.pl>
This commit is contained in:
Vladyslav Fedoriuk 2023-10-28 21:39:02 +02:00 committed by GitHub
parent 02fb674332
commit 2fdd348a15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
97 changed files with 110761 additions and 16653 deletions

68
.github/workflows/app.yaml vendored Normal file
View File

@ -0,0 +1,68 @@
name: Python App Quality and Testing
on: [push]
jobs:
quality:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.11]
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with: # https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md#caching-packages
python-version: ${{ matrix.python-version }}
cache: "pip"
cache-dependency-path: "requirements/dev.txt"
- name: Install dev dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements/dev.txt
- name: Lint with ruff
run: |
python -m ruff check --verbose --format=github .
- name: Lint with mypy
run: |
python -m mypy --show-error-codes --pretty --show-column-numbers --show-error-context .
- name: Lint with black
run: |
python -m black --check --verbose .
- name: Lint with pyproject-fmt
run: |
python -m pyproject_fmt --check --indent=4 .
test:
needs: [quality]
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.11]
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with: # https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md#caching-packages
python-version: ${{ matrix.python-version }}
cache: "pip"
cache-dependency-path: "requirements/test.txt"
- name: Install test dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements/test.txt
- name: Test with pytest
run: |
python -m pytest -v -s --failed-first --cov=app --cov-report=xml --cov-branch
- name: Generate Coverage Report
run: |
python -m coverage report -m
- name: Upload coverage to Codecov
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
if: ${{ env.CODECOV_TOKEN }}
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: coverage.xml
name: python ${{ matrix.python-version }}

120
.github/workflows/frontend.yaml vendored Normal file
View File

@ -0,0 +1,120 @@
# Sample workflow for building and deploying a Next.js site to GitHub Pages
#
# To get started with Next.js see: https://nextjs.org/docs/getting-started
#
name: Build and Deploy Next.js to GitHub Pages
on:
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run
workflow_run:
workflows:
- "Scraping the repositories from Source Graph"
- "Python App Quality and Testing"
branches: [main]
types:
- completed
# Allows you to run this workflow manually from the Actions tab
# https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Build job
build:
runs-on: ubuntu-latest
# Use ``frontend`` as the working directory
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_iddefaultsrun
defaults:
run:
working-directory: ./frontend
strategy:
matrix:
node-version: [18.17.1]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up pnpm
uses: pnpm/action-setup@v2
with:
version: 8
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: "pnpm"
cache-dependency-path: "./frontend/pnpm-lock.yaml"
- name: Install dependencies
run: pnpm install
- name: Setup Pages
uses: actions/configure-pages@v3
with:
# Automatically inject basePath in your Next.js configuration file and disable
# server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized).
#
# You may remove this line if you want to manage the configuration yourself.
static_site_generator: next
- name: Build with Next.js
run: pnpm next build
- name: Static HTML export with Next.js
run: pnpm next export
- name: Upload artifact
if: ${{ !env.ACT }} # skip during local actions testing
uses: actions/upload-pages-artifact@v2
with:
path: ./frontend/out
# Lint job
lint:
runs-on: ubuntu-latest
# Use ``frontend`` as the working directory
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_iddefaultsrun
defaults:
run:
working-directory: ./frontend
strategy:
matrix:
node-version: [18.17.1]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up pnpm
uses: pnpm/action-setup@v2
with:
version: 8
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: "pnpm"
cache-dependency-path: "./frontend/pnpm-lock.yaml"
- name: Install dependencies
run: pnpm install
- name: Lint with ESLint
run: pnpm lint
- name: Lint with Prettier
run: pnpm prettier:lint
# Deployment job
deploy:
if: ${{ !github.event.act }} # skip during local actions testing
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2

51
.github/workflows/scraping.yaml vendored Normal file
View File

@ -0,0 +1,51 @@
name: Scraping the repositories from Source Graph
on:
schedule:
# Trigger every day at midnight
# https://crontab.guru/#0_0_*_*_*
- cron: '0 0 * * *'
# Allows you to run this workflow manually from the Actions tab
# https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
workflow_dispatch:
concurrency: # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency
group: "scraping"
cancel-in-progress: false
jobs:
scraping:
if: ${{ !github.event.act }} # skip during local actions testing
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.11]
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
cache-dependency-path: "requirements/base.txt"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements/base.txt
- name: Scrape the repositories
run: |
python -m app.scrape scrape-repos
- name: Parse the dependencies
run: |
python -m app.scrape parse-dependencies
- name: Generate the repositories index
run: |
python -m app.index index-repos
- name: Generate the dependencies index
run: |
python -m app.index index-dependencies
- name: Commit the changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "Scraped repositories from Source Graph, parsed the dependencies, and generated the indexes"

166
.gitignore vendored
View File

@ -1,6 +1,162 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
links.txt
unique_links.txt
imports.txt
reps/
.vscode
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
# Ruff cache
.ruff_cache/

2
.gitlint Normal file
View File

@ -0,0 +1,2 @@
[general]
ignore=body-is-missing

1
.node-version Normal file
View File

@ -0,0 +1 @@
v18.18.0

53
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,53 @@
---
default_language_version:
python: python3.11
default_install_hook_types: [pre-commit, commit-msg]
default_stages: [commit]
fail_fast: false
minimum_pre_commit_version: 3.3.3
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: mixed-line-ending
args: ["--fix=lf"]
- id: check-added-large-files
- id: check-toml
- id: check-yaml
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.280
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: local
hooks:
- id: mypy
name: mypy
entry: |
python -m mypy .
types: [python]
language: system
require_serial: true
pass_filenames: false
- repo: https://github.com/ambv/black
rev: 23.7.0
hooks:
- id: black
- repo: https://github.com/tox-dev/pyproject-fmt
rev: "0.13.0"
hooks:
- id: pyproject-fmt
args: ["--indent=4"]
- repo: https://github.com/pre-commit/mirrors-prettier
rev: "v3.0.3"
hooks:
- id: prettier
entry: prettier --write --list-different --ignore-unknown --config frontend/.prettierrc --ignore-path frontend/.prettierignore
files: ^frontend/
language_version: 18.18.0
- repo: https://github.com/jorisroovers/gitlint
rev: "v0.19.1"
hooks:
- id: gitlint

139
Makefile Normal file
View File

@ -0,0 +1,139 @@
# we want bash behaviour in all shell invocations
SHELL := bash
# Run each target in a separate shell
.ONESHELL:
# Fail on error inside any functions or subshells
.SHELLFLAGS := -eu -o pipefail -c
# Remove partially created files on error
.DELETE_ON_ERROR:
# Warn when an undefined variable is referenced
MAKEFLAGS += --warn-undefined-variables
# Disable built-in rules
MAKEFLAGS += --no-builtin-rules
# A catalog of requirements files
REQUIREMENTS?=requirements
help: # Show this help
@echo "Usage: make [target]"
@echo ""
@echo "Targets:"
@echo " help Show this help"
@echo " requirements-base Compile base requirements"
@echo " requirements-test Compile test requirements"
@echo " requirements-dev Compile dev requirements"
@echo " requirements Compile all requirements"
@echo " install Install the app locally"
@echo " install-front Install frontend"
@echo " install-test Install the app locally with test dependencies"
@echo " install-dev Install the app locally with dev dependencies"
@echo " install-test-dev Install the app locally with test and dev dependencies"
@echo " init-test-dev Install the app locally with test and dev dependencies. Also install pre-commit hooks."
@echo " reinit-test-dev Reinstall pre-commit hooks"
@echo " lint Run linters"
@echo " test Run tests"
@echo " migrate Run migrations"
@echo " revision Create a new migration"
@echo " front Run frontend"
@echo " scrape-repos Scrape repos"
@echo " parse-dependencies Scrape dependencies"
@echo " index-repos Index repos"
@echo " index-dependencies Index dependencies"
requirements-base: # Compile base requirements
python -m piptools compile \
--output-file=requirements/base.txt \
-v \
pyproject.toml
requirements-test: requirements-base # Compile test requirements
python -m piptools compile \
--extra=test \
--output-file=requirements/test.txt \
-v \
pyproject.toml
requirements-dev: requirements-base # Compile dev requirements
python -m piptools compile \
--extra=dev \
--output-file=requirements/dev.txt \
-v \
pyproject.toml
requirements: requirements-base requirements-test requirements-dev # Compile all requirements
.PHONY: requirements
install: # Install the app locally
python -m pip install -r $(REQUIREMENTS)/base.txt .
.PHONY: install
install-test: # Install the app locally with test dependencies
python -m pip install \
-r $(REQUIREMENTS)/base.txt \
-r $(REQUIREMENTS)/test.txt \
--editable .
.PHONY: install-test
install-dev: # Install the app locally with dev dependencies
python -m pip install \
-r $(REQUIREMENTS)/base.txt \
-r $(REQUIREMENTS)/dev.txt \
--editable .
.PHONY: install-dev
install-test-dev: # Install the app locally with test and dev dependencies
python -m pip install \
-r $(REQUIREMENTS)/base.txt \
-r $(REQUIREMENTS)/test.txt \
-r $(REQUIREMENTS)/dev.txt \
--editable .
.PHONY: install-test-dev
install-front: # Install frontend
cd frontend && pnpm install
.PHONY: install-front
init-test-dev: install-test-dev # Install the app locally with test and dev dependencies. Also install pre-commit hooks.
pre-commit install
.PHONY: init-test-dev
reinit-test-dev: init-test-dev # Reinstall pre-commit hooks
pre-commit install --install-hooks --overwrite
.PHONY: reinit-test-dev
lint: # Run linters
pre-commit run --all-files
.PHONY: lint
test: # Run tests
python -m pytest -vv -s --cov=app --cov-report=xml --cov-branch app
.PHONY: test
migrate: # Run migrations
python -m alembic upgrade heads
.PHONY: migrate
revision: # Create a new migration
python -m alembic revision --autogenerate -m "$(message)"
.PHONY: revision
front: install-front # Run frontend
cd frontend && pnpm dev
.PHONY: front
scrape-repos: # Scrape repos
python -m app.scrape scrape-repos
.PHONY: scrape-repos
parse-dependencies: # Scrape dependencies
python -m app.scrape parse-dependencies
.PHONY: parse-dependencies
index-repos: # Index repos
python -m app.index index-repos
.PHONY: index-repos
index-dependencies: # Index dependencies
python -m app.index index-dependencies
.PHONY: index-dependencies
.DEFAULT_GOAL := init-test-dev # Set the default goal to init-dev-test

591
README.md
View File

@ -1,550 +1,57 @@
# Awesome FastAPI Projects
> **Warning**
> If you want to help me to maintain this project, please send a message on https://github.com/Kludex/awesome-fastapi-projects/issues/16.
> I'll happily onboard you.
View the website: https://Kludex.github.io/awesome-fastapi-projects/
The aim of this repository is to have an organized list of projects that use FastAPI.
## Local Development
If you're looking for FastAPI content, you might want to check [Awesome FastAPI](https://github.com/mjhea0/awesome-fastapi).
### Setup
## Table
#### Python and Virtual Environment
| Project | Dependencies |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|[2020_slowdelivery_take](https://github.com/zekaio/2020_slowdelivery_take ) |aiohttp, pytest, tortoise |
|[AI-Service](https://github.com/eHelply/AI-Service ) |kombu, setuptools, pymongo, redis, sentry_asgi, sentry_sdk, pymlconf, socketio, src |
|[African_Wildlife_Classifier](https://github.com/peterbacalso/African_Wildlife_Classifier ) |aiohttp, fastai, torch |
|[Auth-Service](https://github.com/eHelply/Auth-Service ) |kombu, requests, setuptools, passlib, pymongo, redis, sentry_asgi, sentry_sdk, pymlconf, jwt, socketio, src, bson |
|[BenchmarkRoundOne](https://github.com/peterdeme/BenchmarkRoundOne ) |aiohttp |
|[Benchmarker](https://github.com/vutran1710/Benchmarker ) |apis |
|[Blog](https://github.com/elbruno/Blog ) |face_recognition, imutils, PIL, flask, cv2 |
|[CCTO](https://github.com/SnarferX/CCTO ) |sets, SimpleHTTPSErver, requests, dircache, ovm_lib, jarray, pip, httplib, urllib3, SockerServer, ansible, hello, java, ovmclient |
|[CFE_30D.PY](https://github.com/torredefarol24/CFE_30D.PY ) |formatting, flask, scrape, logger, requests, pandas, download_util, requests_html |
|[COVID-19API](https://github.com/zeroday0619/COVID-19API ) |aiohttp, ujson, async_lru, API, scrapy, fastapi_plugins, aioredis, bs4 |
|[COVID-QA](https://github.com/deepset-ai/COVID-QA ) |elasticapm, eval, sentence_transformers, sklearn, elasticsearch, tqdm, scrapy, requests, backend, nltk, haystack, preprocess, farm, langid, datasources, torch, tfidf_train, covid_nlp |
|[CUCM-Phone-Info](https://github.com/jsteinberg1/CUCM-Phone-Info ) |rq, cryptography, zeep, requests, redis, lxml, lib, apscheduler, api, OpenSSL, sqlalchemy, jwt, bs4 |
|[Chatbot](https://github.com/aramakus/Chatbot ) |nltk, chatterbot, sklearn, requests, tqdm, chatbot |
|[ChatiChatou](https://github.com/auredentan/ChatiChatou ) |chat, aioredis |
|[CheckersAI](https://github.com/HuiiBuh/CheckersAI ) |pytest, aiohttp, game, api, conftest, checkers |
|[Cloud_APS1](https://github.com/ehrhardt98/Cloud_APS1 ) |pymongo, requests |
|[CryptoViz](https://github.com/MohanVashist1/CryptoViz ) |bs4, requests, pyti, pymongo, lib, binance, dateutil, cryptocalculator, channelfinder, dotenv, flask, boto3, click, fastapi_users |
|[DS-API](https://github.com/BW-Post-Here-06-2020/DS-API ) |dotenv, praw |
|[Daft](https://github.com/mpalka31/DaftAcademyCourse ) |main, queries, schemas, pytest, jose, database, crud |
|[Daims_FastAPI](https://github.com/GeorgeMiao219/Daims_FastAPI ) |auth, dns, dataset, config, url, utils, database |
|[Data-Engineering](https://github.com/De-Dash/Data-Engineering ) |nltk, aiohttp, api |
|[Docker-Builder](https://github.com/Javier162380/Docker-Builder ) |rq, pytest, endpoints, requests, redis, builder, docker, settings, docker_builder, models, worker, middlewares, router |
|[Dispatch](https://github.com/Netflix/dispatch ) |SQLAlchemy-Searchable, aiofiles, alembic arrow bcrypt, cachetools, click, email-validator, emails, fastapi_permissions, google-api-python-client, google-auth-oauthlib, h11, httpx, jinja2, jira, joblib, numpy, oauth2client, pandas, pdpyras, psycopg2-binary, pyparsing, python-dateutil, python-jose, python-multipart, pytz, requests, rsa, schedule, sentry-asgi, sentry-sdk, sh, slackclient, spacy, sqlalchemy, sqlalchemy-filters, statsmodels, tabulate, tenacity, uvicorn |
|[DockerImageResNet50](https://github.com/OrenLeung/DockerImageResNet50 ) |redis, PIL, locust, keras |
|[Downotifier](https://github.com/herbzhao/Downotifier ) |twilio, bs4, requests, URLChecker, TwilioWhatsapp |
|[ExcelTools](https://github.com/xx2life/ExcelTools ) |motor, databases |
|[ExpenseAPI](https://github.com/MushroomMaula/ExpenseAPI ) |pytest, faker, sqlalchemy, myapp, fastapi_login, alembic, dotenv |
|[FAAS](https://github.com/jacksonhenry3/FAAS ) |flask |
|[Fast-API-Starter](https://github.com/khaman1/Fast-API-Starter ) |shared, urls |
|[Fast-Project](https://github.com/alex-2201/Fast-Project ) |redis, conn, cassandra, apis, pymysql, logzero, models, utils, middlewares |
|[FastAPI-Auth](https://github.com/Madpilot0/FastAPI-Auth ) |bcrypt, lib, routes, yaml, jwt, MySQLdb |
|[FastAPI-CRUD](https://github.com/Mr-Manna/FastAPI-CRUD ) |databases, sqlalchemy, post, config |
|[FastAPI-Demo](https://github.com/JPMike/FastAPI-Demo ) |requests |
|[FastAPI-Example](https://github.com/gauravgola96/FastAPI-Example ) |botocore, aiobotocore, dotenv, s3_events, boto3, utils |
|[FastAPI-Learning-Example](https://github.com/oinsd/FastAPI-Learning-Example ) |main, main_b, jwt, routers, sqlalchemy, database, passlib |
|[FastAPI-React-PostgreSQL_Full-Stack](https://github.com/scionoftech/FastAPI-React-PostgreSQL_Full-Stack ) |db, setuptools, logs, passlib, utils, sqlalchemy, conf, routes, auth, jwt |
|[FastAPITutorial](https://github.com/HeywoodKing/FastAPITutorial ) |invoke, config |
|[FastAPI_Tortoise_template](https://github.com/GoddessEyes/FastAPI_Tortoise_template ) |celery, jwt, tortoise, template, passlib, emails |
|[FastAPI_Vue](https://github.com/quietking0312/FastAPI_Vue ) |pymongo, apps |
|[FastAPI_app1](https://github.com/Sai-Vamsi-Ogety/FastAPI_app1 ) |spacy |
|[FastAPI_proto](https://github.com/bartomo/FastAPI_proto ) |controllers, urls, sqlalchemy, db, models |
|[FastAdmin](https://github.com/CoderCharm/FastAdmin ) |passlib, loguru, sqlalchemy, myapp, jose, alembic |
|[Fastapi](https://github.com/xyz25/Fastapi ) |router_app, sqlalchemy |
|[FastapiLearn](https://github.com/xuqm/FastapiLearn ) |part4, part11, part7, part8, part15, part2, part10, application, part14, part12, part9, part13, part3, part16, part1, part5, part6 |
|[Fusion-Vision](https://github.com/sdhnshu/Fusion-Vision ) |wandb, pytest, sklearn, requests, tqdm, torch, text_classification |
|[GET_POST](https://github.com/mitsumushibayama/GET_POST ) |MySQLdb |
|[GraphQLAPI](https://github.com/webjunkie01/GraphQLAPI ) |graphene, cryptacular, pytest, graphene_sqlalchemy, sqlalchemy |
|[Gringotts](https://github.com/cning112/Gringotts ) |werkzeug, requests, flask_restplus, typing_extensions, apis, flask_cors, libs, flask, routers, models |
|[HjwzwApi](https://github.com/k1dave6412/HjwzwApi ) |backend, requests, aiohttp, asyncpg, loguru, sqlalchemy, myapp, alembic, databases, bs4 |
|[Image-Diff-back](https://github.com/filipe-guerra/Image-Diff-back ) |imutils, skimage, imageDiff, cv2 |
|[Item-Xref](https://github.com/Roselingit/Item-Xref ) |psycopg2 |
|[KOARCH](https://github.com/janstrohschein/KOARCH ) |classes, emotion_recognition_master, pydash, sklearn, requests, tweepy, scipy, kafka, yaml, psycopg2, emotion_predictor, avro, keras |
|[Logging-Service](https://github.com/eHelply/Logging-Service ) |kombu, setuptools, pymongo, redis, sentry_asgi, sentry_sdk, pymlconf, socketio, src |
|[MLServer](https://github.com/SeldonIO/MLServer ) |orjson, grpc, click, pytest, mlserver, google, setuptools |
|[MallAPI](https://github.com/CoderCharm/MallAPI ) |alembic, loguru, sqlalchemy, extensions, setting, myapp, api, utils |
|[MealCare](https://github.com/hack4impact-mcgill/MealCare ) |pony, passlib, config, tests, sqlalchemy, psycopg2, jwt |
|[MetodoClasificacionTexto](https://github.com/talend-Erick/MetodoClasificacionTexto ) |gensim, nltk, spacy, src, pandas |
|[MyChild](https://github.com/YunusovSamat/MyChild ) |passlib, asyncpg, tortoise, sqlalchemy, alembic, databases, jwt |
|[MyNotes](https://github.com/wq758511990/MyNotes ) |serial, werkzeug, flask_sqlalchemy, flask_httpauth, sqlalchemy, wtforms, pytz, webapp, flask, itsdangerous |
|[NIMSPARQL](https://github.com/Ningensei848/NIMSPARQL ) |elasticapm, sqlalchemy, elasticsearch, db, api |
|[NT118](https://github.com/maivanhung33/NT118 ) |request, kombu, common, elasticsearch, geopy, requests, injector, pymongo, redis, consul, boltons, cachetools, controller, elasticsearch_dsl, sqlalchemy, service, pytz, response |
|[News-Summarizer](https://github.com/CYBINT-IN/News-Summarizer ) |scipy, sentence_transformers, flask, sklearn, torch, requests, transformers, pyLDAvis, bs4 |
|[Notification-Service](https://github.com/eHelply/Notification-Service ) |kombu, setuptools, pymongo, redis, sentry_asgi, sentry_sdk, pymlconf, socketio, src |
|[Pycharm](https://github.com/godori004/Pycharm ) |urllib3, flask_restful, flask, src, pandas, google |
|[Python-example](https://github.com/hzjsea/Python-example ) |netmiko, static_files, requests, basedb, sqlalchemy, ansible, zabbix_info |
|[Python3Test](https://github.com/hjslovehr/Python3Test ) |requests, redis, openpyxl, sqlhelper, pymssql, md5_helper, flask, helpers, bs4 |
|[PythonFastApi](https://github.com/kbeaugrand/PythonFastApi ) |win32service, win32event, servicemanager, win32serviceutil, yaml |
|[RemoteVP-Npc](https://github.com/viccom/RemoteVP-Npc ) |win32serviceutil, serial, requests, apps, pythoncom, cores, helper, ping3, bases, hbmqtt, conf, Crypto, wmi |
|[RestFramework](https://github.com/rakesh4real/RestFramework ) |django, streamapp, rest_framework, other_app, jwt, senddata, my_app, passlib |
|[SOA](https://github.com/FisnikL/SOA ) |prometheus_client, sqlalchemy, sqlalchemy_utils, database |
|[Semester-Stats](https://github.com/Rushyanth111/Semester-Stats ) |playhouse, faker, setuptools, peewee, mailmerge, docx |
|[Service-Template](https://github.com/eHelply/Service-Template ) |kombu, setuptools, pymongo, redis, sentry_asgi, sentry_sdk, pymlconf, socketio, src |
|[SpotifyAPI](https://github.com/dixneuf19/SpotifyAPI ) |spotipy, dotenv, src |
|[StanleyIpkiss](https://github.com/JimmiBram/StanleyIpkiss ) |tests, sibase |
|[Studium-ds](https://github.com/Lambda-School-Labs/Studium-ds ) |retrieve_definition, gauge_plot, requests, calendar_heatmap, inflect |
|[TT_COVID19_API_site_and_emailer](https://github.com/VSpectrum/TT_COVID19_API_site_and_emailer ) |email_validator, requests, config, emailer |
|[TaskXenter](https://github.com/CoolSpring8/TaskXenter ) |celery, sentry_sdk, loguru, databases, jwt, tortoise, passlib, httpx |
|[Telegram-BusBot-DataManager](https://github.com/David-Lor/Telegram-BusBot-DataManager ) |pymongo, motor, busbot_data_manager |
|[WAM_server_API_template](https://github.com/rl-institut/WAM_server_API_template ) |flask_app, celery, flask, pytest, worker, sphinx_rtd_theme |
|[WEB](https://github.com/maivanhung33/WEB ) |request, kombu, common, elasticsearch, geopy, requests, injector, pymongo, redis, consul, boltons, cachetools, controller, elasticsearch_dsl, sqlalchemy, service, pytz, response |
|[WFM](https://github.com/unegade/WFM ) |pika, aio_pika, BSSAPI, locust |
|[WebApp-PhoneClassifier](https://github.com/minh-dg/WebApp-PhoneClassifier ) |fastai |
|[WitnessMe](https://github.com/byt3bl33d3r/WitnessMe ) |xmltodict, imgcat, pytest, pyppeteer, jinja2, terminaltables, prompt_toolkit, pkg_resources, aiosqlite, yaml, witnessme |
|[Words_record](https://github.com/LMFrank/Words_record ) |databases, pytest, pymysql, sqlalchemy, requests |
|[Workspace](https://github.com/AYCHSPACE/Workspace ) |tqdm, jupyter_core, setuptools, tornado, crontab, pip, psutil, IPython, git, notebook |
|[YoutubeBackup](https://github.com/FratStar/YoutubeBackup ) |google_auth_oauthlib, zeep, googleapiclient, spyne, google |
|[Zulu](https://github.com/OSS-team-zulu/Zulu ) |requests, passlib, pymongo, geojson, tests, zulu, dynaconf, jwt, bson, pytest |
|[ai-dungeon](https://github.com/AntonNeld/ai-dungeon ) |errors, test_utils, typing_extensions, pytest, models, api, dungeon |
|[aioprometheus](https://github.com/claws/aioprometheus ) |setuptools, aiohttp, alabaster, quart, psutil, asynctest, sphinx, aioprometheus, quantile, prometheus_metrics_proto |
|[aita](https://github.com/logan-connolly/aita ) |pytest, requests, tqdm, aiohttp, asyncpg, aita, loguru, orm, typer, sqlalchemy, databases, praw |
|[alda-online](https://github.com/JesseChua94/alda-online ) |models, alda |
|[alg_interface_fastapi_project](https://github.com/wuzaipei/alg_interface_fastapi_project ) |system_file, pymysql, sqlalchemy, data_model |
|[alice-yamaha-skill](https://github.com/toshka/alice-yamaha-skill ) |exceptions, auth, yaml, capabilities, routers, rxv, config, httpx |
|[allay-ds](https://github.com/Lambda-School-Labs/allay-ds ) |wandb, spacy, sklearn, requests, scrapy, process_data, fastapi_app, tensorflow, numpy, indeed, en_core_web_sm, dotenv |
|[allure_reporter](https://github.com/penguinlav/allure_reporter ) |jinja2, requests, allure_reporter, loguru, aiofiles, async_generator, pytest |
|[andrewhou-zonar](https://github.com/amhou/andrewhou-zonar ) |main, requests, util |
|[apex-tracker](https://github.com/Timzan/apex-tracker ) |routers, requests, config |
|[api](https://github.com/wuzaipei/alg_interface_fastapi_project ) |pyazo_api, alembic, dotenv, jwt, sqlalchemy, passlib |
|[api-ocr](https://github.com/dzakyputra/api-ocr ) |tesserocr, PIL, cv2, modules |
|[api-poc](https://github.com/igorfarias30/fastapi-poc ) |sklearn |
|[api.authentication](https://github.com/jrhuerta/api.authentication ) |api_authentication |
|[api_works](https://github.com/omrylcn/api_works ) |PIL, requests |
|[apiestas](https://github.com/franloza/apiestas ) |crawling, scrapy, fuzzywuzzy, loguru, slugify, api, js2xml, dateparser, typer, twisted, pytz, motor |
|[apitoolbox](https://github.com/zuarbase/apitoolbox ) |pytest, setuptools, passlib, sqlalchemy_filters, tests, sqlalchemy, ordered_uuid, tzlocal, pytz, jwt, apitoolbox, itsdangerous |
|[arcas](https://github.com/maialogic/arcas ) |graphene, snapshottest |
|[asgi-server-timing-middleware](https://github.com/sm-Fifteen/asgi-server-timing-middleware ) |yappi, asgi_server_timing, setuptools |
|[asu-schedule](https://github.com/skhortiuk/asu-schedule ) |aiohttp, src, validators, bs4 |
|[async_django_session](https://github.com/imbolc/async_django_session ) |setuptools, aiohttp, asyncpg, async_django_session, cfg, django, databases |
|[authal-poc](https://github.com/michal-nakoneczny/authal-poc ) |authal, asynctest, pytest, bson, requests, tests, httpx |
|[auto_populate](https://github.com/NealWhitlock/auto_populate ) |psycopg2, getter |
|[autoloadtest](https://github.com/hkiang01/autoloadtest ) |locust, hypothesis |
|[automagic_hashtag](https://github.com/MarianMalvin/automagic_hashtag ) |utils, google |
|[b0mb3r](https://github.com/crinny/b0mb3r ) |setuptools, sentry_sdk, loguru, pkg_resources, b0mb3r, phonenumbers, click, httpx |
|[b2blue-challenge](https://github.com/lfvilella/b2blue-challenge ) |pydantic_sqlalchemy, sqlalchemy |
|[b3ta](https://github.com/nm17/b3ta ) |setuptools, sentry_sdk, loguru, pkg_resources, service, b0mb3r, phonenumbers, click, httpx |
|[backend](https://github.com/ElusiveSpirit/fbd-backend ) |asynctest, transliterate |
|[backend-skeleton](https://github.com/dmontagu/backend-skeleton ) |pytest, requests, typing_extensions, sqlalchemy_utils, tests, sqlalchemy, myapp, alembic, tenacity |
|[balikobot_tmp_2](https://github.com/Horac-Bouthon/balikobot_tmp_2 ) |logger_wrapper, databases, schemas, sqlalchemy, conf, routers, sql_factory |
|[base-fastapi-postgresql](https://github.com/alldevic/base-fastapi-postgresql ) |alembic, arq, sqlalchemy, sqlalchemy_utils, gino |
|[basic-python-postgis-docker](https://github.com/stephenhillier/basic-python-postgis-docker ) |alembic, tenacity, sqlalchemy, myapp |
|[bc_rates](https://github.com/MRobalinho/bc_rates ) |bc |
|[belajar-fastapi](https://github.com/aansubarkah/belajar-fastapi ) |yfinance, sqlalchemy, models, config, tutorial, database |
|[bench-rest-api-frameworks](https://github.com/py4mac/bench-rest-api-frameworks ) |sanic, locust, aiohttp, tornado, api, main, core |
|[biomedical-computing-project-backend](https://github.com/SinaKhalili/biomedical-computing-project-backend ) |extra, xlrd, CoronaAnalysis |
|[blog](https://github.com/deagle-z/blog ) |blog, loguru, jwt, sqlalchemy |
|[blog-posts](https://github.com/tiangolo/blog-posts ) |pytest, sqlalchemy, jose, passlib |
|[bluesky](https://github.com/paulorodriguesxv/bluesky ) |pytest, passlib, aiohttp, decouple, sqlalchemy_utils, sqlalchemy, myapp, alembic, jwt |
|[boilerplate](https://github.com/pmcarlos/fast-api-boilerplate ) |utils, config |
|[book-graphics](https://github.com/kamartem/book-graphics ) |alembic, sentry_sdk, asyncpg, loguru, sqlalchemy, gino |
|[bplustogether](https://github.com/wborbajr/bplustogether ) |dynaconf, databases, loguru, sqlalchemy, bpapi |
|[bracket_install](https://github.com/mobjack/bracket_install ) |six, flask, requests, colorama |
|[bread-app](https://github.com/aidan-mcbride/bread-app ) |pyArango, pytest, jwt, routers, api, tests, passlib |
|[bridgeapp](https://github.com/jasujm/bridgeapp ) |click, orjson, bridgeapp, click_log, pytest, zmq |
|[budget-blocks-ds](https://github.com/Lambda-School-Labs/budget-blocks-ds ) |DB, geopy, transactionhist, mainhelp, census, main, psycopg2, dotenv, routers |
|[bullshit-website](https://github.com/kaylynn234/bullshit-website ) |corporate_bullshit |
|[burriking](https://github.com/txemac/burriking ) |infrastructure, dependency_injector, werkzeug, requests, pymongo, freezegun, tests, config, main, user_interface, application, database, flask, bson, pytest, flasgger, domain |
|[bw3_attempt](https://github.com/worldwidekatie/bw3_attempt ) |dotenv, sklearn, requests, joblib |
|[c4p2n](https://github.com/piterpy-meetup/c4p2n ) |c4p2n, fastapi_security_typeform, notion, ppm_telegram_bot_client |
|[cah-v2](https://github.com/Mdellit110/cah-v2 ) |graphene, schema, graphene_sqlalchemy, sqlalchemy, models, config, schema_blackcards, database, schema_whitecards |
|[calculator](https://github.com/ch0c01ate/calculator ) |pymongo, calculator, requests, dbsetup |
|[canvote](https://github.com/alvintangz/canvote ) |jinja2, requests, passlib, sqlalchemy_pagination, humps, sqlalchemy, myapp, pytz, alembic, secure, jwt |
|[cashflow](https://github.com/VSpectrum/cashflow ) |pytest, config |
|[ccrbackend](https://github.com/danieldominguete/ccrbackend ) |six, dotenv, dynamorm, mangum, src, jose, marshmallow |
|[challenge](https://github.com/Creditas/challenge ) |iris_classifier, sklearn |
|[chapushillo](https://github.com/maxipavlovic/chapushillo ) |pusher, dotenv, pusher_client |
|[checkmarx](https://github.com/zetkin/checkmarx ) |scanner, checkmarx, pytest, pyzbar, setuptools |
|[chinook_fastapi](https://github.com/sandervandorsten/chinook_fastapi ) |dotenv, setuptools, chinook_fastapi |
|[cloudrun-fastapi](https://github.com/anthcor/cloudrun-fastapi ) |pytest, actions, passlib, sqlalchemy_utils, config, tests, main, sqlalchemy, myapp, database, google, alembic, schemas, jwt, routers, gunicorn_config, models |
|[cnapp-fastapi](https://github.com/cnapp/cnapp-fastapi ) |sanic, daiquiri, jinja2, prometheus_client, cnapps, starlette_prometheus |
|[code_example_fastapi](https://github.com/d-tamirlan/code_example_fastapi ) |tortoise, src, envparse, fastapi_users |
|[codewars-watchdog](https://github.com/uriyyo/codewars-watchdog ) |git |
|[coding-challenges](https://github.com/fjemi/coding-challenges ) |password_generator, tqdm, jsbeautifier, dateutil, matplotlib, flask_api, word_square_check, flask |
|[concurrency](https://github.com/Jorricks/concurrency ) |PIL, setuptools, redis, dataclasses_json, src, asgiref, click |
|[contact-form](https://github.com/k4ssyi/contact-form ) |dotenv, controllers, urls, settings, utils, request_body |
|[cookiecutter-python](https://github.com/ValentinCalomme/cookiecutter-python ) |typer |
|[cookiecutter-simcore-py-fastapi](https://github.com/pcrespov/cookiecutter-simcore-py-fastapi ) |cryptography, pytest, servicelib, setuptools, simcore_service_catalog, aiohttp, pkg_resources, attr, ptvsd, aiopg, sqlalchemy, tenacity, yarl, httpx |
|[coronavirus-tg-api](https://github.com/egbakou/coronavirus-tg-api ) |aiohttp, invoke, asyncmock, dateparser, async_asgi_testclient, async_generator, dotenv, pytest, bs4 |
|[coursera-ibm-ai-workflow-submission](https://github.com/eightBEC/coursera-ibm-ai-workflow-submission ) |loguru, sklearn, pytest, joblib |
|[coursework](https://github.com/algorithm-ssau/coursework ) |dotenv, databases, motor |
|[covid-19-Chile](https://github.com/RentadroneCL/covid-19-Chile ) |orator, dotenv, routes, pendulum, covid_19_chile, config, database |
|[covid-19-dashboard-api](https://github.com/zeshuaro/covid-19-dashboard-api ) |sortedcontainers, dotenv, jwt, pycountry, requests, google, passlib |
|[covid19-id](https://github.com/anzharip/covid19-id ) |selenium, requests |
|[covidfaq](https://github.com/dialoguemd/covidfaq ) |pytest, spacy, sklearn, tqdm, requests, covidfaq, selenium, bert_reranker, structlog, spacy_langdetect, yaml, html2text, boto3, torch, transformers, bs4 |
|[covidsage](https://github.com/chancey-gardener/covidsage ) |spacy, data_loader, requests, backends, nlu_client, numpy, matplotlib, plotter, rasa, rasa_sdk, pymysql, discourse |
|[cpython3-fastapi](https://github.com/phongln/cpython3-fastapi ) |blog, admin |
|[custom-actions-app-python](https://github.com/Frameio/custom-actions-app-python ) |pytest, requests, custom_actions |
|[daftacademy-python-levelup](https://github.com/holdenkold/daftacademy-python-levelup ) |main, pytest |
|[daiei-backend](https://github.com/a-nakajima-at-shokuryu/daiei-backend ) |fastapi_server, dotenv, models, utils, dateutil, settings |
|[daizu-online-judge-backend](https://github.com/SoyBeansLab/daizu-online-judge-backend ) |psycopg2, infrastructure, marshmallow_dataclass, interface, marshmallow, domain |
|[dask-remote](https://github.com/octoenergy/dask-remote ) |distributed, typing_extensions, pytest, requests, dask_remote, setuptools |
|[datarepo](https://github.com/PUG-PB-Traducao/datarepo ) |bcrypt, dotenv, fastapi_sqlalchemy, sqlalchemy |
|[debitcard](https://github.com/xpnewmedia/debitcard ) |debitcard |
|[debts](https://github.com/afonasev/debts ) |pytest, locust, factory, passlib, sentry_asgi, sentry_sdk, contextvars_executor, server, context_logging, sqlalchemy, alembic, jwt |
|[decentralized-news-publishing](https://github.com/teddymarkov/decentralized-news-publishing ) |ariadne |
|[demo-dms](https://github.com/gucharbon/demo-dms ) |urllib3, typer, pytest, minio, backend |
|[deploy](https://github.com/pcmalves/codeploy-teste ) |main |
|[devops-assignment](https://github.com/fokinpv/devops-assignment ) |asynctest, pytest, service, pulp |
|[devs-conn-api](https://github.com/txemac/devs-conn-api ) |github, pytest, sqlalchemy, sqlalchemy_utils, data, twitter, tests |
|[dfstore](https://github.com/Exhor/dfstore ) |requests, src, tests, feather |
|[dig-bioindex](https://github.com/broadinstitute/dig-bioindex ) |requests, colorama, orjson, lib, enlighten, sqlalchemy, dotenv, boto3, click |
|[django-fastapi-example](https://github.com/jordaneremieff/django-fastapi-example ) |django, api |
|[docker-fastapi-demo](https://github.com/pylixm/docker-fastapi-demo ) |alembic, loguru, databases, core, sqlalchemy, service, myapp, api |
|[docker-workshop](https://github.com/blairdrummond/docker-workshop ) |scipy, PIL, dash, flask, inference, sklearn, requests, numpy, joblib, flask_caching |
|[downloads_statistics](https://github.com/mmidu/downloads_statistics ) |redis, main, seeds, controllers, DownloadSeeder, requests, models, config, utils, DownloadsController |
|[dreamcatcher](https://github.com/sbathgate/dreamcatcher ) |pytest, passlib, sqlalchemy, myapp, jose, alembic, celery, tenacity, raven, emails |
|[duke](https://github.com/jamescurtin/duke ) |duke, PIL, pytest |
|[eXchangeAPI-PY](https://github.com/wborbajr/eXchangeAPI-PY ) |pymongo, dynaconf, exchangeapi, motor |
|[educator_api](https://github.com/wycliffogembo87/educator_api ) |pony, requests, passlib, loguru, api, settings, schemas, core, models, util |
|[effortless_fast_api](https://github.com/davideasaf/effortless_fast_api ) |requests, passlib, invoke, config, utils, main, sqlalchemy, schemas, jwt, models, services, pytest |
|[embl_python_software_engineer_test](https://github.com/yusra-haider/embl_python_software_engineer_test ) |sqlalchemy, requests |
|[eml_analyzer](https://github.com/ninoseki/eml_analyzer ) |async_timeout, pytest, eml_parser, compressed_rtf, arrow, compoundfiles, olefile, loguru, fastapi_utils, tests, dateparser, asynctest, magic, aiospamc, ioc_finder, respx, httpx |
|[entroprise-api](https://github.com/peterdeepsix/entroprise-api ) |simpletransformers, service, models, api |
|[eu-taxation-customs-api](https://github.com/aditya-08/eu-taxation-customs-api ) |main, zeep, requests |
|[events-api](https://github.com/txemac/events-api ) |pytz, xmltodict, pytest, sqlalchemy, sqlalchemy_utils, apscheduler, data, requests, tests |
|[example-fastapi-sqlachemy-pytest](https://github.com/timhughes/example-fastapi-sqlachemy-pytest ) |example, pytest, sqlalchemy |
|[excerpt-formatter](https://github.com/cmckillop/excerpt-formatter ) |text_formatter, slack_manager, requests, models |
|[fake-news-game](https://github.com/jsandovalc/fake-news-game ) |databases |
|[fantasy-fencing](https://github.com/Innoviox/fantasy-fencing ) |colorlog, selenium, click, scrape, requests, logs, bs4 |
|[fapi](https://github.com/glebofff/fapi ) |api, sqlalchemy, myapp, alembic, fastapi_sqlalchemy, core, models, click |
|[fast](https://github.com/foobar8675/fastai-bite ) |routers, user |
|[fast-api-asyncdb](https://github.com/tsadimas/fast-api-asyncdb ) |dotenv, databases, sqlalchemy, settings, fastapi_users |
|[fast-api-boilerplate](https://github.com/pmcarlos/fast-api-boilerplate ) |alembic, dotenv, fastapi_sqlalchemy, core, sqlalchemy, myapp |
|[fast-api-rest](https://github.com/javier-lopez/fast-api-rest ) |config, bjoern |
|[fast-api-sql-template](https://github.com/Jonatha-Varjao/fast-api-sql-template ) |pytest, googletrans, requests, passlib, sqlalchemy_utils, sqlalchemy, alembic, jwt, emails |
|[fast-elm](https://github.com/yuzebin/fast-elm ) |bcrypt, fmmodel, requests, fmsecurity, passlib, fmdb, slugify, fmcrud, fmapi, databases, motor, jwt, fmtoken, bson |
|[fastAPI-be](https://github.com/BonneC/fastAPI-be ) |alembic, dotenv, sqlalchemy, models, api, config, myapp, crud |
|[fastApi](https://github.com/fionasummer/fastApiSelf ) |my_super_project, graphene, projetStage, sqlalchemy |
|[fastApiSelf](https://github.com/fionasummer/fastApiSelf ) |pytest, rr, sqlalchemy, websocket, fackApi, app1 |
|[fastApiSimple](https://github.com/marirs/fastApiSimple ) |pymongo, geoip2, motor, server |
|[fastAppAppointment](https://github.com/EdvinaNakos/fastAppAppointment ) |main, controller, databases, sqlalchemy, db, service |
|[fast_api](https://github.com/davideasaf/effortless_fast_api ) |app_utils, bcrypt, schemas, jwt, sqlalchemy, models, database, crud |
|[fast_api_camelcase_example](https://github.com/ahmednafies/fast_api_camelcase_example ) |humps, models |
|[fast_api_self_study](https://github.com/cuongld2/fast_api_self_study ) |bcrypt, jwt, sqlalchemy, sql_app |
|[fastaaps](https://github.com/sergio-chumacero/fastaaps ) |pymongo, celery, motor |
|[fastai-bite](https://github.com/foobar8675/fastai-bite ) |PIL, graphene, my_utils, fastai2, cv2, httpx |
|[fastapi-GraphQL-full-stack-docker-github-actions-graphene-test-client-template](https://github.com/gaylonalfano/fastapi-GraphQL-full-stack-docker-github-actions-graphene-test-client-template )|graphene, pytest, sqlalchemy, graphql, snapshottest |
|[fastapi-GraphQL-full-stack-docker-travisci-starlette-test-client-template](https://github.com/gaylonalfano/fastapi-GraphQL-full-stack-docker-travisci-starlette-test-client-template ) |graphene, pytest |
|[fastapi-admin](https://github.com/long2ice/fastapi-admin ) |colorama, passlib, fastapi_admin, prompt_toolkit, tortoise, module, xlsxwriter, jwt |
|[fastapi-auth](https://github.com/dmontagu/fastapi-auth ) |argon2, bcrypt, pytest, requests, typing_extensions, fastapi_auth, tests, sqlalchemy, jwt |
|[fastapi-backend](https://github.com/dev-courses/fastapi-backend ) |bcrypt, pytest, passlib, asyncpg, loguru, slugify, tests, asgi_lifespan, sqlalchemy, docker, alembic, psycopg2, databases, jwt, httpx |
|[fastapi-boilerplate](https://github.com/teamhide/fastapi-boilerplate ) |alembic, jwt, sqlalchemy, core, myapp |
|[fastapi-celery](https://github.com/GregaVrbancic/fastapi-celery ) |worker, celery |
|[fastapi-celery-redis-rabbitmq](https://github.com/karthikasasanka/fastapi-celery-redis-rabbitmq ) |redis, celery, shopping |
|[fastapi-cool](https://github.com/genchsusu/fastapi-cool ) |kombu, aiosmtplib, tortoise, yaml, settings, celery, jwt, ldap3 |
|[fastapi-crud](https://github.com/sophiabrandt/fastapi-crud ) |databases, pytest, sqlalchemy, db |
|[fastapi-crud-sync](https://github.com/testdrivenio/fastapi-crud-sync ) |pytest, sqlalchemy |
|[fastapi-demo](https://github.com/sonhal/fastapi-demo ) |rethinkdb, fastapi_demo |
|[fastapi-discovery](https://github.com/DenisOH/fastapi-discovery ) |sqlalchemy, fastapi_discovery |
|[fastapi-docs-cn](https://github.com/apachecn/fastapi-docs-cn ) |graphene, passlib, peewee, couchbase, sqlalchemy, flask, databases, jwt |
|[fastapi-esf-demo](https://github.com/hightfly/fastapi-esf-demo ) |databases, sqlalchemy, sqlalchemy_utils |
|[fastapi-etag](https://github.com/steinitzu/fastapi-etag ) |pytest, requests, fastapi_etag |
|[fastapi-exploring](https://github.com/manjurulhoque/fastapi-exploring ) |alembic, dotenv, fastapi_sqlalchemy, sqlalchemy, myapp |
|[fastapi-for-firebase](https://github.com/attakei/fastapi-for-firebase ) |fastapi_for_firebase, pytest |
|[fastapi-fullstack](https://github.com/lfvilella/fastapi-fullstack ) |pytest, sqlalchemy, validate_docbr |
|[fastapi-healthcheck](https://github.com/jeffsiver/fastapi-healthcheck ) |healthcheck, setuptools |
|[fastapi-helloworld](https://github.com/yashwanthl/fastapi-helloworld ) |nltk, sklearn, modules |
|[fastapi-hero](https://github.com/Hedde/fastapi-heroku-test ) |dotenv, motor, core, db, bson, models, api |
|[fastapi-hex-boilerplate](https://github.com/GArmane/fastapi-hex-boilerplate ) |factory, toolz, tests, sqlalchemy, myapp, alembic, dotenv, databases, pytest |
|[fastapi-jsonrpc](https://github.com/smagafurov/fastapi-jsonrpc ) |fastapi_jsonrpc, aiojobs, pytest, setuptools |
|[fastapi-jwt](https://github.com/carminati-marco/fastapi-jwt ) |ms_auth, auth, jwt, passlib |
|[fastapi-layered-architecture](https://github.com/teamhide/fastapi-layered-architecture ) |alembic, pythondi, jwt, sqlalchemy, core, myapp |
|[fastapi-login](https://github.com/parsd/fastapi-login ) |pytest, requests, setuptools, fastapi_login, assertpy |
|[fastapi-mako](https://github.com/LouisYZK/fastapi-mako ) |mako, setuptools |
|[fastapi-mangum-example](https://github.com/chgangaraju/fastapi-mangum-example ) |mangum |
|[fastapi-microblog](https://github.com/vkhnychenko/fastapi-microblog ) |alembic, core, sqlalchemy, microblog, myapp, user |
|[fastapi-ml-scaffolding](https://github.com/jmeisele/fastapi-ml-scaffolding ) |loguru, pytest, fastapi_scaffolding, joblib |
|[fastapi-ml-skeleton](https://github.com/eightBEC/fastapi-ml-skeleton ) |loguru, pytest, fastapi_skeleton, joblib |
|[fastapi-mount](https://github.com/Midnighter/fastapi-mount ) |mount_demo |
|[fastapi-nuxt-blog](https://github.com/tokusumi/fastapi-nuxt-blog ) |PIL, passlib, sqlalchemy_utils, sqlalchemy, myapp, sendgrid, pytz, alembic, jwt, boto3, pytest |
|[fastapi-permissions](https://github.com/holgi/fastapi-permissions ) |pytest, jwt, fastapi_permissions, passlib |
|[fastapi-playground](https://github.com/FlorianBorn/fastapi-playground ) |PIL, fastai |
|[fastapi-plugins](https://github.com/madkote/fastapi-plugins ) |fastapi_plugins, setuptools, aioredis, tenacity, aiojobs, pytest |
|[fastapi-poc](https://github.com/igorfarias30/fastapi-poc ) |main, data, models, todo |
|[fastapi-postgres-aws-lambda](https://github.com/KurtKline/fastapi-postgres-aws-lambda ) |mangum, sqlalchemy |
|[fastapi-realworld-example-app-mysql](https://github.com/xiaozl/fastapi-realworld-example-app-mysql ) |bcrypt, passlib, asyncpg, loguru, aiomysql, tests, asgi_lifespan, docker, psycopg2, databases, jwt, pytest, httpx |
|[fastapi-route](https://github.com/franodos/fastapi-route ) |response, setuptools |
|[fastapi-satella-metrics](https://github.com/piotrmaslanka/fastapi-satella-metrics ) |fastapi_satella_metrics, requests, setuptools, satella |
|[fastapi-scaffold](https://github.com/ibegyourpardon/fastapi-scaffold ) |xuan |
|[fastapi-simple-cachecontrol](https://github.com/attakei/fastapi-simple-cachecontrol ) |fastapi_simple_cachecontrol, pytest |
|[fastapi-simple-template](https://github.com/MushroomMaula/fastapi-simple-template ) |alembic, dotenv, pytest, faker, sqlalchemy, myapp, fastapi_login |
|[fastapi-snippets](https://github.com/hhatto/fastapi-snippets ) |caches, fastapi_plugins, aioredis |
|[fastapi-sqlalchemy](https://github.com/zuarbase/fastapi-sqlalchemy-example ) |pytest, setuptools, passlib, sqlalchemy_filters, tests, sqlalchemy, ordered_uuid, tzlocal, pytz, fastapi_sqlalchemy, jwt, itsdangerous |
|[fastapi-sqlalchemy-example](https://github.com/zuarbase/fastapi-sqlalchemy-example ) |alembic, itsdangerous, fastapi_sqlalchemy, pytest, fastapi_sqlalchemy_example, sqlalchemy, myapp, click, setuptools |
|[fastapi-starter-kit](https://github.com/Shinichi-Nakagawa/fastapi-starter-kit ) |book, pytest, sqlalchemy, db |
|[fastapi-tdd-docker](https://github.com/pmcarlos/fastapi-tdd-docker ) |pytest, tortoise |
|[fastapi-template](https://github.com/jefmud/fastapi-templates ) |pytest, setuptools, passlib, sentry_sdk, sqlalchemy_utils, gino, sqlalchemy, jose, alembic, fastapi_template, migrations |
|[fastapi-test](https://github.com/jrwalk/fastapi-test ) |pytest, pandas |
|[fastapi-tools](https://github.com/so1n/fastapi-tools ) |fastapi_tools, prometheus_client, httpx |
|[fastapi-tortoise](https://github.com/prostomarkeloff/fastapi-tortoise ) |loguru, pytest, tortoise, requests, tests |
|[fastapi-users](https://github.com/frankie567/fastapi-users ) |passlib, tortoise, tests, asynctest, asgi_lifespan, sqlalchemy, httpx_oauth, makefun, databases, motor, jwt, fastapi_users, pytest, httpx |
|[fastapi-utils](https://github.com/dmontagu/fastapi-utils ) |pytest, fastapi_utils, tests, sqlalchemy |
|[fastapi-uvicorn-gunicorn-nginx-supervisor-boilerplate](https://github.com/sumitsk20/fastapi-uvicorn-gunicorn-nginx-supervisor-boilerplate ) |orjson, motor, core, server, bson, apps, utils |
|[fastapi-versioning](https://github.com/DeanWay/fastapi-versioning ) |example, typing_extensions, fastapi_versioning, setuptools |
|[fastapi-vue-test](https://github.com/abreumatheus/fastapi-vue-test ) |PIL, sqlalchemy, myapp, pytz, alembic, boto3 |
|[fastapi-websockets](https://github.com/natanael-silvamt/fastapi-websockets ) |api |
|[fastapi-whisper-rest-api](https://github.com/BolajiOlajide/fastapi-whisper-rest-api ) |api |
|[fastapi_admin](https://github.com/Chise1/fastapi_admin ) |apps, setuptools, passlib, fastapi_admin, sqlalchemy, settings, databases, pymysql, jwt |
|[fastapi_catchup](https://github.com/Kamihara/fastapi_catchup ) |intro |
|[fastapi_douyin](https://github.com/bigdataboy2020/fastapi_douyin ) |routers, requests, settings, exceptions, spiders |
|[fastapi_gino](https://github.com/pengyejun/fastapi_gino ) |gino_starlette, pytest, gino_fastapi_demo, sqlalchemy, myapp, aioredis, alembic, poetry, urllib2 |
|[fastapi_microblog](https://github.com/mrworksome/fastapi_microblog ) |alembic, databases, core, sqlalchemy, microblog, myapp, user, passlib, fastapi_users |
|[fastapi_mock](https://github.com/superxuu/fastapi_mock ) |apis, yaml, common |
|[fastapi_model](https://github.com/Nathanlauga/fastapi_model ) |loguru, joblib |
|[fastapi_playground](https://github.com/Rurson/fastapi_playground ) |pony, db |
|[fastapi_preset](https://github.com/cln-m4rie/fastapi_preset ) |setuptools |
|[fastapi_router](https://github.com/christopherzimmerman/fastapi_router ) |fastapi_router, trimport, setuptools |
|[fastapi_serviceutils](https://github.com/skallfass/fastapi_serviceutils_template ) |pytest, requests, setuptools, toolz, loguru, fastapi_serviceutils, yaml, cookiecutter, sqlalchemy, databases |
|[fastapi_serviceutils_template](https://github.com/skallfass/fastapi_serviceutils_template ) |fastapi_serviceutils |
|[fastapi_stu](https://github.com/Thousandhack/fastapi_stu ) |aliyunsdkcore, jwt, sqlalchemy, passlib |
|[fastapi_template](https://github.com/ytxfate/fastapi_template ) |pymongo, redis, jwt, minio, project |
|[fastapi_todo_hex](https://github.com/josemlp91/fastapi_todo_hex ) |factory, toolz, pytest_factoryboy, tests, sqlalchemy, myapp, alembic, dotenv, databases, pytest, todolist |
|[fastbroker](https://github.com/cetanu/fastbroker ) |pkg_resources, ujson, fastbroker, jsonschema, setuptools |
|[fastrf](https://github.com/iancleary/fastrf ) |asgi_lifespan, pytest, fastrf, httpx |
|[fbd-backend](https://github.com/ElusiveSpirit/fbd-backend ) |redis, pytest_mock, celery, loguru, ujson, pytest, tests |
|[finance-api](https://github.com/rennerocha/finance-api ) |finance_api, dynaconf, pytest, requests |
|[first_fastapi](https://github.com/vittorduartte/first_fastapi ) |routes, ext, schemas, sqlalchemy, rules, models |
|[firstderm_demo](https://github.com/polyrand/firstderm_demo ) |requests |
|[foreign-subs](https://github.com/joe-eklund/foreign-subs ) |fsubs, setuptools, pymongo, typer, jwt, bson |
|[frontapp](https://github.com/Blasterai/frontapp ) |decorator, frontapp, requests, envparse, attr |
|[fullasync](https://github.com/lipengsh/fullasync ) |celery, tasks, core, api |
|[fullstack-fastapi-elasticsearch](https://github.com/cleobulo/fullstack-fastapi-elasticsearch ) |core, elasticsearch, db, models, api |
|[fuzzy-octo-funicular](https://github.com/mattkatz/fuzzy-octo-funicular ) |main |
|[gaia-fastapi-demo](https://github.com/muslax/gaia-fastapi-demo ) |email_validator, passlib, pymongo, sentry_sdk, motor, jwt, bson, emails |
|[gaki-server](https://github.com/shitangdama/gaki-server ) |alembic, jwt, sqlalchemy, myapp, passlib |
|[galicea-odoo-addons-ecosystem](https://github.com/galicea/galicea-odoo-addons-ecosystem ) |cryptography, werkzeug, jwcrypto, odoo, git |
|[game](https://github.com/jsandovalc/fake-news-game ) |basegame |
|[gateway-microservice](https://github.com/anforaProject/gateway-microservice ) |aiohttp, v1 |
|[gerenciador-tarefas](https://github.com/matheuspsouza/gerenciador-tarefas ) |gerenciador_tarefas |
|[gfw-tile-cache](https://github.com/wri/gfw-tile-cache ) |gino_starlette, mercantile, pytest, pendulum, async_lru, requests, shapely, cachetools, sqlalchemy, aenum |
|[gifter_api](https://github.com/zhanymkanov/gifter_api ) |pytest, jwt, sqlalchemy, tests, passlib |
|[gigscovery_backend](https://github.com/martijnboers/gigscovery_backend ) |functions, sklearn, bandsintown, spotipy |
|[gino-admin](https://github.com/xnuinside/gino-admin ) |sanic, pytest, click, jinja2, db, requests, passlib, expiring_dict, gino_admin, asyncpg, dsnparse, sqlalchemy_utils, gino, urllib3, aiofiles, yaml, sqlalchemy, sanic_jwt, sanic_jinja2 |
|[gino-starlette](https://github.com/python-gino/gino-starlette ) |requests, gino_fastapi_demo, asyncpg, gino, urllib3, importlib_metadata, sqlalchemy, alembic, pytest, click |
|[girandole](https://github.com/bartkl/girandole ) |beets, plugin, girandole, yaml |
|[girias.json](https://github.com/kvnol/girias.json ) |tinydb |
|[gitea-dispatcher](https://github.com/Trim21/gitea-dispatcher ) |httpx |
|[gke-cicd-sandbox](https://github.com/mana-ysh/gke-cicd-sandbox ) |exampleapp, pytest |
|[glittr-fastapi](https://github.com/kellischeuble/glittr-fastapi ) |glittr, sqlalchemy |
|[graph-server](https://github.com/ZettaAI/graph-server ) |pychunkedgraph, numpy |
|[graphql-python-server](https://github.com/apoveda25/graphql-python-server ) |env, gql, dotenv, schemas, ariadne, models, database, arango |
|[graphql-tutorial](https://github.com/jcremona/graphql-tutorial ) |schema, graphene |
|[grocery-stores-home-delivery](https://github.com/dz-experts/grocery-stores-home-delivery ) |db, app_factory, setuptools, crud, api, typer, sqlalchemy, myapp, alembic, constans, schemas, core, models |
|[guid_tracker](https://github.com/nwcell/guid_tracker ) |alembic, databases, aiocache, guid, pytest, sqlalchemy, sqlalchemy_utils, myapp |
|[hackaton-berlin-legal-tech-2020](https://github.com/jjanczur/hackaton-berlin-legal-tech-2020 ) |pytest, sklearn, joblib, nltk, loguru, cleaner, config, fastapi_skeleton, bs4 |
|[hello-world-fastapi](https://github.com/benhid/hello-world-fastapi ) |fastapp, setuptools, rich |
|[henry](https://github.com/jacksonhenry3/FAAS ) |infrastructure, interface, sqlalchemy |
|[heroku-google-translate-api](https://github.com/fawazahmed0/heroku-google-translate-api ) |googletrans |
|[hh_parser](https://github.com/Kuzyashin/hh_parser ) |passlib, aiohttp, tortoise, template, celery, jwt, emails |
|[home_recruiters](https://github.com/Mohamed-Kaizen/home_recruiters ) |users, pendulum, passlib, jobs, tortoise, typer, usernames, jwt, core, confusable_homoglyphs, username |
|[http-battle](https://github.com/MihaiAnei/http-battle ) |flask_restful, flask, python_flask |
|[hvilkenfisk](https://github.com/David-IL/hvilkenfisk ) |imutils, fish_utils, sklearn, h5py, cv2, keras, img_preprocess, model_utils |
|[iam_working](https://github.com/carlosporta/iam_working ) |iam_working |
|[iem-web-services](https://github.com/akrherz/iem-web-services ) |setuptools, pyiem, shapely, metpy, pytz, pygrib, pyproj, pandas, geopandas, pytest |
|[ihan-productizer-example](https://github.com/digitalliving/ihan-productizer-example ) |aiohttp, ujson, settings_local, settings |
|[image_capabilities_backend](https://github.com/alejgo06/image_capabilities_backend ) |PIL, cv2 |
|[image_classifier_backend](https://github.com/alejgo06/image_classifier_backend ) |PIL, cv2 |
|[image_detector_backend](https://github.com/alejgo06/image_detector_backend ) |PIL, torch, utils, torchvision, pycocotools, models, cv2 |
|[img-filter-api](https://github.com/RaRhAeu/img-filter-api ) |aiohttp, cv2, api, requests, pytest |
|[ingaia_app](https://github.com/higaooliveira/ingaia_app ) |pytest, sqlalchemy, resources, requests, config, spotipy, domain |
|[innovativeproject-photographers-portfolio](https://github.com/nokia-wroclaw/innovativeproject-photographers-portfolio ) |fastapi_mail, jwt, sqlalchemy, src, database, passlib |
|[inpainting_backen](https://github.com/kaikai03/inpainting_backen ) |tinydb |
|[introduction-to-async-await](https://github.com/ci42/introduction-to-async-await ) |unsync, unsyncable, colorama |
|[iter8-analytics](https://github.com/iter8-tools/iter8-analytics ) |analytics_namespace, requests, flask_restplus, setuptools, experiment_namespace, yaml, jsonschema, iter8_analytics, django, flask, requests_mock |
|[jjs](https://github.com/jjs-dev/jjs ) |bcrypt, pytest, api_models, pymongo, db_models, routes, auth, db_connect |
|[jobsearch_statistics](https://github.com/JobtechSwe/jobsearch_statistics ) |certifi, searchstatistics, elasticsearch |
|[json-fastapi](https://github.com/stocky37/json-fastapi ) |json_fastapi, tinydb, slugify, link_header, util |
|[juice-box](https://github.com/dannytannertantrum/juice-box ) |tests |
|[jupyter_fastapi](https://github.com/Zsailer/jupyter_fastapi ) |jupyter_server, tornado, hypothesis, pytest, jupyter_fastapi, hypothesis_jsonschema, setuptools |
|[k8s-traefik-example](https://github.com/Hedde/k8s-traefik-example ) |flask |
|[kartu-beckend](https://github.com/AntonKristiono/kartu-beckend ) |PIL, config, yaml, autocrop, routes, motor, bson, cv2 |
|[koalachat](https://github.com/therumbler/koalachat ) |koalachat, aiofiles |
|[koalastream](https://github.com/therumbler/koalastream ) |aiofiles, koalastream |
|[kritika](https://github.com/Egnod/kritika ) |alembic, sitri, slugify, sqlalchemy, myapp, kritika |
|[kubeflow-containers-desktop](https://github.com/StatCan/kubeflow-containers-desktop ) |tqdm, jupyter_core, setuptools, tornado, crontab, pip, psutil, IPython, git, notebook |
|[kubernetes-experiments](https://github.com/richard-to/kubernetes-experiments ) |redis, alembic, sqlalchemy, myapp, passlib |
|[kuma](https://github.com/deepalikumar/sync_async_compare ) |bcrypt, docstring_parser, passlib, orjson, loguru, sqlalchemy, myapp, jupyter_client, alembic, databases, jwt, nbformat |
|[kvmail](https://github.com/la9ran9e/kvmail ) |tarantool, dotenv, settings |
|[lab_monitor](https://github.com/nutanix-japan/lab_monitor ) |pymongo, requests, schedule, client |
|[lagom](https://github.com/meadsteve/lagom ) |sybil, pytest, lagom, typing_extensions, tests, django, flask |
|[lang-python](https://github.com/tim-barnes/lang-python ) |submod2, worker_a, etcd3, rabbit, worker_b, optmod1, psutil, mongoengine, pika, test_pb2, grpc, google, optmod2, submod1, celery, flask, models, pytest |
|[league-manager](https://github.com/Project-SRC/league-manager ) |jwt, src, environs, passlib |
|[learn-kubernetes](https://github.com/quan-vu/learn-kubernetes ) |flask, flask_restful |
|[lgbsttracker_api](https://github.com/py4mac/lgbsttracker_api ) |lgbsttracker, lgbsttracker_api |
|[lightgbm-project-demo](https://github.com/raywu60kg/lightgbm-project-demo ) |psycopg2, sklearn, src, tests, ray |
|[linkalong-pre-inteview-task](https://github.com/pydevd/linkalong-pre-inteview-task ) |decouple, linkalong |
|[love-alarm](https://github.com/dl-eric/love-alarm ) |pymongo, redis, nexmo, jwt, boto3, bson, passlib |
|[maale-map-bot](https://github.com/kudanai/maale-map-bot ) |pyngrok, dotenv, discord, bots, viberbot, models, settings, fuzzywuzzy, telegram |
|[manageme-api](https://github.com/managemeapp/manageme-api ) |mangum, today_app, setuptools |
|[mangum-fastapi-aws-test](https://github.com/dan-danciu/mangum-fastapi-aws-test ) |mangum |
|[mars-rover](https://github.com/rSkogeby/mars-rover ) |models, views |
|[memefly-ds](https://github.com/Lambda-School-Labs/memefly-ds ) |wandb, memefly, requests, pymongo, decouple, api, tensorflow, dotenv, boto3, click |
|[metabot](https://github.com/vasyukvv42/metabot ) |metabot, requests, fastapi_metabot, setuptools, aiohttp, pymongo, help, typing_extensions, feedback, aioredis, vacations, slackers, motor, mockaioredis, bson, slack, pytest, httpx |
|[micro-data-lake](https://github.com/abxda/micro-data-lake ) |sklearn, newspaper, altair, airflow, sqlalchemy, IPython, minio, setproctitle |
|[microservices](https://github.com/hugosteixeira/microservices ) |requests |
|[mironov_blog_pwa](https://github.com/yuriymironov96/mironov_blog_pwa ) |alembic, dotenv, sqlalchemy, myapp, apps |
|[ml-project-template](https://github.com/raywu60kg/ml-project-template ) |psycopg2, src, tests, ray |
|[ml-workspace](https://github.com/DennisRasey/ml-workspace ) |jupyter_core, tqdm, setuptools, tornado, crontab, pip, psutil, IPython, git, notebook |
|[modelo-fast-api](https://github.com/knienkotter/modelo-fast-api ) |pytest, gerenciador_tarefas |
|[moneyTransfer](https://github.com/williamsyb/moneyTransfer ) |faker, db, app_factory, passlib, apis, config, utils, main, sqlalchemy, auth, schemas, jwt, pytest |
|[mongodb_admin](https://github.com/ArtemZaitsev1994/mongodb_admin ) |trafaret_config, envparse, pymongo, base, motor, jwt, bson |
|[mri_image_reconstruction](https://github.com/Pradhy729/mri_image_reconstruction ) |utils, config |
|[msys2-web](https://github.com/msys2/msys2-web ) |pytest, pgpdump, jinja2, fastapi_etag, respx, httpx |
|[musixfy_service](https://github.com/divyam234/musixfy_service ) |requests, Cryptodome |
|[mv-backend](https://github.com/Sreerajta/mv-backend ) |cassandra, requests, passlib, redis, fnc, global_config, sqlalchemy, jwt, greenstalk |
|[mvp-metric](https://github.com/DjaPy/mvp-metric ) |databases, sqlalchemy, dateutil |
|[mvs_eland_api](https://github.com/rl-institut/mvs_eland_api ) |celery, pytest, worker, mvs_eland_tool, sphinx_rtd_theme |
|[my-notes-app](https://github.com/jgabriel1/my-notes-app ) |databases, pytest, jwt, sqlalchemy, passlib |
|[mychef](https://github.com/logan-connolly/mychef ) |spacy, requests, scrapy, tqdm, aiohttp, asyncpg, loguru, orm, reddit, scraper, sqlalchemy, databases, praw, pytest, jsonlines, bs4 |
|[nasa_neo](https://github.com/cmmarti/nasa_neo ) |repo, requests |
|[nereid](https://github.com/Geosyntec/nereid ) |nereid, pytest, redis, typing_extensions, numpy, matplotlib, scipy, yaml, pint, celery, pandas |
|[ners](https://github.com/cedricconol/ners ) |utils, config |
|[netpalm](https://github.com/tbotnz/netpalm ) |xmltodict, rq, netmiko, pytest, jinja2, backend, netpalm_pinned_worker, requests, jinja2schema, redis, lxml, tests, jsonschema, ncclient, routers, napalm |
|[next-word-sentence-pred-api](https://github.com/rakesh4real/next-word-sentence-pred-api ) |tree, sqlalchemy, models, database |
|[nile-api](https://github.com/mattgeiger/nile-api ) |alembic, bcrypt, databases, jwt, sqlalchemy, api |
|[nlp_api](https://github.com/rdenadai/nlp_api ) |nltk, decouple, spacy, utils |
|[nmdc-server](https://github.com/microbiomedata/nmdc-server ) |pytest, faker, factory, requests, setuptools, pkg_resources, sqlalchemy, alembic, nmdc_server |
|[nomine](https://github.com/gzzo/nomine ) |graphql_sqlalchemy, ariadne, sqlalchemy, nomine, graphql |
|[nurse-schedule](https://github.com/csabex94/nurse-schedule ) |spital_routes, mongoengine, nurse_routes, jwt, models, utils, passlib |
|[oasis](https://github.com/instedd/oasis ) |users, bcrypt, pytest, stories, requests, mysql, flask_cors, sqlalchemy, myapp, sigfig, database, jenkspy, alembic, flask, auth, jwt, router, emails |
|[ocfapi](https://github.com/nikhiljha/ocfapi ) |ocflib |
|[oreMeet](https://github.com/mfortini/oreMeet ) |ics, worker |
|[owi_Result-Collector](https://github.com/JensGe/owi_Result-Collector ) |sqlalchemy, tests |
|[page-visitor-counter](https://github.com/trapflag/page-visitor-counter ) |redis |
|[paste.bin](https://github.com/magiskboy/paste.bin ) |pymongo, redis, gridfs, bson |
| |PIL, PyPDF4 |
|[perfume-ai](https://github.com/gurutaka/perfume-ai ) |PIL, torchvision, predict, cv2, torch |
|[persistent-identifier-service](https://github.com/OpertusMundi/persistent-identifier-service ) |ompid, yaml, sqlalchemy |
|[personal-learning](https://github.com/hoangthienan95/personal-learning ) |pyimagesearch, sklearn, calculator, cv2, keras |
|[pi-camera-hardware-server](https://github.com/NSnietol/pi-camera-hardware-server ) |loguru, picamera, requests, src |
|[piccolo_api](https://github.com/piccolo-orm/piccolo_api ) |setuptools, asyncpg, test_session, piccolo, livereload, jwt, piccolo_api, asgiref |
|[plarin_task](https://github.com/jjoskey/plarin_task ) |pymongo, main, employees, pytest, faker, bson, settings |
|[plonkowski.b-gmail.com](https://github.com/Raroog/plonkowski.b-gmail.com ) |main |
|[plotly-graphene](https://github.com/mdpham/plotly-graphene ) |pymongo, mutation, graphene, schema, minio, loompy, bson, query, minio_client |
|[pneumoniadetection](https://github.com/aalikadic/pneumoniadetection ) |kaggle, PIL, classifier, keras |
|[pol](https://github.com/RedHatInsights/policies-notifications ) |pytest, requests, aioresponses, etc, orjson, aiohttp, redis, sentry_sdk, tests, sqlalchemy, myapp, aioredis, pytz, alembic, databases, aiologger |
|[policies-notifications](https://github.com/RedHatInsights/policies-notifications ) |pytest, jinja2, aiokafka, aiohttp, asyncpg, prometheus_client, apscheduler, gino, tests, sqlalchemy, myapp, starlette_prometheus, alembic |
|[poll-app](https://github.com/jgabriel1/poll-app ) |pymongo, dotenv, selenium, pytest, flask_testing, tests, config |
|[ppm-telegram-bot](https://github.com/piterpy-meetup/ppm-telegram-bot ) |pip, aiogram, fastapi_security_telegram_webhook, ppm_telegram_bot |
|[ppr](https://github.com/bcgov/ppr ) |pytest, endpoints, requests, setuptools, sentry_sdk, freezegun, config, main, repository, sqlalchemy, myapp, datedelta, pytz, alembic, dotenv, schemas, models |
|[practical-python](https://github.com/sudharsan2020/practical-python ) |redis, celery_with_fastapi, celery |
|[programs](https://github.com/deta/programs ) |deta, jinja2, colors, svgs, passlib |
|[projects](https://github.com/hungd25/projects ) |sklearn, lrsgd, utils, numpy, matplotlib, nose, models_partc, src, phonenumbers |
|[property-prediction](https://github.com/solanyn/property-prediction ) |botocore, psycopg2, pytest, catboost, sklearn, hello_world, boto3, requests |
|[proxmox-slack-bot](https://github.com/PlenusPyramis/proxmox-slack-bot ) |slack_model, requests, slack |
|[proxy-checker](https://github.com/infaticaio/proxy-checker ) |aiohttp, main, checker, aiosocks |
|[py-cidemia-security](https://github.com/cidemia/py-cidemia-security ) |werkzeug, requests, setuptools, passlib, yaml, cidemiasecurity, jwt |
|[pyBets](https://github.com/GabrielCappelli/pyBets ) |error_messages, db_models, views, sqlalchemy, application, database, app_logging, models, services, pytest |
|[pyapi](https://github.com/srghosh29/pyapi ) |apis |
|[pycon2020-FastAPI](https://github.com/gloriasky/pycon2020-FastAPI ) |schemas, sqlalchemy, models, api, database |
|[pyctuator](https://github.com/SolarEdgeTech/pyctuator ) |werkzeug, multidict, requests, aiohttp, redis, tests, psutil, pyctuator, sqlalchemy, flask, pytest |
|[pydantic-ddd-exploration](https://github.com/allgreed/pydantic-ddd-exploration ) |sqlalchemy, src |
|[pyml](https://github.com/dockerian/pyml ) |PIL, pytest, setuptools, gevent, h5py, tests, numpy, dateutil, matplotlib, scipy, mock, connexion, yaml, google, jsonpickle, flask, ml, asgiref |
|[pypis](https://github.com/jurelou/pypis ) |packaging, setuptools, asyncpg, loguru, pkg_resources, sqlalchemy, stdlib_list, dynaconf, pypis, httpx |
|[python](https://github.com/jijinggang/test_python ) |requests, requests_html, unidecode, lxml, openpyxl, send_mail, download_util, formatting, settings, templates, flask |
|[python-api-template](https://github.com/mana-ysh/python-api-template ) |pytest |
|[python-asyncio-crud](https://github.com/aleimu/python-asyncio-crud ) |sanic, six, uvloop, muggle_ocr, redis, flask_sqlalchemy, aiomysql, sqlalchemy, aioredis, flask |
|[python-crash-course](https://github.com/cyberinsane/python-crash-course ) |tinydb, schema, pandas, requests |
|[python-deployment-samples](https://github.com/edisga/python-deployment-samples ) |aiohttp, webtest, django, pyramidsite, flask, pyramid, flask_cors, my_app, setuptools, other_app |
|[python-fastapi-hex-todo](https://github.com/GArmane/python-fastapi-hex-todo ) |pytest, faker, factory, passlib, toolz, asyncpg, pytest_factoryboy, tests, sqlalchemy, myapp, alembic, dotenv, databases, jwt, todolist |
|[python-graphql](https://github.com/tsungchih/python-graphql ) |graphene, aiohttp, loguru, ujson, psutil, graphql |
|[python-ml-service-template](https://github.com/paramoshin/python-ml-service-template ) |yaml, joblib, starlette_prometheus |
|[python-playground](https://github.com/tgmti/python-playground ) |flask_restful, flask, sqlalchemy |
|[python-poetry-docker-example](https://github.com/michael0liver/python-poetry-docker-example ) |pytest |
|[python-private-service-layout](https://github.com/U-Company/python-private-service-layout ) |fire, loguru, prometheus_client, pytest, vault_client, info, clients, tests, setuptools |
|[python_benchmark](https://github.com/T4D3K/python_benchmark ) |fastapi_frm, locust, sqlalchemy, tortoise, falcon, gino, falcon_frm |
|[python_common_tools](https://github.com/CheungChan/python_common_tools ) |requests, setuptools, redis, python_common_tools, paramiko, stackprinter, DBUtils, pymysql |
|[python_fastapi](https://github.com/playwhyyza/python_fastapi ) |jwt, passlib |
|[qa-api](https://github.com/venuraja79/qa-api ) |elasticapm, controller, haystack, config |
|[qhub-home](https://github.com/Quansight/qhub-home ) |toml, flit, setuptools |
|[qr-generator](https://github.com/gosha20777/qr-generator ) |qrcode |
|[rakm](https://github.com/emanuelaguna/rakm ) |pytest, requests, aiohttp, asyncache, invoke, asyncmock, tests, dateutil, cachetools, async_asgi_testclient, async_generator, dotenv |
|[random_projects](https://github.com/thepartisan101/random_projects ) |flask_restful, graphene, extraction, selenium, flask, flask_graphql, schema, sqlalchemy, requests |
|[recommender_fastapi](https://github.com/gjorgjinac/recommender_fastapi ) |repository, pybreaker, helper, sqlalchemy, default_ad_listener, requests, web, defaults |
|[recommender_server](https://github.com/gjorgjinac/recommender_server ) |repository, pybreaker, helper, sqlalchemy, default_ad_listener, requests, web, defaults |
|[ref-final-project-backend](https://github.com/Reyvel/ref-final-project-backend ) |faust, kafka, msgpack, settings, utils |
|[repost-fastapi](https://github.com/pckv/repost-fastapi ) |dotenv, jwt, sqlalchemy, repost, passlib |
|[responsive-layout-part](https://github.com/lmacchiavelli/responsive-layout-part ) |PIL |
|[rest_api_docker_mongo_aws](https://github.com/RodrigoMachado9/rest_api_docker_mongo_aws ) |pymongo, six, bottle_resource, beartype, bottle, spacy, passlib |
|[restbot](https://github.com/cwerner/restbot ) |restbot, loguru, pytest, joblib |
|[reternal-backend](https://github.com/d3vzer0/reternal-backend ) |pymongo, redis, flask_restful, flask_jwt_extended, sigma, workers, mongoengine, yaml, environment, database, pytz, flask_socketio, celery, flask, jwt, bson |
|[reverse-geocoder](https://github.com/claws/reverse-geocoder ) |databases, sqlalchemy, geoalchemy2 |
|[rjgtoys-xc](https://github.com/bobgautier/rjgtoys-xc ) |pytest, jinja2, requests, rjgtoys, apierrors, sphinx, sphinx_autodoc_typehints |
|[rn-fastapi-app](https://github.com/cloudeyes/rn-fastapi-app ) |sample, psycopg2, fastapi_login, MySQLdb, sqlalchemy, fastalchemy, passlib |
|[runn](https://github.com/alex-2201/runn ) |requests, passlib, tests, utils, sqlalchemy, jwt, logzero, pytest, emails |
|[sauti-fastapi](https://github.com/taycurran/sauti-fastapi ) |dotenv, pstgres, sqlalchemy |
|[sauti-monitor-ds-api](https://github.com/taycurran/sauti-monitor-ds-api ) |dotenv, sqlalchemy |
|[scaling-spoon](https://github.com/bloomingmath/scaling-spoon ) |email_validator, pony, bcrypt, pytest, extensions, passlib, pymongo, selenium, blinker, main, async_asgi_testclient, dotenv, motor, schemas, routers, bson, models |
|[sensehat-fastapi](https://github.com/cmlccie/sensehat-fastapi ) |sense_hat, senseapi |
|[server-open-alpr](https://github.com/NSnietol/server-open-alpr ) |openalpr, loguru, src |
|[serverless-fastapi-cdk](https://github.com/jaehyeon-kim/serverless-fastapi-cdk ) |mangum, resources, src, aws_cdk |
|[show-tell-api](https://github.com/team-eyespace/show-tell-api ) |nltk, PIL, TensorBoardCaption, NIC, evaluate, flask, jwt, preprocessing, keras, utils |
|[signal-cli-rest-api](https://github.com/SebastianLuebke/signal-cli-rest-api ) |pyqrcode, requests, signal_cli_rest_api |
|[simple-kp](https://github.com/ranking-agent/simple-kp ) |aiosqlite, pytest, simple_kp, reasoner_pydantic, data, setuptools |
|[simple-messenger](https://github.com/IvanDubrowin/simple-messenger ) |server |
|[simple-report-data-table-vuetify](https://github.com/shizidushu/simple-report-data-table-vuetify ) |bcrypt, dotenv, mongoengine, jwt, pypandoc, bson, casbin, passlib |
|[simpleapp-aws-fargate](https://github.com/kbaafi/simpleapp-aws-fargate ) |controllers, databases, sqlalchemy, boto3, data, config, services, settings, requests |
|[siso-library](https://github.com/nfowl/siso-library ) |databases, sqlalchemy |
|[sklearn-docker-api](https://github.com/crocopie/sklearn-docker-api ) |sklearn, service, joblib |
|[slowapi](https://github.com/laurentS/slowapi ) |limits, redis, slowapi, tests, hiro, mock |
|[smart-social-distancing](https://github.com/neuralet/smart-social-distancing ) |openvino, tflite_runtime, invoke, ui, tools, wget, scipy, libs |
|[sms_gateway](https://github.com/arxell/sms_gateway ) |passlib, aiohttp, sentry_sdk, aiopg, sqlalchemy, myapp, grpc, google, alembic, psycopg2, jwt, click, grpclib |
|[social-insights](https://github.com/dsc-umass/social-insights ) |sklearn, requests, joblib, nltk, tweepy, numpy, firebase_admin, twitter_credentials, scipy, spellchecker, get_tweets, google, flask, keras, xgboost, suggest |
|[sociallyhigh](https://github.com/NikhilSharmay/sociallyhigh ) |pkg_resources, sociallyhigh |
|[sparky](https://github.com/perfecto25/sparky ) |sparky, config |
|[speechRecognition_api](https://github.com/X-CCS/speechRecognition_api ) |librosa, sklearn, aukit, aip, Django_jianlong, videototextapp, videoaddsubtitleapp, myapp, IPython, my_app, other_app, djcelery, django, celery, video2audio_noiseReduction, keras |
|[start-fastapi](https://github.com/utmhikari/start-fastapi ) |model, middleware, controller, service, application, dotenv |
|[startapp](https://github.com/marlin-dev/startapp ) |extensions, marshmallow, setuptools, passlib, flask_env, flask_jwt_extended, sentry_sdk, flask_sqlalchemy, sqlalchemy_utils, gino, sqlalchemy, flask_marshmallow, takeaway, settings, flask_migrate, starlette_prometheus, flask, app_init, core|
|[statsfy](https://github.com/skmatz/statsfy ) |spotifier |
|[stock-tracker](https://github.com/jgabriel1/stock-tracker ) |pymongo, aiohttp, dotenv, pytest, jwt, server, requests, passlib |
|[stores](https://github.com/dz-experts/grocery-stores-home-delivery ) |stores, pytest, api, util |
|[storyboard_renderer](https://github.com/Weltii/storyboard_renderer ) |render_job, layouts, bridge, statics, layout_bridge, utils |
|[summaries](https://github.com/bradstimpson/summaries ) |nltk, newspaper, pytest, tortoise |
|[summarize-api](https://github.com/gary23w/summarize-api ) |nltk, newspaper, pytest, tortoise |
|[surfacescan](https://github.com/vbogretsov/surfacescan ) |networkx, pytest, faker, atomiclong, locust, surfacescan, pkg_resources, tests |
|[sweetHome](https://github.com/zkity/sweetHome ) |serial, lib |
|[sync_async_compare](https://github.com/deepalikumar/sync_async_compare ) |blog, faker, marshmallow, flask_sqlalchemy, sqlalchemy_utils, flask_apispec, commands, sqlalchemy, myapp, resources, settings, flask_migrate, alembic, dotenv, flask, databases, pytest |
|[takeAction-Backend](https://github.com/AndyKChen/takeAction-Backend ) |ml_controller, googlesearch, sklearn, getURL, bs4, keras, utils, numpy |
|[tariffengineapi](https://github.com/SofieneEnnaoui/tariffengineapi ) |memory_profiler, redis, numba, tariffs_modules, tests, api_fastapi, memory |
|[task_manager](https://github.com/VladOsiichuk/task_manager ) |passlib, gino, sqlalchemy, myapp, alembic, jwt |
|[taskriptor-web](https://github.com/nasuka/taskriptor-web ) |alembic, sqlalchemy, myapp |
|[tdd-fastapi-template](https://github.com/markusntz/tdd-fastapi-template ) |fastapi_tdd_docker, pytest, tortoise |
|[teached](https://github.com/Mohamed-Kaizen/teached ) |pytest, pendulum, requests, passlib, loguru, tortoise, teached, typer, importlib_metadata, nox, usernames, dropbox, jwt, confusable_homoglyphs, username |
|[techsoulai_backend](https://github.com/zhanymkanov/techsoulai_backend ) |pytest, jamspell, jwt, sqlalchemy, pymystem3, passlib |
|[temperature-web](https://github.com/sj175/temperature-web ) |board, dotenv, adafruit_dht, boto3, requests |
|[test_fastapi](https://github.com/leblancfg/test_fastapi ) |PIL, magic, fastapi_versioning, autocrop, cv2, requests, google |
|[test_shop](https://github.com/Ayaks7/test_shop ) |requests, passlib, peewee, user_orders, my_app, other_app, django, yoyo, catalog, auth, jwt, pytest, peewee_async, tastypie |
|[testfastapi](https://github.com/18438655078/testfastapi ) |tortoise, boto3 |
|[todo-list-fastapi](https://github.com/mcauto/todo-list-fastapi ) |aiofiles, pytest, jwt, sqlalchemy, src, passlib |
|[todoapp](https://github.com/prashunchitkr/todoapp ) |alembic, jwt, sqlalchemy, myapp, passlib |
|[trainee_mi](https://github.com/goncharov-roman/trainee_mi ) |pymongo |
|[transactions_api](https://github.com/txemac/transactions_api ) |pytest, sqlalchemy, sqlalchemy_utils, database |
|[transformers](https://github.com/raphtlw/transformers ) |aitextgen |
|[translator](https://github.com/eightytwo/translator ) |translator, schemas, api, httpx |
|[try-fast-api](https://github.com/kayshcache/try-fast-api ) |dotenv |
|[users-service](https://github.com/falled10/users-service ) |werkzeug, pytest, oauth2client, sqlalchemy_utils, api, config, main, repository, humps, sqlalchemy, myapp, alembic, jwt, routers, authlib, services |
|[uvicorn-gunicorn-fastapi](https://github.com/dshadow/uvicorn-gunicorn-fastapi-docker ) |test_utils, docker, requests, pytest |
|[vollmacht](https://github.com/ogeller/vollmacht ) |fitz |
|[volunteer-database](https://github.com/crowdsourcemedical/volunteer-database ) |alembic, pytest, jwt, sqlalchemy, myapp, passlib |
|[wamedex2](https://github.com/gwf-uwaterloo/wamedex2 ) |pytest, pyserini, hnswlib, pkg_resources, helper, freezegun, dateparser |
|[wazo-router-calld](https://github.com/wazo-platform/wazo-router-calld ) |wazo_router_calld, consul, click, sqlalchemy, setuptools |
|[web-api](https://github.com/aroio/web-api ) |exceptions, yaml, auth, jwt, routers, models, data |
|[web-avatarify](https://github.com/charlielito/web-avatarify ) |PIL, afy, skimage, moviepy, requests, imageio, tqdm, animate, sync_batchnorm, ffmpeg, torch, matplotlib, scipy, face_alignment, yaml, python_path, cv2, modules |
|[web-frameworks-benchmark](https://github.com/kesha1225/web-frameworks-benchmark ) |muffin, sanic, pyramid, falcon, requests, bottle, aiohttp, bobo, quart, hug, japronto, request_bench, my_app, other_app, django, flask, cherrypy, kumquat, freezy |
|[web_speedtest](https://github.com/Kulikovpavel/web_speedtest ) |flask |
|[weblink-downloader](https://github.com/cortexin/weblink-downloader ) |passlib, asyncpg, tests, link_downloader, databases, pytest, httpx |
|[xo_back](https://github.com/octomen/xo_back ) |pytest, api |
|[xpublish](https://github.com/xarray-contrib/xpublish ) |xarray, pytest, cachey, xpublish, setuptools, pkg_resources, h5py, netCDF4, numcodecs, dask, zarr |
|[xraysink](https://github.com/garyd203/xraysink ) |aiohttp, jsonpickle, xraysink, async_asgi_testclient, aws_xray_sdk, requests, pytest |
|[yappfm-backend](https://github.com/yappfm/yappfm-backend ) |alembic, sqlalchemy, myapp, yappfm, gino |
|[yatsm](https://github.com/danielmartins/yatsm ) |dramatiq, walrus, pytest, pendulum, passlib, apscheduler, typer, assertpy, pytz, jwt, yatsm |
|[yumemi_intern_API](https://github.com/tkrk1209/yumemi_intern_API ) |aiohttp, sqlalchemy, myapp, google, alembic |
|[zo](https://github.com/wazo-platform/wazo-router-calld ) |PIL, requests, ssdb, setuptools, loguru, urllib3, zo, munch |
The instructions below assume you have [pyenv](https://github.com/pyenv/pyenv) installed.
If you don't, use any other method to create a virtual environment
and install Python 3.11.4.
## Contributing
- Install Python 3.11.4
Pull requests are welcome.
```shell
pyenv install 3.11.4
```
- Create a virtual environment
```shell
pyenv virtualenv 3.11.4 awesome-fastapi-projects
```
- Activate the virtual environment
```shell
pyenv local awesome-fastapi-projects
```
#### Install dependencies and pre-commit hooks
There is a `Makefile` with some useful commands to help you get started.
For available commands, run `make help`. To install dependencies and pre-commit hooks, run:
```shell
make
```
#### Frontend
The frontend is built with [React](https://reactjs.org/) and [Next.js](https://nextjs.org/).
It is being statically built and served on GitHub Pages: https://Kludex.github.io/awesome-fastapi-projects/
To run the frontend locally, you need to install [Node.js](https://nodejs.org/en/) and [pnpm](https://pnpm.io/).
The node version is specified in the `.node-version` file.
To easily manage the node version, you can use [fnm](https://github.com/Schniz/fnm).
Then, run the following commands:
```shell
make front
```
This will install the dependencies and start the development server.
The frontend will be available at http://localhost:3000.

107
alembic.ini Normal file
View File

@ -0,0 +1,107 @@
# A generic, single database configuration.
[alembic]
# path to migration scripts
script_location = migrations
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
# Uncomment the line below if you want the files to be prepended with date and time
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
# sys.path path, will be prepended to sys.path if present.
# defaults to the current working directory.
prepend_sys_path = .
# timezone to use when rendering the date within the migration file
# as well as the filename.
# If specified, requires the python-dateutil library that can be
# installed by adding `alembic[tz]` to the pip requirements
# string value is passed to dateutil.tz.gettz()
# leave blank for localtime
# timezone =
# max length of characters to apply to the
# "slug" field
# truncate_slug_length = 40
# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false
# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false
# version location specification; This defaults
# to migrations/versions. When using multiple version
# directories, initial revisions must be specified with --version-path.
# The path separator used here should be the separator specified by "version_path_separator" below.
# version_locations = %(here)s/bar:%(here)s/bat:migrations/versions
# version path separator; As mentioned above, this is the character used to split
# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
# Valid values for version_path_separator are:
#
# version_path_separator = :
# version_path_separator = ;
# version_path_separator = space
version_path_separator = os # Use os.pathsep. Default configuration used for new projects.
# set to 'true' to search source files recursively
# in each "version_locations" directory
# new in Alembic version 1.10
# recursive_version_locations = false
# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8
sqlalchemy.url = sqlite+aiosqlite:///db.sqlite3
[post_write_hooks]
# post_write_hooks defines scripts or Python functions that are run
# on newly generated revision scripts. See the documentation for further
# detail and examples
# format using "black" - use the console_scripts runner, against the "black" entrypoint
# hooks = black
# black.type = console_scripts
# black.entrypoint = black
# black.options = -l 79 REVISION_SCRIPT_FILENAME
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

1
app/__init__.py Normal file
View File

@ -0,0 +1 @@
"""A web application for indexing the projects using FastAPI."""

105
app/conftest.py Normal file
View File

@ -0,0 +1,105 @@
"""The application-level conftest."""
import asyncio
import contextlib
from collections.abc import AsyncGenerator, Generator
from typing import Literal
import pytest
import stamina
from dirty_equals import IsList
from pytest_mock import MockerFixture
from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession
from app.database import Dependency, Repo
from app.factories import DependencyCreateDataFactory
from app.source_graph.factories import SourceGraphRepoDataFactory
from app.source_graph.models import SourceGraphRepoData
@pytest.fixture(autouse=True, scope="session")
def anyio_backend() -> Literal["asyncio"]:
"""Use asyncio as the async backend."""
return "asyncio"
@pytest.fixture(autouse=True, scope="session")
def _deactivate_retries() -> None:
"""Deactivate stamina retries."""
stamina.set_active(False)
@pytest.fixture(autouse=True)
def _test_db(mocker: MockerFixture) -> None:
"""Use the in-memory database for tests."""
mocker.patch("app.database.DB_PATH", "")
@pytest.fixture(scope="session")
def event_loop(
request: pytest.FixtureRequest,
) -> Generator[asyncio.AbstractEventLoop, None, None]:
"""
Create an instance of the default event loop for a session.
An event loop is destroyed at the end of the test session.
https://docs.pytest.org/en/6.2.x/fixture.html#fixture-scopes
"""
with contextlib.closing(loop := asyncio.get_event_loop_policy().get_event_loop()):
yield loop
@pytest.fixture(scope="session")
async def test_db_connection() -> AsyncGenerator[AsyncConnection, None]:
"""Use the in-memory database for tests."""
from app.database import Base, engine
try:
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.drop_all)
await conn.run_sync(Base.metadata.create_all)
yield conn
finally:
# for AsyncEngine created in function scope, close and
# clean-up pooled connections
await engine.dispose()
@pytest.fixture()
async def test_db_session(
test_db_connection: AsyncConnection,
) -> AsyncGenerator[AsyncSession, None]:
"""Use the in-memory database for tests."""
from app.uow import async_session_uow
async with async_session_uow() as session:
yield session
@pytest.fixture()
async def some_repos(
test_db_session: AsyncSession,
source_graph_repo_data_factory: SourceGraphRepoDataFactory,
dependency_create_data_factory: DependencyCreateDataFactory,
) -> list[Repo]:
"""Create some repos."""
source_graph_repos_data: list[
SourceGraphRepoData
] = source_graph_repo_data_factory.batch(10)
assert source_graph_repos_data == IsList(length=10)
repos = [
Repo(
url=str(source_graph_repo_data.repo_url),
description=source_graph_repo_data.description,
stars=source_graph_repo_data.stars,
source_graph_repo_id=source_graph_repo_data.repo_id,
dependencies=[
Dependency(**dependency_create_data.model_dump())
for dependency_create_data in dependency_create_data_factory.batch(5)
],
)
for source_graph_repo_data in source_graph_repos_data
]
test_db_session.add_all(repos)
await test_db_session.flush()
await asyncio.gather(*[test_db_session.refresh(repo) for repo in repos])
return repos

107
app/database.py Normal file
View File

@ -0,0 +1,107 @@
"""
Database models and session.
The database is a SQLite database, and is stored in the root
of the project as `db.sqlite3`.
The database is managed using Alembic, and migrations
are stored in the `migrations/` directory.
The module defines the following models:
- `Repo`: A repository that is being tracked.
- `Dependency`: A dependency of a repository.
- `RepoDependency`: A relationship between a repository and a dependency.
The database is accessed asynchronously using SQLAlchemy's async API.
"""
from collections.abc import AsyncGenerator
from pathlib import PurePath
from typing import Final
from sqlalchemy import BigInteger, ForeignKey, MetaData, String, Text, UniqueConstraint
from sqlalchemy.ext.asyncio import (
AsyncAttrs,
AsyncEngine,
AsyncSession,
async_sessionmaker,
create_async_engine,
)
from sqlalchemy.orm import (
Mapped,
declarative_base,
mapped_column,
relationship,
)
DB_PATH: Final[PurePath] = PurePath(__file__).parent.parent / "db.sqlite3"
SQLALCHEMY_DATABASE_URL: Final[str] = f"sqlite+aiosqlite:///{DB_PATH}"
engine: Final[AsyncEngine] = create_async_engine(SQLALCHEMY_DATABASE_URL)
async_session_maker: Final[async_sessionmaker[AsyncSession]] = async_sessionmaker(
engine, expire_on_commit=False, autoflush=False, autocommit=False
)
metadata = MetaData(
naming_convention={
"ix": "ix_%(table_name)s_%(column_0_N_name)s ",
"uq": "uq_%(table_name)s_%(column_0_N_name)s ",
"ck": "ck_%(table_name)s_%(constraint_name)s ",
"fk": "fk_%(table_name)s_%(column_0_N_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s",
}
)
async def get_async_session() -> AsyncGenerator[AsyncSession, None]:
"""Get an async session."""
async with async_session_maker() as session:
yield session
Base = declarative_base(metadata=metadata, cls=AsyncAttrs)
class Repo(Base):
"""A repository that is being tracked."""
__tablename__ = "repo"
id: Mapped[int] = mapped_column(primary_key=True)
url: Mapped[str] = mapped_column(nullable=False, unique=True)
description: Mapped[str] = mapped_column(Text, nullable=False)
stars: Mapped[int] = mapped_column(BigInteger, nullable=False)
source_graph_repo_id: Mapped[int | None] = mapped_column(
BigInteger, nullable=True, unique=True
)
dependencies: Mapped[list["Dependency"]] = relationship(
"Dependency", secondary="repo_dependency", back_populates="repos"
)
last_checked_revision: Mapped[str | None] = mapped_column(
String(255), nullable=True
)
__table_args__ = (UniqueConstraint("url", "source_graph_repo_id"),)
class Dependency(Base):
"""A dependency of a repository."""
__tablename__ = "dependency"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(255), nullable=False, unique=True)
repos: Mapped[list["Repo"]] = relationship(
"Repo", secondary="repo_dependency", back_populates="dependencies"
)
class RepoDependency(Base):
"""A relationship between a repository and a dependency."""
__tablename__ = "repo_dependency"
repo_id: Mapped[int] = mapped_column(
ForeignKey(Repo.id, ondelete="CASCADE"), primary_key=True
)
dependency_id: Mapped[int] = mapped_column(
ForeignKey(Dependency.id, ondelete="CASCADE"), primary_key=True
)

149
app/dependencies.py Normal file
View File

@ -0,0 +1,149 @@
"""Dependencies parsing."""
import asyncio
import subprocess
from collections.abc import Sequence
import aiofiles.tempfile
import stamina
from loguru import logger
from app.database import Repo
from app.models import DependencyCreateData
from app.types import RevisionHash
async def run_command(*cmd: str, cwd: str | None = None) -> str:
"""
Run the given command in a subprocess and return the stdout as plain text.
:param cmd: The command to run.
:param cwd: The working directory to run the command in.
:return: The stdout result
"""
process = await asyncio.create_subprocess_exec(
*cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=cwd,
)
stdout, stderr = await process.communicate()
if process.returncode != 0:
raise RuntimeError(
f"Command '{cmd}' failed with exit code '{process.returncode}':\n"
f"[stdout]: '{stdout.decode()}'\n"
f"[stderr]: '{stderr.decode()}'"
)
return stdout.decode()
async def acquire_dependencies_data_for_repository(
repo: Repo,
) -> tuple[RevisionHash, list[DependencyCreateData]]:
"""
Acquire dependencies for the given repository.
The function will use the "third-party-imports" tool to
parse the third-party dependencies of the repository.
Since this tool has been written in Rust and is basically
a CLI tool, the parsing will happen is a subprocess.
:param repo: A repository for which to return the dependencies.
:return: The dependencies data required to create the dependencies in the DB.
"""
logger.info(
"Acquiring the dependencies data for the repo with id {repo_id}.",
repo_id=repo.id,
enqueue=True,
)
async with aiofiles.tempfile.TemporaryDirectory() as directory:
# Clone the repository
logger.info(
"Cloning the repo with id {repo_id} into the directory {directory}.",
repo_id=repo.id,
directory=directory,
enqueue=True,
)
await run_command(
"git",
"clone",
"--depth",
"1",
repo.url,
directory,
)
# Get the latest commit hash
logger.info(
"Getting the latest commit hash for the repo with id {repo_id}.",
repo_id=repo.id,
enqueue=True,
)
revision: str = await run_command(
"git",
"rev-parse",
"HEAD",
cwd=directory,
)
if repo.last_checked_revision == revision:
# Assume there are no new dependencies to return
# since all the repo dependencies have already
# been parsed.
logger.info(
"The repo with id {repo_id} has already been updated.",
repo_id=repo.id,
enqueue=True,
)
return RevisionHash(revision), []
# Parse the dependencies
async for attempt in stamina.retry_context(on=RuntimeError, attempts=3):
with attempt:
logger.info(
"Parsing the dependencies for the repo with id {repo_id}.",
repo_id=repo.id,
enqueue=True,
)
dependencies: str = await run_command(
"third-party-imports",
directory,
)
if dependencies:
logger.info(
"Successfully parsed the dependencies for the repo with id {repo_id}.",
repo_id=repo.id,
enqueue=True,
)
# Split the dependencies by new line
dependencies_list: Sequence[str] = dependencies.split("\n")
# Drop the first two lines (the info lines)
dependencies_list = (
dependencies_list[2:] if len(dependencies_list) > 2 else []
)
logger.info(
"Found {count} dependencies for the repo with id {repo_id}.",
count=len(dependencies_list),
repo_id=repo.id,
enqueue=True,
)
else:
logger.info(
"No dependencies found for the repo with id {repo_id}.",
repo_id=repo.id,
enqueue=True,
)
dependencies_list = []
return (
RevisionHash(revision),
[
DependencyCreateData(
name=dependency.strip(),
)
for dependency in dependencies_list
if dependency.strip()
],
)

12
app/factories.py Normal file
View File

@ -0,0 +1,12 @@
"""Factories for creating models for testing."""
from polyfactory.factories.pydantic_factory import ModelFactory
from polyfactory.pytest_plugin import register_fixture
from app.models import DependencyCreateData
@register_fixture
class DependencyCreateDataFactory(ModelFactory[DependencyCreateData]):
"""Factory for creating DependencyCreateData."""
__model__ = DependencyCreateData

104
app/index.py Normal file
View File

@ -0,0 +1,104 @@
"""
Create repos and dependencies indexes.
This script creates can create two indexes:
- ``repos_index.json``: Contains all the repositories and their dependencies.
- ``dependencies_index.json``: Contains all the dependencies and the
repositories that depend on them.
The indexes are used by the frontend to display the data and perform searches.
"""
import asyncio
import json
from pathlib import Path
from typing import Final
import aiofiles
import sqlalchemy.orm
import typer
from app.database import Dependency, Repo
from app.models import DependencyDetail, RepoDetail
from app.uow import async_session_uow
#: The path to the repos index file.
REPOS_INDEX_PATH: Final[Path] = Path(__file__).parent.parent / "repos_index.json"
#: The path to the dependencies index file.
DEPENDENCIES_INDEX_PATH: Final[Path] = (
Path(__file__).parent.parent / "dependencies_index.json"
)
app = typer.Typer()
async def create_repos_index() -> None:
"""
Create repos_index.json file from database.
:return: None
"""
async with async_session_uow() as session, aiofiles.open(
REPOS_INDEX_PATH, "w"
) as index_file:
await index_file.write(
json.dumps(
{
"repos": [
RepoDetail.model_validate(repo).model_dump()
async for repo in (
await session.stream_scalars(
sqlalchemy.select(Repo)
.order_by(Repo.id)
.options(sqlalchemy.orm.selectinload(Repo.dependencies))
)
)
],
},
indent=4,
)
)
async def create_dependencies_index() -> None:
"""
Create dependencies_index.json file from database.
:return: None
"""
async with async_session_uow() as session, aiofiles.open(
DEPENDENCIES_INDEX_PATH, "w"
) as index_file:
dependencies = [
DependencyDetail.model_validate(dependency).model_dump()
async for dependency in (
await session.stream_scalars(
sqlalchemy.select(Dependency).order_by(Dependency.id)
)
)
if dependency.name
]
await index_file.write(
json.dumps(
{
"dependencies": dependencies,
},
indent=4,
)
)
@app.command()
def index_repos() -> None:
"""Create ``repos_index.json``."""
asyncio.run(create_repos_index())
@app.command()
def index_dependencies() -> None:
"""Create ``dependencies_index.json``."""
asyncio.run(create_dependencies_index())
if __name__ == "__main__":
app()

38
app/models.py Normal file
View File

@ -0,0 +1,38 @@
"""Module contains the models for the application."""
from pydantic import BaseModel, ConfigDict, NonNegativeInt
from app.types import DependencyId, RepoId, RevisionHash
class DependencyCreateData(BaseModel):
"""A dependency of a repository."""
name: str
class DependencyDetail(BaseModel):
"""A dependency of a repository."""
model_config = ConfigDict(
from_attributes=True,
)
id: DependencyId
name: str
class RepoDetail(BaseModel):
"""A repository that is being tracked."""
model_config = ConfigDict(
from_attributes=True,
)
id: RepoId
url: str
description: str
stars: NonNegativeInt
source_graph_repo_id: int
dependencies: list[DependencyDetail]
last_checked_revision: RevisionHash | None

243
app/scrape.py Normal file
View File

@ -0,0 +1,243 @@
"""The logic for scraping the source graph data processing it."""
import asyncio
import sqlalchemy.dialects.sqlite
import typer
from loguru import logger
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import Dependency, Repo, RepoDependency
from app.dependencies import acquire_dependencies_data_for_repository
from app.source_graph.client import AsyncSourceGraphSSEClient
from app.source_graph.mapper import create_or_update_repos_from_source_graph_repos_data
from app.types import RepoId
from app.uow import async_session_uow
async def _create_dependencies_for_repo(session: AsyncSession, repo: Repo) -> None:
"""
Create dependencies for a repo.
For each parsed dependency, creates a new record in the database, if such a
dependency does not exist.
Then, assigns the dependencies to the given repo.
:param session: An asynchronous session object
:param repo: A repo for which to create and assign the dependencies
"""
# Acquire the dependencies data for the repo
logger.info(
"Acquiring the dependencies data for the repo with id {repo_id}.",
repo_id=repo.id,
enqueue=True,
)
try:
(
revision,
dependencies_create_data,
) = await acquire_dependencies_data_for_repository(repo)
except RuntimeError:
# If the parsing fails,
# just skip creating the dependencies
logger.error(
"Failed to acquire the dependencies data for the repo with id {repo_id}.",
repo_id=repo.id,
enqueue=True,
)
return
if repo.last_checked_revision == revision:
# If the repo has already been updated,
# just skip creating the dependencies
logger.info(
"The repo with id {repo_id} has fresh dependencies.",
repo_id=repo.id,
enqueue=True,
)
return
if not dependencies_create_data:
# If there are no dependencies,
# just skip creating the dependencies
logger.info(
"The repo with id {repo_id} has no dependencies.",
repo_id=repo.id,
enqueue=True,
)
return
# Update the repo with the revision hash
logger.info(
"Updating the repo with id {repo_id} with the revision hash {revision}.",
repo_id=repo.id,
revision=revision,
enqueue=True,
)
update_repo_statement = (
sqlalchemy.update(Repo)
.where(Repo.id == repo.id)
.values(last_checked_revision=revision)
)
await session.execute(update_repo_statement)
# Create dependencies - on conflict do nothing.
# This is to avoid creating duplicate dependencies.
logger.info(
"Creating the dependencies for the repo with id {repo_id}.",
repo_id=repo.id,
enqueue=True,
)
insert_dependencies_statement = sqlalchemy.dialects.sqlite.insert(
Dependency
).on_conflict_do_nothing(index_elements=[Dependency.name])
await session.execute(
insert_dependencies_statement.returning(Dependency),
[
{
"name": dependency_data.name,
}
for dependency_data in dependencies_create_data
],
)
# Re-fetch the dependencies from the database
dependencies = (
await session.scalars(
sqlalchemy.select(Dependency).where(
Dependency.name.in_(
[
dependency_data.name
for dependency_data in dependencies_create_data
]
)
)
)
).all()
# Add the dependencies to the repo
insert_repo_dependencies_statement = sqlalchemy.dialects.sqlite.insert(
RepoDependency
).on_conflict_do_nothing([RepoDependency.repo_id, RepoDependency.dependency_id])
await session.execute(
insert_repo_dependencies_statement,
[
{
"repo_id": repo.id,
"dependency_id": dependency.id,
}
for dependency in dependencies
],
)
async def scrape_source_graph_repos() -> None:
"""
Iterate over the source graph repos and create or update them in the database.
:return: None
"""
async with AsyncSourceGraphSSEClient() as sg_client:
async with async_session_uow() as session:
async with asyncio.TaskGroup() as tg:
logger.info(
"Creating or updating repos from source graph repos data.",
enqueue=True,
)
async for sg_repos_data in sg_client.aiter_fastapi_repos():
logger.info(
"Received {count} repos.",
count=len(sg_repos_data),
enqueue=True,
)
tg.create_task(
create_or_update_repos_from_source_graph_repos_data(
session=session,
source_graph_repos_data=sg_repos_data,
)
)
await session.commit()
async def parse_dependencies_for_repo(
semaphore: asyncio.Semaphore, repo_id: RepoId
) -> None:
"""
Parse the dependencies for a given repo and create them in the database.
:param semaphore: A semaphore to limit the number of concurrent requests
:param repo_id: The id of the repo for which to parse the dependencies
:return: None
"""
async with async_session_uow() as session, semaphore:
# Fetch the repo from the database
logger.info(
"Fetching the repo with id {repo_id}.", repo_id=repo_id, enqueue=True
)
repo = (
await session.scalars(sqlalchemy.select(Repo).where(Repo.id == repo_id))
).one()
# Create the dependencies for the repo
logger.info(
"Creating the dependencies for the repo with id {repo_id}.",
repo_id=repo_id,
enqueue=True,
)
await _create_dependencies_for_repo(session=session, repo=repo)
await session.commit()
async def parse_dependencies_for_repos() -> None:
"""
Parse the dependencies for all the repos in the database.
:return: None.
"""
logger.info("Fetching the repos from the database.", enqueue=True)
async with async_session_uow() as session:
repo_ids = (
await session.scalars(
sqlalchemy.select(Repo.id).order_by(
Repo.last_checked_revision.is_(None).desc()
)
)
).all()
logger.info("Fetched {count} repos.", count=len(repo_ids), enqueue=True)
logger.info("Parsing the dependencies for the repos.", enqueue=True)
semaphore = asyncio.Semaphore(10)
async with asyncio.TaskGroup() as tg:
for repo_id in repo_ids:
logger.info(
"Parsing the dependencies for repo {repo_id}.",
repo_id=repo_id,
enqueue=True,
)
tg.create_task(
parse_dependencies_for_repo(
semaphore=semaphore, repo_id=RepoId(repo_id)
)
)
app = typer.Typer()
@app.command()
def scrape_repos() -> None:
"""
Scrape the FastAPI-related repositories utilizing the source graph API.
:return: None
"""
logger.info("Scraping the source graph repos.", enqueue=True)
asyncio.run(scrape_source_graph_repos())
@app.command()
def parse_dependencies() -> None:
"""
Parse the dependencies for all the repos in the database.
:return: None.
"""
logger.info(
"Parsing the dependencies for all the repos in the database.", enqueue=True
)
asyncio.run(parse_dependencies_for_repos())
if __name__ == "__main__":
app()

View File

@ -0,0 +1 @@
"""Scraping module for the application."""

123
app/source_graph/client.py Normal file
View File

@ -0,0 +1,123 @@
"""The client for the SourceGraph API."""
import asyncio
from collections.abc import AsyncGenerator, Mapping, MutableMapping
from contextlib import asynccontextmanager
from datetime import timedelta
from types import TracebackType
from typing import Any, Final, Self
from urllib.parse import quote
import httpx
import stamina
from httpx_sse import EventSource, ServerSentEvent, aconnect_sse
from loguru import logger
from app.source_graph.models import SourceGraphRepoData, SourceGraphRepoDataListAdapter
#: The URL of the SourceGraph SSE API.
SOURCE_GRAPH_STREAM_API_URL: Final[str] = "https://sourcegraph.com/.api/search/stream"
#: The query parameters for the SourceGraph SSE API.
FASTAPI_REPOS_QUERY_PARAMS: Final[Mapping[str, str]] = {
"q": quote(
" ".join(
[
"repo:has.content(from fastapi import FastApi)",
"type:repo",
"visibility:public",
"archived:no",
"fork:no",
]
)
),
}
class AsyncSourceGraphSSEClient:
"""
A client for the SourceGraph SSE API.
To learn more about the underlying API, see the ``SourceGraph SSE API``
https://docs.sourcegraph.com/api/stream_api#sourcegraph-stream-api
"""
def __init__(self: Self) -> None:
"""Initialize the client."""
self._last_event_id: str | None = None
self._reconnection_delay: float = 0.0
self._aclient: httpx.AsyncClient = httpx.AsyncClient()
async def __aenter__(self: Self) -> Self:
"""Enter the async context manager."""
await self._aclient.__aenter__()
return self
async def __aexit__(
self: Self,
exc_type: type[BaseException] | None = None,
exc_val: BaseException | None = None,
exc_tb: TracebackType | None = None,
) -> None:
"""Exit the async context manager."""
return await self._aclient.__aexit__(exc_type, exc_val, exc_tb)
@asynccontextmanager
async def _aconnect_sse(
self: Self, **kwargs: MutableMapping[str, Any]
) -> AsyncGenerator[EventSource, None]:
"""Connect to the SourceGraph SSE API."""
headers = kwargs.pop("headers", {})
if self._last_event_id is not None:
headers["Last-Event-ID"] = self._last_event_id
async with aconnect_sse(
client=self._aclient,
url=str(SOURCE_GRAPH_STREAM_API_URL),
method="GET",
headers=headers,
**kwargs,
) as event_source:
yield event_source
async def _aiter_sse(
self: Self, **kwargs: MutableMapping[str, Any]
) -> AsyncGenerator[ServerSentEvent, None]:
"""Iterate over the SourceGraph SSE API."""
async with self._aconnect_sse(**kwargs) as event_source:
async for event in event_source.aiter_sse():
yield event
async def _aiter_sse_with_retries(
self: Self, **kwargs: MutableMapping[str, Any]
) -> AsyncGenerator[ServerSentEvent, None]:
"""Iterate over the SourceGraph SSE API with retries."""
async for attempt in stamina.retry_context(
on=(httpx.ReadError, httpx.ReadTimeout)
):
with attempt:
await asyncio.sleep(self._reconnection_delay)
async for event in self._aiter_sse(**kwargs):
self._last_event_id = event.id
if event.retry is not None:
logger.error(
"Received a retry event from the SourceGraph SSE API. "
"Schedule a reconnection in {retry} milliseconds.",
retry=event.retry,
enqueue=True,
)
self._reconnection_delay = timedelta(
milliseconds=event.retry
).total_seconds()
else:
self._reconnection_delay = 0.0
yield event
async def aiter_fastapi_repos(
self: Self,
) -> AsyncGenerator[list[SourceGraphRepoData], None]:
"""Iterate over the SourceGraph SSE API with retries."""
async for event in self._aiter_sse_with_retries(
params=dict(FASTAPI_REPOS_QUERY_PARAMS)
):
if event.event == "matches":
yield SourceGraphRepoDataListAdapter.validate_python(event.json())

View File

@ -0,0 +1,12 @@
"""Factories for creating test data."""
from polyfactory.factories.pydantic_factory import ModelFactory
from polyfactory.pytest_plugin import register_fixture
from app.source_graph.models import SourceGraphRepoData
@register_fixture
class SourceGraphRepoDataFactory(ModelFactory[SourceGraphRepoData]):
"""Factory for creating RepoCreateData."""
__model__ = SourceGraphRepoData

View File

@ -0,0 +1,46 @@
"""Mapper for source graph models to the database objects."""
from collections.abc import Sequence
import sqlalchemy.dialects.sqlite
from sqlalchemy.ext.asyncio import AsyncSession
from app import database
from app.source_graph.models import SourceGraphRepoData
async def create_or_update_repos_from_source_graph_repos_data(
session: AsyncSession, source_graph_repos_data: Sequence[SourceGraphRepoData]
) -> Sequence[database.Repo]:
"""
Create repos from source graph repos data.
If any repos already exist, update them.
:param session: The database session.
:param source_graph_repos_data: The source graph repos data.
"""
insert_statement = sqlalchemy.dialects.sqlite.insert(database.Repo)
update_statement = insert_statement.on_conflict_do_update(
index_elements=[database.Repo.source_graph_repo_id],
set_={
"url": insert_statement.excluded.url,
"description": insert_statement.excluded.description,
"stars": insert_statement.excluded.stars,
"source_graph_repo_id": insert_statement.excluded.source_graph_repo_id,
},
)
return (
await session.scalars(
update_statement.returning(database.Repo),
[
{
"url": str(repo_data.repo_url),
"description": repo_data.description,
"stars": repo_data.stars,
"source_graph_repo_id": repo_data.repo_id,
}
for repo_data in source_graph_repos_data
],
)
).all()

View File

@ -0,0 +1,39 @@
"""The models for the Source Graph data."""
import datetime
from typing import Literal, NewType, Self
from pydantic import (
BaseModel,
Field,
HttpUrl,
NonNegativeInt,
TypeAdapter,
computed_field,
)
#: The ID of a repository from the SourceGraph API.
SourceGraphRepoId = NewType("SourceGraphRepoId", int)
class SourceGraphRepoData(BaseModel):
"""The data of a repository."""
type: Literal["repo"]
repo_id: SourceGraphRepoId = Field(..., alias="repositoryID")
repo_handle: str = Field(..., alias="repository")
stars: NonNegativeInt = Field(..., alias="repoStars")
last_fetched_at: datetime.datetime = Field(..., alias="repoLastFetched")
description: str = Field(default="")
@computed_field # type: ignore[misc]
@property
def repo_url(self: Self) -> HttpUrl:
"""The URL of the repository."""
return TypeAdapter(HttpUrl).validate_python(f"https://{self.repo_handle}")
#: The type adapter for the SourceGraphRepoData.
SourceGraphRepoDataAdapter = TypeAdapter(SourceGraphRepoData)
#: The type adapter for the SourceGraphRepoData list.
SourceGraphRepoDataListAdapter = TypeAdapter(list[SourceGraphRepoData])

View File

@ -0,0 +1 @@
"""Test the scraping of the SourceGraph API."""

View File

@ -0,0 +1,120 @@
"""Test the client module for the source graph."""
from typing import Any
import pytest
from dirty_equals import HasLen, IsDatetime, IsInstance, IsPositiveInt
from pydantic import Json, TypeAdapter
from app.source_graph.models import SourceGraphRepoData
@pytest.fixture()
def source_graph_matched_repos_data() -> Json[Any]:
"""Return the sample data of the matched repositories."""
return [
{
"type": "repo",
"repositoryID": 55636527,
"repository": "github.com/tiangolo/sqlmodel",
"repoStars": 10277,
"repoLastFetched": "2023-07-31T18:47:22.875731Z",
"description": (
"SQL databases in Python, designed "
"for simplicity, compatibility, "
"and robustness."
),
"metadata": {
"fastapi": "null",
"json": "null",
"json-schema": "null",
"pydantic": "null",
"python": "null",
"sql": "null",
"sqlalchemy": "null",
},
},
{
"type": "repo",
"repositoryID": 59434622,
"repository": "github.com/reflex-dev/reflex",
"repoStars": 10061,
"repoLastFetched": "2023-07-31T08:58:42.692906Z",
"description": "(Previously Pynecone) 🕸 Web apps in pure Python 🐍",
},
{
"type": "repo",
"repositoryID": 42982149,
"repository": "github.com/PaddlePaddle/PaddleNLP",
"repoStars": 9804,
"repoLastFetched": "2023-07-31T16:48:08.839209Z",
"description": (
"👑 Easy-to-use and powerful NLP library with 🤗 "
"Awesome model zoo, supporting wide-range of NLP tasks "
"from research to industrial applications, including"
" 🗂Text Classification, 🔍 Neural Search, ❓ Question "
"Answering, Information Extraction, "
"📄 Document Intelligence, 💌 Sentiment Analysis etc."
),
"metadata": {
"bert": "null",
"embedding": "null",
"ernie": "null",
"information-extraction": "null",
"neural-search": "null",
"nlp": "null",
"paddlenlp": "null",
"pretrained-models": "null",
"question-answering": "null",
"search-engine": "null",
"semantic-analysis": "null",
"sentiment-analysis": "null",
"seq2seq": "null",
"transformer": "null",
"transformers": "null",
"uie": "null",
},
},
{
"type": "repo",
"repositoryID": 36246068,
"repository": "github.com/realpython/materials",
"repoStars": 4359,
"repoLastFetched": "2023-07-31T05:15:16.993896Z",
},
]
def test_source_graph_repo_data(source_graph_matched_repos_data: Json[Any]) -> None:
"""Test the SourceGraphRepoData deserialization."""
assert source_graph_matched_repos_data == HasLen(4)
_SourceGraphRepoDataListValidator = TypeAdapter(list[SourceGraphRepoData])
repos_parsed = _SourceGraphRepoDataListValidator.validate_python(
source_graph_matched_repos_data
)
assert repos_parsed == HasLen(4)
assert all(repo == IsInstance[SourceGraphRepoData] for repo in repos_parsed)
assert all(
repo.repo_id == repo_data["repositoryID"]
for repo, repo_data in zip(
repos_parsed, source_graph_matched_repos_data, strict=True
)
)
assert all(
repo.repo_handle == repo_data["repository"]
for repo, repo_data in zip(
repos_parsed, source_graph_matched_repos_data, strict=True
)
)
assert all(
repo.stars == IsPositiveInt and repo.stars == repo_data["repoStars"]
for repo, repo_data in zip(
repos_parsed, source_graph_matched_repos_data, strict=True
)
)
assert all(
str(repo.repo_url) == f"https://{repo_data['repository']}"
for repo, repo_data in zip(
repos_parsed, source_graph_matched_repos_data, strict=True
)
)
assert all(repo.last_fetched_at == IsDatetime for repo in repos_parsed)

View File

@ -0,0 +1,65 @@
"""The tests for the source graph mapper to the database objects."""
import pytest
import sqlalchemy
from dirty_equals import IsInstance, IsList
from sqlalchemy.ext.asyncio import AsyncSession
from app import database
from app.source_graph.factories import SourceGraphRepoDataFactory
from app.source_graph.mapper import create_or_update_repos_from_source_graph_repos_data
from app.source_graph.models import SourceGraphRepoData
pytestmark = pytest.mark.anyio
async def test_create_or_update_repos_from_source_graph_repos_data(
test_db_session: AsyncSession,
source_graph_repo_data_factory: SourceGraphRepoDataFactory,
) -> None:
"""Test creating repos from source graph repos data."""
source_graph_repo_data: list[
SourceGraphRepoData
] = source_graph_repo_data_factory.batch(5)
repos = await create_or_update_repos_from_source_graph_repos_data(
test_db_session, source_graph_repo_data
)
assert repos == IsList(length=5)
assert all(repo == IsInstance[database.Repo] for repo in repos)
assert all(repo.id is not None for repo in repos)
async def test_create_or_update_repos_from_source_graph_repos_data_update(
some_repos: list[database.Repo],
test_db_session: AsyncSession,
source_graph_repo_data_factory: SourceGraphRepoDataFactory,
) -> None:
"""Test updating repos from source graph repos data."""
assert (
await test_db_session.execute(
sqlalchemy.select(sqlalchemy.func.count(database.Repo.id))
)
).scalar() == len(some_repos)
source_graph_repos_data: list[
SourceGraphRepoData
] = source_graph_repo_data_factory.batch(len(some_repos))
source_graph_repos_data = [
SourceGraphRepoData(
**(
repo_data.model_dump(by_alias=True)
| {"repositoryID": repo.source_graph_repo_id}
)
)
for repo, repo_data in zip(some_repos, source_graph_repos_data, strict=True)
]
repos = await create_or_update_repos_from_source_graph_repos_data(
test_db_session, source_graph_repos_data
)
assert repos == IsList(length=len(some_repos))
assert all(repo == IsInstance[database.Repo] for repo in repos)
assert all(repo.id is not None for repo in repos)
assert (
await test_db_session.execute(
sqlalchemy.select(sqlalchemy.func.count(database.Repo.id))
)
).scalar() == len(some_repos)

1
app/tests/__init__.py Normal file
View File

@ -0,0 +1 @@
"""The application tests."""

103
app/tests/test_database.py Normal file
View File

@ -0,0 +1,103 @@
"""Test the operations on the database models."""
import pytest
import sqlalchemy as sa
import sqlalchemy.orm
from dirty_equals import IsList
from sqlalchemy.ext.asyncio import AsyncSession
from app import database
from app.factories import DependencyCreateDataFactory
from app.models import DependencyCreateData
from app.source_graph.factories import SourceGraphRepoDataFactory
from app.source_graph.models import SourceGraphRepoData
pytestmark = pytest.mark.anyio
def _assert_repo_properties(
repo: database.Repo, source_graph_repo_data: SourceGraphRepoData
) -> bool:
"""Assert that the repo has the expected properties."""
assert repo.id is not None
assert repo.url == str(source_graph_repo_data.repo_url)
assert repo.description == source_graph_repo_data.description
assert repo.stars == source_graph_repo_data.stars
assert repo.source_graph_repo_id == source_graph_repo_data.repo_id
return True
async def test_create_repo_no_dependencies(
test_db_session: AsyncSession,
source_graph_repo_data_factory: SourceGraphRepoDataFactory,
) -> None:
"""Test creating a repo."""
source_graph_repo_data: SourceGraphRepoData = source_graph_repo_data_factory.build()
repo = database.Repo(
url=str(source_graph_repo_data.repo_url),
description=source_graph_repo_data.description,
stars=source_graph_repo_data.stars,
source_graph_repo_id=source_graph_repo_data.repo_id,
)
test_db_session.add(repo)
await test_db_session.flush()
await test_db_session.refresh(repo)
_assert_repo_properties(repo, source_graph_repo_data)
assert (await repo.awaitable_attrs.dependencies) == IsList(length=0)
async def test_create_repo_with_dependencies(
test_db_session: AsyncSession,
source_graph_repo_data_factory: SourceGraphRepoDataFactory,
dependency_create_data_factory: DependencyCreateDataFactory,
) -> None:
"""Test creating a repo with dependencies."""
source_graph_repo_data: SourceGraphRepoData = source_graph_repo_data_factory.build()
dependencies_create_data: list[
DependencyCreateData
] = dependency_create_data_factory.batch(5)
repo = database.Repo(
url=str(source_graph_repo_data.repo_url),
description=source_graph_repo_data.description,
stars=source_graph_repo_data.stars,
source_graph_repo_id=source_graph_repo_data.repo_id,
dependencies=[
database.Dependency(**dependency_create_data.model_dump())
for dependency_create_data in dependencies_create_data
],
)
test_db_session.add(repo)
await test_db_session.flush()
await test_db_session.refresh(repo)
_assert_repo_properties(repo, source_graph_repo_data)
repo_dependencies = await repo.awaitable_attrs.dependencies
assert repo_dependencies == IsList(length=5)
assert all(
repo_dependency.name == dependency.name
for repo_dependency, dependency in zip(
repo_dependencies, dependencies_create_data, strict=True
)
)
async def test_list_repositories(
test_db_session: AsyncSession,
some_repos: list[database.Repo],
) -> None:
"""Test listing repositories."""
repos_from_db_result = await test_db_session.execute(
sa.select(database.Repo).options(
sqlalchemy.orm.joinedload(database.Repo.dependencies)
)
)
repos_from_db = repos_from_db_result.scalars().unique().all()
assert repos_from_db == IsList(length=10)
assert all(
repo.id == repo_data.id
and all(
repo_dependency.name == dependency.name
for repo_dependency, dependency in zip(
repo.dependencies, repo_data.dependencies, strict=True
)
)
for repo, repo_data in zip(repos_from_db, some_repos, strict=True)
)

6
app/types.py Normal file
View File

@ -0,0 +1,6 @@
"""Type definitions for the application."""
from typing import NewType
RepoId = NewType("RepoId", int)
DependencyId = NewType("DependencyId", int)
RevisionHash = NewType("RevisionHash", str)

27
app/uow.py Normal file
View File

@ -0,0 +1,27 @@
"""
The Unit of Work pattern implementation.
To learn more about the UoW, see:
https://www.cosmicpython.com/book/chapter_06_uow.html
"""
from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import async_session_maker
@asynccontextmanager
async def async_session_uow() -> AsyncGenerator[AsyncSession, None]:
"""
Provide a transactional scope around a series of operations.
:return: a UoW instance
"""
async with async_session_maker() as session:
async with session.begin():
try:
yield session
finally:
await session.rollback()

BIN
db.sqlite3 Normal file

Binary file not shown.

19180
dependencies_index.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,533 +0,0 @@
| Project | Dependencies |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|[2020_slowdelivery_take](https://github.com/zekaio/2020_slowdelivery_take ) |aiohttp, pytest, tortoise |
|[AI-Service](https://github.com/eHelply/AI-Service ) |kombu, setuptools, pymongo, redis, sentry_asgi, sentry_sdk, pymlconf, socketio, src |
|[African_Wildlife_Classifier](https://github.com/peterbacalso/African_Wildlife_Classifier ) |aiohttp, fastai, torch |
|[Auth-Service](https://github.com/eHelply/Auth-Service ) |kombu, requests, setuptools, passlib, pymongo, redis, sentry_asgi, sentry_sdk, pymlconf, jwt, socketio, src, bson |
|[BenchmarkRoundOne](https://github.com/peterdeme/BenchmarkRoundOne ) |aiohttp |
|[Benchmarker](https://github.com/vutran1710/Benchmarker ) |apis |
|[Blog](https://github.com/elbruno/Blog ) |face_recognition, imutils, PIL, flask, cv2 |
|[CCTO](https://github.com/SnarferX/CCTO ) |sets, SimpleHTTPSErver, requests, dircache, ovm_lib, jarray, pip, httplib, urllib3, SockerServer, ansible, hello, java, ovmclient |
|[CFE_30D.PY](https://github.com/torredefarol24/CFE_30D.PY ) |formatting, flask, scrape, logger, requests, pandas, download_util, requests_html |
|[COVID-19API](https://github.com/zeroday0619/COVID-19API ) |aiohttp, ujson, async_lru, API, scrapy, fastapi_plugins, aioredis, bs4 |
|[COVID-QA](https://github.com/deepset-ai/COVID-QA ) |elasticapm, eval, sentence_transformers, sklearn, elasticsearch, tqdm, scrapy, requests, backend, nltk, haystack, preprocess, farm, langid, datasources, torch, tfidf_train, covid_nlp |
|[CUCM-Phone-Info](https://github.com/jsteinberg1/CUCM-Phone-Info ) |rq, cryptography, zeep, requests, redis, lxml, lib, apscheduler, api, OpenSSL, sqlalchemy, jwt, bs4 |
|[Chatbot](https://github.com/aramakus/Chatbot ) |nltk, chatterbot, sklearn, requests, tqdm, chatbot |
|[ChatiChatou](https://github.com/auredentan/ChatiChatou ) |chat, aioredis |
|[CheckersAI](https://github.com/HuiiBuh/CheckersAI ) |pytest, aiohttp, game, api, conftest, checkers |
|[Cloud_APS1](https://github.com/ehrhardt98/Cloud_APS1 ) |pymongo, requests |
|[CryptoViz](https://github.com/MohanVashist1/CryptoViz ) |bs4, requests, pyti, pymongo, lib, binance, dateutil, cryptocalculator, channelfinder, dotenv, flask, boto3, click, fastapi_users |
|[DS-API](https://github.com/BW-Post-Here-06-2020/DS-API ) |dotenv, praw |
|[Daft](https://github.com/mpalka31/DaftAcademyCourse ) |main, queries, schemas, pytest, jose, database, crud |
|[Daims_FastAPI](https://github.com/GeorgeMiao219/Daims_FastAPI ) |auth, dns, dataset, config, url, utils, database |
|[Data-Engineering](https://github.com/De-Dash/Data-Engineering ) |nltk, aiohttp, api |
|[Docker-Builder](https://github.com/Javier162380/Docker-Builder ) |rq, pytest, endpoints, requests, redis, builder, docker, settings, docker_builder, models, worker, middlewares, router |
|[DockerImageResNet50](https://github.com/OrenLeung/DockerImageResNet50 ) |redis, PIL, locust, keras |
|[Downotifier](https://github.com/herbzhao/Downotifier ) |twilio, bs4, requests, URLChecker, TwilioWhatsapp |
|[ExcelTools](https://github.com/xx2life/ExcelTools ) |motor, databases |
|[ExpenseAPI](https://github.com/MushroomMaula/ExpenseAPI ) |pytest, faker, sqlalchemy, myapp, fastapi_login, alembic, dotenv |
|[FAAS](https://github.com/jacksonhenry3/FAAS ) |flask |
|[Fast-API-Starter](https://github.com/khaman1/Fast-API-Starter ) |shared, urls |
|[Fast-Project](https://github.com/alex-2201/Fast-Project ) |redis, conn, cassandra, apis, pymysql, logzero, models, utils, middlewares |
|[FastAPI-Auth](https://github.com/Madpilot0/FastAPI-Auth ) |bcrypt, lib, routes, yaml, jwt, MySQLdb |
|[FastAPI-CRUD](https://github.com/Mr-Manna/FastAPI-CRUD ) |databases, sqlalchemy, post, config |
|[FastAPI-Demo](https://github.com/JPMike/FastAPI-Demo ) |requests |
|[FastAPI-Example](https://github.com/gauravgola96/FastAPI-Example ) |botocore, aiobotocore, dotenv, s3_events, boto3, utils |
|[FastAPI-Learning-Example](https://github.com/oinsd/FastAPI-Learning-Example ) |main, main_b, jwt, routers, sqlalchemy, database, passlib |
|[FastAPI-React-PostgreSQL_Full-Stack](https://github.com/scionoftech/FastAPI-React-PostgreSQL_Full-Stack ) |db, setuptools, logs, passlib, utils, sqlalchemy, conf, routes, auth, jwt |
|[FastAPITutorial](https://github.com/HeywoodKing/FastAPITutorial ) |invoke, config |
|[FastAPI_Tortoise_template](https://github.com/GoddessEyes/FastAPI_Tortoise_template ) |celery, jwt, tortoise, template, passlib, emails |
|[FastAPI_Vue](https://github.com/quietking0312/FastAPI_Vue ) |pymongo, apps |
|[FastAPI_app1](https://github.com/Sai-Vamsi-Ogety/FastAPI_app1 ) |spacy |
|[FastAPI_proto](https://github.com/bartomo/FastAPI_proto ) |controllers, urls, sqlalchemy, db, models |
|[FastAdmin](https://github.com/CoderCharm/FastAdmin ) |passlib, loguru, sqlalchemy, myapp, jose, alembic |
|[Fastapi](https://github.com/xyz25/Fastapi ) |router_app, sqlalchemy |
|[FastapiLearn](https://github.com/xuqm/FastapiLearn ) |part4, part11, part7, part8, part15, part2, part10, application, part14, part12, part9, part13, part3, part16, part1, part5, part6 |
|[Fusion-Vision](https://github.com/sdhnshu/Fusion-Vision ) |wandb, pytest, sklearn, requests, tqdm, torch, text_classification |
|[GET_POST](https://github.com/mitsumushibayama/GET_POST ) |MySQLdb |
|[GraphQLAPI](https://github.com/webjunkie01/GraphQLAPI ) |graphene, cryptacular, pytest, graphene_sqlalchemy, sqlalchemy |
|[Gringotts](https://github.com/cning112/Gringotts ) |werkzeug, requests, flask_restplus, typing_extensions, apis, flask_cors, libs, flask, routers, models |
|[HjwzwApi](https://github.com/k1dave6412/HjwzwApi ) |backend, requests, aiohttp, asyncpg, loguru, sqlalchemy, myapp, alembic, databases, bs4 |
|[Image-Diff-back](https://github.com/filipe-guerra/Image-Diff-back ) |imutils, skimage, imageDiff, cv2 |
|[Item-Xref](https://github.com/Roselingit/Item-Xref ) |psycopg2 |
|[KOARCH](https://github.com/janstrohschein/KOARCH ) |classes, emotion_recognition_master, pydash, sklearn, requests, tweepy, scipy, kafka, yaml, psycopg2, emotion_predictor, avro, keras |
|[Logging-Service](https://github.com/eHelply/Logging-Service ) |kombu, setuptools, pymongo, redis, sentry_asgi, sentry_sdk, pymlconf, socketio, src |
|[MLServer](https://github.com/SeldonIO/MLServer ) |orjson, grpc, click, pytest, mlserver, google, setuptools |
|[MallAPI](https://github.com/CoderCharm/MallAPI ) |alembic, loguru, sqlalchemy, extensions, setting, myapp, api, utils |
|[MealCare](https://github.com/hack4impact-mcgill/MealCare ) |pony, passlib, config, tests, sqlalchemy, psycopg2, jwt |
|[MetodoClasificacionTexto](https://github.com/talend-Erick/MetodoClasificacionTexto ) |gensim, nltk, spacy, src, pandas |
|[MyChild](https://github.com/YunusovSamat/MyChild ) |passlib, asyncpg, tortoise, sqlalchemy, alembic, databases, jwt |
|[MyNotes](https://github.com/wq758511990/MyNotes ) |serial, werkzeug, flask_sqlalchemy, flask_httpauth, sqlalchemy, wtforms, pytz, webapp, flask, itsdangerous |
|[NIMSPARQL](https://github.com/Ningensei848/NIMSPARQL ) |elasticapm, sqlalchemy, elasticsearch, db, api |
|[NT118](https://github.com/maivanhung33/NT118 ) |request, kombu, common, elasticsearch, geopy, requests, injector, pymongo, redis, consul, boltons, cachetools, controller, elasticsearch_dsl, sqlalchemy, service, pytz, response |
|[News-Summarizer](https://github.com/CYBINT-IN/News-Summarizer ) |scipy, sentence_transformers, flask, sklearn, torch, requests, transformers, pyLDAvis, bs4 |
|[Notification-Service](https://github.com/eHelply/Notification-Service ) |kombu, setuptools, pymongo, redis, sentry_asgi, sentry_sdk, pymlconf, socketio, src |
|[Pycharm](https://github.com/godori004/Pycharm ) |urllib3, flask_restful, flask, src, pandas, google |
|[Python-example](https://github.com/hzjsea/Python-example ) |netmiko, static_files, requests, basedb, sqlalchemy, ansible, zabbix_info |
|[Python3Test](https://github.com/hjslovehr/Python3Test ) |requests, redis, openpyxl, sqlhelper, pymssql, md5_helper, flask, helpers, bs4 |
|[PythonFastApi](https://github.com/kbeaugrand/PythonFastApi ) |win32service, win32event, servicemanager, win32serviceutil, yaml |
|[RemoteVP-Npc](https://github.com/viccom/RemoteVP-Npc ) |win32serviceutil, serial, requests, apps, pythoncom, cores, helper, ping3, bases, hbmqtt, conf, Crypto, wmi |
|[RestFramework](https://github.com/rakesh4real/RestFramework ) |django, streamapp, rest_framework, other_app, jwt, senddata, my_app, passlib |
|[SOA](https://github.com/FisnikL/SOA ) |prometheus_client, sqlalchemy, sqlalchemy_utils, database |
|[Semester-Stats](https://github.com/Rushyanth111/Semester-Stats ) |playhouse, faker, setuptools, peewee, mailmerge, docx |
|[Service-Template](https://github.com/eHelply/Service-Template ) |kombu, setuptools, pymongo, redis, sentry_asgi, sentry_sdk, pymlconf, socketio, src |
|[SpotifyAPI](https://github.com/dixneuf19/SpotifyAPI ) |spotipy, dotenv, src |
|[StanleyIpkiss](https://github.com/JimmiBram/StanleyIpkiss ) |tests, sibase |
|[Studium-ds](https://github.com/Lambda-School-Labs/Studium-ds ) |retrieve_definition, gauge_plot, requests, calendar_heatmap, inflect |
|[TT_COVID19_API_site_and_emailer](https://github.com/VSpectrum/TT_COVID19_API_site_and_emailer ) |email_validator, requests, config, emailer |
|[TaskXenter](https://github.com/CoolSpring8/TaskXenter ) |celery, sentry_sdk, loguru, databases, jwt, tortoise, passlib, httpx |
|[Telegram-BusBot-DataManager](https://github.com/David-Lor/Telegram-BusBot-DataManager ) |pymongo, motor, busbot_data_manager |
|[WAM_server_API_template](https://github.com/rl-institut/WAM_server_API_template ) |flask_app, celery, flask, pytest, worker, sphinx_rtd_theme |
|[WEB](https://github.com/maivanhung33/WEB ) |request, kombu, common, elasticsearch, geopy, requests, injector, pymongo, redis, consul, boltons, cachetools, controller, elasticsearch_dsl, sqlalchemy, service, pytz, response |
|[WFM](https://github.com/unegade/WFM ) |pika, aio_pika, BSSAPI, locust |
|[WebApp-PhoneClassifier](https://github.com/minh-dg/WebApp-PhoneClassifier ) |fastai |
|[WitnessMe](https://github.com/byt3bl33d3r/WitnessMe ) |xmltodict, imgcat, pytest, pyppeteer, jinja2, terminaltables, prompt_toolkit, pkg_resources, aiosqlite, yaml, witnessme |
|[Words_record](https://github.com/LMFrank/Words_record ) |databases, pytest, pymysql, sqlalchemy, requests |
|[Workspace](https://github.com/AYCHSPACE/Workspace ) |tqdm, jupyter_core, setuptools, tornado, crontab, pip, psutil, IPython, git, notebook |
|[YoutubeBackup](https://github.com/FratStar/YoutubeBackup ) |google_auth_oauthlib, zeep, googleapiclient, spyne, google |
|[Zulu](https://github.com/OSS-team-zulu/Zulu ) |requests, passlib, pymongo, geojson, tests, zulu, dynaconf, jwt, bson, pytest |
|[ai-dungeon](https://github.com/AntonNeld/ai-dungeon ) |errors, test_utils, typing_extensions, pytest, models, api, dungeon |
|[aioprometheus](https://github.com/claws/aioprometheus ) |setuptools, aiohttp, alabaster, quart, psutil, asynctest, sphinx, aioprometheus, quantile, prometheus_metrics_proto |
|[aita](https://github.com/logan-connolly/aita ) |pytest, requests, tqdm, aiohttp, asyncpg, aita, loguru, orm, typer, sqlalchemy, databases, praw |
|[alda-online](https://github.com/JesseChua94/alda-online ) |models, alda |
|[alg_interface_fastapi_project](https://github.com/wuzaipei/alg_interface_fastapi_project ) |system_file, pymysql, sqlalchemy, data_model |
|[alice-yamaha-skill](https://github.com/toshka/alice-yamaha-skill ) |exceptions, auth, yaml, capabilities, routers, rxv, config, httpx |
|[allay-ds](https://github.com/Lambda-School-Labs/allay-ds ) |wandb, spacy, sklearn, requests, scrapy, process_data, fastapi_app, tensorflow, numpy, indeed, en_core_web_sm, dotenv |
|[allure_reporter](https://github.com/penguinlav/allure_reporter ) |jinja2, requests, allure_reporter, loguru, aiofiles, async_generator, pytest |
|[andrewhou-zonar](https://github.com/amhou/andrewhou-zonar ) |main, requests, util |
|[apex-tracker](https://github.com/Timzan/apex-tracker ) |routers, requests, config |
|[api](https://github.com/wuzaipei/alg_interface_fastapi_project ) |pyazo_api, alembic, dotenv, jwt, sqlalchemy, passlib |
|[api-ocr](https://github.com/dzakyputra/api-ocr ) |tesserocr, PIL, cv2, modules |
|[api-poc](https://github.com/igorfarias30/fastapi-poc ) |sklearn |
|[api.authentication](https://github.com/jrhuerta/api.authentication ) |api_authentication |
|[api_works](https://github.com/omrylcn/api_works ) |PIL, requests |
|[apiestas](https://github.com/franloza/apiestas ) |crawling, scrapy, fuzzywuzzy, loguru, slugify, api, js2xml, dateparser, typer, twisted, pytz, motor |
|[apitoolbox](https://github.com/zuarbase/apitoolbox ) |pytest, setuptools, passlib, sqlalchemy_filters, tests, sqlalchemy, ordered_uuid, tzlocal, pytz, jwt, apitoolbox, itsdangerous |
|[arcas](https://github.com/maialogic/arcas ) |graphene, snapshottest |
|[asgi-server-timing-middleware](https://github.com/sm-Fifteen/asgi-server-timing-middleware ) |yappi, asgi_server_timing, setuptools |
|[asu-schedule](https://github.com/skhortiuk/asu-schedule ) |aiohttp, src, validators, bs4 |
|[async_django_session](https://github.com/imbolc/async_django_session ) |setuptools, aiohttp, asyncpg, async_django_session, cfg, django, databases |
|[authal-poc](https://github.com/michal-nakoneczny/authal-poc ) |authal, asynctest, pytest, bson, requests, tests, httpx |
|[auto_populate](https://github.com/NealWhitlock/auto_populate ) |psycopg2, getter |
|[autoloadtest](https://github.com/hkiang01/autoloadtest ) |locust, hypothesis |
|[automagic_hashtag](https://github.com/MarianMalvin/automagic_hashtag ) |utils, google |
|[b0mb3r](https://github.com/crinny/b0mb3r ) |setuptools, sentry_sdk, loguru, pkg_resources, b0mb3r, phonenumbers, click, httpx |
|[b2blue-challenge](https://github.com/lfvilella/b2blue-challenge ) |pydantic_sqlalchemy, sqlalchemy |
|[b3ta](https://github.com/nm17/b3ta ) |setuptools, sentry_sdk, loguru, pkg_resources, service, b0mb3r, phonenumbers, click, httpx |
|[backend](https://github.com/ElusiveSpirit/fbd-backend ) |asynctest, transliterate |
|[backend-skeleton](https://github.com/dmontagu/backend-skeleton ) |pytest, requests, typing_extensions, sqlalchemy_utils, tests, sqlalchemy, myapp, alembic, tenacity |
|[balikobot_tmp_2](https://github.com/Horac-Bouthon/balikobot_tmp_2 ) |logger_wrapper, databases, schemas, sqlalchemy, conf, routers, sql_factory |
|[base-fastapi-postgresql](https://github.com/alldevic/base-fastapi-postgresql ) |alembic, arq, sqlalchemy, sqlalchemy_utils, gino |
|[basic-python-postgis-docker](https://github.com/stephenhillier/basic-python-postgis-docker ) |alembic, tenacity, sqlalchemy, myapp |
|[bc_rates](https://github.com/MRobalinho/bc_rates ) |bc |
|[belajar-fastapi](https://github.com/aansubarkah/belajar-fastapi ) |yfinance, sqlalchemy, models, config, tutorial, database |
|[bench-rest-api-frameworks](https://github.com/py4mac/bench-rest-api-frameworks ) |sanic, locust, aiohttp, tornado, api, main, core |
|[biomedical-computing-project-backend](https://github.com/SinaKhalili/biomedical-computing-project-backend ) |extra, xlrd, CoronaAnalysis |
|[blog](https://github.com/deagle-z/blog ) |blog, loguru, jwt, sqlalchemy |
|[blog-posts](https://github.com/tiangolo/blog-posts ) |pytest, sqlalchemy, jose, passlib |
|[bluesky](https://github.com/paulorodriguesxv/bluesky ) |pytest, passlib, aiohttp, decouple, sqlalchemy_utils, sqlalchemy, myapp, alembic, jwt |
|[boilerplate](https://github.com/pmcarlos/fast-api-boilerplate ) |utils, config |
|[book-graphics](https://github.com/kamartem/book-graphics ) |alembic, sentry_sdk, asyncpg, loguru, sqlalchemy, gino |
|[bplustogether](https://github.com/wborbajr/bplustogether ) |dynaconf, databases, loguru, sqlalchemy, bpapi |
|[bracket_install](https://github.com/mobjack/bracket_install ) |six, flask, requests, colorama |
|[bread-app](https://github.com/aidan-mcbride/bread-app ) |pyArango, pytest, jwt, routers, api, tests, passlib |
|[bridgeapp](https://github.com/jasujm/bridgeapp ) |click, orjson, bridgeapp, click_log, pytest, zmq |
|[budget-blocks-ds](https://github.com/Lambda-School-Labs/budget-blocks-ds ) |DB, geopy, transactionhist, mainhelp, census, main, psycopg2, dotenv, routers |
|[bullshit-website](https://github.com/kaylynn234/bullshit-website ) |corporate_bullshit |
|[burriking](https://github.com/txemac/burriking ) |infrastructure, dependency_injector, werkzeug, requests, pymongo, freezegun, tests, config, main, user_interface, application, database, flask, bson, pytest, flasgger, domain |
|[bw3_attempt](https://github.com/worldwidekatie/bw3_attempt ) |dotenv, sklearn, requests, joblib |
|[c4p2n](https://github.com/piterpy-meetup/c4p2n ) |c4p2n, fastapi_security_typeform, notion, ppm_telegram_bot_client |
|[cah-v2](https://github.com/Mdellit110/cah-v2 ) |graphene, schema, graphene_sqlalchemy, sqlalchemy, models, config, schema_blackcards, database, schema_whitecards |
|[calculator](https://github.com/ch0c01ate/calculator ) |pymongo, calculator, requests, dbsetup |
|[canvote](https://github.com/alvintangz/canvote ) |jinja2, requests, passlib, sqlalchemy_pagination, humps, sqlalchemy, myapp, pytz, alembic, secure, jwt |
|[cashflow](https://github.com/VSpectrum/cashflow ) |pytest, config |
|[ccrbackend](https://github.com/danieldominguete/ccrbackend ) |six, dotenv, dynamorm, mangum, src, jose, marshmallow |
|[challenge](https://github.com/Creditas/challenge ) |iris_classifier, sklearn |
|[chapushillo](https://github.com/maxipavlovic/chapushillo ) |pusher, dotenv, pusher_client |
|[checkmarx](https://github.com/zetkin/checkmarx ) |scanner, checkmarx, pytest, pyzbar, setuptools |
|[chinook_fastapi](https://github.com/sandervandorsten/chinook_fastapi ) |dotenv, setuptools, chinook_fastapi |
|[cloudrun-fastapi](https://github.com/anthcor/cloudrun-fastapi ) |pytest, actions, passlib, sqlalchemy_utils, config, tests, main, sqlalchemy, myapp, database, google, alembic, schemas, jwt, routers, gunicorn_config, models |
|[cnapp-fastapi](https://github.com/cnapp/cnapp-fastapi ) |sanic, daiquiri, jinja2, prometheus_client, cnapps, starlette_prometheus |
|[code_example_fastapi](https://github.com/d-tamirlan/code_example_fastapi ) |tortoise, src, envparse, fastapi_users |
|[codewars-watchdog](https://github.com/uriyyo/codewars-watchdog ) |git |
|[coding-challenges](https://github.com/fjemi/coding-challenges ) |password_generator, tqdm, jsbeautifier, dateutil, matplotlib, flask_api, word_square_check, flask |
|[concurrency](https://github.com/Jorricks/concurrency ) |PIL, setuptools, redis, dataclasses_json, src, asgiref, click |
|[contact-form](https://github.com/k4ssyi/contact-form ) |dotenv, controllers, urls, settings, utils, request_body |
|[cookiecutter-python](https://github.com/ValentinCalomme/cookiecutter-python ) |typer |
|[cookiecutter-simcore-py-fastapi](https://github.com/pcrespov/cookiecutter-simcore-py-fastapi ) |cryptography, pytest, servicelib, setuptools, simcore_service_catalog, aiohttp, pkg_resources, attr, ptvsd, aiopg, sqlalchemy, tenacity, yarl, httpx |
|[coronavirus-tg-api](https://github.com/egbakou/coronavirus-tg-api ) |aiohttp, invoke, asyncmock, dateparser, async_asgi_testclient, async_generator, dotenv, pytest, bs4 |
|[coursera-ibm-ai-workflow-submission](https://github.com/eightBEC/coursera-ibm-ai-workflow-submission ) |loguru, sklearn, pytest, joblib |
|[coursework](https://github.com/algorithm-ssau/coursework ) |dotenv, databases, motor |
|[covid-19-Chile](https://github.com/RentadroneCL/covid-19-Chile ) |orator, dotenv, routes, pendulum, covid_19_chile, config, database |
|[covid-19-dashboard-api](https://github.com/zeshuaro/covid-19-dashboard-api ) |sortedcontainers, dotenv, jwt, pycountry, requests, google, passlib |
|[covid19-id](https://github.com/anzharip/covid19-id ) |selenium, requests |
|[covidfaq](https://github.com/dialoguemd/covidfaq ) |pytest, spacy, sklearn, tqdm, requests, covidfaq, selenium, bert_reranker, structlog, spacy_langdetect, yaml, html2text, boto3, torch, transformers, bs4 |
|[covidsage](https://github.com/chancey-gardener/covidsage ) |spacy, data_loader, requests, backends, nlu_client, numpy, matplotlib, plotter, rasa, rasa_sdk, pymysql, discourse |
|[cpython3-fastapi](https://github.com/phongln/cpython3-fastapi ) |blog, admin |
|[custom-actions-app-python](https://github.com/Frameio/custom-actions-app-python ) |pytest, requests, custom_actions |
|[daftacademy-python-levelup](https://github.com/holdenkold/daftacademy-python-levelup ) |main, pytest |
|[daiei-backend](https://github.com/a-nakajima-at-shokuryu/daiei-backend ) |fastapi_server, dotenv, models, utils, dateutil, settings |
|[daizu-online-judge-backend](https://github.com/SoyBeansLab/daizu-online-judge-backend ) |psycopg2, infrastructure, marshmallow_dataclass, interface, marshmallow, domain |
|[dask-remote](https://github.com/octoenergy/dask-remote ) |distributed, typing_extensions, pytest, requests, dask_remote, setuptools |
|[datarepo](https://github.com/PUG-PB-Traducao/datarepo ) |bcrypt, dotenv, fastapi_sqlalchemy, sqlalchemy |
|[debitcard](https://github.com/xpnewmedia/debitcard ) |debitcard |
|[debts](https://github.com/afonasev/debts ) |pytest, locust, factory, passlib, sentry_asgi, sentry_sdk, contextvars_executor, server, context_logging, sqlalchemy, alembic, jwt |
|[decentralized-news-publishing](https://github.com/teddymarkov/decentralized-news-publishing ) |ariadne |
|[demo-dms](https://github.com/gucharbon/demo-dms ) |urllib3, typer, pytest, minio, backend |
|[deploy](https://github.com/pcmalves/codeploy-teste ) |main |
|[devops-assignment](https://github.com/fokinpv/devops-assignment ) |asynctest, pytest, service, pulp |
|[devs-conn-api](https://github.com/txemac/devs-conn-api ) |github, pytest, sqlalchemy, sqlalchemy_utils, data, twitter, tests |
|[dfstore](https://github.com/Exhor/dfstore ) |requests, src, tests, feather |
|[dig-bioindex](https://github.com/broadinstitute/dig-bioindex ) |requests, colorama, orjson, lib, enlighten, sqlalchemy, dotenv, boto3, click |
|[django-fastapi-example](https://github.com/jordaneremieff/django-fastapi-example ) |django, api |
|[docker-fastapi-demo](https://github.com/pylixm/docker-fastapi-demo ) |alembic, loguru, databases, core, sqlalchemy, service, myapp, api |
|[docker-workshop](https://github.com/blairdrummond/docker-workshop ) |scipy, PIL, dash, flask, inference, sklearn, requests, numpy, joblib, flask_caching |
|[downloads_statistics](https://github.com/mmidu/downloads_statistics ) |redis, main, seeds, controllers, DownloadSeeder, requests, models, config, utils, DownloadsController |
|[dreamcatcher](https://github.com/sbathgate/dreamcatcher ) |pytest, passlib, sqlalchemy, myapp, jose, alembic, celery, tenacity, raven, emails |
|[duke](https://github.com/jamescurtin/duke ) |duke, PIL, pytest |
|[eXchangeAPI-PY](https://github.com/wborbajr/eXchangeAPI-PY ) |pymongo, dynaconf, exchangeapi, motor |
|[educator_api](https://github.com/wycliffogembo87/educator_api ) |pony, requests, passlib, loguru, api, settings, schemas, core, models, util |
|[effortless_fast_api](https://github.com/davideasaf/effortless_fast_api ) |requests, passlib, invoke, config, utils, main, sqlalchemy, schemas, jwt, models, services, pytest |
|[embl_python_software_engineer_test](https://github.com/yusra-haider/embl_python_software_engineer_test ) |sqlalchemy, requests |
|[eml_analyzer](https://github.com/ninoseki/eml_analyzer ) |async_timeout, pytest, eml_parser, compressed_rtf, arrow, compoundfiles, olefile, loguru, fastapi_utils, tests, dateparser, asynctest, magic, aiospamc, ioc_finder, respx, httpx |
|[entroprise-api](https://github.com/peterdeepsix/entroprise-api ) |simpletransformers, service, models, api |
|[eu-taxation-customs-api](https://github.com/aditya-08/eu-taxation-customs-api ) |main, zeep, requests |
|[events-api](https://github.com/txemac/events-api ) |pytz, xmltodict, pytest, sqlalchemy, sqlalchemy_utils, apscheduler, data, requests, tests |
|[example-fastapi-sqlachemy-pytest](https://github.com/timhughes/example-fastapi-sqlachemy-pytest ) |example, pytest, sqlalchemy |
|[excerpt-formatter](https://github.com/cmckillop/excerpt-formatter ) |text_formatter, slack_manager, requests, models |
|[fake-news-game](https://github.com/jsandovalc/fake-news-game ) |databases |
|[fantasy-fencing](https://github.com/Innoviox/fantasy-fencing ) |colorlog, selenium, click, scrape, requests, logs, bs4 |
|[fapi](https://github.com/glebofff/fapi ) |api, sqlalchemy, myapp, alembic, fastapi_sqlalchemy, core, models, click |
|[fast](https://github.com/foobar8675/fastai-bite ) |routers, user |
|[fast-api-asyncdb](https://github.com/tsadimas/fast-api-asyncdb ) |dotenv, databases, sqlalchemy, settings, fastapi_users |
|[fast-api-boilerplate](https://github.com/pmcarlos/fast-api-boilerplate ) |alembic, dotenv, fastapi_sqlalchemy, core, sqlalchemy, myapp |
|[fast-api-rest](https://github.com/javier-lopez/fast-api-rest ) |config, bjoern |
|[fast-api-sql-template](https://github.com/Jonatha-Varjao/fast-api-sql-template ) |pytest, googletrans, requests, passlib, sqlalchemy_utils, sqlalchemy, alembic, jwt, emails |
|[fast-elm](https://github.com/yuzebin/fast-elm ) |bcrypt, fmmodel, requests, fmsecurity, passlib, fmdb, slugify, fmcrud, fmapi, databases, motor, jwt, fmtoken, bson |
|[fastAPI-be](https://github.com/BonneC/fastAPI-be ) |alembic, dotenv, sqlalchemy, models, api, config, myapp, crud |
|[fastApi](https://github.com/fionasummer/fastApiSelf ) |my_super_project, graphene, projetStage, sqlalchemy |
|[fastApiSelf](https://github.com/fionasummer/fastApiSelf ) |pytest, rr, sqlalchemy, websocket, fackApi, app1 |
|[fastApiSimple](https://github.com/marirs/fastApiSimple ) |pymongo, geoip2, motor, server |
|[fastAppAppointment](https://github.com/EdvinaNakos/fastAppAppointment ) |main, controller, databases, sqlalchemy, db, service |
|[fast_api](https://github.com/davideasaf/effortless_fast_api ) |app_utils, bcrypt, schemas, jwt, sqlalchemy, models, database, crud |
|[fast_api_camelcase_example](https://github.com/ahmednafies/fast_api_camelcase_example ) |humps, models |
|[fast_api_self_study](https://github.com/cuongld2/fast_api_self_study ) |bcrypt, jwt, sqlalchemy, sql_app |
|[fastaaps](https://github.com/sergio-chumacero/fastaaps ) |pymongo, celery, motor |
|[fastai-bite](https://github.com/foobar8675/fastai-bite ) |PIL, graphene, my_utils, fastai2, cv2, httpx |
|[fastapi-GraphQL-full-stack-docker-github-actions-graphene-test-client-template](https://github.com/gaylonalfano/fastapi-GraphQL-full-stack-docker-github-actions-graphene-test-client-template )|graphene, pytest, sqlalchemy, graphql, snapshottest |
|[fastapi-GraphQL-full-stack-docker-travisci-starlette-test-client-template](https://github.com/gaylonalfano/fastapi-GraphQL-full-stack-docker-travisci-starlette-test-client-template ) |graphene, pytest |
|[fastapi-admin](https://github.com/long2ice/fastapi-admin ) |colorama, passlib, fastapi_admin, prompt_toolkit, tortoise, module, xlsxwriter, jwt |
|[fastapi-auth](https://github.com/dmontagu/fastapi-auth ) |argon2, bcrypt, pytest, requests, typing_extensions, fastapi_auth, tests, sqlalchemy, jwt |
|[fastapi-backend](https://github.com/dev-courses/fastapi-backend ) |bcrypt, pytest, passlib, asyncpg, loguru, slugify, tests, asgi_lifespan, sqlalchemy, docker, alembic, psycopg2, databases, jwt, httpx |
|[fastapi-boilerplate](https://github.com/teamhide/fastapi-boilerplate ) |alembic, jwt, sqlalchemy, core, myapp |
|[fastapi-celery](https://github.com/GregaVrbancic/fastapi-celery ) |worker, celery |
|[fastapi-celery-redis-rabbitmq](https://github.com/karthikasasanka/fastapi-celery-redis-rabbitmq ) |redis, celery, shopping |
|[fastapi-cool](https://github.com/genchsusu/fastapi-cool ) |kombu, aiosmtplib, tortoise, yaml, settings, celery, jwt, ldap3 |
|[fastapi-crud](https://github.com/sophiabrandt/fastapi-crud ) |databases, pytest, sqlalchemy, db |
|[fastapi-crud-sync](https://github.com/testdrivenio/fastapi-crud-sync ) |pytest, sqlalchemy |
|[fastapi-demo](https://github.com/sonhal/fastapi-demo ) |rethinkdb, fastapi_demo |
|[fastapi-discovery](https://github.com/DenisOH/fastapi-discovery ) |sqlalchemy, fastapi_discovery |
|[fastapi-docs-cn](https://github.com/apachecn/fastapi-docs-cn ) |graphene, passlib, peewee, couchbase, sqlalchemy, flask, databases, jwt |
|[fastapi-esf-demo](https://github.com/hightfly/fastapi-esf-demo ) |databases, sqlalchemy, sqlalchemy_utils |
|[fastapi-etag](https://github.com/steinitzu/fastapi-etag ) |pytest, requests, fastapi_etag |
|[fastapi-exploring](https://github.com/manjurulhoque/fastapi-exploring ) |alembic, dotenv, fastapi_sqlalchemy, sqlalchemy, myapp |
|[fastapi-for-firebase](https://github.com/attakei/fastapi-for-firebase ) |fastapi_for_firebase, pytest |
|[fastapi-fullstack](https://github.com/lfvilella/fastapi-fullstack ) |pytest, sqlalchemy, validate_docbr |
|[fastapi-healthcheck](https://github.com/jeffsiver/fastapi-healthcheck ) |healthcheck, setuptools |
|[fastapi-helloworld](https://github.com/yashwanthl/fastapi-helloworld ) |nltk, sklearn, modules |
|[fastapi-hero](https://github.com/Hedde/fastapi-heroku-test ) |dotenv, motor, core, db, bson, models, api |
|[fastapi-hex-boilerplate](https://github.com/GArmane/fastapi-hex-boilerplate ) |factory, toolz, tests, sqlalchemy, myapp, alembic, dotenv, databases, pytest |
|[fastapi-jsonrpc](https://github.com/smagafurov/fastapi-jsonrpc ) |fastapi_jsonrpc, aiojobs, pytest, setuptools |
|[fastapi-jwt](https://github.com/carminati-marco/fastapi-jwt ) |ms_auth, auth, jwt, passlib |
|[fastapi-layered-architecture](https://github.com/teamhide/fastapi-layered-architecture ) |alembic, pythondi, jwt, sqlalchemy, core, myapp |
|[fastapi-login](https://github.com/parsd/fastapi-login ) |pytest, requests, setuptools, fastapi_login, assertpy |
|[fastapi-mako](https://github.com/LouisYZK/fastapi-mako ) |mako, setuptools |
|[fastapi-mangum-example](https://github.com/chgangaraju/fastapi-mangum-example ) |mangum |
|[fastapi-microblog](https://github.com/vkhnychenko/fastapi-microblog ) |alembic, core, sqlalchemy, microblog, myapp, user |
|[fastapi-ml-scaffolding](https://github.com/jmeisele/fastapi-ml-scaffolding ) |loguru, pytest, fastapi_scaffolding, joblib |
|[fastapi-ml-skeleton](https://github.com/eightBEC/fastapi-ml-skeleton ) |loguru, pytest, fastapi_skeleton, joblib |
|[fastapi-mount](https://github.com/Midnighter/fastapi-mount ) |mount_demo |
|[fastapi-nuxt-blog](https://github.com/tokusumi/fastapi-nuxt-blog ) |PIL, passlib, sqlalchemy_utils, sqlalchemy, myapp, sendgrid, pytz, alembic, jwt, boto3, pytest |
|[fastapi-permissions](https://github.com/holgi/fastapi-permissions ) |pytest, jwt, fastapi_permissions, passlib |
|[fastapi-playground](https://github.com/FlorianBorn/fastapi-playground ) |PIL, fastai |
|[fastapi-plugins](https://github.com/madkote/fastapi-plugins ) |fastapi_plugins, setuptools, aioredis, tenacity, aiojobs, pytest |
|[fastapi-poc](https://github.com/igorfarias30/fastapi-poc ) |main, data, models, todo |
|[fastapi-postgres-aws-lambda](https://github.com/KurtKline/fastapi-postgres-aws-lambda ) |mangum, sqlalchemy |
|[fastapi-realworld-example-app-mysql](https://github.com/xiaozl/fastapi-realworld-example-app-mysql ) |bcrypt, passlib, asyncpg, loguru, aiomysql, tests, asgi_lifespan, docker, psycopg2, databases, jwt, pytest, httpx |
|[fastapi-route](https://github.com/franodos/fastapi-route ) |response, setuptools |
|[fastapi-satella-metrics](https://github.com/piotrmaslanka/fastapi-satella-metrics ) |fastapi_satella_metrics, requests, setuptools, satella |
|[fastapi-scaffold](https://github.com/ibegyourpardon/fastapi-scaffold ) |xuan |
|[fastapi-simple-cachecontrol](https://github.com/attakei/fastapi-simple-cachecontrol ) |fastapi_simple_cachecontrol, pytest |
|[fastapi-simple-template](https://github.com/MushroomMaula/fastapi-simple-template ) |alembic, dotenv, pytest, faker, sqlalchemy, myapp, fastapi_login |
|[fastapi-snippets](https://github.com/hhatto/fastapi-snippets ) |caches, fastapi_plugins, aioredis |
|[fastapi-sqlalchemy](https://github.com/zuarbase/fastapi-sqlalchemy-example ) |pytest, setuptools, passlib, sqlalchemy_filters, tests, sqlalchemy, ordered_uuid, tzlocal, pytz, fastapi_sqlalchemy, jwt, itsdangerous |
|[fastapi-sqlalchemy-example](https://github.com/zuarbase/fastapi-sqlalchemy-example ) |alembic, itsdangerous, fastapi_sqlalchemy, pytest, fastapi_sqlalchemy_example, sqlalchemy, myapp, click, setuptools |
|[fastapi-starter-kit](https://github.com/Shinichi-Nakagawa/fastapi-starter-kit ) |book, pytest, sqlalchemy, db |
|[fastapi-tdd-docker](https://github.com/pmcarlos/fastapi-tdd-docker ) |pytest, tortoise |
|[fastapi-template](https://github.com/jefmud/fastapi-templates ) |pytest, setuptools, passlib, sentry_sdk, sqlalchemy_utils, gino, sqlalchemy, jose, alembic, fastapi_template, migrations |
|[fastapi-test](https://github.com/jrwalk/fastapi-test ) |pytest, pandas |
|[fastapi-tools](https://github.com/so1n/fastapi-tools ) |fastapi_tools, prometheus_client, httpx |
|[fastapi-tortoise](https://github.com/prostomarkeloff/fastapi-tortoise ) |loguru, pytest, tortoise, requests, tests |
|[fastapi-users](https://github.com/frankie567/fastapi-users ) |passlib, tortoise, tests, asynctest, asgi_lifespan, sqlalchemy, httpx_oauth, makefun, databases, motor, jwt, fastapi_users, pytest, httpx |
|[fastapi-utils](https://github.com/dmontagu/fastapi-utils ) |pytest, fastapi_utils, tests, sqlalchemy |
|[fastapi-uvicorn-gunicorn-nginx-supervisor-boilerplate](https://github.com/sumitsk20/fastapi-uvicorn-gunicorn-nginx-supervisor-boilerplate ) |orjson, motor, core, server, bson, apps, utils |
|[fastapi-versioning](https://github.com/DeanWay/fastapi-versioning ) |example, typing_extensions, fastapi_versioning, setuptools |
|[fastapi-vue-test](https://github.com/abreumatheus/fastapi-vue-test ) |PIL, sqlalchemy, myapp, pytz, alembic, boto3 |
|[fastapi-websockets](https://github.com/natanael-silvamt/fastapi-websockets ) |api |
|[fastapi-whisper-rest-api](https://github.com/BolajiOlajide/fastapi-whisper-rest-api ) |api |
|[fastapi_admin](https://github.com/Chise1/fastapi_admin ) |apps, setuptools, passlib, fastapi_admin, sqlalchemy, settings, databases, pymysql, jwt |
|[fastapi_catchup](https://github.com/Kamihara/fastapi_catchup ) |intro |
|[fastapi_douyin](https://github.com/bigdataboy2020/fastapi_douyin ) |routers, requests, settings, exceptions, spiders |
|[fastapi_gino](https://github.com/pengyejun/fastapi_gino ) |gino_starlette, pytest, gino_fastapi_demo, sqlalchemy, myapp, aioredis, alembic, poetry, urllib2 |
|[fastapi_microblog](https://github.com/mrworksome/fastapi_microblog ) |alembic, databases, core, sqlalchemy, microblog, myapp, user, passlib, fastapi_users |
|[fastapi_mock](https://github.com/superxuu/fastapi_mock ) |apis, yaml, common |
|[fastapi_model](https://github.com/Nathanlauga/fastapi_model ) |loguru, joblib |
|[fastapi_playground](https://github.com/Rurson/fastapi_playground ) |pony, db |
|[fastapi_preset](https://github.com/cln-m4rie/fastapi_preset ) |setuptools |
|[fastapi_router](https://github.com/christopherzimmerman/fastapi_router ) |fastapi_router, trimport, setuptools |
|[fastapi_serviceutils](https://github.com/skallfass/fastapi_serviceutils_template ) |pytest, requests, setuptools, toolz, loguru, fastapi_serviceutils, yaml, cookiecutter, sqlalchemy, databases |
|[fastapi_serviceutils_template](https://github.com/skallfass/fastapi_serviceutils_template ) |fastapi_serviceutils |
|[fastapi_stu](https://github.com/Thousandhack/fastapi_stu ) |aliyunsdkcore, jwt, sqlalchemy, passlib |
|[fastapi_template](https://github.com/ytxfate/fastapi_template ) |pymongo, redis, jwt, minio, project |
|[fastapi_todo_hex](https://github.com/josemlp91/fastapi_todo_hex ) |factory, toolz, pytest_factoryboy, tests, sqlalchemy, myapp, alembic, dotenv, databases, pytest, todolist |
|[fastbroker](https://github.com/cetanu/fastbroker ) |pkg_resources, ujson, fastbroker, jsonschema, setuptools |
|[fastrf](https://github.com/iancleary/fastrf ) |asgi_lifespan, pytest, fastrf, httpx |
|[fbd-backend](https://github.com/ElusiveSpirit/fbd-backend ) |redis, pytest_mock, celery, loguru, ujson, pytest, tests |
|[finance-api](https://github.com/rennerocha/finance-api ) |finance_api, dynaconf, pytest, requests |
|[first_fastapi](https://github.com/vittorduartte/first_fastapi ) |routes, ext, schemas, sqlalchemy, rules, models |
|[firstderm_demo](https://github.com/polyrand/firstderm_demo ) |requests |
|[foreign-subs](https://github.com/joe-eklund/foreign-subs ) |fsubs, setuptools, pymongo, typer, jwt, bson |
|[frontapp](https://github.com/Blasterai/frontapp ) |decorator, frontapp, requests, envparse, attr |
|[fullasync](https://github.com/lipengsh/fullasync ) |celery, tasks, core, api |
|[fullstack-fastapi-elasticsearch](https://github.com/cleobulo/fullstack-fastapi-elasticsearch ) |core, elasticsearch, db, models, api |
|[fuzzy-octo-funicular](https://github.com/mattkatz/fuzzy-octo-funicular ) |main |
|[gaia-fastapi-demo](https://github.com/muslax/gaia-fastapi-demo ) |email_validator, passlib, pymongo, sentry_sdk, motor, jwt, bson, emails |
|[gaki-server](https://github.com/shitangdama/gaki-server ) |alembic, jwt, sqlalchemy, myapp, passlib |
|[galicea-odoo-addons-ecosystem](https://github.com/galicea/galicea-odoo-addons-ecosystem ) |cryptography, werkzeug, jwcrypto, odoo, git |
|[game](https://github.com/jsandovalc/fake-news-game ) |basegame |
|[gateway-microservice](https://github.com/anforaProject/gateway-microservice ) |aiohttp, v1 |
|[gerenciador-tarefas](https://github.com/matheuspsouza/gerenciador-tarefas ) |gerenciador_tarefas |
|[gfw-tile-cache](https://github.com/wri/gfw-tile-cache ) |gino_starlette, mercantile, pytest, pendulum, async_lru, requests, shapely, cachetools, sqlalchemy, aenum |
|[gifter_api](https://github.com/zhanymkanov/gifter_api ) |pytest, jwt, sqlalchemy, tests, passlib |
|[gigscovery_backend](https://github.com/martijnboers/gigscovery_backend ) |functions, sklearn, bandsintown, spotipy |
|[gino-admin](https://github.com/xnuinside/gino-admin ) |sanic, pytest, click, jinja2, db, requests, passlib, expiring_dict, gino_admin, asyncpg, dsnparse, sqlalchemy_utils, gino, urllib3, aiofiles, yaml, sqlalchemy, sanic_jwt, sanic_jinja2 |
|[gino-starlette](https://github.com/python-gino/gino-starlette ) |requests, gino_fastapi_demo, asyncpg, gino, urllib3, importlib_metadata, sqlalchemy, alembic, pytest, click |
|[girandole](https://github.com/bartkl/girandole ) |beets, plugin, girandole, yaml |
|[girias.json](https://github.com/kvnol/girias.json ) |tinydb |
|[gitea-dispatcher](https://github.com/Trim21/gitea-dispatcher ) |httpx |
|[gke-cicd-sandbox](https://github.com/mana-ysh/gke-cicd-sandbox ) |exampleapp, pytest |
|[glittr-fastapi](https://github.com/kellischeuble/glittr-fastapi ) |glittr, sqlalchemy |
|[graph-server](https://github.com/ZettaAI/graph-server ) |pychunkedgraph, numpy |
|[graphql-python-server](https://github.com/apoveda25/graphql-python-server ) |env, gql, dotenv, schemas, ariadne, models, database, arango |
|[graphql-tutorial](https://github.com/jcremona/graphql-tutorial ) |schema, graphene |
|[grocery-stores-home-delivery](https://github.com/dz-experts/grocery-stores-home-delivery ) |db, app_factory, setuptools, crud, api, typer, sqlalchemy, myapp, alembic, constans, schemas, core, models |
|[guid_tracker](https://github.com/nwcell/guid_tracker ) |alembic, databases, aiocache, guid, pytest, sqlalchemy, sqlalchemy_utils, myapp |
|[hackaton-berlin-legal-tech-2020](https://github.com/jjanczur/hackaton-berlin-legal-tech-2020 ) |pytest, sklearn, joblib, nltk, loguru, cleaner, config, fastapi_skeleton, bs4 |
|[hello-world-fastapi](https://github.com/benhid/hello-world-fastapi ) |fastapp, setuptools, rich |
|[henry](https://github.com/jacksonhenry3/FAAS ) |infrastructure, interface, sqlalchemy |
|[heroku-google-translate-api](https://github.com/fawazahmed0/heroku-google-translate-api ) |googletrans |
|[hh_parser](https://github.com/Kuzyashin/hh_parser ) |passlib, aiohttp, tortoise, template, celery, jwt, emails |
|[home_recruiters](https://github.com/Mohamed-Kaizen/home_recruiters ) |users, pendulum, passlib, jobs, tortoise, typer, usernames, jwt, core, confusable_homoglyphs, username |
|[http-battle](https://github.com/MihaiAnei/http-battle ) |flask_restful, flask, python_flask |
|[hvilkenfisk](https://github.com/David-IL/hvilkenfisk ) |imutils, fish_utils, sklearn, h5py, cv2, keras, img_preprocess, model_utils |
|[iam_working](https://github.com/carlosporta/iam_working ) |iam_working |
|[iem-web-services](https://github.com/akrherz/iem-web-services ) |setuptools, pyiem, shapely, metpy, pytz, pygrib, pyproj, pandas, geopandas, pytest |
|[ihan-productizer-example](https://github.com/digitalliving/ihan-productizer-example ) |aiohttp, ujson, settings_local, settings |
|[image_capabilities_backend](https://github.com/alejgo06/image_capabilities_backend ) |PIL, cv2 |
|[image_classifier_backend](https://github.com/alejgo06/image_classifier_backend ) |PIL, cv2 |
|[image_detector_backend](https://github.com/alejgo06/image_detector_backend ) |PIL, torch, utils, torchvision, pycocotools, models, cv2 |
|[img-filter-api](https://github.com/RaRhAeu/img-filter-api ) |aiohttp, cv2, api, requests, pytest |
|[ingaia_app](https://github.com/higaooliveira/ingaia_app ) |pytest, sqlalchemy, resources, requests, config, spotipy, domain |
|[innovativeproject-photographers-portfolio](https://github.com/nokia-wroclaw/innovativeproject-photographers-portfolio ) |fastapi_mail, jwt, sqlalchemy, src, database, passlib |
|[inpainting_backen](https://github.com/kaikai03/inpainting_backen ) |tinydb |
|[introduction-to-async-await](https://github.com/ci42/introduction-to-async-await ) |unsync, unsyncable, colorama |
|[iter8-analytics](https://github.com/iter8-tools/iter8-analytics ) |analytics_namespace, requests, flask_restplus, setuptools, experiment_namespace, yaml, jsonschema, iter8_analytics, django, flask, requests_mock |
|[jjs](https://github.com/jjs-dev/jjs ) |bcrypt, pytest, api_models, pymongo, db_models, routes, auth, db_connect |
|[jobsearch_statistics](https://github.com/JobtechSwe/jobsearch_statistics ) |certifi, searchstatistics, elasticsearch |
|[json-fastapi](https://github.com/stocky37/json-fastapi ) |json_fastapi, tinydb, slugify, link_header, util |
|[juice-box](https://github.com/dannytannertantrum/juice-box ) |tests |
|[jupyter_fastapi](https://github.com/Zsailer/jupyter_fastapi ) |jupyter_server, tornado, hypothesis, pytest, jupyter_fastapi, hypothesis_jsonschema, setuptools |
|[k8s-traefik-example](https://github.com/Hedde/k8s-traefik-example ) |flask |
|[kartu-beckend](https://github.com/AntonKristiono/kartu-beckend ) |PIL, config, yaml, autocrop, routes, motor, bson, cv2 |
|[koalachat](https://github.com/therumbler/koalachat ) |koalachat, aiofiles |
|[koalastream](https://github.com/therumbler/koalastream ) |aiofiles, koalastream |
|[kritika](https://github.com/Egnod/kritika ) |alembic, sitri, slugify, sqlalchemy, myapp, kritika |
|[kubeflow-containers-desktop](https://github.com/StatCan/kubeflow-containers-desktop ) |tqdm, jupyter_core, setuptools, tornado, crontab, pip, psutil, IPython, git, notebook |
|[kubernetes-experiments](https://github.com/richard-to/kubernetes-experiments ) |redis, alembic, sqlalchemy, myapp, passlib |
|[kuma](https://github.com/deepalikumar/sync_async_compare ) |bcrypt, docstring_parser, passlib, orjson, loguru, sqlalchemy, myapp, jupyter_client, alembic, databases, jwt, nbformat |
|[kvmail](https://github.com/la9ran9e/kvmail ) |tarantool, dotenv, settings |
|[lab_monitor](https://github.com/nutanix-japan/lab_monitor ) |pymongo, requests, schedule, client |
|[lagom](https://github.com/meadsteve/lagom ) |sybil, pytest, lagom, typing_extensions, tests, django, flask |
|[lang-python](https://github.com/tim-barnes/lang-python ) |submod2, worker_a, etcd3, rabbit, worker_b, optmod1, psutil, mongoengine, pika, test_pb2, grpc, google, optmod2, submod1, celery, flask, models, pytest |
|[league-manager](https://github.com/Project-SRC/league-manager ) |jwt, src, environs, passlib |
|[learn-kubernetes](https://github.com/quan-vu/learn-kubernetes ) |flask, flask_restful |
|[lgbsttracker_api](https://github.com/py4mac/lgbsttracker_api ) |lgbsttracker, lgbsttracker_api |
|[lightgbm-project-demo](https://github.com/raywu60kg/lightgbm-project-demo ) |psycopg2, sklearn, src, tests, ray |
|[linkalong-pre-inteview-task](https://github.com/pydevd/linkalong-pre-inteview-task ) |decouple, linkalong |
|[love-alarm](https://github.com/dl-eric/love-alarm ) |pymongo, redis, nexmo, jwt, boto3, bson, passlib |
|[maale-map-bot](https://github.com/kudanai/maale-map-bot ) |pyngrok, dotenv, discord, bots, viberbot, models, settings, fuzzywuzzy, telegram |
|[manageme-api](https://github.com/managemeapp/manageme-api ) |mangum, today_app, setuptools |
|[mangum-fastapi-aws-test](https://github.com/dan-danciu/mangum-fastapi-aws-test ) |mangum |
|[mars-rover](https://github.com/rSkogeby/mars-rover ) |models, views |
|[memefly-ds](https://github.com/Lambda-School-Labs/memefly-ds ) |wandb, memefly, requests, pymongo, decouple, api, tensorflow, dotenv, boto3, click |
|[metabot](https://github.com/vasyukvv42/metabot ) |metabot, requests, fastapi_metabot, setuptools, aiohttp, pymongo, help, typing_extensions, feedback, aioredis, vacations, slackers, motor, mockaioredis, bson, slack, pytest, httpx |
|[micro-data-lake](https://github.com/abxda/micro-data-lake ) |sklearn, newspaper, altair, airflow, sqlalchemy, IPython, minio, setproctitle |
|[microservices](https://github.com/hugosteixeira/microservices ) |requests |
|[mironov_blog_pwa](https://github.com/yuriymironov96/mironov_blog_pwa ) |alembic, dotenv, sqlalchemy, myapp, apps |
|[ml-project-template](https://github.com/raywu60kg/ml-project-template ) |psycopg2, src, tests, ray |
|[ml-workspace](https://github.com/DennisRasey/ml-workspace ) |jupyter_core, tqdm, setuptools, tornado, crontab, pip, psutil, IPython, git, notebook |
|[modelo-fast-api](https://github.com/knienkotter/modelo-fast-api ) |pytest, gerenciador_tarefas |
|[moneyTransfer](https://github.com/williamsyb/moneyTransfer ) |faker, db, app_factory, passlib, apis, config, utils, main, sqlalchemy, auth, schemas, jwt, pytest |
|[mongodb_admin](https://github.com/ArtemZaitsev1994/mongodb_admin ) |trafaret_config, envparse, pymongo, base, motor, jwt, bson |
|[mri_image_reconstruction](https://github.com/Pradhy729/mri_image_reconstruction ) |utils, config |
|[msys2-web](https://github.com/msys2/msys2-web ) |pytest, pgpdump, jinja2, fastapi_etag, respx, httpx |
|[musixfy_service](https://github.com/divyam234/musixfy_service ) |requests, Cryptodome |
|[mv-backend](https://github.com/Sreerajta/mv-backend ) |cassandra, requests, passlib, redis, fnc, global_config, sqlalchemy, jwt, greenstalk |
|[mvp-metric](https://github.com/DjaPy/mvp-metric ) |databases, sqlalchemy, dateutil |
|[mvs_eland_api](https://github.com/rl-institut/mvs_eland_api ) |celery, pytest, worker, mvs_eland_tool, sphinx_rtd_theme |
|[my-notes-app](https://github.com/jgabriel1/my-notes-app ) |databases, pytest, jwt, sqlalchemy, passlib |
|[mychef](https://github.com/logan-connolly/mychef ) |spacy, requests, scrapy, tqdm, aiohttp, asyncpg, loguru, orm, reddit, scraper, sqlalchemy, databases, praw, pytest, jsonlines, bs4 |
|[nasa_neo](https://github.com/cmmarti/nasa_neo ) |repo, requests |
|[nereid](https://github.com/Geosyntec/nereid ) |nereid, pytest, redis, typing_extensions, numpy, matplotlib, scipy, yaml, pint, celery, pandas |
|[ners](https://github.com/cedricconol/ners ) |utils, config |
|[netpalm](https://github.com/tbotnz/netpalm ) |xmltodict, rq, netmiko, pytest, jinja2, backend, netpalm_pinned_worker, requests, jinja2schema, redis, lxml, tests, jsonschema, ncclient, routers, napalm |
|[next-word-sentence-pred-api](https://github.com/rakesh4real/next-word-sentence-pred-api ) |tree, sqlalchemy, models, database |
|[nile-api](https://github.com/mattgeiger/nile-api ) |alembic, bcrypt, databases, jwt, sqlalchemy, api |
|[nlp_api](https://github.com/rdenadai/nlp_api ) |nltk, decouple, spacy, utils |
|[nmdc-server](https://github.com/microbiomedata/nmdc-server ) |pytest, faker, factory, requests, setuptools, pkg_resources, sqlalchemy, alembic, nmdc_server |
|[nomine](https://github.com/gzzo/nomine ) |graphql_sqlalchemy, ariadne, sqlalchemy, nomine, graphql |
|[nurse-schedule](https://github.com/csabex94/nurse-schedule ) |spital_routes, mongoengine, nurse_routes, jwt, models, utils, passlib |
|[oasis](https://github.com/instedd/oasis ) |users, bcrypt, pytest, stories, requests, mysql, flask_cors, sqlalchemy, myapp, sigfig, database, jenkspy, alembic, flask, auth, jwt, router, emails |
|[ocfapi](https://github.com/nikhiljha/ocfapi ) |ocflib |
|[oreMeet](https://github.com/mfortini/oreMeet ) |ics, worker |
|[owi_Result-Collector](https://github.com/JensGe/owi_Result-Collector ) |sqlalchemy, tests |
|[page-visitor-counter](https://github.com/trapflag/page-visitor-counter ) |redis |
|[paste.bin](https://github.com/magiskboy/paste.bin ) |pymongo, redis, gridfs, bson |
| |PIL, PyPDF4 |
|[perfume-ai](https://github.com/gurutaka/perfume-ai ) |PIL, torchvision, predict, cv2, torch |
|[persistent-identifier-service](https://github.com/OpertusMundi/persistent-identifier-service ) |ompid, yaml, sqlalchemy |
|[personal-learning](https://github.com/hoangthienan95/personal-learning ) |pyimagesearch, sklearn, calculator, cv2, keras |
|[pi-camera-hardware-server](https://github.com/NSnietol/pi-camera-hardware-server ) |loguru, picamera, requests, src |
|[piccolo_api](https://github.com/piccolo-orm/piccolo_api ) |setuptools, asyncpg, test_session, piccolo, livereload, jwt, piccolo_api, asgiref |
|[plarin_task](https://github.com/jjoskey/plarin_task ) |pymongo, main, employees, pytest, faker, bson, settings |
|[plonkowski.b-gmail.com](https://github.com/Raroog/plonkowski.b-gmail.com ) |main |
|[plotly-graphene](https://github.com/mdpham/plotly-graphene ) |pymongo, mutation, graphene, schema, minio, loompy, bson, query, minio_client |
|[pneumoniadetection](https://github.com/aalikadic/pneumoniadetection ) |kaggle, PIL, classifier, keras |
|[pol](https://github.com/RedHatInsights/policies-notifications ) |pytest, requests, aioresponses, etc, orjson, aiohttp, redis, sentry_sdk, tests, sqlalchemy, myapp, aioredis, pytz, alembic, databases, aiologger |
|[policies-notifications](https://github.com/RedHatInsights/policies-notifications ) |pytest, jinja2, aiokafka, aiohttp, asyncpg, prometheus_client, apscheduler, gino, tests, sqlalchemy, myapp, starlette_prometheus, alembic |
|[poll-app](https://github.com/jgabriel1/poll-app ) |pymongo, dotenv, selenium, pytest, flask_testing, tests, config |
|[ppm-telegram-bot](https://github.com/piterpy-meetup/ppm-telegram-bot ) |pip, aiogram, fastapi_security_telegram_webhook, ppm_telegram_bot |
|[ppr](https://github.com/bcgov/ppr ) |pytest, endpoints, requests, setuptools, sentry_sdk, freezegun, config, main, repository, sqlalchemy, myapp, datedelta, pytz, alembic, dotenv, schemas, models |
|[practical-python](https://github.com/sudharsan2020/practical-python ) |redis, celery_with_fastapi, celery |
|[programs](https://github.com/deta/programs ) |deta, jinja2, colors, svgs, passlib |
|[projects](https://github.com/hungd25/projects ) |sklearn, lrsgd, utils, numpy, matplotlib, nose, models_partc, src, phonenumbers |
|[property-prediction](https://github.com/solanyn/property-prediction ) |botocore, psycopg2, pytest, catboost, sklearn, hello_world, boto3, requests |
|[proxmox-slack-bot](https://github.com/PlenusPyramis/proxmox-slack-bot ) |slack_model, requests, slack |
|[proxy-checker](https://github.com/infaticaio/proxy-checker ) |aiohttp, main, checker, aiosocks |
|[py-cidemia-security](https://github.com/cidemia/py-cidemia-security ) |werkzeug, requests, setuptools, passlib, yaml, cidemiasecurity, jwt |
|[pyBets](https://github.com/GabrielCappelli/pyBets ) |error_messages, db_models, views, sqlalchemy, application, database, app_logging, models, services, pytest |
|[pyapi](https://github.com/srghosh29/pyapi ) |apis |
|[pycon2020-FastAPI](https://github.com/gloriasky/pycon2020-FastAPI ) |schemas, sqlalchemy, models, api, database |
|[pyctuator](https://github.com/SolarEdgeTech/pyctuator ) |werkzeug, multidict, requests, aiohttp, redis, tests, psutil, pyctuator, sqlalchemy, flask, pytest |
|[pydantic-ddd-exploration](https://github.com/allgreed/pydantic-ddd-exploration ) |sqlalchemy, src |
|[pyml](https://github.com/dockerian/pyml ) |PIL, pytest, setuptools, gevent, h5py, tests, numpy, dateutil, matplotlib, scipy, mock, connexion, yaml, google, jsonpickle, flask, ml, asgiref |
|[pypis](https://github.com/jurelou/pypis ) |packaging, setuptools, asyncpg, loguru, pkg_resources, sqlalchemy, stdlib_list, dynaconf, pypis, httpx |
|[python](https://github.com/jijinggang/test_python ) |requests, requests_html, unidecode, lxml, openpyxl, send_mail, download_util, formatting, settings, templates, flask |
|[python-api-template](https://github.com/mana-ysh/python-api-template ) |pytest |
|[python-asyncio-crud](https://github.com/aleimu/python-asyncio-crud ) |sanic, six, uvloop, muggle_ocr, redis, flask_sqlalchemy, aiomysql, sqlalchemy, aioredis, flask |
|[python-crash-course](https://github.com/cyberinsane/python-crash-course ) |tinydb, schema, pandas, requests |
|[python-deployment-samples](https://github.com/edisga/python-deployment-samples ) |aiohttp, webtest, django, pyramidsite, flask, pyramid, flask_cors, my_app, setuptools, other_app |
|[python-fastapi-hex-todo](https://github.com/GArmane/python-fastapi-hex-todo ) |pytest, faker, factory, passlib, toolz, asyncpg, pytest_factoryboy, tests, sqlalchemy, myapp, alembic, dotenv, databases, jwt, todolist |
|[python-graphql](https://github.com/tsungchih/python-graphql ) |graphene, aiohttp, loguru, ujson, psutil, graphql |
|[python-ml-service-template](https://github.com/paramoshin/python-ml-service-template ) |yaml, joblib, starlette_prometheus |
|[python-playground](https://github.com/tgmti/python-playground ) |flask_restful, flask, sqlalchemy |
|[python-poetry-docker-example](https://github.com/michael0liver/python-poetry-docker-example ) |pytest |
|[python-private-service-layout](https://github.com/U-Company/python-private-service-layout ) |fire, loguru, prometheus_client, pytest, vault_client, info, clients, tests, setuptools |
|[python_benchmark](https://github.com/T4D3K/python_benchmark ) |fastapi_frm, locust, sqlalchemy, tortoise, falcon, gino, falcon_frm |
|[python_common_tools](https://github.com/CheungChan/python_common_tools ) |requests, setuptools, redis, python_common_tools, paramiko, stackprinter, DBUtils, pymysql |
|[python_fastapi](https://github.com/playwhyyza/python_fastapi ) |jwt, passlib |
|[qa-api](https://github.com/venuraja79/qa-api ) |elasticapm, controller, haystack, config |
|[qhub-home](https://github.com/Quansight/qhub-home ) |toml, flit, setuptools |
|[qr-generator](https://github.com/gosha20777/qr-generator ) |qrcode |
|[rakm](https://github.com/emanuelaguna/rakm ) |pytest, requests, aiohttp, asyncache, invoke, asyncmock, tests, dateutil, cachetools, async_asgi_testclient, async_generator, dotenv |
|[random_projects](https://github.com/thepartisan101/random_projects ) |flask_restful, graphene, extraction, selenium, flask, flask_graphql, schema, sqlalchemy, requests |
|[recommender_fastapi](https://github.com/gjorgjinac/recommender_fastapi ) |repository, pybreaker, helper, sqlalchemy, default_ad_listener, requests, web, defaults |
|[recommender_server](https://github.com/gjorgjinac/recommender_server ) |repository, pybreaker, helper, sqlalchemy, default_ad_listener, requests, web, defaults |
|[ref-final-project-backend](https://github.com/Reyvel/ref-final-project-backend ) |faust, kafka, msgpack, settings, utils |
|[repost-fastapi](https://github.com/pckv/repost-fastapi ) |dotenv, jwt, sqlalchemy, repost, passlib |
|[responsive-layout-part](https://github.com/lmacchiavelli/responsive-layout-part ) |PIL |
|[rest_api_docker_mongo_aws](https://github.com/RodrigoMachado9/rest_api_docker_mongo_aws ) |pymongo, six, bottle_resource, beartype, bottle, spacy, passlib |
|[restbot](https://github.com/cwerner/restbot ) |restbot, loguru, pytest, joblib |
|[reternal-backend](https://github.com/d3vzer0/reternal-backend ) |pymongo, redis, flask_restful, flask_jwt_extended, sigma, workers, mongoengine, yaml, environment, database, pytz, flask_socketio, celery, flask, jwt, bson |
|[reverse-geocoder](https://github.com/claws/reverse-geocoder ) |databases, sqlalchemy, geoalchemy2 |
|[rjgtoys-xc](https://github.com/bobgautier/rjgtoys-xc ) |pytest, jinja2, requests, rjgtoys, apierrors, sphinx, sphinx_autodoc_typehints |
|[rn-fastapi-app](https://github.com/cloudeyes/rn-fastapi-app ) |sample, psycopg2, fastapi_login, MySQLdb, sqlalchemy, fastalchemy, passlib |
|[runn](https://github.com/alex-2201/runn ) |requests, passlib, tests, utils, sqlalchemy, jwt, logzero, pytest, emails |
|[sauti-fastapi](https://github.com/taycurran/sauti-fastapi ) |dotenv, pstgres, sqlalchemy |
|[sauti-monitor-ds-api](https://github.com/taycurran/sauti-monitor-ds-api ) |dotenv, sqlalchemy |
|[scaling-spoon](https://github.com/bloomingmath/scaling-spoon ) |email_validator, pony, bcrypt, pytest, extensions, passlib, pymongo, selenium, blinker, main, async_asgi_testclient, dotenv, motor, schemas, routers, bson, models |
|[sensehat-fastapi](https://github.com/cmlccie/sensehat-fastapi ) |sense_hat, senseapi |
|[server-open-alpr](https://github.com/NSnietol/server-open-alpr ) |openalpr, loguru, src |
|[serverless-fastapi-cdk](https://github.com/jaehyeon-kim/serverless-fastapi-cdk ) |mangum, resources, src, aws_cdk |
|[show-tell-api](https://github.com/team-eyespace/show-tell-api ) |nltk, PIL, TensorBoardCaption, NIC, evaluate, flask, jwt, preprocessing, keras, utils |
|[signal-cli-rest-api](https://github.com/SebastianLuebke/signal-cli-rest-api ) |pyqrcode, requests, signal_cli_rest_api |
|[simple-kp](https://github.com/ranking-agent/simple-kp ) |aiosqlite, pytest, simple_kp, reasoner_pydantic, data, setuptools |
|[simple-messenger](https://github.com/IvanDubrowin/simple-messenger ) |server |
|[simple-report-data-table-vuetify](https://github.com/shizidushu/simple-report-data-table-vuetify ) |bcrypt, dotenv, mongoengine, jwt, pypandoc, bson, casbin, passlib |
|[simpleapp-aws-fargate](https://github.com/kbaafi/simpleapp-aws-fargate ) |controllers, databases, sqlalchemy, boto3, data, config, services, settings, requests |
|[siso-library](https://github.com/nfowl/siso-library ) |databases, sqlalchemy |
|[sklearn-docker-api](https://github.com/crocopie/sklearn-docker-api ) |sklearn, service, joblib |
|[slowapi](https://github.com/laurentS/slowapi ) |limits, redis, slowapi, tests, hiro, mock |
|[smart-social-distancing](https://github.com/neuralet/smart-social-distancing ) |openvino, tflite_runtime, invoke, ui, tools, wget, scipy, libs |
|[sms_gateway](https://github.com/arxell/sms_gateway ) |passlib, aiohttp, sentry_sdk, aiopg, sqlalchemy, myapp, grpc, google, alembic, psycopg2, jwt, click, grpclib |
|[social-insights](https://github.com/dsc-umass/social-insights ) |sklearn, requests, joblib, nltk, tweepy, numpy, firebase_admin, twitter_credentials, scipy, spellchecker, get_tweets, google, flask, keras, xgboost, suggest |
|[sociallyhigh](https://github.com/NikhilSharmay/sociallyhigh ) |pkg_resources, sociallyhigh |
|[sparky](https://github.com/perfecto25/sparky ) |sparky, config |
|[speechRecognition_api](https://github.com/X-CCS/speechRecognition_api ) |librosa, sklearn, aukit, aip, Django_jianlong, videototextapp, videoaddsubtitleapp, myapp, IPython, my_app, other_app, djcelery, django, celery, video2audio_noiseReduction, keras |
|[start-fastapi](https://github.com/utmhikari/start-fastapi ) |model, middleware, controller, service, application, dotenv |
|[startapp](https://github.com/marlin-dev/startapp ) |extensions, marshmallow, setuptools, passlib, flask_env, flask_jwt_extended, sentry_sdk, flask_sqlalchemy, sqlalchemy_utils, gino, sqlalchemy, flask_marshmallow, takeaway, settings, flask_migrate, starlette_prometheus, flask, app_init, core|
|[statsfy](https://github.com/skmatz/statsfy ) |spotifier |
|[stock-tracker](https://github.com/jgabriel1/stock-tracker ) |pymongo, aiohttp, dotenv, pytest, jwt, server, requests, passlib |
|[stores](https://github.com/dz-experts/grocery-stores-home-delivery ) |stores, pytest, api, util |
|[storyboard_renderer](https://github.com/Weltii/storyboard_renderer ) |render_job, layouts, bridge, statics, layout_bridge, utils |
|[summaries](https://github.com/bradstimpson/summaries ) |nltk, newspaper, pytest, tortoise |
|[summarize-api](https://github.com/gary23w/summarize-api ) |nltk, newspaper, pytest, tortoise |
|[surfacescan](https://github.com/vbogretsov/surfacescan ) |networkx, pytest, faker, atomiclong, locust, surfacescan, pkg_resources, tests |
|[sweetHome](https://github.com/zkity/sweetHome ) |serial, lib |
|[sync_async_compare](https://github.com/deepalikumar/sync_async_compare ) |blog, faker, marshmallow, flask_sqlalchemy, sqlalchemy_utils, flask_apispec, commands, sqlalchemy, myapp, resources, settings, flask_migrate, alembic, dotenv, flask, databases, pytest |
|[takeAction-Backend](https://github.com/AndyKChen/takeAction-Backend ) |ml_controller, googlesearch, sklearn, getURL, bs4, keras, utils, numpy |
|[tariffengineapi](https://github.com/SofieneEnnaoui/tariffengineapi ) |memory_profiler, redis, numba, tariffs_modules, tests, api_fastapi, memory |
|[task_manager](https://github.com/VladOsiichuk/task_manager ) |passlib, gino, sqlalchemy, myapp, alembic, jwt |
|[taskriptor-web](https://github.com/nasuka/taskriptor-web ) |alembic, sqlalchemy, myapp |
|[tdd-fastapi-template](https://github.com/markusntz/tdd-fastapi-template ) |fastapi_tdd_docker, pytest, tortoise |
|[teached](https://github.com/Mohamed-Kaizen/teached ) |pytest, pendulum, requests, passlib, loguru, tortoise, teached, typer, importlib_metadata, nox, usernames, dropbox, jwt, confusable_homoglyphs, username |
|[techsoulai_backend](https://github.com/zhanymkanov/techsoulai_backend ) |pytest, jamspell, jwt, sqlalchemy, pymystem3, passlib |
|[temperature-web](https://github.com/sj175/temperature-web ) |board, dotenv, adafruit_dht, boto3, requests |
|[test_fastapi](https://github.com/leblancfg/test_fastapi ) |PIL, magic, fastapi_versioning, autocrop, cv2, requests, google |
|[test_shop](https://github.com/Ayaks7/test_shop ) |requests, passlib, peewee, user_orders, my_app, other_app, django, yoyo, catalog, auth, jwt, pytest, peewee_async, tastypie |
|[testfastapi](https://github.com/18438655078/testfastapi ) |tortoise, boto3 |
|[todo-list-fastapi](https://github.com/mcauto/todo-list-fastapi ) |aiofiles, pytest, jwt, sqlalchemy, src, passlib |
|[todoapp](https://github.com/prashunchitkr/todoapp ) |alembic, jwt, sqlalchemy, myapp, passlib |
|[trainee_mi](https://github.com/goncharov-roman/trainee_mi ) |pymongo |
|[transactions_api](https://github.com/txemac/transactions_api ) |pytest, sqlalchemy, sqlalchemy_utils, database |
|[transformers](https://github.com/raphtlw/transformers ) |aitextgen |
|[translator](https://github.com/eightytwo/translator ) |translator, schemas, api, httpx |
|[try-fast-api](https://github.com/kayshcache/try-fast-api ) |dotenv |
|[users-service](https://github.com/falled10/users-service ) |werkzeug, pytest, oauth2client, sqlalchemy_utils, api, config, main, repository, humps, sqlalchemy, myapp, alembic, jwt, routers, authlib, services |
|[uvicorn-gunicorn-fastapi](https://github.com/dshadow/uvicorn-gunicorn-fastapi-docker ) |test_utils, docker, requests, pytest |
|[vollmacht](https://github.com/ogeller/vollmacht ) |fitz |
|[volunteer-database](https://github.com/crowdsourcemedical/volunteer-database ) |alembic, pytest, jwt, sqlalchemy, myapp, passlib |
|[wamedex2](https://github.com/gwf-uwaterloo/wamedex2 ) |pytest, pyserini, hnswlib, pkg_resources, helper, freezegun, dateparser |
|[wazo-router-calld](https://github.com/wazo-platform/wazo-router-calld ) |wazo_router_calld, consul, click, sqlalchemy, setuptools |
|[web-api](https://github.com/aroio/web-api ) |exceptions, yaml, auth, jwt, routers, models, data |
|[web-avatarify](https://github.com/charlielito/web-avatarify ) |PIL, afy, skimage, moviepy, requests, imageio, tqdm, animate, sync_batchnorm, ffmpeg, torch, matplotlib, scipy, face_alignment, yaml, python_path, cv2, modules |
|[web-frameworks-benchmark](https://github.com/kesha1225/web-frameworks-benchmark ) |muffin, sanic, pyramid, falcon, requests, bottle, aiohttp, bobo, quart, hug, japronto, request_bench, my_app, other_app, django, flask, cherrypy, kumquat, freezy |
|[web_speedtest](https://github.com/Kulikovpavel/web_speedtest ) |flask |
|[weblink-downloader](https://github.com/cortexin/weblink-downloader ) |passlib, asyncpg, tests, link_downloader, databases, pytest, httpx |
|[xo_back](https://github.com/octomen/xo_back ) |pytest, api |
|[xpublish](https://github.com/xarray-contrib/xpublish ) |xarray, pytest, cachey, xpublish, setuptools, pkg_resources, h5py, netCDF4, numcodecs, dask, zarr |
|[xraysink](https://github.com/garyd203/xraysink ) |aiohttp, jsonpickle, xraysink, async_asgi_testclient, aws_xray_sdk, requests, pytest |
|[yappfm-backend](https://github.com/yappfm/yappfm-backend ) |alembic, sqlalchemy, myapp, yappfm, gino |
|[yatsm](https://github.com/danielmartins/yatsm ) |dramatiq, walrus, pytest, pendulum, passlib, apscheduler, typer, assertpy, pytz, jwt, yatsm |
|[yumemi_intern_API](https://github.com/tkrk1209/yumemi_intern_API ) |aiohttp, sqlalchemy, myapp, google, alembic |
|[zo](https://github.com/wazo-platform/wazo-router-calld ) |PIL, requests, ssdb, setuptools, loguru, urllib3, zo, munch |

2
env
View File

@ -1,2 +0,0 @@
USERNAME=YOUR_USERNAME
PASSWORD=YOUR_PASSWORD

1
frontend/.env Normal file
View File

@ -0,0 +1 @@
NEXT_PUBLIC_PROJECT_REPO_URL="https://github.com/Kludex/awesome-fastapi-projects"

3
frontend/.eslintrc.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": ["next/core-web-vitals", "prettier"]
}

35
frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

3
frontend/.prettierignore Normal file
View File

@ -0,0 +1,3 @@
out
.next
next-env.d.ts

19
frontend/.prettierrc Normal file
View File

@ -0,0 +1,19 @@
{
"arrowParens": "always",
"bracketSameLine": false,
"bracketSpacing": true,
"semi": true,
"singleQuote": false,
"jsxSingleQuote": false,
"quoteProps": "as-needed",
"trailingComma": "all",
"htmlWhitespaceSensitivity": "css",
"vueIndentScriptAndStyle": false,
"proseWrap": "preserve",
"insertPragma": false,
"printWidth": 80,
"requirePragma": false,
"tabWidth": 2,
"useTabs": false,
"embeddedLanguageFormatting": "auto"
}

34
frontend/README.md Normal file
View File

@ -0,0 +1,34 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

16
frontend/components.json Normal file
View File

@ -0,0 +1,16 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}

22
frontend/next.config.js Normal file
View File

@ -0,0 +1,22 @@
/** @type {import('next').NextConfig} */
const pkg = require("./package.json");
// starts a command line process to get the git hash
const commitHash = require("child_process")
.execSync('git log --pretty=format:"%h" -n1')
.toString()
.trim();
const nextConfig = {
output: "export",
basePath:
// TODO: Change to load from env variable
process.env.NODE_ENV === "production" ? "/awesome-fastapi-projects" : "",
env: {
commitHash,
frontendAppVersion: pkg.version,
},
};
module.exports = nextConfig;

47
frontend/package.json Normal file
View File

@ -0,0 +1,47 @@
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"prettier:lint": "prettier --check .",
"prettier:format": "prettier --write ."
},
"dependencies": {
"@hookform/resolvers": "^3.3.1",
"@orama/orama": "^1.2.3",
"@radix-ui/react-avatar": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-slot": "^1.0.2",
"@tanstack/react-table": "^8.9.3",
"@tanstack/react-virtual": "3.0.0-alpha.0",
"@types/node": "20.5.1",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"autoprefixer": "10.4.15",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cmdk": "^0.2.0",
"eslint": "8.47.0",
"eslint-config-next": "13.4.18",
"lucide-react": "^0.269.0",
"next": "13.4.18",
"postcss": "8.4.28",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.46.1",
"tailwind-merge": "^1.14.0",
"tailwindcss": "3.3.3",
"tailwindcss-animate": "^1.0.6",
"typescript": "5.1.6",
"zod": "^3.21.4"
},
"devDependencies": {
"eslint-config-prettier": "^9.0.0",
"prettier": "^3.0.3"
}
}

4475
frontend/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

1
frontend/public/next.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>

After

Width:  |  Height:  |  Size: 630 B

View File

@ -0,0 +1,94 @@
"use client";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Repo } from "@/lib/schemas";
import { ColumnDef } from "@tanstack/react-table";
import { ArrowUpDown, MoreHorizontal } from "lucide-react";
export const columns: ColumnDef<Repo>[] = [
{
accessorKey: "url",
header: function () {
return (
<div>
Project
<span role="img" aria-label="rocket" className="ml-1">
🚀
</span>
</div>
);
},
cell: function ({ row }) {
return (
<Button variant="link" className="text-accent-foreground">
<svg
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.49933 0.25C3.49635 0.25 0.25 3.49593 0.25 7.50024C0.25 10.703 2.32715 13.4206 5.2081 14.3797C5.57084 14.446 5.70302 14.2222 5.70302 14.0299C5.70302 13.8576 5.69679 13.4019 5.69323 12.797C3.67661 13.235 3.25112 11.825 3.25112 11.825C2.92132 10.9874 2.44599 10.7644 2.44599 10.7644C1.78773 10.3149 2.49584 10.3238 2.49584 10.3238C3.22353 10.375 3.60629 11.0711 3.60629 11.0711C4.25298 12.1788 5.30335 11.8588 5.71638 11.6732C5.78225 11.205 5.96962 10.8854 6.17658 10.7043C4.56675 10.5209 2.87415 9.89918 2.87415 7.12104C2.87415 6.32925 3.15677 5.68257 3.62053 5.17563C3.54576 4.99226 3.29697 4.25521 3.69174 3.25691C3.69174 3.25691 4.30015 3.06196 5.68522 3.99973C6.26337 3.83906 6.8838 3.75895 7.50022 3.75583C8.1162 3.75895 8.73619 3.83906 9.31523 3.99973C10.6994 3.06196 11.3069 3.25691 11.3069 3.25691C11.7026 4.25521 11.4538 4.99226 11.3795 5.17563C11.8441 5.68257 12.1245 6.32925 12.1245 7.12104C12.1245 9.9063 10.4292 10.5192 8.81452 10.6985C9.07444 10.9224 9.30633 11.3648 9.30633 12.0413C9.30633 13.0102 9.29742 13.7922 9.29742 14.0299C9.29742 14.2239 9.42828 14.4496 9.79591 14.3788C12.6746 13.4179 14.75 10.7025 14.75 7.50024C14.75 3.49593 11.5036 0.25 7.49933 0.25Z"
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
></path>
</svg>
<a
className="ml-1"
href={row.getValue<string>("url")}
target="_blank"
rel="noopener noreferrer"
>
Github
</a>
</Button>
);
},
},
{
accessorKey: "description",
header: function () {
return (
<div>
Description
<span role="img" aria-label="writing" className="ml-1">
</span>
</div>
);
},
cell: function ({ row }) {
return (
<p className="max-w-md truncate hover:overflow-visible hover:whitespace-normal leading-7 [&:not(:first-child)]:mt-6">
{row.getValue<string>("description") || "No description"}
</p>
);
},
},
{
accessorKey: "stars",
header: function ({ column }) {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Stars
<span role="img" aria-label="star" className="ml-1">
</span>
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
cell: function ({ row }) {
return (
<Badge variant="outline">
{row.getValue<number>("stars").toLocaleString("en-US")}
</Badge>
);
},
},
];

View File

@ -0,0 +1,118 @@
"use client";
import {
ColumnDef,
SortingState,
flexRender,
getCoreRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { useState } from "react";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
}
export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = useState<SortingState>([]);
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onSortingChange: setSorting,
getSortedRowModel: getSortedRowModel(),
state: {
sorting,
},
});
return (
<div>
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<div className="flex items-center justify-end space-x-2 py-4">
<Button
variant="outline"
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</Button>
</div>
</div>
);
}

View File

@ -0,0 +1,31 @@
"use client";
import {
createDependenciesOrama,
prepareDependenciesOramaIndex,
DependenciesOramaContext,
} from "@/lib/search";
import { PropsWithChildren } from "react";
import { SearchProvider } from "./search-provider";
import { DependenciesIndex } from "@/lib/schemas";
export function DependenciesSearchProvider({
children,
dependencies,
}: PropsWithChildren<{
dependencies: DependenciesIndex["dependencies"];
}>) {
const prepareOramaIndex = async () => {
const orama = await createDependenciesOrama();
await prepareDependenciesOramaIndex(orama, dependencies);
return orama;
};
return (
<SearchProvider
createIndex={prepareOramaIndex}
OramaContext={DependenciesOramaContext}
>
{children}
</SearchProvider>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,59 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 142.1 76.2% 36.3%;
--primary-foreground: 355.7 100% 97.3%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 142.1 76.2% 36.3%;
--radius: 0.5rem;
}
.dark {
--background: 20 14.3% 4.1%;
--foreground: 0 0% 95%;
--card: 24 9.8% 10%;
--card-foreground: 0 0% 95%;
--popover: 0 0% 9%;
--popover-foreground: 0 0% 95%;
--primary: 142.1 70.6% 45.3%;
--primary-foreground: 144.9 80.4% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 15%;
--muted-foreground: 240 5% 64.9%;
--accent: 12 6.5% 15.1%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 85.7% 97.3%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 142.4 71.8% 29.2%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

147
frontend/src/app/layout.tsx Normal file
View File

@ -0,0 +1,147 @@
import { cn } from "@/lib/utils";
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { buttonVariants } from "@/components/ui/button";
import { Icons } from "@/components/ui/icons";
import Link from "next/link";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import { FolderGit, Rocket } from "lucide-react";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Awesome FastAPI projects",
description: "An automatically generated list of awesome FastAPI projects",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<div className="hidden flex-col md:flex">
<div className="border-b">
<div className="w-full flex h-16 items-center justify-center px-4">
<nav className="container flex items-center justify-between space-x-4 lg:space-x-6 mx-6">
<p className="text-md font-medium transition-colors">
A list of FastAPI projects! 😎 🚀
</p>
<Link
target="_blank"
rel="noreferrer"
href={process.env.NEXT_PUBLIC_PROJECT_REPO_URL ?? ""}
className={cn(
buttonVariants({ variant: "ghost" }),
"h-6 w-6 flex items-center justify-center p-0 rounded-full",
)}
>
<Icons.gitHub className="h-6 w-6" />
</Link>
</nav>
</div>
</div>
</div>
<main className="container">
<h1 className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl text-center mt-8">
Awesome FastAPI projects{" "}
<span role="img" aria-label="party">
🎉
</span>
</h1>
{children}
</main>
<div className="border-t">
<footer className="bg-white dark:bg-gray-900">
<div className="w-full max-w-screen-xl mx-auto p-4 md:py-8">
<div className="sm:flex sm:items-center sm:justify-between gap-4">
<div className="grid gap-4 md:grid-cols-1 lg:grid-cols-2">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Revision
</CardTitle>
<FolderGit className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-xl font-bold">
{process.env.commitHash}
</div>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 space-x-4 pb-2">
<CardTitle className="text-sm font-medium">
Application Version
</CardTitle>
<Rocket className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-xl font-bold">
{process.env.frontendAppVersion}
</div>
</CardContent>
</Card>
</div>
<div className="flex flex-col mt-4 sm:mt-0 sm:flex-row sm:items-center sm:justify-between">
<p className="text-sm leading-7 [&:not(:first-child)]:mt-6">
This project wouldn&apos;t be possible without{" "}
<a
href="https://nextjs.org/"
className="font-bold hover:underline"
target="_blank"
rel="noreferrer"
>
Next.js
</a>
,{" "}
<a
href="https://ui.shadcn.com/"
className="font-bold hover:underline"
target="_blank"
rel="noreferrer"
>
Shadcn UI
</a>
,{" "}
<a
href="https://tailwindcss.com/"
className="font-bold hover:underline"
target="_blank"
rel="noreferrer"
>
Tailwind CSS
</a>
,{" "}
<a
href="https://react.dev/"
className="font-bold hover:underline"
target="_blank"
rel="noreferrer"
>
React
</a>{" "}
and{" "}
<a
href="https://www.oramasearch.com/"
className="font-bold hover:underline"
target="_blank"
rel="noreferrer"
>
Orama Search
</a>
</p>
</div>
</div>
</div>
</footer>
</div>
</body>
</html>
);
}
// TODO: improve pagination - sync with the URL, add a "go to page" input
// TODO: refactor the layout and the components

22
frontend/src/app/page.tsx Normal file
View File

@ -0,0 +1,22 @@
import {
loadDependenciesIndexServerOnly,
loadReposIndexServerOnly,
} from "@/lib/indexes";
import { ReposTable } from "./repos-table";
import { ReposSearchProvider } from "./repos-search-provider";
import { DependenciesSearchProvider } from "./dependencies-search-provider";
export default async function Home() {
const { repos } = await loadReposIndexServerOnly();
const { dependencies } = await loadDependenciesIndexServerOnly();
// refactor repos and dependencies to be loaded from the context
return (
<section className="py-10">
<ReposSearchProvider repos={repos}>
<DependenciesSearchProvider dependencies={dependencies}>
<ReposTable repos={repos} dependencies={dependencies} />
</DependenciesSearchProvider>
</ReposSearchProvider>
</section>
);
}

View File

@ -0,0 +1,31 @@
"use client";
import {
createReposOrama,
prepareReposOramaIndex,
ReposOramaContext,
} from "@/lib/search";
import { PropsWithChildren } from "react";
import { SearchProvider } from "./search-provider";
import { RepoIndex } from "@/lib/schemas";
export function ReposSearchProvider({
children,
repos,
}: PropsWithChildren<{
repos: RepoIndex["repos"];
}>) {
const prepareOramaIndex = async () => {
const orama = await createReposOrama();
await prepareReposOramaIndex(orama, repos);
return orama;
};
return (
<SearchProvider
createIndex={prepareOramaIndex}
OramaContext={ReposOramaContext}
>
{children}
</SearchProvider>
);
}

View File

@ -0,0 +1,82 @@
"use client";
import { Repo, Dependency } from "@/lib/schemas";
import { search } from "@orama/orama";
import { SearchForm } from "./search-form";
import { columns } from "./columns";
import { DataTable } from "./data-table";
import { useReposOrama } from "@/lib/search";
import { useState } from "react";
import { useQuerySearchFormData } from "@/lib/hooks";
import React from "react";
export function ReposTable({
repos,
dependencies,
}: {
repos: Repo[];
dependencies: Dependency[];
}) {
const reposOrama = useReposOrama();
const [searchedRepos, setSearchedRepos] = useState<Repo[]>(repos);
const { searchQueryFromQueryParam, dependenciesQueryFromQueryParam } =
useQuerySearchFormData(dependencies);
const onSearchSubmit = React.useCallback(
async ({
search: description,
dependencies,
}: {
search: string;
dependencies: Dependency[];
}) => {
if (!reposOrama.isIndexed || !reposOrama.orama) {
throw new Error("Repos Orama is not initialized");
}
const results = await search<Repo>(reposOrama.orama, {
term: description,
properties: ["description"],
limit: repos.length,
});
const searchedRepos = results.hits.map((hit) => hit.document as Repo);
// Workaround because Orama doesn't support filtering by properties of objects in arrays
const filteredRepos = searchedRepos.filter((repo) => {
return dependencies.every((dependency) => {
return repo.dependencies.some(
(repoDependency) => repoDependency.id === dependency.id,
);
});
});
setSearchedRepos(filteredRepos);
},
[repos, reposOrama.isIndexed, reposOrama.orama],
);
const _ref = React.useCallback(
(node: HTMLDivElement | null) => {
if (node !== null) {
if (reposOrama.isIndexed && reposOrama.orama) {
onSearchSubmit({
search: searchQueryFromQueryParam(),
dependencies: dependenciesQueryFromQueryParam(),
});
}
}
},
[
dependenciesQueryFromQueryParam,
onSearchSubmit,
reposOrama.isIndexed,
reposOrama.orama,
searchQueryFromQueryParam,
],
);
return (
<>
<div className="container mb-4 max-w-xl" ref={_ref}>
<SearchForm onSubmit={onSearchSubmit} dependencies={dependencies} />
</div>
<DataTable columns={columns} data={searchedRepos} />
</>
);
}

View File

@ -0,0 +1,125 @@
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import * as z from "zod";
import { Button } from "@/components/ui/button";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { MultiSelect } from "@/components/ui/multiselect";
import { Dependency, dependencySchema } from "@/lib/schemas";
import { useSearchParams, useRouter, usePathname } from "next/navigation";
import React from "react";
import { useQuerySearchFormData } from "@/lib/hooks";
const FormSchema = z.object({
search: z
.string()
.min(0)
.max(256, { message: "Search must be less than 256 characters" })
.default(""),
dependencies: z.array(dependencySchema).default(() => []),
});
export interface SearchFormProps {
onSubmit: (data: z.infer<typeof FormSchema>) => void;
dependencies: Dependency[];
}
export function SearchForm({ onSubmit, dependencies }: SearchFormProps) {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const {
searchQueryFromQueryParam,
searchQueryToQueryParam,
dependenciesQueryFromQueryParam,
dependenciesQueryToQueryParam,
} = useQuerySearchFormData(dependencies);
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
search: searchQueryFromQueryParam(),
dependencies: dependenciesQueryFromQueryParam(),
},
});
const createQueryString = React.useCallback(
({
searchQueryValue,
dependenciesQueryValue,
}: {
searchQueryValue: string;
dependenciesQueryValue: Dependency[];
}) => {
const params = new URLSearchParams(searchParams);
params.set("search", searchQueryToQueryParam(searchQueryValue));
params.set(
"dependencies",
dependenciesQueryToQueryParam(dependenciesQueryValue),
);
return params.toString();
},
[dependenciesQueryToQueryParam, searchParams, searchQueryToQueryParam],
);
const onSubmitWrapper = (data: z.infer<typeof FormSchema>) => {
onSubmit(data);
// update URL search params
const queryString = createQueryString({
searchQueryValue: data.search,
dependenciesQueryValue: data.dependencies,
});
router.replace(`${pathname}?${queryString}`);
};
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmitWrapper)} className="space-y-6">
<FormField
control={form.control}
name="search"
render={({ field }) => (
<FormItem>
<FormLabel>Search for a repository</FormLabel>
<FormControl>
<Input placeholder="Search..." {...field} />
</FormControl>
<FormDescription>
The search is performed on the repository description.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="dependencies"
render={({ field }) => (
<FormItem>
<FormLabel>Dependencies</FormLabel>
<FormControl>
<MultiSelect data={dependencies} {...field} />
</FormControl>
<FormDescription>
Filter by dependencies used in the repository.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Search</Button>
</form>
</Form>
);
}

View File

@ -0,0 +1,38 @@
"use client";
import { IOramaContext } from "@/lib/search";
import { Context, PropsWithChildren, useEffect, useState } from "react";
import { Orama, ProvidedTypes as OramaProvidedTypes } from "@orama/orama";
export type SearchProviderProps<
OramaParameters extends Partial<OramaProvidedTypes> = any,
> = PropsWithChildren<{
OramaContext: Context<IOramaContext<OramaParameters>>;
createIndex: () => Promise<Orama<OramaParameters>>;
}>;
export function SearchProvider<
OramaParameters extends Partial<OramaProvidedTypes>,
>({
children,
OramaContext,
createIndex,
}: SearchProviderProps<OramaParameters>) {
const [orama, setOrama] = useState<Orama<OramaParameters> | null>(null);
const [isIndexed, setIsIndexed] = useState(false);
useEffect(() => {
async function initializeOrama() {
setIsIndexed(false);
await createIndex().then(setOrama);
setIsIndexed(true);
}
initializeOrama();
}, [createIndex]);
return (
<OramaContext.Provider value={{ orama, isIndexed }}>
{children}
</OramaContext.Provider>
);
}

View File

@ -0,0 +1,36 @@
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
},
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
);
}
export { Badge, badgeVariants };

View File

@ -0,0 +1,56 @@
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
},
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button";
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
},
);
Button.displayName = "Button";
export { Button, buttonVariants };

View File

@ -0,0 +1,86 @@
import * as React from "react";
import { cn } from "@/lib/utils";
const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-lg border bg-card text-card-foreground shadow-sm",
className,
)}
{...props}
/>
));
Card.displayName = "Card";
const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
));
CardHeader.displayName = "CardHeader";
const CardTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn(
"text-2xl font-semibold leading-none tracking-tight",
className,
)}
{...props}
/>
));
CardTitle.displayName = "CardTitle";
const CardDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
));
CardDescription.displayName = "CardDescription";
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
));
CardContent.displayName = "CardContent";
const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
));
CardFooter.displayName = "CardFooter";
export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardDescription,
CardContent,
};

View File

@ -0,0 +1,155 @@
"use client";
import * as React from "react";
import { DialogProps } from "@radix-ui/react-dialog";
import { Command as CommandPrimitive } from "cmdk";
import { Search } from "lucide-react";
import { cn } from "@/lib/utils";
import { Dialog, DialogContent } from "@/components/ui/dialog";
const Command = React.forwardRef<
React.ElementRef<typeof CommandPrimitive>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
>(({ className, ...props }, ref) => (
<CommandPrimitive
ref={ref}
className={cn(
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
className,
)}
{...props}
/>
));
Command.displayName = CommandPrimitive.displayName;
interface CommandDialogProps extends DialogProps {}
const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
return (
<Dialog {...props}>
<DialogContent className="overflow-hidden p-0 shadow-lg">
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
{children}
</Command>
</DialogContent>
</Dialog>
);
};
const CommandInput = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Input>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
>(({ className, ...props }, ref) => (
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
ref={ref}
className={cn(
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
{...props}
/>
</div>
));
CommandInput.displayName = CommandPrimitive.Input.displayName;
const CommandList = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.List>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
>(({ className, ...props }, ref) => (
<CommandPrimitive.List
ref={ref}
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
{...props}
/>
));
CommandList.displayName = CommandPrimitive.List.displayName;
const CommandEmpty = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Empty>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
>((props, ref) => (
<CommandPrimitive.Empty
ref={ref}
className="py-6 text-center text-sm"
{...props}
/>
));
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
const CommandGroup = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Group>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Group
ref={ref}
className={cn(
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
className,
)}
{...props}
/>
));
CommandGroup.displayName = CommandPrimitive.Group.displayName;
const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Separator
ref={ref}
className={cn("-mx-1 h-px bg-border", className)}
{...props}
/>
));
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
const CommandItem = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
{...props}
/>
));
CommandItem.displayName = CommandPrimitive.Item.displayName;
const CommandShortcut = ({
className,
...props
}: React.HTMLAttributes<HTMLSpanElement>) => {
return (
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className,
)}
{...props}
/>
);
};
CommandShortcut.displayName = "CommandShortcut";
export {
Command,
CommandDialog,
CommandInput,
CommandList,
CommandEmpty,
CommandGroup,
CommandItem,
CommandShortcut,
CommandSeparator,
};

View File

@ -0,0 +1,123 @@
"use client";
import * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { X } from "lucide-react";
import { cn } from "@/lib/utils";
const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger;
const DialogPortal = ({
className,
...props
}: DialogPrimitive.DialogPortalProps) => (
<DialogPrimitive.Portal className={cn(className)} {...props} />
);
DialogPortal.displayName = DialogPrimitive.Portal.displayName;
const DialogOverlay = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Overlay>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
{...props}
/>
));
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<DialogPortal>
<DialogOverlay />
<DialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full",
className,
)}
{...props}
>
{children}
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogPortal>
));
DialogContent.displayName = DialogPrimitive.Content.displayName;
const DialogHeader = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-1.5 text-center sm:text-left",
className,
)}
{...props}
/>
);
DialogHeader.displayName = "DialogHeader";
const DialogFooter = ({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className,
)}
{...props}
/>
);
DialogFooter.displayName = "DialogFooter";
const DialogTitle = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Title
ref={ref}
className={cn(
"text-lg font-semibold leading-none tracking-tight",
className,
)}
{...props}
/>
));
DialogTitle.displayName = DialogPrimitive.Title.displayName;
const DialogDescription = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => (
<DialogPrimitive.Description
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
));
DialogDescription.displayName = DialogPrimitive.Description.displayName;
export {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
};

View File

@ -0,0 +1,177 @@
import * as React from "react";
import * as LabelPrimitive from "@radix-ui/react-label";
import { Slot } from "@radix-ui/react-slot";
import {
Controller,
ControllerProps,
FieldPath,
FieldValues,
FormProvider,
useFormContext,
} from "react-hook-form";
import { cn } from "@/lib/utils";
import { Label } from "@/components/ui/label";
const Form = FormProvider;
type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = {
name: TName;
};
const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue,
);
const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>({
...props
}: ControllerProps<TFieldValues, TName>) => {
return (
<FormFieldContext.Provider value={{ name: props.name }}>
<Controller {...props} />
</FormFieldContext.Provider>
);
};
const useFormField = () => {
const fieldContext = React.useContext(FormFieldContext);
const itemContext = React.useContext(FormItemContext);
const { getFieldState, formState } = useFormContext();
const fieldState = getFieldState(fieldContext.name, formState);
if (!fieldContext) {
throw new Error("useFormField should be used within <FormField>");
}
const { id } = itemContext;
return {
id,
name: fieldContext.name,
formItemId: `${id}-form-item`,
formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`,
...fieldState,
};
};
type FormItemContextValue = {
id: string;
};
const FormItemContext = React.createContext<FormItemContextValue>(
{} as FormItemContextValue,
);
const FormItem = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
const id = React.useId();
return (
<FormItemContext.Provider value={{ id }}>
<div ref={ref} className={cn("space-y-2", className)} {...props} />
</FormItemContext.Provider>
);
});
FormItem.displayName = "FormItem";
const FormLabel = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
>(({ className, ...props }, ref) => {
const { error, formItemId } = useFormField();
return (
<Label
ref={ref}
className={cn(error && "text-destructive", className)}
htmlFor={formItemId}
{...props}
/>
);
});
FormLabel.displayName = "FormLabel";
const FormControl = React.forwardRef<
React.ElementRef<typeof Slot>,
React.ComponentPropsWithoutRef<typeof Slot>
>(({ ...props }, ref) => {
const { error, formItemId, formDescriptionId, formMessageId } =
useFormField();
return (
<Slot
ref={ref}
id={formItemId}
aria-describedby={
!error
? `${formDescriptionId}`
: `${formDescriptionId} ${formMessageId}`
}
aria-invalid={!!error}
{...props}
/>
);
});
FormControl.displayName = "FormControl";
const FormDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => {
const { formDescriptionId } = useFormField();
return (
<p
ref={ref}
id={formDescriptionId}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
);
});
FormDescription.displayName = "FormDescription";
const FormMessage = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, children, ...props }, ref) => {
const { error, formMessageId } = useFormField();
const body = error ? String(error?.message) : children;
if (!body) {
return null;
}
return (
<p
ref={ref}
id={formMessageId}
className={cn("text-sm font-medium text-destructive", className)}
{...props}
>
{body}
</p>
);
});
FormMessage.displayName = "FormMessage";
export {
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
};

View File

@ -0,0 +1,97 @@
type IconProps = React.HTMLAttributes<SVGElement>;
export const Icons = {
logo: (props: IconProps) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" {...props}>
<rect width="256" height="256" fill="none" />
<line
x1="208"
y1="128"
x2="128"
y2="208"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="16"
/>
<line
x1="192"
y1="40"
x2="40"
y2="192"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="16"
/>
</svg>
),
gitHub: (props: IconProps) => (
<svg viewBox="0 0 438.549 438.549" {...props}>
<path
fill="currentColor"
d="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 01-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z"
></path>
</svg>
),
radix: (props: IconProps) => (
<svg viewBox="0 0 25 25" fill="none" {...props}>
<path
d="M12 25C7.58173 25 4 21.4183 4 17C4 12.5817 7.58173 9 12 9V25Z"
fill="currentcolor"
></path>
<path d="M12 0H4V8H12V0Z" fill="currentcolor"></path>
<path
d="M17 8C19.2091 8 21 6.20914 21 4C21 1.79086 19.2091 0 17 0C14.7909 0 13 1.79086 13 4C13 6.20914 14.7909 8 17 8Z"
fill="currentcolor"
></path>
</svg>
),
aria: (props: IconProps) => (
<svg role="img" viewBox="0 0 24 24" fill="currentColor" {...props}>
<path d="M13.966 22.624l-1.69-4.281H8.122l3.892-9.144 5.662 13.425zM8.884 1.376H0v21.248zm15.116 0h-8.884L24 22.624Z" />
</svg>
),
pnpm: (props: IconProps) => (
<svg viewBox="0 0 24 24" {...props}>
<path
d="M0 0v7.5h7.5V0zm8.25 0v7.5h7.498V0zm8.25 0v7.5H24V0zM8.25 8.25v7.5h7.498v-7.5zm8.25 0v7.5H24v-7.5zM0 16.5V24h7.5v-7.5zm8.25 0V24h7.498v-7.5zm8.25 0V24H24v-7.5z"
fill="currentColor"
/>
</svg>
),
react: (props: IconProps) => (
<svg viewBox="0 0 24 24" {...props}>
<path
d="M14.23 12.004a2.236 2.236 0 0 1-2.235 2.236 2.236 2.236 0 0 1-2.236-2.236 2.236 2.236 0 0 1 2.235-2.236 2.236 2.236 0 0 1 2.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38-.318-.184-.688-.277-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44-.96-.236-2.006-.417-3.107-.534-.66-.905-1.345-1.727-2.035-2.447 1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442-1.107.117-2.154.298-3.113.538-.112-.49-.195-.964-.254-1.42-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87-.728.063-1.466.098-2.21.098-.74 0-1.477-.035-2.202-.093-.406-.582-.802-1.204-1.183-1.86-.372-.64-.71-1.29-1.018-1.946.303-.657.646-1.313 1.013-1.954.38-.66.773-1.286 1.18-1.868.728-.064 1.466-.098 2.21-.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933-.2-.39-.41-.783-.64-1.174-.225-.392-.465-.774-.705-1.146zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493-.28-.958-.646-1.956-1.1-2.98.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98-.45 1.017-.812 2.01-1.086 2.964-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39.24-.375.48-.762.705-1.158.225-.39.435-.788.636-1.18zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143-.695-.102-1.365-.23-2.006-.386.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295-.22-.005-.406-.05-.553-.132-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z"
fill="currentColor"
/>
</svg>
),
tailwind: (props: IconProps) => (
<svg viewBox="0 0 24 24" {...props}>
<path
d="M12.001,4.8c-3.2,0-5.2,1.6-6,4.8c1.2-1.6,2.6-2.2,4.2-1.8c0.913,0.228,1.565,0.89,2.288,1.624 C13.666,10.618,15.027,12,18.001,12c3.2,0,5.2-1.6,6-4.8c-1.2,1.6-2.6,2.2-4.2,1.8c-0.913-0.228-1.565-0.89-2.288-1.624 C16.337,6.182,14.976,4.8,12.001,4.8z M6.001,12c-3.2,0-5.2,1.6-6,4.8c1.2-1.6,2.6-2.2,4.2-1.8c0.913,0.228,1.565,0.89,2.288,1.624 c1.177,1.194,2.538,2.576,5.512,2.576c3.2,0,5.2-1.6,6-4.8c-1.2,1.6-2.6,2.2-4.2,1.8c-0.913-0.228-1.565-0.89-2.288-1.624 C10.337,13.382,8.976,12,6.001,12z"
fill="currentColor"
/>
</svg>
),
spinner: (props: IconProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
{...props}
>
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
</svg>
),
};

View File

@ -0,0 +1,25 @@
import * as React from "react";
import { cn } from "@/lib/utils";
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
{...props}
/>
);
},
);
Input.displayName = "Input";
export { Input };

View File

@ -0,0 +1,26 @@
"use client";
import * as React from "react";
import * as LabelPrimitive from "@radix-ui/react-label";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
);
const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}
className={cn(labelVariants(), className)}
{...props}
/>
));
Label.displayName = LabelPrimitive.Root.displayName;
export { Label };

View File

@ -0,0 +1,194 @@
"use client";
import * as React from "react";
import { X } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Command, CommandGroup, CommandItem } from "@/components/ui/command";
import { Command as CommandPrimitive } from "cmdk";
import { useVirtual } from "@tanstack/react-virtual";
import { useDependenciesOrama } from "@/lib/search";
import { search } from "@orama/orama";
import { Dependency } from "@/lib/schemas";
export function MultiSelect<DataType extends { id: string; name: string }>({
data,
onChange,
value,
}: {
data: DataType[];
onChange: (data: DataType[]) => void;
value: DataType[];
}) {
const inputRef = React.useRef<HTMLInputElement>(null);
const scrollableContainerRef = React.useRef(null);
const [open, setOpen] = React.useState(false);
const [selected, setSelected] = React.useState<DataType[]>(value);
const [selectables, setSelectables] = React.useState<DataType[]>(
data.filter((dataPoint) => !value.some((el) => el.id === dataPoint.id)),
);
const [inputValue, setInputValue] = React.useState("");
const dependenciesOrama = useDependenciesOrama();
const onChangeInputValue = React.useCallback(
async (dependencyName: string) => {
if (!dependenciesOrama.isIndexed || !dependenciesOrama.orama) {
throw new Error("Dependencies Orama is not initialized");
}
const results = await search<Dependency>(dependenciesOrama.orama, {
term: dependencyName,
properties: ["name"],
limit: data.length,
});
setSelectables(
results.hits
.map((hit) => hit.document as DataType)
.filter(
(dataPoint) => !selected.some((el) => el.id === dataPoint.id),
),
);
setInputValue(dependencyName);
},
[data, dependenciesOrama.isIndexed, dependenciesOrama.orama, selected],
);
const rowVirtualizer = useVirtual({
size: selectables.length,
parentRef: scrollableContainerRef,
overscan: 10,
});
const handleUnselect = React.useCallback(
(dataPoint: DataType) => {
if (selected.length === 1) {
setSelected([]);
setSelectables(data);
onChange([]);
inputRef.current?.focus();
return;
} else {
setSelected((prev) => prev.filter((el) => el.id !== dataPoint.id));
setSelectables((prev) =>
!prev.some((el) => el.id === dataPoint.id)
? [dataPoint, ...prev]
: prev,
);
onChange(selected.filter((el) => el.id !== dataPoint.id));
}
},
[selected, data, onChange],
);
const handleSelect = React.useCallback(
(dataPoint: DataType) => {
setInputValue("");
setSelected((prev) => [...prev, dataPoint]);
setSelectables((prev) => prev.filter((el) => el.id !== dataPoint.id));
onChange([...selected, dataPoint]);
},
[onChange, selected],
);
const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
const input = inputRef.current;
if (input) {
if (e.key === "Delete" || e.key === "Backspace") {
if (input.value === "") {
if (selected.length > 0) {
handleUnselect(selected[selected.length - 1]);
}
}
}
// This is not a default behaviour of the <input /> field
if (e.key === "Escape") {
input.blur();
}
}
};
return (
<Command
onKeyDown={handleKeyDown}
className="overflow-visible bg-transparent"
>
<div className="group border border-input px-3 py-2 text-sm ring-offset-background rounded-md focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2">
<div className="flex gap-1 flex-wrap">
{selected.map((dataPoint) => {
return (
<Badge key={dataPoint.id} variant="secondary">
{dataPoint.name}
<button
className="ml-1 ring-offset-background rounded-full outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
onKeyDown={(e) => {
if (e.key === "Enter") {
handleUnselect(dataPoint);
}
}}
onMouseDown={(e) => {
e.preventDefault();
e.stopPropagation();
}}
onClick={() => handleUnselect(dataPoint)}
>
<X className="h-3 w-3 text-muted-foreground hover:text-foreground" />
</button>
</Badge>
);
})}
{/* Avoid having the "Search" Icon */}
<CommandPrimitive.Input
ref={inputRef}
value={inputValue}
onValueChange={onChangeInputValue}
onBlur={() => setOpen(false)}
onFocus={() => setOpen(true)}
placeholder="Select..."
className="ml-2 bg-transparent outline-none placeholder:text-muted-foreground flex-1"
/>
</div>
</div>
<div className="relative mt-2">
{open && selectables.length > 0 ? (
<div className="absolute w-full z-10 top-0 rounded-md border bg-popover text-popover-foreground shadow-md outline-none animate-in">
<CommandGroup
ref={scrollableContainerRef}
className="h-96 overflow-auto"
>
<div
style={{
height: `${rowVirtualizer.totalSize}px`,
width: "100%",
position: "relative",
}}
>
{rowVirtualizer.virtualItems.map((virtualRow) => (
<CommandItem
key={virtualRow.index}
onMouseDown={(e) => {
e.preventDefault();
e.stopPropagation();
}}
onSelect={() => {
handleSelect(selectables[virtualRow.index]);
}}
className="cursor-pointer"
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: `${virtualRow.size}px`,
transform: `translateY(${virtualRow.start}px)`,
}}
>
{selectables[virtualRow.index].name}
</CommandItem>
))}
</div>
</CommandGroup>
</div>
) : null}
</div>
</Command>
);
}

View File

@ -0,0 +1,114 @@
import * as React from "react";
import { cn } from "@/lib/utils";
const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="w-full overflow-auto">
<table
ref={ref}
className={cn("w-full caption-bottom text-sm", className)}
{...props}
/>
</div>
));
Table.displayName = "Table";
const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
));
TableHeader.displayName = "TableHeader";
const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody
ref={ref}
className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
));
TableBody.displayName = "TableBody";
const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tfoot
ref={ref}
className={cn("bg-primary font-medium text-primary-foreground", className)}
{...props}
/>
));
TableFooter.displayName = "TableFooter";
const TableRow = React.forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr
ref={ref}
className={cn(
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className,
)}
{...props}
/>
));
TableRow.displayName = "TableRow";
const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th
ref={ref}
className={cn(
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
className,
)}
{...props}
/>
));
TableHead.displayName = "TableHead";
const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td
ref={ref}
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
{...props}
/>
));
TableCell.displayName = "TableCell";
const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props}
/>
));
TableCaption.displayName = "TableCaption";
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
};

77
frontend/src/lib/hooks.ts Normal file
View File

@ -0,0 +1,77 @@
import { usePathname, useSearchParams, useRouter } from "next/navigation";
import React from "react";
import { Dependency } from "./schemas";
export const useQuerySearchFormData = (dependencies: Dependency[]) => {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const searchQueryToQueryParam = React.useCallback(
(searchQueryValue: string) => {
if (!searchQueryValue) {
return "";
}
return encodeURIComponent(searchQueryValue);
},
[],
);
const searchQueryFromQueryParam = React.useCallback(() => {
if (!searchParams.has("search")) {
return "";
}
return decodeURIComponent(searchParams.get("search") ?? "");
}, [searchParams]);
const dependenciesQueryToQueryParam = React.useCallback(
(dependenciesQueryValue: Dependency[]) => {
if (!dependenciesQueryValue) {
return "";
}
// join dependencies names with `~`
let encodedArray = dependenciesQueryValue.map(
(dependency) => dependency.name,
);
// join the names with `~`
let encodedArrayValue = encodedArray.join("~");
// URL encode the string
return encodeURIComponent(encodedArrayValue);
},
[],
);
const dependenciesQueryFromQueryParam = React.useCallback(() => {
if (!searchParams.has("dependencies")) {
return [];
}
// URL decode the string
let decodedArray = decodeURIComponent(
searchParams.get("dependencies") ?? "",
);
// split dependencies names with `~`
const dependenciesNames = decodedArray.split("~");
// deduplicate dependencies names
const uniqueDependenciesNames = new Set(dependenciesNames).values();
// filter out empty strings
const filteredDependenciesNames = Array.from(
uniqueDependenciesNames,
).filter((dependencyName) => dependencyName !== "");
// return dependencies objects
return (
filteredDependenciesNames
.map((dependencyName) =>
dependencies.find((dependency) => dependency.name === dependencyName),
)
// filter out undefined values
.filter(Boolean) as Dependency[]
);
}, [searchParams, dependencies]);
return {
searchQueryToQueryParam,
searchQueryFromQueryParam,
dependenciesQueryToQueryParam,
dependenciesQueryFromQueryParam,
};
};

View File

@ -0,0 +1,69 @@
import { cache } from "react";
import "server-only";
import * as fs from "fs";
import * as path from "path";
import { dependenciesIndexSchema, reposIndexSchema } from "./schemas";
import { ZodError } from "zod";
// TODO: docstrings
export const REPOS_INDEX_FILE_PATH = path.normalize(
path.join(__dirname, "..", "..", "..", "..", "repos_index.json"),
);
export const DEPENDENCIES_INDEX_FILE_PATH = path.normalize(
path.join(__dirname, "..", "..", "..", "..", "dependencies_index.json"),
);
export const preload = () => {
void loadReposIndexServerOnly();
void loadDependenciesIndexServerOnly();
};
// TODO: tests
export const loadReposIndexServerOnly = cache(async () => {
try {
const indexData = JSON.parse(
await fs.promises.readFile(REPOS_INDEX_FILE_PATH, "utf-8"),
(key, value) => {
if (key === "id" || key === "source_graph_repo_id") {
return String(value);
}
return value;
},
);
return await reposIndexSchema.parseAsync(indexData);
} catch (err) {
if (err instanceof ZodError) {
throw new Error(
`Failed to parse the repos index: ${JSON.stringify(err.format())}`,
);
}
throw new Error(`Failed to load the repos index: ${err}`);
}
});
export const loadDependenciesIndexServerOnly = cache(async () => {
try {
const indexData = JSON.parse(
await fs.promises.readFile(DEPENDENCIES_INDEX_FILE_PATH, "utf-8"),
(key, value) => {
if (key === "id") {
return String(value);
}
return value;
},
);
return await dependenciesIndexSchema.parseAsync(indexData);
} catch (err) {
if (err instanceof ZodError) {
throw new Error(
`Failed to parse the dependencies index: ${JSON.stringify(
err.format(),
)}`,
);
}
throw new Error(`Failed to load the dependencies index: ${err}`);
}
});

View File

@ -0,0 +1,67 @@
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context";
export interface QueryParamsManagerInterface {
requestQueryUpdate: (key: string, value: string) => void;
requestQueryDelete: (key: string) => void;
requestQueryClear: () => void;
commit: () => void;
}
export class QueryParamsManager implements QueryParamsManagerInterface {
constructor(
private readonly router: AppRouterInstance,
private readonly pathname: string,
private readonly initialParams: URLSearchParams,
private readonly _queue: Array<
[key: string, value: string | null] | ["clear"]
> = [],
private readonly _internalState: Map<string, string> = new Map(),
) {
this.initialParams.forEach((value, key) => {
this._internalState.set(key, value);
});
}
requestQueryUpdate(key: string, value: string) {
this._queue.push([key, value]);
}
requestQueryDelete(key: string) {
this._queue.push([key, null]);
}
requestQueryClear() {
this._queue.push(["clear"]);
}
private _processQueue() {
for (const request of this._queue) {
if (request.length === 1) {
const [command] = request;
if (command === "clear") {
this._internalState.clear();
}
} else {
if (request.length === 2) {
const [key, value] = request;
if (value === null) {
this._internalState.delete(key);
} else {
this._internalState.set(key, value);
}
}
}
}
this._queue.length = 0;
}
commit() {
this._processQueue();
const params = new URLSearchParams();
this._internalState.forEach((value, key) => {
params.set(key, value);
});
const newUrl = `${this.pathname}?${params.toString()}`;
this.router.replace(newUrl);
}
}

View File

@ -0,0 +1,29 @@
import { z } from "zod";
export const dependencySchema = z.object({
id: z.string(),
name: z.string(),
});
export const repoSchema = z.object({
id: z.string(),
url: z.string(),
description: z.string(),
stars: z.number().min(0),
source_graph_repo_id: z.string(),
dependencies: z.array(dependencySchema),
last_checked_revision: z.nullable(z.string()),
});
export const reposIndexSchema = z.object({
repos: z.array(repoSchema),
});
export const dependenciesIndexSchema = z.object({
dependencies: z.array(dependencySchema),
});
export type Dependency = z.infer<typeof dependencySchema>;
export type Repo = z.infer<typeof repoSchema>;
export type RepoIndex = z.infer<typeof reposIndexSchema>;
export type DependenciesIndex = z.infer<typeof dependenciesIndexSchema>;

View File

@ -0,0 +1,88 @@
import {
Orama,
ProvidedTypes as OramaProvidedTypes,
create,
insertMultiple,
} from "@orama/orama";
import { DependenciesIndex, RepoIndex } from "./schemas";
import { Context, createContext, useContext } from "react";
export interface IOramaContext<
OramaParameters extends Partial<OramaProvidedTypes> = any,
> {
isIndexed: boolean;
orama: Orama<OramaParameters> | null;
}
export function createOramaContext<
OramaParameters extends Partial<OramaProvidedTypes>,
>(): Context<IOramaContext<OramaParameters>> {
return createContext<IOramaContext<OramaParameters>>({
isIndexed: false,
orama: null,
});
}
export interface ReposOramaParameters extends Partial<OramaProvidedTypes> {
Index: { description: string };
}
export type ReposOrama = Orama<ReposOramaParameters>;
export async function createReposOrama(): Promise<ReposOrama> {
const orama = await create({
schema: {
description: "string",
},
id: "repos-index",
});
return orama;
}
export async function prepareReposOramaIndex(
orama: ReposOrama,
data: RepoIndex["repos"],
): Promise<ReposOrama> {
await insertMultiple(orama, data, 100);
return orama;
}
export const ReposOramaContext = createOramaContext<ReposOramaParameters>();
ReposOramaContext.displayName = "ReposOramaContext";
export const useReposOrama = () => {
return useContext(ReposOramaContext);
};
export interface DependenciesOramaParameters
extends Partial<OramaProvidedTypes> {
Index: { name: string };
}
export type DependenciesOrama = Orama<DependenciesOramaParameters>;
export async function createDependenciesOrama(): Promise<DependenciesOrama> {
const orama = await create({
schema: {
name: "string",
},
id: "dependencies-index",
});
return orama;
}
export async function prepareDependenciesOramaIndex(
orama: DependenciesOrama,
data: DependenciesIndex["dependencies"],
): Promise<DependenciesOrama> {
await insertMultiple(orama, data, 100);
return orama;
}
export const DependenciesOramaContext =
createOramaContext<DependenciesOramaParameters>();
DependenciesOramaContext.displayName = "DependenciesOramaContext";
export const useDependenciesOrama = () => {
return useContext(DependenciesOramaContext);
};

10
frontend/src/lib/utils.ts Normal file
View File

@ -0,0 +1,10 @@
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function wait(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

View File

@ -0,0 +1,75 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ["class"],
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
keyframes: {
"accordion-down": {
from: { height: 0 },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
},
plugins: [require("tailwindcss-animate")],
};

27
frontend/tsconfig.json Normal file
View File

@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}

View File

@ -1,40 +0,0 @@
from typing import List
import json
from pytablewriter import MarkdownTableWriter
from stdlib_list import stdlib_list
NATIVE = ["fastapi", "starlette", "pydantic", "typing", "uvicorn", "app"]
def filter_list(dependencies: List[str]) -> List[str]:
return [
dependency
for dependency in dependencies
if not (
dependency in NATIVE
or dependency in stdlib_list("3.8")
or dependency.startswith("_")
)
]
def format_with_link(project: str) -> str:
links = open("unique_links.txt", "r")
for link in links.readlines():
if project in link:
return f"[{project}]({link})"
with open("results.json") as json_file:
data = json.load(json_file)
writer = MarkdownTableWriter()
writer.headers = ["Project", "Dependencies"]
writer.value_matrix = [
[format_with_link(project), ", ".join(filter_list(dependencies))]
for project, dependencies in data.items()
if (
len(filter_list(dependencies)) > 0
and len(filter_list(dependencies)) < 20
and project != ""
)
]
writer.write_table()

1
migrations/README Normal file
View File

@ -0,0 +1 @@
Generic single-database configuration with an async dbapi.

0
migrations/__init__.py Normal file
View File

90
migrations/env.py Normal file
View File

@ -0,0 +1,90 @@
import asyncio
from logging.config import fileConfig
from alembic import context
from sqlalchemy import pool
from sqlalchemy.engine import Connection
from sqlalchemy.ext.asyncio import async_engine_from_config
from app.database import Base
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
# Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
fileConfig(config.config_file_name)
# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = Base.metadata
# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.
def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def do_run_migrations(connection: Connection) -> None:
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
async def run_async_migrations() -> None:
"""In this scenario we need to create an Engine
and associate a connection with the context.
"""
connectable = async_engine_from_config(
config.get_section(config.config_ini_section, {}),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
await connectable.dispose()
def run_migrations_online() -> None:
"""Run migrations in 'online' mode."""
asyncio.run(run_async_migrations())
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()

24
migrations/script.py.mako Normal file
View File

@ -0,0 +1,24 @@
"""${message}
Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}
"""
from alembic import op
import sqlalchemy as sa
${imports if imports else ""}
# revision identifiers, used by Alembic.
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}
def upgrade() -> None:
${upgrades if upgrades else "pass"}
def downgrade() -> None:
${downgrades if downgrades else "pass"}

View File

@ -0,0 +1,73 @@
"""Set up the database
Revision ID: 90eb9d1f9267
Revises:
Create Date: 2023-08-15 14:13:30.562069
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = "90eb9d1f9267"
down_revision = None
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"dependency",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.String(length=255), nullable=False),
sa.PrimaryKeyConstraint("id", name=op.f("pk_dependency")),
sa.UniqueConstraint("name", name=op.f("uq_dependency_name ")),
)
op.create_table(
"repo",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("url", sa.String(), nullable=False),
sa.Column("description", sa.Text(), nullable=False),
sa.Column("stars", sa.BigInteger(), nullable=False),
sa.Column("source_graph_repo_id", sa.BigInteger(), nullable=True),
sa.PrimaryKeyConstraint("id", name=op.f("pk_repo")),
sa.UniqueConstraint(
"source_graph_repo_id", name=op.f("uq_repo_source_graph_repo_id ")
),
sa.UniqueConstraint(
"url",
"source_graph_repo_id",
name=op.f("uq_repo_url_source_graph_repo_id "),
),
sa.UniqueConstraint("url", name=op.f("uq_repo_url ")),
)
op.create_table(
"repo_dependency",
sa.Column("repo_id", sa.Integer(), nullable=False),
sa.Column("dependency_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["dependency_id"],
["dependency.id"],
name=op.f("fk_repo_dependency_dependency_id_dependency"),
ondelete="CASCADE",
),
sa.ForeignKeyConstraint(
["repo_id"],
["repo.id"],
name=op.f("fk_repo_dependency_repo_id_repo"),
ondelete="CASCADE",
),
sa.PrimaryKeyConstraint(
"repo_id", "dependency_id", name=op.f("pk_repo_dependency")
),
)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("repo_dependency")
op.drop_table("repo")
op.drop_table("dependency")
# ### end Alembic commands ###

View File

View File

@ -0,0 +1,29 @@
"""Add a last_checked_revision column
Revision ID: ac7c35039d70
Revises: 90eb9d1f9267
Create Date: 2023-08-16 22:35:25.314490
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = "ac7c35039d70"
down_revision = "90eb9d1f9267"
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"repo", sa.Column("last_checked_revision", sa.String(length=255), nullable=True)
)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("repo", "last_checked_revision")
# ### end Alembic commands ###

138
pyproject.toml Normal file
View File

@ -0,0 +1,138 @@
[project]
name = "awesome-fastapi-projects"
version = "0.1.0"
description = "A web app built to index awesome projects built with FastAPI."
authors = [
{name = "Vladyslav Fedoriuk", email="vlad.fedoriuk2000@gmail.com"}
]
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
]
dependencies = [
"aiofiles",
"aiosqlite",
"alembic",
"anyio",
"httpx",
"httpx-sse",
"loguru",
"pydantic",
"sqlalchemy[asyncio,mypy]",
"stamina",
"third-party-imports",
"typer[all]",
]
[project.optional-dependencies]
dev = [
"black",
"ipython",
"mypy",
"pip-tools",
"pre-commit",
"pyproject-fmt",
"ruff",
"types-aiofiles",
]
test = [
"dirty-equals",
"polyfactory",
"pytest",
"pytest-anyio",
"pytest-cov",
"pytest-mock",
]
[tool.setuptools]
py-modules = ["app"]
[tool.black]
line-length = 88
target_version = ['py311']
include = '\.pyi?$'
force-exclude = '''
(
/(
\.bzr
| \.direnv
| \.eggs
| \.git
| \.git-rewrite
| \.hg
| \.mypy_cache
| \.ruff_cache
| \.tox
| \.nox
| \.pants.d
| \.pytype
| \.venv
| \.svn
| \.ipynb_checkpoints
| \.egg-info
| __pypackages__
| _build
| buck-out
| build
| dist
| node_modules
| venv
)/
)
''' # To comply with ruff config
[tool.ruff]
line-length = 88
target-version = 'py311'
required-version = "0.0.280"
extend-select = [
"D", # pydocstyle
"W", # pycodestyle
"C90", # mccabe
"I", # isort
"UP", # pyupgrade
"ASYNC", # flake8-async
"S", # flake8-bandit
"B", # flake8-bugbear
"ANN", # flake8-annotations
"S", # flake8-bandit
"C4", # flake8-comprehensions
"T10", # flake8-debugger
"INP", # flake8-no-pep420
"PT", # flake8-pytest-style
"TID", # flake8-tidy-imports
"PTH", # flake8-use-pathlib
"ERA", # eradicate
"Q", # flake8-quotes
]
[tool.ruff.per-file-ignores]
# Ignore missing docstrings in migrations and alembic files
"**/migrations/*.py" = ["D"]
"**/migrations/env.py" = ["ERA001"]
"**/tests/*.py" = ["S101"]
"**/conftest.py" = ["S101"]
[tool.ruff.pydocstyle]
convention = "numpy"
[tool.pytest.ini_options]
testpaths = "tests"
[tool.coverage.run]
branch = true
omit = [
"tests/*",
]
[tool.mypy]
plugins = [
"pydantic.mypy",
"sqlalchemy.ext.mypy.plugin",
]
strict = true
exclude = [
"tests",
"migrations",
"conftest.py",
"factories.py",
]

81834
repos_index.json Normal file

File diff suppressed because it is too large Load Diff

89
requirements/base.txt Normal file
View File

@ -0,0 +1,89 @@
#
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile --output-file=requirements/base.txt pyproject.toml
#
aiofiles==23.1.0
# via awesome-fastapi-projects (pyproject.toml)
aiosqlite==0.19.0
# via awesome-fastapi-projects (pyproject.toml)
alembic==1.11.1
# via awesome-fastapi-projects (pyproject.toml)
annotated-types==0.5.0
# via pydantic
anyio==3.7.1
# via
# awesome-fastapi-projects (pyproject.toml)
# httpcore
certifi==2023.7.22
# via
# httpcore
# httpx
click==8.1.6
# via typer
colorama==0.4.6
# via typer
greenlet==2.0.2
# via sqlalchemy
h11==0.14.0
# via httpcore
httpcore==0.18.0
# via httpx
httpx==0.25.0
# via awesome-fastapi-projects (pyproject.toml)
httpx-sse==0.3.1
# via awesome-fastapi-projects (pyproject.toml)
idna==3.4
# via
# anyio
# httpx
loguru==0.7.2
# via awesome-fastapi-projects (pyproject.toml)
mako==1.2.4
# via alembic
markdown-it-py==3.0.0
# via rich
markupsafe==2.1.3
# via mako
mdurl==0.1.2
# via markdown-it-py
mypy==1.4.1
# via sqlalchemy
mypy-extensions==1.0.0
# via mypy
pydantic==2.1.1
# via awesome-fastapi-projects (pyproject.toml)
pydantic-core==2.4.0
# via pydantic
pygments==2.15.1
# via rich
rich==13.5.2
# via typer
shellingham==1.5.0.post1
# via typer
sniffio==1.3.0
# via
# anyio
# httpcore
# httpx
sqlalchemy[asyncio,mypy]==2.0.19
# via
# alembic
# awesome-fastapi-projects (pyproject.toml)
stamina==23.1.0
# via awesome-fastapi-projects (pyproject.toml)
tenacity==8.2.2
# via stamina
third-party-imports==0.0.7
# via awesome-fastapi-projects (pyproject.toml)
typer[all]==0.9.0
# via awesome-fastapi-projects (pyproject.toml)
typing-extensions==4.7.1
# via
# alembic
# mypy
# pydantic
# pydantic-core
# sqlalchemy
# typer

185
requirements/dev.txt Normal file
View File

@ -0,0 +1,185 @@
#
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile --extra=dev --output-file=requirements/dev.txt pyproject.toml
#
aiofiles==23.1.0
# via awesome-fastapi-projects (pyproject.toml)
aiosqlite==0.19.0
# via awesome-fastapi-projects (pyproject.toml)
alembic==1.11.1
# via awesome-fastapi-projects (pyproject.toml)
annotated-types==0.5.0
# via pydantic
anyio==3.7.1
# via
# awesome-fastapi-projects (pyproject.toml)
# httpcore
asttokens==2.2.1
# via stack-data
backcall==0.2.0
# via ipython
black==23.7.0
# via awesome-fastapi-projects (pyproject.toml)
build==0.10.0
# via pip-tools
certifi==2023.7.22
# via
# httpcore
# httpx
cfgv==3.3.1
# via pre-commit
click==8.1.6
# via
# black
# pip-tools
# typer
colorama==0.4.6
# via typer
decorator==5.1.1
# via ipython
distlib==0.3.7
# via virtualenv
executing==1.2.0
# via stack-data
filelock==3.12.2
# via virtualenv
greenlet==2.0.2
# via sqlalchemy
h11==0.14.0
# via httpcore
httpcore==0.18.0
# via httpx
httpx==0.25.0
# via awesome-fastapi-projects (pyproject.toml)
httpx-sse==0.3.1
# via awesome-fastapi-projects (pyproject.toml)
identify==2.5.26
# via pre-commit
idna==3.4
# via
# anyio
# httpx
ipython==8.14.0
# via awesome-fastapi-projects (pyproject.toml)
jedi==0.19.0
# via ipython
loguru==0.7.2
# via awesome-fastapi-projects (pyproject.toml)
mako==1.2.4
# via alembic
markdown-it-py==3.0.0
# via rich
markupsafe==2.1.3
# via mako
matplotlib-inline==0.1.6
# via ipython
mdurl==0.1.2
# via markdown-it-py
mypy==1.4.1
# via
# awesome-fastapi-projects (pyproject.toml)
# sqlalchemy
mypy-extensions==1.0.0
# via
# black
# mypy
natsort==8.4.0
# via pyproject-fmt
nodeenv==1.8.0
# via pre-commit
packaging==23.1
# via
# black
# build
# pyproject-fmt
parso==0.8.3
# via jedi
pathspec==0.11.1
# via black
pexpect==4.8.0
# via ipython
pickleshare==0.7.5
# via ipython
pip-tools==7.1.0
# via awesome-fastapi-projects (pyproject.toml)
platformdirs==3.9.1
# via
# black
# virtualenv
pre-commit==3.3.3
# via awesome-fastapi-projects (pyproject.toml)
prompt-toolkit==3.0.39
# via ipython
ptyprocess==0.7.0
# via pexpect
pure-eval==0.2.2
# via stack-data
pydantic==2.1.1
# via awesome-fastapi-projects (pyproject.toml)
pydantic-core==2.4.0
# via pydantic
pygments==2.15.1
# via
# ipython
# rich
pyproject-fmt==0.13.0
# via awesome-fastapi-projects (pyproject.toml)
pyproject-hooks==1.0.0
# via build
pyyaml==6.0.1
# via pre-commit
rich==13.5.2
# via typer
ruff==0.0.280
# via awesome-fastapi-projects (pyproject.toml)
shellingham==1.5.0.post1
# via typer
six==1.16.0
# via asttokens
sniffio==1.3.0
# via
# anyio
# httpcore
# httpx
sqlalchemy[asyncio,mypy]==2.0.19
# via
# alembic
# awesome-fastapi-projects (pyproject.toml)
stack-data==0.6.2
# via ipython
stamina==23.1.0
# via awesome-fastapi-projects (pyproject.toml)
tenacity==8.2.2
# via stamina
third-party-imports==0.0.7
# via awesome-fastapi-projects (pyproject.toml)
tomlkit==0.12.1
# via pyproject-fmt
traitlets==5.9.0
# via
# ipython
# matplotlib-inline
typer[all]==0.9.0
# via awesome-fastapi-projects (pyproject.toml)
types-aiofiles==23.1.0.5
# via awesome-fastapi-projects (pyproject.toml)
typing-extensions==4.7.1
# via
# alembic
# mypy
# pydantic
# pydantic-core
# sqlalchemy
# typer
virtualenv==20.24.2
# via pre-commit
wcwidth==0.2.6
# via prompt-toolkit
wheel==0.41.0
# via pip-tools
# The following packages are considered to be unsafe in a requirements file:
# pip
# setuptools

123
requirements/test.txt Normal file
View File

@ -0,0 +1,123 @@
#
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile --extra=test --output-file=requirements/test.txt pyproject.toml
#
aiofiles==23.1.0
# via awesome-fastapi-projects (pyproject.toml)
aiosqlite==0.19.0
# via awesome-fastapi-projects (pyproject.toml)
alembic==1.11.1
# via awesome-fastapi-projects (pyproject.toml)
annotated-types==0.5.0
# via pydantic
anyio==3.7.1
# via
# awesome-fastapi-projects (pyproject.toml)
# httpcore
# pytest-anyio
certifi==2023.7.22
# via
# httpcore
# httpx
click==8.1.6
# via typer
colorama==0.4.6
# via typer
coverage[toml]==7.2.7
# via pytest-cov
dirty-equals==0.6.0
# via awesome-fastapi-projects (pyproject.toml)
faker==19.2.0
# via polyfactory
greenlet==2.0.2
# via sqlalchemy
h11==0.14.0
# via httpcore
httpcore==0.18.0
# via httpx
httpx==0.25.0
# via awesome-fastapi-projects (pyproject.toml)
httpx-sse==0.3.1
# via awesome-fastapi-projects (pyproject.toml)
idna==3.4
# via
# anyio
# httpx
iniconfig==2.0.0
# via pytest
loguru==0.7.2
# via awesome-fastapi-projects (pyproject.toml)
mako==1.2.4
# via alembic
markdown-it-py==3.0.0
# via rich
markupsafe==2.1.3
# via mako
mdurl==0.1.2
# via markdown-it-py
mypy==1.4.1
# via sqlalchemy
mypy-extensions==1.0.0
# via mypy
packaging==23.1
# via pytest
pluggy==1.2.0
# via pytest
polyfactory==2.7.0
# via awesome-fastapi-projects (pyproject.toml)
pydantic==2.1.1
# via awesome-fastapi-projects (pyproject.toml)
pydantic-core==2.4.0
# via pydantic
pygments==2.15.1
# via rich
pytest==7.4.0
# via
# awesome-fastapi-projects (pyproject.toml)
# pytest-anyio
# pytest-cov
# pytest-mock
pytest-anyio==0.0.0
# via awesome-fastapi-projects (pyproject.toml)
pytest-cov==4.1.0
# via awesome-fastapi-projects (pyproject.toml)
pytest-mock==3.11.1
# via awesome-fastapi-projects (pyproject.toml)
python-dateutil==2.8.2
# via faker
pytz==2023.3
# via dirty-equals
rich==13.5.2
# via typer
shellingham==1.5.0.post1
# via typer
six==1.16.0
# via python-dateutil
sniffio==1.3.0
# via
# anyio
# httpcore
# httpx
sqlalchemy[asyncio,mypy]==2.0.19
# via
# alembic
# awesome-fastapi-projects (pyproject.toml)
stamina==23.1.0
# via awesome-fastapi-projects (pyproject.toml)
tenacity==8.2.2
# via stamina
third-party-imports==0.0.7
# via awesome-fastapi-projects (pyproject.toml)
typer[all]==0.9.0
# via awesome-fastapi-projects (pyproject.toml)
typing-extensions==4.7.1
# via
# alembic
# mypy
# polyfactory
# pydantic
# pydantic-core
# sqlalchemy
# typer

15385
results.json

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +0,0 @@
import shutil
import git
from git.repo.base import Repo
from giturlparse import parse
# class Progress(git.remote.RemoteProgress):
# def update(self, op_code, cur_count, max_count=None, message=''):
# print(self._cur_line)
with open("unique_links.txt") as fp:
links = fp.readlines()
for i, link in enumerate(links, start=1):
link = link.rstrip()
name = parse(link).name
print(f"File num: {i}")
Repo.clone_from(link, name)
try:
shutil.move(name, "reps")
except:
shutil.rmtree(name)

View File

@ -1,13 +0,0 @@
f_in = open("links.txt", "r")
f_out = open("unique_links.txt", "w")
links = set()
for line in f_in.readlines():
links.add(line)
for link in links:
f_out.write(link)
f_in.close()
f_out.close()

View File

@ -1,29 +0,0 @@
import json
import re
from typing import Dict, Union
f_in = open("imports.txt", "r")
mp: Dict[str, Union[set, list]] = {}
for line in f_in.readlines():
try:
rep_name = line.split("/")[1]
except IndexError:
rep_name = ""
mp[rep_name] = mp.get(rep_name, set())
result = re.search(r"from (\w+)[\.\w+]*|:[ ]*import (\w*)\n", line)
if result:
if result.group(1):
mp[rep_name].add(result.group(1))
if result.group(2):
mp[rep_name].add(result.group(2))
for key in mp:
mp[key] = list(mp[key])
with open("results.json", "w") as f:
json.dump(mp, f, sort_keys=True, indent=2)
print(len(mp))
f_in.close()

View File

@ -1,4 +0,0 @@
for file in $(find reps -maxdepth 1 -type d); do
grep -r "import" --include \*.py $file > imports.txt
done

View File

@ -1,57 +0,0 @@
import json
import os
import sys
from time import sleep
import requests
from dotenv import load_dotenv
load_dotenv()
username = os.getenv("GITHUB_USERNAME")
password = os.getenv("GITHUB_PASSWORD")
API_URL = "https://api.github.com"
def get_response(page: int) -> dict:
res = requests.get(
f"{API_URL}/search/code",
auth=(username, password),
params={"q": "fastapi language:Python", "per_page": 100, "page": page},
)
return res
def get_next_link(link_header: str) -> str:
return getattr(
{
rel: link
for (link, rel) in re.findall(r'<(http.*?)>; rel="(.*?)"', link_header)
},
"next",
None,
)
filename = "links.txt"
file1 = open(filename, "a") # append mode
has_next = True
page = 1
while has_next:
sleep(1)
res = get_response(page)
res_json = res.json()
if "items" in res_json:
for item in res_json["items"]:
file1.write(f"{item['repository']['html_url']}\n")
print(f"Page: {page}")
print(res.headers)
# print(json.dumps(res_json, indent=4, sort_keys=True))
# print(res.headers.get('X-RateLimit-Reset', 0))
if int(
res.headers.get("X-RateLimit-Remaining", 0)
) == 0 or "422" in res.headers.get("Status", "422"):
has_next = False
page += 1
file1.close()

View File

@ -1,22 +0,0 @@
import re
import sys
filename_in = sys.argv[1]
filename_out = sys.argv[2]
file_in = open(filename_in, "r")
lines = file_in.readlines()
file_out = open(filename_out, "w")
imports = set()
for line in lines:
match1 = re.search(r"(from *(?!\.)(.+?)(?= |\.))", line)
match2 = re.search(r"(: *(import) (.+))", line)
if match1 is not None:
imports.add(match1.group(2))
if match2 is not None:
imports.add(match2.group(3))
for imp in sorted(list(imports)):
file_out.write(f"{imp}\n")