From 6ac4693991ba0becfd50800f4013fedd566f2b20 Mon Sep 17 00:00:00 2001 From: CristhianMotoche Date: Mon, 23 Sep 2024 17:01:18 -0500 Subject: [PATCH 1/5] chore: Set up environment --- .../flask-sqlalchemy-typing/.envrc | 3 + .../flask-sqlalchemy-typing/.gitignore | 9 + .../flask-sqlalchemy-typing/README.md | 11 ++ .../flask-sqlalchemy-typing/devenv.lock | 160 ++++++++++++++++++ .../flask-sqlalchemy-typing/devenv.nix | 16 ++ .../flask-sqlalchemy-typing/devenv.yaml | 8 + .../flask-sqlalchemy-typing/requirements.txt | 0 7 files changed, 207 insertions(+) create mode 100644 python/typing-models/flask-sqlalchemy-typing/.envrc create mode 100644 python/typing-models/flask-sqlalchemy-typing/.gitignore create mode 100644 python/typing-models/flask-sqlalchemy-typing/README.md create mode 100644 python/typing-models/flask-sqlalchemy-typing/devenv.lock create mode 100644 python/typing-models/flask-sqlalchemy-typing/devenv.nix create mode 100644 python/typing-models/flask-sqlalchemy-typing/devenv.yaml create mode 100644 python/typing-models/flask-sqlalchemy-typing/requirements.txt diff --git a/python/typing-models/flask-sqlalchemy-typing/.envrc b/python/typing-models/flask-sqlalchemy-typing/.envrc new file mode 100644 index 0000000..5bf8fc1 --- /dev/null +++ b/python/typing-models/flask-sqlalchemy-typing/.envrc @@ -0,0 +1,3 @@ +source_url "https://raw.githubusercontent.com/cachix/devenv/95f329d49a8a5289d31e0982652f7058a189bfca/direnvrc" "sha256-d+8cBpDfDBj41inrADaJt+bDWhOktwslgoP5YiGJ1v0=" + +use devenv \ No newline at end of file diff --git a/python/typing-models/flask-sqlalchemy-typing/.gitignore b/python/typing-models/flask-sqlalchemy-typing/.gitignore new file mode 100644 index 0000000..4d058db --- /dev/null +++ b/python/typing-models/flask-sqlalchemy-typing/.gitignore @@ -0,0 +1,9 @@ +# Devenv +.devenv* +devenv.local.nix + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml diff --git a/python/typing-models/flask-sqlalchemy-typing/README.md b/python/typing-models/flask-sqlalchemy-typing/README.md new file mode 100644 index 0000000..e723dcf --- /dev/null +++ b/python/typing-models/flask-sqlalchemy-typing/README.md @@ -0,0 +1,11 @@ +# Flask-SQLAlchemy models + +## Requirements + +* `devenv` + +## Start + +``` +devenv shell +``` diff --git a/python/typing-models/flask-sqlalchemy-typing/devenv.lock b/python/typing-models/flask-sqlalchemy-typing/devenv.lock new file mode 100644 index 0000000..e5233a2 --- /dev/null +++ b/python/typing-models/flask-sqlalchemy-typing/devenv.lock @@ -0,0 +1,160 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1727098005, + "owner": "cachix", + "repo": "devenv", + "rev": "f318d27a4637aff765a378106d82dfded124c3b3", + "treeHash": "c77efa71afb25615542aed9d7e805a3b6216b6a2", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "treeHash": "2addb7b71a20a25ea74feeaf5c2f6a6b30898ecb", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "treeHash": "2addb7b71a20a25ea74feeaf5c2f6a6b30898ecb", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "treeHash": "ca14199cabdfe1a06a7b1654c76ed49100a689f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1716977621, + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "4267e705586473d3e5c8d50299e71503f16a6fb6", + "treeHash": "6d9f1f7ca0faf1bc2eeb397c78a49623260d3412", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs-python": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722978926, + "owner": "cachix", + "repo": "nixpkgs-python", + "rev": "7c550bca7e6cf95898e32eb2173efe7ebb447460", + "treeHash": "d9d38ef1b6fc92be18170b74e9889a7ab9174f6e", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "nixpkgs-python", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1726969270, + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "23cbb250f3bf4f516a2d0bf03c51a30900848075", + "treeHash": "f150876866adcc3af432c103db116c2f516f49b1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat_2", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1726745158, + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "4e743a6920eab45e8ba0fbe49dc459f1423a4b74", + "treeHash": "56fbe2a9610b3ad9163a74011131e7624f6b3b81", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs", + "nixpkgs-python": "nixpkgs-python", + "pre-commit-hooks": "pre-commit-hooks" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/python/typing-models/flask-sqlalchemy-typing/devenv.nix b/python/typing-models/flask-sqlalchemy-typing/devenv.nix new file mode 100644 index 0000000..83c02ab --- /dev/null +++ b/python/typing-models/flask-sqlalchemy-typing/devenv.nix @@ -0,0 +1,16 @@ +{ pkgs, lib, config, inputs, ... }: + +{ + packages = [ + pkgs.sqlite + ]; + + languages.python = { + enable = true; + version = "3.12.0"; + venv = { + enable = true; + requirements = "requirements.txt"; + }; + }; +} diff --git a/python/typing-models/flask-sqlalchemy-typing/devenv.yaml b/python/typing-models/flask-sqlalchemy-typing/devenv.yaml new file mode 100644 index 0000000..184b866 --- /dev/null +++ b/python/typing-models/flask-sqlalchemy-typing/devenv.yaml @@ -0,0 +1,8 @@ +inputs: + nixpkgs: + url: github:cachix/devenv-nixpkgs/rolling + nixpkgs-python: + url: github:cachix/nixpkgs-python + inputs: + nixpkgs: + follows: nixpkgs diff --git a/python/typing-models/flask-sqlalchemy-typing/requirements.txt b/python/typing-models/flask-sqlalchemy-typing/requirements.txt new file mode 100644 index 0000000..e69de29 From 519815272a86ff4eccdc79c3b10f32b39e55176c Mon Sep 17 00:00:00 2001 From: CristhianMotoche Date: Mon, 23 Sep 2024 17:03:49 -0500 Subject: [PATCH 2/5] chore: Set up deps --- .../flask-sqlalchemy-typing/requirements.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/python/typing-models/flask-sqlalchemy-typing/requirements.txt b/python/typing-models/flask-sqlalchemy-typing/requirements.txt index e69de29..aa30d58 100644 --- a/python/typing-models/flask-sqlalchemy-typing/requirements.txt +++ b/python/typing-models/flask-sqlalchemy-typing/requirements.txt @@ -0,0 +1,10 @@ +blinker==1.8.2 +click==8.1.7 +Flask==3.0.3 +Flask-SQLAlchemy==3.1.1 +itsdangerous==2.2.0 +Jinja2==3.1.4 +MarkupSafe==2.1.5 +SQLAlchemy==2.0.35 +typing_extensions==4.12.2 +Werkzeug==3.0.4 From 9f99cddf2d67a64d05cf2ac3d2ce95cf1f06131f Mon Sep 17 00:00:00 2001 From: CristhianMotoche Date: Wed, 2 Oct 2024 08:29:30 -0500 Subject: [PATCH 3/5] chore: Define model --- .../flask-sqlalchemy-typing/app/main.py | 42 ++++++++++++++++++ .../instance/project.db | Bin 0 -> 12288 bytes 2 files changed, 42 insertions(+) create mode 100644 python/typing-models/flask-sqlalchemy-typing/app/main.py create mode 100644 python/typing-models/flask-sqlalchemy-typing/instance/project.db diff --git a/python/typing-models/flask-sqlalchemy-typing/app/main.py b/python/typing-models/flask-sqlalchemy-typing/app/main.py new file mode 100644 index 0000000..a28dd41 --- /dev/null +++ b/python/typing-models/flask-sqlalchemy-typing/app/main.py @@ -0,0 +1,42 @@ +from datetime import datetime +import sys + +from flask import Flask + +from flask_sqlalchemy import SQLAlchemy + +from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column + +# Web Application + +app = Flask(__name__) + +# Database + +class Base(DeclarativeBase): + pass + +db = SQLAlchemy(model_class=Base) + +app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///project.db" + +db.init_app(app) + + +class Notification(db.Model): + __tablename__ = "notifications" + + id: Mapped[int] = mapped_column(primary_key=True, index=True) + description: Mapped[str] + email: Mapped[str] = mapped_column(nullable=False) + date: Mapped[datetime] = mapped_column(nullable=False) + url: Mapped[str] + read: Mapped[bool] = mapped_column(default=False) + +if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] == 'db': + print("Creating db...") + with app.app_context(): + db.create_all() + + app.run() diff --git a/python/typing-models/flask-sqlalchemy-typing/instance/project.db b/python/typing-models/flask-sqlalchemy-typing/instance/project.db new file mode 100644 index 0000000000000000000000000000000000000000..97a32d86660fa2c182f1036f6336324ef2c3df49 GIT binary patch literal 12288 zcmeI#-AcnS6bJCM6J-TI?sj`_qz=TJy@1&kblA08tGKI?Egb~5R@y4_QoQp)d`?qw zV5ED2@eicQAs_Ae_3GT;1-eRUkryjjQIDN4$6=R5j4{{rmg$>T$9tQ=jLx6=wyDc5 zUOx}bs(bXsjy>~0g8&2|009U<00Izz00bZa0SIgrn7R9%p6|TrOr>kRo@RNa7kVx$ zooD4#D=TgdV!;zZqi`sms9`rnAz3HrOsnpD=^S)?-}yMLWYR zYiniRoQNwCQy3)_J_Nxzd2N-J^Flw@UrdiY9$a&KJzYt?Y+O;&6zD^fQ8F3}>&};= z`9zUQMg1rW1P`qPxAADq;|bk}$xqH+x30}i(T@fJ2tWV=5P$##AOHafKmY;|fWQt5 hcy(^5|9AKgBQ*#>00Izz00bZa0SG_<0uX=zW8bqBb4maJ literal 0 HcmV?d00001 From 5249b868dc1c515b777c3200b0babc72d6b2d60b Mon Sep 17 00:00:00 2001 From: CristhianMotoche Date: Wed, 2 Oct 2024 17:22:37 -0500 Subject: [PATCH 4/5] chore: Connect with App and get simple form --- .../flask-sqlalchemy-typing/app/main.py | 52 +++++++++++++++++- .../app/templates/root.html | 34 ++++++++++++ .../instance/project.db | Bin 12288 -> 12288 bytes 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 python/typing-models/flask-sqlalchemy-typing/app/templates/root.html diff --git a/python/typing-models/flask-sqlalchemy-typing/app/main.py b/python/typing-models/flask-sqlalchemy-typing/app/main.py index a28dd41..b2343fb 100644 --- a/python/typing-models/flask-sqlalchemy-typing/app/main.py +++ b/python/typing-models/flask-sqlalchemy-typing/app/main.py @@ -1,7 +1,8 @@ from datetime import datetime import sys +from typing import Optional, TypedDict -from flask import Flask +from flask import Flask, Response, jsonify, render_template, request from flask_sqlalchemy import SQLAlchemy @@ -23,6 +24,15 @@ class Base(DeclarativeBase): db.init_app(app) +class NotificationModel(TypedDict): + id: int + description: Optional[str] + email: str + date: datetime + url: Optional[str] + read: bool + + class Notification(db.Model): __tablename__ = "notifications" @@ -33,10 +43,48 @@ class Notification(db.Model): url: Mapped[str] read: Mapped[bool] = mapped_column(default=False) + def to_dict(self) -> NotificationModel: + return { + "id": self.id, + "description": self.description, + "email": self.email, + "date": self.date, + "url": self.url, + "read": self.read, + } + + +def get_all(): + return db.session.query(Notification).all() + + +def get_unread(): + return db.session.query(Notification).filter(Notification.read.is_(False)).all() + + +@app.route("/", methods=["GET"]) +def root(): + return render_template("root.html") + + +@app.route("/notifications", methods=["GET", "POST"]) +def notifications() -> Response: + if request.method == "POST": + new_notification = Notification( + **dict(request.form, date=datetime.fromisoformat(request.form["date"])) + ) + db.session.add(new_notification) + db.session.commit() + + notifications = get_all() + return jsonify([notification.to_dict() for notification in notifications]) + + if __name__ == "__main__": if len(sys.argv) > 1 and sys.argv[1] == 'db': print("Creating db...") with app.app_context(): db.create_all() + sys.exit(0) - app.run() + app.run(debug=True) diff --git a/python/typing-models/flask-sqlalchemy-typing/app/templates/root.html b/python/typing-models/flask-sqlalchemy-typing/app/templates/root.html new file mode 100644 index 0000000..787016c --- /dev/null +++ b/python/typing-models/flask-sqlalchemy-typing/app/templates/root.html @@ -0,0 +1,34 @@ + + + + + + Notification Form + + +

