diff --git a/.gitignore b/.gitignore index 780eabf..a0cdabe 100644 --- a/.gitignore +++ b/.gitignore @@ -138,3 +138,4 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +.aider* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index eaf7f0d..4da70f2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,13 @@ repos: args: [--exit-non-zero-on-fix] - id: ruff-format - - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v3.0.3" + # - repo: https://github.com/pre-commit/mirrors-prettier + # rev: "v3.0.3" + # hooks: + # - id: prettier + + - repo: https://github.com/biomejs/pre-commit + rev: "v0.6.1" hooks: - - id: prettier + - id: biome-check + additional_dependencies: ["@biomejs/biome@1.4.1"] diff --git a/CONVENTIONS.md b/CONVENTIONS.md new file mode 100644 index 0000000..e69de29 diff --git a/app.py b/app.py index e19b240..4b0d5b6 100644 --- a/app.py +++ b/app.py @@ -1,8 +1,18 @@ +import os + +from dotenv import load_dotenv from flask import Flask app = Flask(__name__) -@app.route('/add//') + +@app.route("/") +def hello(): + """Returns a simple greeting.""" + return "hello world" + + +@app.route("/add//") def add(num1: int, num2: int) -> str: """Adds two numbers together. @@ -13,7 +23,8 @@ def add(num1: int, num2: int) -> str: Returns: The sum of the two numbers as a string. """ - return str(num1 + num2) + return str(int(num1) + int(num2)) + def fibonacci(n: int) -> int | str: """Calculates the nth Fibonacci number. @@ -36,7 +47,8 @@ def fibonacci(n: int) -> int | str: a, b = b, a + b return b -@app.route('/fibonacci/') + +@app.route("/fibonacci/") def get_fibonacci(n: int) -> str: """Gets the nth Fibonacci number via the fibonacci function. @@ -48,5 +60,7 @@ def get_fibonacci(n: int) -> str: """ return str(fibonacci(n)) -if __name__ == '__main__': - app.run(debug=True) + +if __name__ == "__main__": + load_dotenv() + app.run(debug=os.getenv("ENV") == "dev") diff --git a/pyproject.toml b/pyproject.toml index 085745f..db17f82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,10 @@ classifiers = [ "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Libraries :: Python Modules", ] +dependencies = [ + "flask>=3.1.0", + "python-dotenv>=1.0.1", +] [project.urls] Homepage = "https://lukemcguire.github.io/flask-test/" diff --git a/tests/test_app.py b/tests/test_app.py index 097d093..f14c36a 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,41 +1,75 @@ import pytest -from app import app + +from app import app, fibonacci + @pytest.fixture def client(): + """Creates a test client for the Flask application.""" + app.config["TESTING"] = True with app.test_client() as client: yield client -def test_add(client): - response = client.get('/add/2/3') - assert response.status_code == 200 - assert response.data == b'5' - response = client.get('/add/-1/1') +def test_hello(client): + """Tests the hello endpoint.""" + response = client.get("/") assert response.status_code == 200 - assert response.data == b'0' + assert response.data.decode("utf-8") == "hello world" + -def test_fibonacci(client): - response = client.get('/fibonacci/1') +def test_add(client): + """Tests the add endpoint with various inputs.""" + # Test positive numbers + response = client.get("/add/1/2") assert response.status_code == 200 - assert response.data == b'0' + assert response.data.decode("utf-8") == "3" - response = client.get('/fibonacci/2') + # Test zero + response = client.get("/add/0/0") assert response.status_code == 200 - assert response.data == b'1' + assert response.data.decode("utf-8") == "0" - response = client.get('/fibonacci/5') + # Test negative numbers + response = client.get("/add/%2D1/1") # Using URL-encoded minus sign assert response.status_code == 200 - assert response.data == b'3' + assert response.data.decode("utf-8") == "0" - response = client.get('/fibonacci/10') + # Additional negative number test cases + response = client.get("/add/%2D5/3") assert response.status_code == 200 - assert response.data == b'55' + assert response.data.decode("utf-8") == "-2" - response = client.get('/fibonacci/0') + +def test_fibonacci_function(): + """Tests the fibonacci function directly.""" + # Test invalid input + assert fibonacci(0) == "Invalid input" + assert fibonacci(-1) == "Invalid input" + + # Test base cases + assert fibonacci(1) == 0 + assert fibonacci(2) == 1 + + # Test other valid inputs + assert fibonacci(3) == 1 + assert fibonacci(4) == 2 + assert fibonacci(5) == 3 + assert fibonacci(6) == 5 + assert fibonacci(7) == 8 + + +def test_fibonacci_endpoint(client): + """Tests the fibonacci endpoint with various inputs.""" + # Test valid inputs + response = client.get("/fibonacci/1") assert response.status_code == 200 - assert response.data == b'Invalid input' + assert response.data.decode("utf-8") == "0" - response = client.get('/fibonacci/-1') + response = client.get("/fibonacci/7") assert response.status_code == 200 - assert response.data == b'Invalid input' + assert response.data.decode("utf-8") == "8" + + # Test invalid input type (will be caught by Flask's routing) + response = client.get("/fibonacci/invalid") + assert response.status_code == 404 diff --git a/uv.lock b/uv.lock index 28da898..325fee3 100644 --- a/uv.lock +++ b/uv.lock @@ -10,6 +10,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ed/20/bc79bc575ba2e2a7f70e8a1155618bb1301eaa5132a8271373a6903f73f8/babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b", size = 9587599 }, ] +[[package]] +name = "blinker" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458 }, +] + [[package]] name = "cachetools" version = "5.5.0" @@ -272,10 +281,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163 }, ] +[[package]] +name = "flask" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "blinker" }, + { name = "click" }, + { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, + { name = "itsdangerous" }, + { name = "jinja2" }, + { name = "werkzeug" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/89/50/dff6380f1c7f84135484e176e0cac8690af72fa90e932ad2a0a60e28c69b/flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac", size = 680824 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/47/93213ee66ef8fae3b93b3e29206f6b251e65c97bd91d8e1c5596ef15af0a/flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136", size = 102979 }, +] + [[package]] name = "flask-test" version = "0.0.1" source = { editable = "." } +dependencies = [ + { name = "flask" }, + { name = "python-dotenv" }, +] [package.dev-dependencies] dev = [ @@ -292,6 +322,10 @@ dev = [ ] [package.metadata] +requires-dist = [ + { name = "flask", specifier = ">=3.1.0" }, + { name = "python-dotenv", specifier = ">=1.0.1" }, +] [package.metadata.requires-dev] dev = [ @@ -370,6 +404,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, ] +[[package]] +name = "itsdangerous" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234 }, +] + [[package]] name = "jinja2" version = "3.1.5" @@ -796,6 +839,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, ] +[[package]] +name = "python-dotenv" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 }, +] + [[package]] name = "pyyaml" version = "6.0.2" @@ -1186,6 +1238,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067 }, ] +[[package]] +name = "werkzeug" +version = "3.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498 }, +] + [[package]] name = "zipp" version = "3.21.0"