Commits: 5
Setup devenv with Python, FastAPI and LSP
Implement a simple server. To run it in development mode:
fastapi dev main.pynew file mode 100644
index 0000000..8c1629e
--- /dev/null
+++ b/.envrc
@@ -0,0 +1,12 @@
+if ! has nix_direnv_version || ! nix_direnv_version 3.1.0; then
+ source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.1.0/direnvrc" "sha256-yMJ2OVMzrFaDPn7q8nCBZFRYpL/f0RcHzhmw/i6btJM="
+fi
+
+export DEVENV_IN_DIRENV_SHELL=true
+
+watch_file flake.nix
+watch_file flake.lock
+if ! use flake . --no-pure-eval
+then
+ echo "devenv could not be built. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2
+finew file mode 100644
index 0000000..18b86e4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.devenv
+.direnv
+__pycache__new file mode 100644
index 0000000..5eb345c
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,223 @@
+{
+ "nodes": {
+ "cachix": {
+ "inputs": {
+ "devenv": [
+ "devenv"
+ ],
+ "flake-compat": [
+ "devenv"
+ ],
+ "git-hooks": [
+ "devenv",
+ "git-hooks"
+ ],
+ "nixpkgs": [
+ "devenv",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1748883665,
+ "narHash": "sha256-R0W7uAg+BLoHjMRMQ8+oiSbTq8nkGz5RDpQ+ZfxxP3A=",
+ "owner": "cachix",
+ "repo": "cachix",
+ "rev": "f707778d902af4d62d8dd92c269f8e70de09acbe",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "ref": "latest",
+ "repo": "cachix",
+ "type": "github"
+ }
+ },
+ "devenv": {
+ "inputs": {
+ "cachix": "cachix",
+ "flake-compat": "flake-compat",
+ "git-hooks": "git-hooks",
+ "nix": "nix",
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1757003908,
+ "narHash": "sha256-Op3cnPTav+ObcL4R4BGuWHEFxW6YS2A0aE3Av6sZN2g=",
+ "owner": "cachix",
+ "repo": "devenv",
+ "rev": "ac8ebf17828c0e7d9be0270d359123fffcc6f066",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "repo": "devenv",
+ "type": "github"
+ }
+ },
+ "flake-compat": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1747046372,
+ "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
+ "owner": "edolstra",
+ "repo": "flake-compat",
+ "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
+ "type": "github"
+ },
+ "original": {
+ "owner": "edolstra",
+ "repo": "flake-compat",
+ "type": "github"
+ }
+ },
+ "flake-parts": {
+ "inputs": {
+ "nixpkgs-lib": [
+ "devenv",
+ "nix",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1733312601,
+ "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "type": "github"
+ }
+ },
+ "git-hooks": {
+ "inputs": {
+ "flake-compat": [
+ "devenv",
+ "flake-compat"
+ ],
+ "gitignore": "gitignore",
+ "nixpkgs": [
+ "devenv",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1750779888,
+ "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=",
+ "owner": "cachix",
+ "repo": "git-hooks.nix",
+ "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "repo": "git-hooks.nix",
+ "type": "github"
+ }
+ },
+ "gitignore": {
+ "inputs": {
+ "nixpkgs": [
+ "devenv",
+ "git-hooks",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1709087332,
+ "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+ "owner": "hercules-ci",
+ "repo": "gitignore.nix",
+ "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "gitignore.nix",
+ "type": "github"
+ }
+ },
+ "nix": {
+ "inputs": {
+ "flake-compat": [
+ "devenv",
+ "flake-compat"
+ ],
+ "flake-parts": "flake-parts",
+ "git-hooks-nix": [
+ "devenv",
+ "git-hooks"
+ ],
+ "nixpkgs": [
+ "devenv",
+ "nixpkgs"
+ ],
+ "nixpkgs-23-11": [
+ "devenv"
+ ],
+ "nixpkgs-regression": [
+ "devenv"
+ ]
+ },
+ "locked": {
+ "lastModified": 1755029779,
+ "narHash": "sha256-3+GHIYGg4U9XKUN4rg473frIVNn8YD06bjwxKS1IPrU=",
+ "owner": "cachix",
+ "repo": "nix",
+ "rev": "b0972b0eee6726081d10b1199f54de6d2917f861",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "ref": "devenv-2.30",
+ "repo": "nix",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1755783167,
+ "narHash": "sha256-gj7qvMNz7YvhjYxNq4I370cAYIZEw2PbVs5BSwaLrD4=",
+ "owner": "cachix",
+ "repo": "devenv-nixpkgs",
+ "rev": "4a880fb247d24fbca57269af672e8f78935b0328",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "ref": "rolling",
+ "repo": "devenv-nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "devenv": "devenv",
+ "nixpkgs": "nixpkgs",
+ "systems": "systems"
+ }
+ },
+ "systems": {
+ "locked": {
+ "lastModified": 1681028828,
+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+ "owner": "nix-systems",
+ "repo": "default",
+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-systems",
+ "repo": "default",
+ "type": "github"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}new file mode 100644
index 0000000..2640694
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,45 @@
+{
+ inputs = {
+ nixpkgs.url = "github:cachix/devenv-nixpkgs/rolling";
+ systems.url = "github:nix-systems/default";
+ devenv.url = "github:cachix/devenv";
+ devenv.inputs.nixpkgs.follows = "nixpkgs";
+ };
+
+ nixConfig = {
+ extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=";
+ extra-substituters = "https://devenv.cachix.org";
+ };
+
+ outputs = { self, nixpkgs, devenv, systems, ... } @ inputs:
+ let
+ forEachSystem = nixpkgs.lib.genAttrs (import systems);
+ in
+ {
+ devShells = forEachSystem
+ (system:
+ let
+ pkgs = nixpkgs.legacyPackages.${system};
+ in
+ {
+ default = devenv.lib.mkShell {
+ inherit inputs pkgs;
+ modules = [
+ {
+ # https://devenv.sh/reference/options/
+ packages = [];
+
+ languages.python = {
+ enable = true;
+ venv.enable = true;
+ venv.requirements = ''
+ fastapi[standard]
+ python-lsp-server[all]
+ '';
+ };
+ }
+ ];
+ };
+ });
+ };
+}new file mode 100644
index 0000000..11e82cc
--- /dev/null
+++ b/main.py
@@ -0,0 +1,7 @@
+from fastapi import FastAPI
+
+app = FastAPI()
+
+@app.get("/")
+def get_root():
+ return "A quick hello"Register a develop process in devenv
To start the development server run
devenv upindex 2640694..75792ae 100644
--- a/flake.nix
+++ b/flake.nix
@@ -37,6 +37,10 @@
= python-lsp-server[all]
= '';
= };
+
+ processes = {
+ develop.exec = "fastapi dev main.py";
+ };
= }
= ];
= };Add docstrings and a hardcoded list of one joke
It's corny.
index 11e82cc..14c9b97 100644
--- a/main.py
+++ b/main.py
@@ -1,7 +1,25 @@
+"""
+A sample REST API service.
+
+You can use it to teach concepts of REST.
+"""
+
=from fastapi import FastAPI
=
=app = FastAPI()
+jokes = [
+ "How do you find a velociraptor?\n\nBy taking the integral of the acceleraptor!"
+]
+
=
=@app.get("/")
-def get_root():
+def get_random_joke():
+ """Get a single random joke."""
= return "A quick hello"
+
+
+@app.get("/jokes")
+def list_jokes():
+ """List all jokes."""
+ return jokes
+Add type hints, define the Joke class
index 14c9b97..367e33d 100644
--- a/main.py
+++ b/main.py
@@ -5,21 +5,31 @@ You can use it to teach concepts of REST.
="""
=
=from fastapi import FastAPI
+from pydantic import BaseModel
=
=app = FastAPI()
+
+
+class Joke(BaseModel):
+ """A joke."""
+
+ text: str
+
+
=jokes = [
- "How do you find a velociraptor?\n\nBy taking the integral of the acceleraptor!"
+ Joke(text="How do you find a velociraptor?\n\n" +
+ "By taking the integral of the acceleraptor!")
=]
=
=
=@app.get("/")
-def get_random_joke():
+def get_random_joke() -> Joke:
= """Get a single random joke."""
- return "A quick hello"
+ return jokes[0]
=
=
=@app.get("/jokes")
-def list_jokes():
+def list_jokes() -> list[Joke]:
= """List all jokes."""
= return jokes
=Implement the POST /jokes/ endpoint
index 367e33d..1afcfec 100644
--- a/main.py
+++ b/main.py
@@ -33,3 +33,9 @@ def list_jokes() -> list[Joke]:
= """List all jokes."""
= return jokes
=
+
+@app.post("/jokes")
+def new_joke(joke: Joke) -> Joke:
+ """Write a new joke."""
+ jokes.append(joke)
+ return joke