├── .gitignore ├── README.md ├── main.py ├── poetry.lock └── pyproject.toml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/python,macos,windows,linux,vim,visualstudiocode 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=python,macos,windows,linux,vim,visualstudiocode 4 | 5 | ### Linux ### 6 | *~ 7 | 8 | # temporary files which can be created if a process still has a handle open of a deleted file 9 | .fuse_hidden* 10 | 11 | # KDE directory preferences 12 | .directory 13 | 14 | # Linux trash folder which might appear on any partition or disk 15 | .Trash-* 16 | 17 | # .nfs files are created when an open file is removed but is still being accessed 18 | .nfs* 19 | 20 | ### macOS ### 21 | # General 22 | .DS_Store 23 | .AppleDouble 24 | .LSOverride 25 | 26 | # Icon must end with two \r 27 | Icon 28 | 29 | 30 | # Thumbnails 31 | ._* 32 | 33 | # Files that might appear in the root of a volume 34 | .DocumentRevisions-V100 35 | .fseventsd 36 | .Spotlight-V100 37 | .TemporaryItems 38 | .Trashes 39 | .VolumeIcon.icns 40 | .com.apple.timemachine.donotpresent 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | 49 | ### Python ### 50 | # Byte-compiled / optimized / DLL files 51 | __pycache__/ 52 | *.py[cod] 53 | *$py.class 54 | 55 | # C extensions 56 | *.so 57 | 58 | # Distribution / packaging 59 | .Python 60 | build/ 61 | develop-eggs/ 62 | dist/ 63 | downloads/ 64 | eggs/ 65 | .eggs/ 66 | lib/ 67 | lib64/ 68 | parts/ 69 | sdist/ 70 | var/ 71 | wheels/ 72 | share/python-wheels/ 73 | *.egg-info/ 74 | .installed.cfg 75 | *.egg 76 | MANIFEST 77 | 78 | # PyInstaller 79 | # Usually these files are written by a python script from a template 80 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 81 | *.manifest 82 | *.spec 83 | 84 | # Installer logs 85 | pip-log.txt 86 | pip-delete-this-directory.txt 87 | 88 | # Unit test / coverage reports 89 | htmlcov/ 90 | .tox/ 91 | .nox/ 92 | .coverage 93 | .coverage.* 94 | .cache 95 | nosetests.xml 96 | coverage.xml 97 | *.cover 98 | *.py,cover 99 | .hypothesis/ 100 | .pytest_cache/ 101 | cover/ 102 | 103 | # Translations 104 | *.mo 105 | *.pot 106 | 107 | # Django stuff: 108 | *.log 109 | local_settings.py 110 | db.sqlite3 111 | db.sqlite3-journal 112 | 113 | # Flask stuff: 114 | instance/ 115 | .webassets-cache 116 | 117 | # Scrapy stuff: 118 | .scrapy 119 | 120 | # Sphinx documentation 121 | docs/_build/ 122 | 123 | # PyBuilder 124 | .pybuilder/ 125 | target/ 126 | 127 | # Jupyter Notebook 128 | .ipynb_checkpoints 129 | 130 | # IPython 131 | profile_default/ 132 | ipython_config.py 133 | 134 | # pyenv 135 | # For a library or package, you might want to ignore these files since the code is 136 | # intended to run in multiple environments; otherwise, check them in: 137 | # .python-version 138 | 139 | # pipenv 140 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 141 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 142 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 143 | # install all needed dependencies. 144 | #Pipfile.lock 145 | 146 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 147 | __pypackages__/ 148 | 149 | # Celery stuff 150 | celerybeat-schedule 151 | celerybeat.pid 152 | 153 | # SageMath parsed files 154 | *.sage.py 155 | 156 | # Environments 157 | .env 158 | .venv 159 | env/ 160 | venv/ 161 | ENV/ 162 | env.bak/ 163 | venv.bak/ 164 | 165 | # Spyder project settings 166 | .spyderproject 167 | .spyproject 168 | 169 | # Rope project settings 170 | .ropeproject 171 | 172 | # mkdocs documentation 173 | /site 174 | 175 | # mypy 176 | .mypy_cache/ 177 | .dmypy.json 178 | dmypy.json 179 | 180 | # Pyre type checker 181 | .pyre/ 182 | 183 | # pytype static type analyzer 184 | .pytype/ 185 | 186 | # Cython debug symbols 187 | cython_debug/ 188 | 189 | ### Vim ### 190 | # Swap 191 | [._]*.s[a-v][a-z] 192 | !*.svg # comment out if you don't need vector files 193 | [._]*.sw[a-p] 194 | [._]s[a-rt-v][a-z] 195 | [._]ss[a-gi-z] 196 | [._]sw[a-p] 197 | 198 | # Session 199 | Session.vim 200 | Sessionx.vim 201 | 202 | # Temporary 203 | .netrwhist 204 | # Auto-generated tag files 205 | tags 206 | # Persistent undo 207 | [._]*.un~ 208 | 209 | ### VisualStudioCode ### 210 | .vscode/* 211 | !.vscode/settings.json 212 | !.vscode/tasks.json 213 | !.vscode/launch.json 214 | !.vscode/extensions.json 215 | *.code-workspace 216 | 217 | # Local History for Visual Studio Code 218 | .history/ 219 | 220 | ### VisualStudioCode Patch ### 221 | # Ignore all local history of files 222 | .history 223 | .ionide 224 | 225 | # Support for Project snippet scope 226 | !.vscode/*.code-snippets 227 | 228 | ### Windows ### 229 | # Windows thumbnail cache files 230 | Thumbs.db 231 | Thumbs.db:encryptable 232 | ehthumbs.db 233 | ehthumbs_vista.db 234 | 235 | # Dump file 236 | *.stackdump 237 | 238 | # Folder config file 239 | [Dd]esktop.ini 240 | 241 | # Recycle Bin used on file shares 242 | $RECYCLE.BIN/ 243 | 244 | # Windows Installer files 245 | *.cab 246 | *.msi 247 | *.msix 248 | *.msm 249 | *.msp 250 | 251 | # Windows shortcuts 252 | *.lnk 253 | 254 | # End of https://www.toptal.com/developers/gitignore/api/python,macos,windows,linux,vim,visualstudiocode 255 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fast API LMS 2 | 3 | This repo goes along with the video on our Faraday Academy YouTube channel: https://youtu.be/gQTRsZpR7Gw 4 | 5 | You can follow along with the video and check out different branches for each step of the tutorial. More work will be done on this repo in future tutorials to finish building all of the features. 6 | 7 | ## Table of Contents 8 | 9 | 1. [Overview & Requirements](#overview-&-requirements) 10 | 1. [Running Locally](#running-the-app-locally) 11 | 1. [Tech Stack](#tech-stack) 12 | 1. [Schema](#schema) 13 | 14 | ## Overview & Requirements 15 | 16 | This is a learning management system where teachers can manage student and students can see their courses. 17 | 18 | - Teachers can perform CRUD operations on students. 19 | - Teachers can create courses with sections and content blocks in each section. 20 | - Teachers can assign courses to students. 21 | - Students can interact view their courses in a list. 22 | - Students can see the sections and content blocks for individual courses that they are taking. 23 | - Students are able to see their progress for each course. 24 | 25 | ## Running the App Locally 26 | 27 | 1. Make sure Python, Poetry, and Postgres are installed. Postgres must be running. *If you need help with this, please follow the instructions in the video linked at the top of this README.* 28 | 2. Create a virtual environment: `python -m venv venv` 29 | 3. Install packages: `poetry install` 30 | 4. Run the development server: `uvicorn main:app --reload` 31 | 32 | ## Tech Stack 33 | 34 | - Fast API 35 | - Python 3.9+ 36 | - Poetry 37 | - Postgres 38 | - SQL Alchemy 1.4+ 39 | - Alembic 40 | - Pydantic 41 | - Black 42 | - Flake8 43 | - Pre-commit 44 | 45 | ## Schema 46 | 47 | **User** 48 | 49 | - email: str 50 | - role: enum (student, teacher) 51 | - is_active: bool 52 | 53 | **Profile** 54 | 55 | - first_name: str 56 | - last_name: str 57 | - bio: str (TextField) 58 | - user_id: fk 59 | 60 | **Course** 61 | 62 | - title: str 63 | - description: str (TextField) 64 | - user_id: fk 65 | 66 | **Section** 67 | 68 | - title 69 | - description 70 | - course_id 71 | 72 | **ContentBlock** 73 | 74 | - title 75 | - description 76 | - type 77 | - url 78 | - content 79 | - section_id 80 | 81 | **StudentCourse** 82 | 83 | *This model is used for teachers to assign courses to students. The 'completed' boolean is False until the student has completed the whole course.* 84 | 85 | - student_id 86 | - course_id 87 | - completed 88 | 89 | **CompletedContentBlock** 90 | 91 | *Every time the student completes a content block, a row is created in this table. The teacher can then go and edit this information when they grade the content block and provide feedback.* 92 | 93 | - student_id 94 | - content_block_id 95 | - url 96 | - feedback 97 | - grade 98 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, List 2 | from fastapi import FastAPI, Path, Query 3 | from pydantic import BaseModel 4 | 5 | app = FastAPI( 6 | title="Fast API LMS", 7 | description="LMS for managing students and courses.", 8 | version="0.0.1", 9 | contact={ 10 | "name": "Gwen", 11 | "email": "gwen@example.com", 12 | }, 13 | license_info={ 14 | "name": "MIT", 15 | }, 16 | ) 17 | 18 | users = [] 19 | 20 | class User(BaseModel): 21 | email: str 22 | is_active: bool 23 | bio: Optional[str] 24 | 25 | 26 | @app.get("/users", response_model=List[User]) 27 | async def get_users(): 28 | return users 29 | 30 | 31 | @app.post("/users") 32 | async def create_user(user: User): 33 | users.append(user) 34 | return "Success" 35 | 36 | 37 | @app.get("/users/{id}") 38 | async def get_user( 39 | id: int = Path(..., description="The ID of the user you want to retrieve.", gt=2), 40 | q: str = Query(None, max_length=5) 41 | ): 42 | return { "user": users[id], "query": q } 43 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "anyio" 3 | version = "3.4.0" 4 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 5 | category = "main" 6 | optional = false 7 | python-versions = ">=3.6.2" 8 | 9 | [package.dependencies] 10 | idna = ">=2.8" 11 | sniffio = ">=1.1" 12 | 13 | [package.extras] 14 | doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] 15 | test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] 16 | trio = ["trio (>=0.16)"] 17 | 18 | [[package]] 19 | name = "asgiref" 20 | version = "3.4.1" 21 | description = "ASGI specs, helper code, and adapters" 22 | category = "main" 23 | optional = false 24 | python-versions = ">=3.6" 25 | 26 | [package.extras] 27 | tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] 28 | 29 | [[package]] 30 | name = "click" 31 | version = "8.0.3" 32 | description = "Composable command line interface toolkit" 33 | category = "main" 34 | optional = false 35 | python-versions = ">=3.6" 36 | 37 | [package.dependencies] 38 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 39 | 40 | [[package]] 41 | name = "colorama" 42 | version = "0.4.4" 43 | description = "Cross-platform colored terminal text." 44 | category = "main" 45 | optional = false 46 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 47 | 48 | [[package]] 49 | name = "fastapi" 50 | version = "0.70.1" 51 | description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" 52 | category = "main" 53 | optional = false 54 | python-versions = ">=3.6.1" 55 | 56 | [package.dependencies] 57 | pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" 58 | starlette = "0.16.0" 59 | 60 | [package.extras] 61 | all = ["requests (>=2.24.0,<3.0.0)", "jinja2 (>=2.11.2,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "itsdangerous (>=1.1.0,<3.0.0)", "pyyaml (>=5.3.1,<6.0.0)", "ujson (>=4.0.1,<5.0.0)", "orjson (>=3.2.1,<4.0.0)", "email_validator (>=1.1.1,<2.0.0)", "uvicorn[standard] (>=0.12.0,<0.16.0)"] 62 | dev = ["python-jose[cryptography] (>=3.3.0,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "uvicorn[standard] (>=0.12.0,<0.16.0)"] 63 | doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=7.1.9,<8.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "typer-cli (>=0.0.12,<0.0.13)", "pyyaml (>=5.3.1,<6.0.0)"] 64 | test = ["pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<4.0.0)", "mypy (==0.910)", "flake8 (>=3.8.3,<4.0.0)", "black (==21.9b0)", "isort (>=5.0.6,<6.0.0)", "requests (>=2.24.0,<3.0.0)", "httpx (>=0.14.0,<0.19.0)", "email_validator (>=1.1.1,<2.0.0)", "sqlalchemy (>=1.3.18,<1.5.0)", "peewee (>=3.13.3,<4.0.0)", "databases[sqlite] (>=0.3.2,<0.6.0)", "orjson (>=3.2.1,<4.0.0)", "ujson (>=4.0.1,<5.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "flask (>=1.1.2,<3.0.0)", "anyio[trio] (>=3.2.1,<4.0.0)", "types-ujson (==0.1.1)", "types-orjson (==3.6.0)", "types-dataclasses (==0.1.7)"] 65 | 66 | [[package]] 67 | name = "h11" 68 | version = "0.12.0" 69 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 70 | category = "main" 71 | optional = false 72 | python-versions = ">=3.6" 73 | 74 | [[package]] 75 | name = "idna" 76 | version = "3.3" 77 | description = "Internationalized Domain Names in Applications (IDNA)" 78 | category = "main" 79 | optional = false 80 | python-versions = ">=3.5" 81 | 82 | [[package]] 83 | name = "pydantic" 84 | version = "1.8.2" 85 | description = "Data validation and settings management using python 3.6 type hinting" 86 | category = "main" 87 | optional = false 88 | python-versions = ">=3.6.1" 89 | 90 | [package.dependencies] 91 | typing-extensions = ">=3.7.4.3" 92 | 93 | [package.extras] 94 | dotenv = ["python-dotenv (>=0.10.4)"] 95 | email = ["email-validator (>=1.0.3)"] 96 | 97 | [[package]] 98 | name = "sniffio" 99 | version = "1.2.0" 100 | description = "Sniff out which async library your code is running under" 101 | category = "main" 102 | optional = false 103 | python-versions = ">=3.5" 104 | 105 | [[package]] 106 | name = "starlette" 107 | version = "0.16.0" 108 | description = "The little ASGI library that shines." 109 | category = "main" 110 | optional = false 111 | python-versions = ">=3.6" 112 | 113 | [package.dependencies] 114 | anyio = ">=3.0.0,<4" 115 | 116 | [package.extras] 117 | full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests", "graphene"] 118 | 119 | [[package]] 120 | name = "typing-extensions" 121 | version = "4.0.1" 122 | description = "Backported and Experimental Type Hints for Python 3.6+" 123 | category = "main" 124 | optional = false 125 | python-versions = ">=3.6" 126 | 127 | [[package]] 128 | name = "uvicorn" 129 | version = "0.16.0" 130 | description = "The lightning-fast ASGI server." 131 | category = "main" 132 | optional = false 133 | python-versions = "*" 134 | 135 | [package.dependencies] 136 | asgiref = ">=3.4.0" 137 | click = ">=7.0" 138 | h11 = ">=0.8" 139 | 140 | [package.extras] 141 | standard = ["httptools (>=0.2.0,<0.4.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "websockets (>=9.1)", "websockets (>=10.0)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"] 142 | 143 | [metadata] 144 | lock-version = "1.1" 145 | python-versions = "^3.9" 146 | content-hash = "d3ff195010d0e41d491676500aaec63d9d97b21f6c6d5c28a3ed3f44d2d0d516" 147 | 148 | [metadata.files] 149 | anyio = [ 150 | {file = "anyio-3.4.0-py3-none-any.whl", hash = "sha256:2855a9423524abcdd652d942f8932fda1735210f77a6b392eafd9ff34d3fe020"}, 151 | {file = "anyio-3.4.0.tar.gz", hash = "sha256:24adc69309fb5779bc1e06158e143e0b6d2c56b302a3ac3de3083c705a6ed39d"}, 152 | ] 153 | asgiref = [ 154 | {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, 155 | {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, 156 | ] 157 | click = [ 158 | {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, 159 | {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, 160 | ] 161 | colorama = [ 162 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 163 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 164 | ] 165 | fastapi = [ 166 | {file = "fastapi-0.70.1-py3-none-any.whl", hash = "sha256:5367226c7bcd7bfb2e17edaf225fd9a983095b1372281e9a3eb661336fb93748"}, 167 | {file = "fastapi-0.70.1.tar.gz", hash = "sha256:21d03979b5336375c66fa5d1f3126c6beca650d5d2166fbb78345a30d33c8d06"}, 168 | ] 169 | h11 = [ 170 | {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, 171 | {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, 172 | ] 173 | idna = [ 174 | {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, 175 | {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, 176 | ] 177 | pydantic = [ 178 | {file = "pydantic-1.8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739"}, 179 | {file = "pydantic-1.8.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4"}, 180 | {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e"}, 181 | {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840"}, 182 | {file = "pydantic-1.8.2-cp36-cp36m-win_amd64.whl", hash = "sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b"}, 183 | {file = "pydantic-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20"}, 184 | {file = "pydantic-1.8.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb"}, 185 | {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1"}, 186 | {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23"}, 187 | {file = "pydantic-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287"}, 188 | {file = "pydantic-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd"}, 189 | {file = "pydantic-1.8.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505"}, 190 | {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e"}, 191 | {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820"}, 192 | {file = "pydantic-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3"}, 193 | {file = "pydantic-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316"}, 194 | {file = "pydantic-1.8.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62"}, 195 | {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f"}, 196 | {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b"}, 197 | {file = "pydantic-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3"}, 198 | {file = "pydantic-1.8.2-py3-none-any.whl", hash = "sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833"}, 199 | {file = "pydantic-1.8.2.tar.gz", hash = "sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b"}, 200 | ] 201 | sniffio = [ 202 | {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, 203 | {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, 204 | ] 205 | starlette = [ 206 | {file = "starlette-0.16.0-py3-none-any.whl", hash = "sha256:38eb24bf705a2c317e15868e384c1b8a12ca396e5a3c3a003db7e667c43f939f"}, 207 | {file = "starlette-0.16.0.tar.gz", hash = "sha256:e1904b5d0007aee24bdd3c43994be9b3b729f4f58e740200de1d623f8c3a8870"}, 208 | ] 209 | typing-extensions = [ 210 | {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, 211 | {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, 212 | ] 213 | uvicorn = [ 214 | {file = "uvicorn-0.16.0-py3-none-any.whl", hash = "sha256:d8c839231f270adaa6d338d525e2652a0b4a5f4c2430b5c4ef6ae4d11776b0d2"}, 215 | {file = "uvicorn-0.16.0.tar.gz", hash = "sha256:eacb66afa65e0648fcbce5e746b135d09722231ffffc61883d4fac2b62fbea8d"}, 216 | ] 217 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "fast-api-lms" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Gwendolyn Faraday "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.9" 9 | uvicorn = "^0.16.0" 10 | fastapi = "^0.70.1" 11 | pydantic = "^1.8.2" 12 | 13 | [tool.poetry.dev-dependencies] 14 | 15 | [build-system] 16 | requires = ["poetry-core>=1.0.0"] 17 | build-backend = "poetry.core.masonry.api" 18 | --------------------------------------------------------------------------------