Add ruff (no automation yet)
This commit is contained in:
parent
51d6a85955
commit
9758991ca5
2
NOTES.md
2
NOTES.md
@ -5,6 +5,8 @@
|
|||||||
- [ ] Basic Deck Definition
|
- [ ] Basic Deck Definition
|
||||||
- [X] Figure out how to return JSON or html (`render_template`)
|
- [X] Figure out how to return JSON or html (`render_template`)
|
||||||
- [X] Basic testing
|
- [X] Basic testing
|
||||||
|
- [ ] ruff
|
||||||
|
- [ ] GitHub Actions for tests and linters
|
||||||
- [ ] Swagger API
|
- [ ] Swagger API
|
||||||
- [ ] Local development tool to clear/seed database
|
- [ ] Local development tool to clear/seed database
|
||||||
...
|
...
|
||||||
|
@ -1 +1,3 @@
|
|||||||
# edh-elo
|
[](https://github.com/astral-sh/ruff)
|
||||||
|
|
||||||
|
This is a score tracker for an EDH ("Commander") group.
|
||||||
|
@ -6,21 +6,25 @@ from flask_sqlalchemy import SQLAlchemy
|
|||||||
|
|
||||||
db = SQLAlchemy()
|
db = SQLAlchemy()
|
||||||
|
|
||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
secret_key = os.environ.get('SECRET_KEY')
|
secret_key = os.environ.get("SECRET_KEY")
|
||||||
if not 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)
|
sys.exit(1)
|
||||||
app.config['SECRET_KEY'] = secret_key
|
app.config["SECRET_KEY"] = secret_key
|
||||||
|
|
||||||
# TODO - support other database types 🙃
|
# 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)
|
db.init_app(app)
|
||||||
|
|
||||||
from .main import main as main_blueprint
|
from .main import main as main_blueprint
|
||||||
|
|
||||||
app.register_blueprint(main_blueprint)
|
app.register_blueprint(main_blueprint)
|
||||||
|
|
||||||
# TODO - understand how this works, since `db.create_all()` requires that the model classes have already been
|
# TODO - understand how this works, since `db.create_all()` requires that the model classes have already been
|
||||||
|
23
app/main.py
23
app/main.py
@ -4,39 +4,42 @@ from .models import Deck, Game, Player
|
|||||||
|
|
||||||
main = Blueprint("main", __name__)
|
main = Blueprint("main", __name__)
|
||||||
|
|
||||||
|
|
||||||
@main.route("/")
|
@main.route("/")
|
||||||
def index():
|
def index():
|
||||||
return 'Hello, World - but new!'
|
return "Hello, World - but new!"
|
||||||
|
|
||||||
|
|
||||||
@main.route("/player", methods=["POST"])
|
@main.route("/player", methods=["POST"])
|
||||||
def create_player():
|
def create_player():
|
||||||
data = request.json
|
data = request.json
|
||||||
player = Player(
|
player = Player(name=data["name"])
|
||||||
name=data['name']
|
|
||||||
)
|
|
||||||
db.session.add(player)
|
db.session.add(player)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return {'id': player.id}
|
return {"id": player.id}
|
||||||
|
|
||||||
|
|
||||||
@main.route("/player/<player_id>")
|
@main.route("/player/<player_id>")
|
||||||
def get_player(player_id: str):
|
def get_player(player_id: str):
|
||||||
player_from_db = db.session.get(Player, int(player_id))
|
player_from_db = db.session.get(Player, int(player_id))
|
||||||
if not player_from_db:
|
if not player_from_db:
|
||||||
return 'Not Found', 404
|
return "Not Found", 404
|
||||||
|
|
||||||
player_data = _jsonify(player_from_db)
|
player_data = _jsonify(player_from_db)
|
||||||
|
|
||||||
content_type = request.headers.get('Content-Type')
|
content_type = request.headers.get("Content-Type")
|
||||||
if content_type == 'application/json':
|
if content_type == "application/json":
|
||||||
return player_data
|
return player_data
|
||||||
else: # Assume they want HTML
|
else: # Assume they want HTML
|
||||||
return render_template('player_detail.html', **player_data)
|
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==`?
|
# 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!
|
# 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
|
# TODO - would this be better as a method on a class extending `db.Model` that the classes in `models.py` could then
|
||||||
# extend?
|
# extend?
|
||||||
# (Probably not, as we'd still need to explicitly call it - it wouldn't be implicitly called _by_ Flask)
|
# (Probably not, as we'd still need to explicitly call it - it wouldn't be implicitly called _by_ Flask)
|
||||||
def _jsonify(o):
|
def _jsonify(o):
|
||||||
return {k: v for (k, v) in o.__dict__.items() if k != '_sa_instance_state'}
|
return {k: v for (k, v) in o.__dict__.items() if k != "_sa_instance_state"}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from . import db
|
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
|
# 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
|
# 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).
|
# 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)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
name = db.Column(db.String, nullable=False)
|
name = db.Column(db.String, nullable=False)
|
||||||
|
|
||||||
|
|
||||||
class Deck(db.Model):
|
class Deck(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
name = db.Column(db.String(60), nullable=False)
|
name = db.Column(db.String(60), nullable=False)
|
||||||
description = db.Column(db.String)
|
description = db.Column(db.String)
|
||||||
owner = db.Column(db.String, db.ForeignKey(Player.__table__.c.id), nullable=False)
|
owner = db.Column(db.String, db.ForeignKey(Player.__table__.c.id), nullable=False)
|
||||||
|
|
||||||
|
|
||||||
class Game(db.Model):
|
class Game(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
# TODO - columns like `location`, `writeups`, etc.
|
# TODO - columns like `location`, `writeups`, etc.
|
||||||
|
@ -2,3 +2,4 @@ Flask
|
|||||||
Flask-SQLAlchemy
|
Flask-SQLAlchemy
|
||||||
flasgger
|
flasgger
|
||||||
flask-login
|
flask-login
|
||||||
|
ruff
|
||||||
|
@ -9,16 +9,17 @@ from app import create_app
|
|||||||
|
|
||||||
# https://flask.palletsprojects.com/en/2.3.x/testing/
|
# https://flask.palletsprojects.com/en/2.3.x/testing/
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def app_fixture():
|
def app_fixture():
|
||||||
# Start afresh!
|
# Start afresh!
|
||||||
test_database_name = 'testing-db.sqlite'
|
test_database_name = "testing-db.sqlite"
|
||||||
database_location = pathlib.Path('instance').joinpath(test_database_name)
|
database_location = pathlib.Path("instance").joinpath(test_database_name)
|
||||||
if database_location.exists():
|
if database_location.exists():
|
||||||
database_location.unlink()
|
database_location.unlink()
|
||||||
|
|
||||||
os.environ['DATABASE_URI'] = f'sqlite:///{test_database_name}'
|
os.environ["DATABASE_URI"] = f"sqlite:///{test_database_name}"
|
||||||
os.environ['SECRET_KEY'] = 'testing-secret-key'
|
os.environ["SECRET_KEY"] = "testing-secret-key"
|
||||||
|
|
||||||
app = create_app()
|
app = create_app()
|
||||||
# app.config.update({
|
# app.config.update({
|
||||||
@ -31,10 +32,12 @@ def app_fixture():
|
|||||||
|
|
||||||
# clean up / reset resources here
|
# clean up / reset resources here
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def client(app_fixture):
|
def client(app_fixture):
|
||||||
return app_fixture.test_client()
|
return app_fixture.test_client()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def runner(app_fixture):
|
def runner(app_fixture):
|
||||||
return app_fixture.test_cli_runner()
|
return app_fixture.test_cli_runner()
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
# These tests expect that the database starts empty.
|
# These tests expect that the database starts empty.
|
||||||
# TODO: create tests with initialized states
|
# TODO: create tests with initialized states
|
||||||
|
|
||||||
|
|
||||||
def test_add_and_retrieve(client):
|
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
|
assert response.status_code == 404
|
||||||
|
|
||||||
client.post('/player', headers={'Content-Type': 'application/json'}, json={'name': 'jason'})
|
client.post(
|
||||||
response_1 = client.get('/player/1', headers={'Content-Type': 'application/json'})
|
"/player", headers={"Content-Type": "application/json"}, json={"name": "jason"}
|
||||||
assert response_1.json['name'] == 'jason'
|
)
|
||||||
|
response_1 = client.get("/player/1", headers={"Content-Type": "application/json"})
|
||||||
|
assert response_1.json["name"] == "jason"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user