From 9758991ca542a81e85c38cb4741270440288c49a Mon Sep 17 00:00:00 2001 From: Jack Jackson Date: Tue, 23 Jan 2024 22:46:17 -0800 Subject: [PATCH] Add ruff (no automation yet) --- NOTES.md | 2 ++ README.md | 4 +++- app/__init__.py | 12 ++++++++---- app/main.py | 25 ++++++++++++++----------- app/models.py | 3 +++ requirements.txt | 1 + tests/conftest.py | 11 +++++++---- tests/test_fresh_db_tests.py | 11 +++++++---- 8 files changed, 45 insertions(+), 24 deletions(-) diff --git a/NOTES.md b/NOTES.md index bbbb26c..f50ee57 100644 --- a/NOTES.md +++ b/NOTES.md @@ -5,6 +5,8 @@ - [ ] Basic Deck Definition - [X] Figure out how to return JSON or html (`render_template`) - [X] Basic testing +- [ ] ruff +- [ ] GitHub Actions for tests and linters - [ ] Swagger API - [ ] Local development tool to clear/seed database ... diff --git a/README.md b/README.md index 928a3ab..8620427 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# edh-elo +[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) + +This is a score tracker for an EDH ("Commander") group. diff --git a/app/__init__.py b/app/__init__.py index a111afe..9adedbd 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -6,21 +6,25 @@ from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() + def create_app(): app = Flask(__name__) - secret_key = os.environ.get('SECRET_KEY') + secret_key = os.environ.get("SECRET_KEY") if not secret_key: - sys.stderr.write('YOU NEED TO SET AN ENV VARIABLE NAMED SECRET_KEY\n') + sys.stderr.write("YOU NEED TO SET AN ENV VARIABLE NAMED SECRET_KEY\n") sys.exit(1) - app.config['SECRET_KEY'] = secret_key + app.config["SECRET_KEY"] = secret_key # TODO - support other database types 🙃 - app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URI', 'sqlite:///db.sqlite') + app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get( + "DATABASE_URI", "sqlite:///db.sqlite" + ) db.init_app(app) from .main import main as main_blueprint + app.register_blueprint(main_blueprint) # TODO - understand how this works, since `db.create_all()` requires that the model classes have already been diff --git a/app/main.py b/app/main.py index 3536e6d..21c9374 100644 --- a/app/main.py +++ b/app/main.py @@ -4,39 +4,42 @@ from .models import Deck, Game, Player main = Blueprint("main", __name__) + @main.route("/") def index(): - return 'Hello, World - but new!' + return "Hello, World - but new!" + @main.route("/player", methods=["POST"]) def create_player(): data = request.json - player = Player( - name=data['name'] - ) + player = Player(name=data["name"]) db.session.add(player) db.session.commit() - return {'id': player.id} + return {"id": player.id} + @main.route("/player/") def get_player(player_id: str): player_from_db = db.session.get(Player, int(player_id)) if not player_from_db: - return 'Not Found', 404 + return "Not Found", 404 player_data = _jsonify(player_from_db) - content_type = request.headers.get('Content-Type') - if content_type == 'application/json': + content_type = request.headers.get("Content-Type") + if content_type == "application/json": return player_data - else: # Assume they want HTML - return render_template('player_detail.html', **player_data) + else: # Assume they want HTML + return render_template("player_detail.html", **player_data) + # TODO - implement a GET method - can it be a separate method, or must it be the same annotation with an `if method==`? # Time for testing, methinks! + # TODO - would this be better as a method on a class extending `db.Model` that the classes in `models.py` could then # extend? # (Probably not, as we'd still need to explicitly call it - it wouldn't be implicitly called _by_ Flask) def _jsonify(o): - return {k: v for (k, v) in o.__dict__.items() if k != '_sa_instance_state'} \ No newline at end of file + return {k: v for (k, v) in o.__dict__.items() if k != "_sa_instance_state"} diff --git a/app/models.py b/app/models.py index 80de9f4..1b3ecc6 100644 --- a/app/models.py +++ b/app/models.py @@ -1,5 +1,6 @@ from . import db + # Note that a `Player` is "someone who plays in the Pod", whereas `User` (which will be implemented later) is "a user of # this system". While all Users will _probably_ be Players, they do not have to be - and, it is likely that several # Players will not be Users (if they don't register to use the system). @@ -7,12 +8,14 @@ class Player(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, nullable=False) + class Deck(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(60), nullable=False) description = db.Column(db.String) owner = db.Column(db.String, db.ForeignKey(Player.__table__.c.id), nullable=False) + class Game(db.Model): id = db.Column(db.Integer, primary_key=True) # TODO - columns like `location`, `writeups`, etc. diff --git a/requirements.txt b/requirements.txt index e0858f3..dbccc87 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ Flask Flask-SQLAlchemy flasgger flask-login +ruff diff --git a/tests/conftest.py b/tests/conftest.py index 816cbdd..0066299 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,16 +9,17 @@ from app import create_app # https://flask.palletsprojects.com/en/2.3.x/testing/ + @pytest.fixture() def app_fixture(): # Start afresh! - test_database_name = 'testing-db.sqlite' - database_location = pathlib.Path('instance').joinpath(test_database_name) + test_database_name = "testing-db.sqlite" + database_location = pathlib.Path("instance").joinpath(test_database_name) if database_location.exists(): database_location.unlink() - os.environ['DATABASE_URI'] = f'sqlite:///{test_database_name}' - os.environ['SECRET_KEY'] = 'testing-secret-key' + os.environ["DATABASE_URI"] = f"sqlite:///{test_database_name}" + os.environ["SECRET_KEY"] = "testing-secret-key" app = create_app() # app.config.update({ @@ -31,10 +32,12 @@ def app_fixture(): # clean up / reset resources here + @pytest.fixture() def client(app_fixture): return app_fixture.test_client() + @pytest.fixture() def runner(app_fixture): return app_fixture.test_cli_runner() diff --git a/tests/test_fresh_db_tests.py b/tests/test_fresh_db_tests.py index c5f0822..837c985 100644 --- a/tests/test_fresh_db_tests.py +++ b/tests/test_fresh_db_tests.py @@ -1,10 +1,13 @@ # These tests expect that the database starts empty. # TODO: create tests with initialized states + def test_add_and_retrieve(client): - response = client.get('/player/1', headers={'Content-Type': 'application/json'}) + response = client.get("/player/1", headers={"Content-Type": "application/json"}) assert response.status_code == 404 - client.post('/player', headers={'Content-Type': 'application/json'}, json={'name': 'jason'}) - response_1 = client.get('/player/1', headers={'Content-Type': 'application/json'}) - assert response_1.json['name'] == 'jason' + client.post( + "/player", headers={"Content-Type": "application/json"}, json={"name": "jason"} + ) + response_1 = client.get("/player/1", headers={"Content-Type": "application/json"}) + assert response_1.json["name"] == "jason"