Skip to content

Commit efe7389

Browse files
authored
Merge pull request #3 from seapagan/add-docs
Start adding documentation
2 parents 7143f25 + 5cb585e commit efe7389

22 files changed

+2656
-1229
lines changed

.github/dependabot.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "pip"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"
7+
target-branch: "develop"
8+
open-pull-requests-limit: 10
9+
- package-ecosystem: "github-actions"
10+
directory: "/"
11+
schedule:
12+
interval: "weekly"
13+
target-branch: "develop"

.github/workflows/codeql.yml

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# For most projects, this workflow file will not need changing; you simply need
2+
# to commit it to your repository.
3+
#
4+
# You may wish to alter this file to override the set of languages analyzed,
5+
# or to provide custom queries or build logic.
6+
#
7+
# ******** NOTE ********
8+
# We have attempted to detect the languages in your repository. Please check
9+
# the `language` matrix defined below to confirm you have the correct set of
10+
# supported CodeQL languages.
11+
#
12+
name: "CodeQL"
13+
14+
on:
15+
push:
16+
branches: [ "main" ]
17+
pull_request:
18+
# The branches below must be a subset of the branches above
19+
branches: [ "main" ]
20+
schedule:
21+
- cron: '29 12 * * 1'
22+
23+
jobs:
24+
analyze:
25+
name: Analyze
26+
runs-on: ubuntu-latest
27+
permissions:
28+
actions: read
29+
contents: read
30+
security-events: write
31+
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
language: [ 'python' ]
36+
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37+
# Use only 'java' to analyze code written in Java, Kotlin or both
38+
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
39+
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
40+
41+
steps:
42+
- name: Checkout repository
43+
uses: actions/checkout@v4
44+
45+
# Initializes the CodeQL tools for scanning.
46+
- name: Initialize CodeQL
47+
uses: github/codeql-action/init@v3
48+
with:
49+
languages: ${{ matrix.language }}
50+
# If you wish to specify custom queries, you can do so here or in a config file.
51+
# By default, queries listed here will override any specified in a config file.
52+
# Prefix the list here with "+" to use these queries and those in the config file.
53+
54+
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
55+
# queries: security-extended,security-and-quality
56+
57+
58+
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
59+
# If this step fails, then you should remove it and run the build manually (see below)
60+
- name: Autobuild
61+
uses: github/codeql-action/autobuild@v3
62+
63+
# ℹ️ Command-line programs to run using the OS shell.
64+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
65+
66+
# If the Autobuild fails above, remove it and uncomment the following three lines.
67+
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
68+
69+
# - run: |
70+
# echo "Run, Build Application using script"
71+
# ./location_of_script_within_repo/buildscript.sh
72+
73+
- name: Perform CodeQL Analysis
74+
uses: github/codeql-action/analyze@v3
75+
with:
76+
category: "/language:${{matrix.language}}"
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Dependency Review Action
2+
#
3+
# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
4+
#
5+
# Source repository: https://github.com/actions/dependency-review-action
6+
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
7+
name: 'Dependency Review'
8+
on: [pull_request]
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
dependency-review:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: 'Checkout Repository'
18+
uses: actions/checkout@v4
19+
- name: 'Dependency Review'
20+
uses: actions/dependency-review-action@v3

.github/workflows/ruff.yml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Linting
2+
3+
on: [push, pull_request, workflow_dispatch]
4+
5+
jobs:
6+
ruff:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v4
10+
- name: Linting
11+
uses: chartboost/ruff-action@v1
12+
with:
13+
args: check
14+
- name: Check Formatting
15+
uses: chartboost/ruff-action@v1
16+
with:
17+
args: format --check

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,4 @@ cython_debug/
208208

209209
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
210210
test.db
211+
.python-version