Notification Form

+
+ + +

+ + + +

+ + + +

+ + + +

+ + + +

+ + +
+ + diff --git a/python/typing-models/flask-sqlalchemy-typing/instance/project.db b/python/typing-models/flask-sqlalchemy-typing/instance/project.db index 97a32d86660fa2c182f1036f6336324ef2c3df49..310aa4d7091b3d62820a76dc50fa36ad5f62dc83 100644 GIT binary patch delta 127 zcmZojXh@hK&B#1a#+i|MW5N=CHb(w!4E)$q4|DjUaRY delta 43 qcmZojXh@hK&B!!S#+i|6W5N=CCI*4cf(ozsCkF7daWMb^oC^Q|ObYY> From 2cd02a7adafaf469ca3ae579f158877c6e1a86bf Mon Sep 17 00:00:00 2001 From: CristhianMotoche Date: Thu, 3 Oct 2024 12:03:22 -0500 Subject: [PATCH 5/5] chore: Install pyright --- python/typing-models/flask-sqlalchemy-typing/app/main.py | 4 ++++ python/typing-models/flask-sqlalchemy-typing/requirements.txt | 2 ++ 2 files changed, 6 insertions(+) diff --git a/python/typing-models/flask-sqlalchemy-typing/app/main.py b/python/typing-models/flask-sqlalchemy-typing/app/main.py index b2343fb..2e59a14 100644 --- a/python/typing-models/flask-sqlalchemy-typing/app/main.py +++ b/python/typing-models/flask-sqlalchemy-typing/app/main.py @@ -61,6 +61,10 @@ def get_all(): def get_unread(): return db.session.query(Notification).filter(Notification.read.is_(False)).all() +reveal_type(get_all) + +reveal_type(get_unread) + @app.route("/", methods=["GET"]) def root(): diff --git a/python/typing-models/flask-sqlalchemy-typing/requirements.txt b/python/typing-models/flask-sqlalchemy-typing/requirements.txt index aa30d58..f37be4b 100644 --- a/python/typing-models/flask-sqlalchemy-typing/requirements.txt +++ b/python/typing-models/flask-sqlalchemy-typing/requirements.txt @@ -5,6 +5,8 @@ Flask-SQLAlchemy==3.1.1 itsdangerous==2.2.0 Jinja2==3.1.4 MarkupSafe==2.1.5 +nodeenv==1.9.1 +pyright==1.1.383 SQLAlchemy==2.0.35 typing_extensions==4.12.2 Werkzeug==3.0.4