From 601c0fe21f7488eb9a473a90abde714c3afd1403 Mon Sep 17 00:00:00 2001 From: Facundo Batista Date: Sat, 22 Jun 2024 11:42:52 -0300 Subject: [PATCH 1/3] Run all the tests in a better way. --- .github/workflows/tests.yaml | 2 +- README.md | 15 +++++++--- kilink/backend.py | 4 +-- kilink/config.py | 1 + kilink/main.py | 6 ++-- requirements-dev.txt | 5 +++- test | 3 -- tests/test_infra.py | 54 ++++++++++++++++++++++++++++++++++++ 8 files changed, 76 insertions(+), 14 deletions(-) delete mode 100755 test create mode 100644 tests/test_infra.py diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 6b5a9f0..018aba4 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -14,7 +14,7 @@ jobs: strategy: matrix: os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04] - python-version: [3.9, "3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12"] runs-on: ${{ matrix.os }} steps: diff --git a/README.md b/README.md index 10d5d0f..974ba82 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Some awesome details: There is a Telegram bot! ------------------------ -Try it [here](https://t.me/linkode_bot). +Try it [here](https://t.me/linkode_bot). Note this bot has a project on its own, [check it!](https://gitlab.com/c0x6a/linkode-bot) @@ -78,6 +78,13 @@ docker build -t kilink . docker run -it -p 5000:5000 kilink ``` +To run the tests: in the virtualenv, do: + +``` +python -m pytest +``` + + How to Translate ---------------- @@ -175,8 +182,8 @@ cd linkode_app pip install -r requirements.txt ``` - -The WSGI configuration file is already in the project, ready to use; for develop + +The WSGI configuration file is already in the project, ready to use; for develop or debugging you can add to it: ``` @@ -190,7 +197,7 @@ application = EvalException(application) Create a virtual host configuration file in /etc/apache2/sites-enabled/ with the name that you want, in this case "linkode" - + `sudo vi /etc/apache2/sites-enabled/linkode` And paste this: diff --git a/kilink/backend.py b/kilink/backend.py index 25daf69..410cc72 100644 --- a/kilink/backend.py +++ b/kilink/backend.py @@ -42,7 +42,7 @@ class KilinkDataTooBigError(Exception): def _get_unique_id(): - """Returns a unique ID everytime it's called.""" + """Return a unique ID everytime it's called.""" arr = [] base = len(ALPHABET) num = uuid.uuid4().int @@ -93,7 +93,7 @@ def __repr__(self): def session_manager(orig_func): - """Decorator to wrap function with the session.""" + """Wrap function with the session.""" def new_func(self, *a, **k): """Wrappend function to manage DB session.""" diff --git a/kilink/config.py b/kilink/config.py index fd1a6c2..be4e07f 100644 --- a/kilink/config.py +++ b/kilink/config.py @@ -11,6 +11,7 @@ class Config(dict): It starts empty, and then the config can be set at any time. """ + def load_file(self, filename): """Set the configuration from a YAML file.""" with open(filename, "rt", encoding="utf8") as fh: diff --git a/kilink/main.py b/kilink/main.py index a84828b..f2b9c7b 100644 --- a/kilink/main.py +++ b/kilink/main.py @@ -29,7 +29,7 @@ @app.errorhandler(backend.KilinkNotFoundError) def handle_not_found_error(error): - """Return 404 on kilink not found""" + """Return 404 on kilink not found.""" msg = str(error) logger.debug(msg) return jsonify({'message': msg}), 404 @@ -37,7 +37,7 @@ def handle_not_found_error(error): @app.errorhandler(backend.KilinkDataTooBigError) def handle_content_data_too_big_error(error): - """Return 413 on content data too big""" + """Return 413 on content data too big.""" logger.debug(error.message) return jsonify({'message': error.message}), 413 @@ -124,7 +124,7 @@ def api_update(linkode_id): @app.route('/api/1/linkodes//', methods=['GET']) @app.route('/api/1/linkodes/', methods=['GET']) def api_get(linkode_id, revno=None): - """Get the kilink and revno content""" + """Get the kilink and revno content.""" logger.debug("API get; linkode_id=%r revno=%r", linkode_id, revno) if revno is not None: # the linkode_id to get the info from is the second token diff --git a/requirements-dev.txt b/requirements-dev.txt index cb64874..9657874 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,5 @@ -pytest +-r requirements.txt + flake8 +pydocstyle +pytest diff --git a/test b/test deleted file mode 100755 index 54af1f4..0000000 --- a/test +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -fades -r requirements.txt -r requirements-dev.txt -m pytest tests -fades -r requirements.txt -r requirements-dev.txt flake8 -x flake8 kilink diff --git a/tests/test_infra.py b/tests/test_infra.py new file mode 100644 index 0000000..b00d20a --- /dev/null +++ b/tests/test_infra.py @@ -0,0 +1,54 @@ +# Copyright 2024 Facundo Batista +# Licensed under the GPL v3 License +# For further info, check https://github.com/facundobatista/kilink + +"""Infrastructure tests.""" + +import os + +import pydocstyle +import pytest +from flake8.api.legacy import get_style_guide + + +def get_python_filepaths(roots): + """Retrieve paths of Python files.""" + python_paths = [] + for root in roots: + for dirpath, dirnames, filenames in os.walk(root): + for filename in filenames: + if filename.endswith(".py"): + python_paths.append(os.path.join(dirpath, filename)) + return python_paths + + +def test_pep8(capsys): + """Verify all files are nicely styled.""" + python_filepaths = get_python_filepaths(["kilink", "tests"]) + style_guide = get_style_guide() + report = style_guide.check_files(python_filepaths) + + # if flake8 didn't report anything, we're done + if report.total_errors == 0: + return + + # grab on which files we have issues + out, _ = capsys.readouterr() + pytest.fail(f"Please fix {report.total_errors} issue(s):\n{''.join(out)}", pytrace=False) + + +def test_pep257(): + """Verify all files have nice docstrings.""" + python_filepaths = get_python_filepaths(["kilink"]) + to_ignore = { + "D105", # Missing docstring in magic method + "D107", # Missing docstring in __init__ + } + to_include = pydocstyle.violations.conventions.pep257 - to_ignore + errors = list(pydocstyle.check(python_filepaths, select=to_include)) + + if errors: + report = ["Please fix files as suggested by pydocstyle ({:d} issues):".format(len(errors))] + report.extend(str(e) for e in errors) + msg = "\n".join(report) + pytest.fail(msg, pytrace=False) From 4d5c744cf13e1e3543da206f6d68377439dd647a Mon Sep 17 00:00:00 2001 From: Facundo Batista Date: Sat, 22 Jun 2024 11:58:49 -0300 Subject: [PATCH 2/3] Improvements after merge. --- .github/workflows/tests.yaml | 4 ++-- kilink/backend.py | 2 ++ kilink/config.py | 2 +- kilink/main.py | 1 - tests/test_api.py | 6 +----- tests/test_backend.py | 3 +-- 6 files changed, 7 insertions(+), 11 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 018aba4..5ff5041 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -2,9 +2,9 @@ name: Tests on: push: - branches: [ main ] + branches: [ master ] pull_request: - branches: [ main ] + branches: [ master ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: diff --git a/kilink/backend.py b/kilink/backend.py index 0ba4386..ef5669a 100644 --- a/kilink/backend.py +++ b/kilink/backend.py @@ -117,6 +117,7 @@ def __init__(self): @property def session(self): + """Return the cached or just built session.""" if self._session is None: db_engine = config[DB_ENGINE_INSTANCE_KEY] Base.metadata.create_all(db_engine) @@ -225,4 +226,5 @@ def build_tree(self, linkode_id): return root_node, len(nodes) + kilinkbackend = KilinkBackend() diff --git a/kilink/config.py b/kilink/config.py index aa8ae3c..8f849e7 100644 --- a/kilink/config.py +++ b/kilink/config.py @@ -28,7 +28,7 @@ def load_file(self, filename): self.update(cfg) def load_config(self, environment=PROD_ENVIRONMENT_VALUE): - + """Load the config.""" if environment == PROD_ENVIRONMENT_VALUE: self.load_file("/home/kilink/project/production/configs/production.yaml") db_engine = self._prod_database_engine() diff --git a/kilink/main.py b/kilink/main.py index c824890..abce678 100644 --- a/kilink/main.py +++ b/kilink/main.py @@ -8,7 +8,6 @@ from flask import Flask, jsonify, render_template, request, make_response from flask_cors import CORS from flask_babel import Babel -from sqlalchemy import create_engine from kilink import backend, loghelper from kilink.config import config, LANGUAGES diff --git a/tests/test_api.py b/tests/test_api.py index 137360a..4643a0e 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,6 +1,4 @@ -# encoding: utf8 - -# Copyright 2011-2017 Facundo Batista, Nicolás César +# Copyright 2011-2024 Facundo Batista, Nicolás César # All Rigths Reserved """API tests.""" @@ -10,8 +8,6 @@ from unittest import TestCase from unittest.mock import patch -from sqlalchemy import create_engine - from kilink import main, backend from kilink.config import config, UNITTESTING_ENVIRONMENT_VALUE diff --git a/tests/test_backend.py b/tests/test_backend.py index d6ece4c..e54983e 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -1,4 +1,4 @@ -# Copyright 2011-2021 Facundo Batista, Nicolás César +# Copyright 2011-2024 Facundo Batista, Nicolás César # All Rigths Reserved """Backend tests.""" @@ -9,7 +9,6 @@ from unittest import TestCase -from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from kilink.backend import ( From d3b090a659fb5fff3b2d9bdb5f3eae84de80c147 Mon Sep 17 00:00:00 2001 From: Facundo Batista Date: Sat, 22 Jun 2024 12:03:11 -0300 Subject: [PATCH 3/3] Upgraded yaml --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a177250..df3ec12 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,5 +2,5 @@ flask==2.0.2 flask-cors==3.0.10 flask-babel==2.0.0 sqlalchemy==1.4.26 -pyyaml==6.0 +pyyaml==6.0.1 werkzeug==2.0.3 # until we get flask updated