.pre-commit-config.yaml

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
ci:
2+
autofix_commit_msg: "[pre-commit.ci] auto fixes from pre-commit.com hooks [dependabot skip]"
3+
repos:
4+
- repo: https://github.com/pre-commit/pre-commit-hooks
5+
rev: v4.5.0
6+
hooks:
7+
- id: check-yaml
8+
args: [--unsafe]
9+
- id: trailing-whitespace
10+
- id: check-toml
11+
- id: check-merge-conflict
12+
- id: end-of-file-fixer
13+
14+
- repo: https://github.com/astral-sh/ruff-pre-commit
15+
rev: v0.1.14
16+
hooks:
17+
- id: ruff
18+
name: "lint with ruff"
19+
- id: ruff-format
20+
name: "format with ruff"
21+
22+
- repo: https://github.com/jackdewinter/pymarkdown
23+
rev: 0.9.16
24+
hooks:
25+
- id: pymarkdown
26+
name: "check markdown"
27+
exclude: ^.github/|CHANGELOG
28+
args: [-d, "MD046", scan]
29+
30+
- repo: https://github.com/pre-commit/mirrors-mypy
31+
rev: "v1.8.0" # Use the sha / tag you want to point at
32+
hooks:
33+
- id: mypy
34+
name: "Check with Mypy"
35+
36+
- repo: https://github.com/RobertCraigie/pyright-python
37+
rev: v1.1.349
38+
hooks:
39+
- id: pyright
40+
name: "Check with Pyright"
41+
exclude: tests
42+
additional_dependencies: [sqlalchemy, uvicorn, fastapi]
43+
44+
- repo: https://github.com/python-poetry/poetry
45+
rev: "1.7.0"
46+
hooks:
47+
- id: poetry-check
48+
name: "check poetry files"
49+
# - id: poetry-lock
50+
51+
- repo: https://github.com/python-poetry/poetry-plugin-export
52+
rev: "1.6.0"
53+
hooks:
54+
- id: poetry-export
55+
name: "export production dependencies"
56+
args:
57+
[
58+
"--without-hashes",
59+
"-f",
60+
"requirements.txt",
61+
"-o",
62+
"requirements.txt",
63+
"--without",
64+
"dev",
65+
]
66+
- id: poetry-export
67+
name: "export development dependencies"
68+
args:
69+
[
70+
"--without-hashes",
71+
"-f",
72+
"requirements.txt",
73+
"-o",
74+
"requirements-dev.txt",
75+
"--with",
76+
"dev",
77+
]

.vscode/settings.json

+25-16
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,58 @@
11
{
22
"[python]": {
33
"editor.codeActionsOnSave": {
4-
"source.organizeImports": true
5-
}
4+
"source.fixAll": "explicit",
5+
"source.organizeImports": "explicit"
6+
},
7+
"editor.defaultFormatter": "charliermarsh.ruff"
68
},
7-
"autoDocstring.startOnNewLine": true,
89
"beautify.language": {
910
"html": ["htm", "html", "django-html"]
1011
},
1112
"editor.formatOnPaste": false,
13+
"editor.formatOnSave": true,
1214
"emmet.includeLanguages": {
15+
"django-html": "html",
1316
"jinja-html": "html"
1417
},
1518
"emmet.triggerExpansionOnTab": true,
1619
"files.associations": {
1720
"**/*.html": "html",
21+
"**/*.tpl": "jinja",
1822
"**/requirements{/**,*}.{txt,in}": "pip-requirements",
1923
"**/templates/**/*": "django-txt",
2024
"**/templates/**/*.html": "jinja-html"
2125
},
2226
"files.eol": "\n",
2327
"files.exclude": {
28+
"**/.cache": true,
29+
"**/.mypy_cache": true,
30+
"**/.pytest_cache": true,
31+
"**/.ruff_cache": true,
2432
"**/__pycache__": true
2533
},
2634
"git.alwaysSignOff": true,
2735
"git.enableCommitSigning": true,
2836
"html.format.indentHandlebars": true,
2937
"html.format.templating": true,
38+
"markdownlint.ignore": ["CHANGELOG.md"],
39+
"material-icon-theme.languages.associations": {
40+
"jinja-html": "django"
41+
},
42+
"mypy-type-checker.args": ["--strict"],
43+
"mypy-type-checker.importStrategy": "useBundled",
44+
"mypy-type-checker.reportingScope": "workspace",
45+
"python.analysis.autoImportCompletions": true,
46+
"python.analysis.autoImportUserSymbols": true,
3047
"python.analysis.extraPaths": [],
48+
"python.analysis.indexing": true,
3149
"python.analysis.stubPath": "/home/seapagan/stubs",
32-
"python.analysis.typeCheckingMode": "basic",
33-
"python.formatting.blackArgs": ["--line-length=80"],
34-
"python.formatting.provider": "black",
50+
"python.analysis.typeCheckingMode": "off",
3551
"python.languageServer": "Pylance",
36-
"python.linting.enabled": true,
37-
"python.linting.flake8Args": ["--max-line-length=80"],
38-
"python.linting.flake8Enabled": true,
39-
"python.linting.mypyEnabled": false,
40-
"python.linting.pydocstyleArgs": ["--convention=google"],
41-
"python.linting.pylintArgs": [],
42-
"python.linting.pylintEnabled": false,
4352
"python.pythonPath": "./.venv/bin/python",
44-
"isort.args": ["--profile", "black", "--src=${workspaceFolder}"],
4553
"python.testing.pytestArgs": ["tests"],
4654
"python.testing.pytestEnabled": true,
47-
"python.testing.unittestArgs": ["-v", "-s", "./tests", "-p", "*_test.py"],
48-
"python.testing.unittestEnabled": false
55+
"python.testing.unittestEnabled": false,
56+
"ruff.fixAll": false,
57+
"ruff.organizeImports": true
4958
}

