diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..8332de349 --- /dev/null +++ b/.flake8 @@ -0,0 +1,3 @@ +[flake8] +max-line-length = 120 +extend-ignore = E203 diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index c2964fb9c..8f904d294 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -7,4 +7,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: psf/black@stable + - name: "Upgrade pip" + run: "pip install --upgrade pip" + - name: "Install package" + run: pip install ".[dev]" + - name: "Run lint checks" + run: invoke lint diff --git a/Dockerfile b/Dockerfile index 7d4ee9c8f..5d25ff74d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,10 @@ FROM python:3.11-bullseye WORKDIR /opt/meshdb -COPY requirements.txt . -RUN pip install -r requirements.txt + +COPY pyproject.toml . +RUN mkdir meshdb +RUN pip install . # FIXME: This probably isn't the file structure we want. COPY . . diff --git a/README.md b/README.md index 12cf3a5b3..97a85f57a 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,9 @@ python3 -m venv .venv source .venv/bin/activate ``` -Next, install the project dependencies +Next, install the project dependencies, including dev dependencies ```sh -pip install -r requirements.txt -pip install -r requirements-dev.txt +pip install -e ".[dev]" ``` Finally, run `pytest`: @@ -73,3 +72,23 @@ Then, in a separate window, or in your IDE, you can run the meshdb server Finally, open another window, and run the tests. `PYTHONPATH=. pytest .` + + +## Invoke.py Commands + +For convenience, this package uses [invoke](https://www.pyinvoke.org/) to wrap common +tasks into one-line commands. For example: + +```sh +invoke format +``` + +Will automatically apply `black` formatting and `isort` import sorting in a single command. + +You can also quickly peform all the relevant lint checks locally using +```sh +invoke lint +``` + +See `tasks.py` for a complete list of the tasks available. + diff --git a/meshdb/models/building.py b/meshdb/models/building.py index d9c65a93c..0abe63f03 100644 --- a/meshdb/models/building.py +++ b/meshdb/models/building.py @@ -22,9 +22,7 @@ class building(Base): id: Mapped[int] = mapped_column(primary_key=True) bin: Mapped[int] = mapped_column() - building_status: Mapped[BuildingStatusEnum] = mapped_column( - SQLAlchemyEnum(BuildingStatusEnum), nullable=False - ) + building_status: Mapped[BuildingStatusEnum] = mapped_column(SQLAlchemyEnum(BuildingStatusEnum), nullable=False) street_address: Mapped[str] = mapped_column(TEXT) city: Mapped[str] = mapped_column(String) state: Mapped[str] = mapped_column(String) diff --git a/meshdb/models/install.py b/meshdb/models/install.py index 84baa9c56..bbba260b1 100644 --- a/meshdb/models/install.py +++ b/meshdb/models/install.py @@ -22,8 +22,6 @@ class install(Base): id: Mapped[int] = mapped_column(primary_key=True) install_number: Mapped[int] = mapped_column() - install_status: Mapped[InstallStatusEnum] = mapped_column( - SQLAlchemyEnum(InstallStatusEnum), nullable=False - ) + install_status: Mapped[InstallStatusEnum] = mapped_column(SQLAlchemyEnum(InstallStatusEnum), nullable=False) building_id: Mapped[int] = mapped_column(ForeignKey("buildings.id")) member_id: Mapped[int] = mapped_column(ForeignKey("members.id")) diff --git a/meshdb/models/request.py b/meshdb/models/request.py index 3cac6b3a3..e3c645467 100644 --- a/meshdb/models/request.py +++ b/meshdb/models/request.py @@ -21,9 +21,7 @@ class request(Base): __tablename__ = "requests" id: Mapped[int] = mapped_column(primary_key=True) - request_status: Mapped[RequestStatusEnum] = mapped_column( - SQLAlchemyEnum(RequestStatusEnum), nullable=False - ) + request_status: Mapped[RequestStatusEnum] = mapped_column(SQLAlchemyEnum(RequestStatusEnum), nullable=False) ticket_id: Mapped[int] = mapped_column() member_id: Mapped[int] = mapped_column(ForeignKey("members.id"), nullable=True) building_id: Mapped[int] = mapped_column(ForeignKey("buildings.id"), nullable=True) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..ee718436d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,54 @@ +[project] +name = "nycmesh-meshdb" +version = "0.1" +dependencies = [ + "Flask==2.3.2", + "gunicorn==21.2.*", + "SQLAlchemy==2.0.20", + "SQLAlchemy_Utils==0.41.1", + "psycopg2-binary==2.9.*", + "python-dotenv==1.0.*", + "stringcase==1.2.*" +] + + +[project.optional-dependencies] +dev = [ + "invoke == 2.2.*", + "pytest == 7.4.*", + "flake8 == 6.1.*", + "black == 23.7.*", + "isort == 5.12.*", + "mypy == 1.5.*" +] + + +[build-system] +requires = [ "setuptools >= 61", "wheel", "mypy" ] +build-backend = "setuptools.build_meta" + +[tool.setuptools] +packages = [ "meshdb" ] + + +[tool.mypy] +check_untyped_defs = true +show_error_codes = true +pretty = true +ignore_missing_imports = true +disallow_untyped_calls = true +disallow_untyped_defs = true +disallow_incomplete_defs = true +warn_unused_configs = true + + +[tool.black] +line-length = 120 +include = '\.pyi?$' + + +[tool.isort] +profile = "black" +line_length = 120 +known_first_party = [ "meshdb" ] + diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 55b033e90..000000000 --- a/requirements-dev.txt +++ /dev/null @@ -1 +0,0 @@ -pytest \ No newline at end of file diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index f298cf63d..000000000 --- a/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -Flask==2.3.2 -gunicorn -SQLAlchemy==2.0.20 -SQLAlchemy_Utils==0.41.1 -psycopg2-binary -python-dotenv -stringcase diff --git a/tasks.py b/tasks.py new file mode 100644 index 000000000..e5f954da8 --- /dev/null +++ b/tasks.py @@ -0,0 +1,20 @@ +from invoke import task + + +@task +def format(context): + context.run("black .") + # context.run("isort .") + + +@task +def lint(context): + context.run("black . --check") + # context.run("isort . --check") + # context.run("flake8 meshdb tests unit_tests") + # context.run("mypy meshdb") + + +@task +def unit_test(context): + context.run("pytest unit_tests/")