LICENSE.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2023 Grant Ramsay
3+
Copyright (c) 2023-2024 Grant Ramsay
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Simple example how to use FastAPI with Async SQLAlchemy 2.0 <!-- omit from toc -->
1+
# Using FastAPI with Async SQLAlchemy 2.0 <!-- omit from toc -->
22

33
- [Introduction](#introduction)
44
- [Installation](#installation)
@@ -109,7 +109,7 @@ This project is licensed under the terms of the MIT license.
109109
```pre
110110
MIT License
111111
112-
Copyright (c) 2023 Grant Ramsay
112+
Copyright (c) 2023-2024 Grant Ramsay
113113
114114
Permission is hereby granted, free of charge, to any person obtaining a copy
115115
of this software and associated documentation files (the "Software"), to deal

db.py

+37-13
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,57 @@
11
"""Set up the database connection and session.""" ""
2-
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
3-
from sqlalchemy.orm import declarative_base
2+
from collections.abc import AsyncGenerator
3+
from typing import Any
4+
5+
from sqlalchemy import MetaData
6+
from sqlalchemy.ext.asyncio import (
7+
AsyncSession,
8+
async_sessionmaker,
9+
create_async_engine,
10+
)
11+
from sqlalchemy.orm import DeclarativeBase
412

513
DATABASE_URL = "postgresql+asyncpg://postgres:postgres@localhost/postgres"
6-
# DATABASE_URL = "sqlite+aiosqlite:///./test.db"
14+
# DATABASE_URL = "sqlite+aiosqlite:///./test.db" # noqa: ERA001
715
# Note that (as far as I can tell from the docs and searching) there is no need
816
# to add 'check_same_thread=False' to the sqlite connection string, as
917
# SQLAlchemy version 1.4+ will automatically add it for you when using SQLite.
1018

11-
engine = create_async_engine(DATABASE_URL, echo=False)
12-
Base = declarative_base()
13-
async_session = async_sessionmaker(engine, expire_on_commit=False)
19+
20+
class Base(DeclarativeBase):
21+
"""Base class for SQLAlchemy models.
22+
23+
All other models should inherit from this class.
24+
"""
25+
26+
metadata = MetaData(
27+
naming_convention={
28+
"ix": "ix_%(column_0_label)s",
29+
"uq": "uq_%(table_name)s_%(column_0_name)s",
30+
"ck": "ck_%(table_name)s_%(constraint_name)s",
31+
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
32+
"pk": "pk_%(table_name)s",
33+
}
34+
)
35+
36+
37+
async_engine = create_async_engine(DATABASE_URL, echo=False)
38+
async_session = async_sessionmaker(async_engine, expire_on_commit=False)
1439

1540

16-
async def get_db():
41+
async def get_db() -> AsyncGenerator[AsyncSession, Any]:
1742
"""Get a database session.
1843
1944
To be used for dependency injection.
2045
"""
21-
async with async_session() as session:
22-
async with session.begin():
23-
yield session
46+
async with async_session() as session, session.begin():
47+
yield session
2448

2549

26-
async def init_models():
50+
async def init_models() -> None:
2751
"""Create tables if they don't already exist.
2852
2953
In a real-life example we would use Alembic to manage migrations.
3054
"""
31-
async with engine.begin() as conn:
32-
# await conn.run_sync(Base.metadata.drop_all)
55+
async with async_engine.begin() as conn:
56+
# await conn.run_sync(Base.metadata.drop_all) # noqa: ERA001
3357
await conn.run_sync(Base.metadata.create_all)

docs/explanation.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Code Explanation
2+
3+
!!! note "Under Construction"
4+
This section is still to be written.

0 commit comments

Comments
 (0)