Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set up basic repo structure #13

Merged
merged 10 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ share/python-wheels/
.installed.cfg
*.egg
MANIFEST
.python-version

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down
17 changes: 7 additions & 10 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "mirrors_qa_backend"
requires-python = ">=3.11,<3.13"
requires-python = ">=3.12,<3.13"
description = "mirrors-qa Backend API"
readme = "README.md"
authors = [
Expand All @@ -15,11 +15,13 @@ dependencies = [
"alembic == 1.13.1",
"fastapi[all] == 0.111.0",
"pydantic == 2.7.2",
"SQLAlchemy == 2.0.30",
"psycopg[binary,pool] == 3.1.19",
]
license = {text = "GPL-3.0-or-later"}
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
]

Expand Down Expand Up @@ -72,9 +74,6 @@ features = ["dev"]
[tool.hatch.envs.test]
features = ["scripts", "test"]

[[tool.hatch.envs.test.matrix]]
python = ["3.11", "3.12"]

[tool.hatch.envs.test.scripts]
run = "inv test --args '{args}'"
run-cov = "inv test-cov --args '{args}'"
Expand Down Expand Up @@ -104,10 +103,10 @@ all = "inv checkall --args '{args}'"

[tool.black]
line-length = 88
target-version = ['py310']
target-version = ['py312']

[tool.ruff]
target-version = "py311"
target-version = "py312"
line-length = 88
src = ["src"]

Expand Down Expand Up @@ -182,8 +181,6 @@ ignore = [
"S603",
# Ignore complexity
"C901", "PLR0911", "PLR0912", "PLR0913", "PLR0915",
# Allow use of typing.Optional, typing.List for type annotations
"UP007", "UP035", "UP006"
]
unfixable = [
# Don't touch unused imports
Expand Down Expand Up @@ -232,6 +229,6 @@ exclude_lines = [
include = ["src", "tests", "tasks.py"]
exclude = [".env/**", ".venv/**"]
extraPaths = ["src"]
pythonVersion = "3.11"
pythonVersion = "3.12"
typeCheckingMode="strict"
disableBytesTypePromotions = true
80 changes: 41 additions & 39 deletions backend/src/backend/db/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

from datetime import datetime
from ipaddress import IPv4Address
from typing import List, Optional
from uuid import UUID

from sqlalchemy import DateTime, Enum, ForeignKey, UniqueConstraint, text
Expand All @@ -23,10 +24,10 @@ class Base(MappedAsDataclass, DeclarativeBase):
# type has to be used.

type_annotation_map = { # noqa: RUF012
str: CITEXT, # transform Python str to PostgreSQL CITEXT
List[str]: ARRAY(
str: CITEXT, # use case-insensitive strings on PostgreSQL backend
list[str]: ARRAY(
item_type=CITEXT
), # transform Python List[str] into PostgreSQL Array of strings
), # transform Python list[str] into PostgreSQL Array of strings
datetime: DateTime(
timezone=False
), # transform Python datetime into PostgreSQL Datetime without timezone
Expand All @@ -50,16 +51,15 @@ class Base(MappedAsDataclass, DeclarativeBase):
class Country(Base):
__tablename__ = "country"

code: Mapped[str] = mapped_column(primary_key=True)
name: Mapped[str]
code: Mapped[str] = mapped_column(
primary_key=True
) # two-letter country codes as defined in ISO 3166-1

worker_id: Mapped[Optional[UUID]] = mapped_column(
ForeignKey("worker.id"), init=False
)
worker: Mapped[Optional["Worker"]] = relationship(
back_populates="countries", init=False
)
mirrors: Mapped[List["Mirror"]] = relationship(
name: Mapped[str] # full name of the country (in English)

worker_id: Mapped[UUID | None] = mapped_column(ForeignKey("worker.id"), init=False)
worker: Mapped[Worker | None] = relationship(back_populates="countries", init=False)
mirrors: Mapped[list[Mirror]] = relationship(
back_populates="country",
init=False,
cascade="all, delete-orphan",
Expand All @@ -71,37 +71,37 @@ class Country(Base):
class Mirror(Base):
__tablename__ = "mirror"

base_url: Mapped[str] = mapped_column(primary_key=True)
id: Mapped[str] = mapped_column(primary_key=True) # hostname of a mirror URL
base_url: Mapped[str]
enabled: Mapped[bool]
# metadata of a mirror from MirroBrain (https://mirrorbrain-docs.readthedocs.io/en/latest/mirrors.html#displaying-details-about-a-mirror)
id: Mapped[Optional[str]]
region: Mapped[Optional[str]]
asn: Mapped[Optional[str]]
score: Mapped[Optional[int]]
latitude: Mapped[Optional[float]]
longitude: Mapped[Optional[float]]
country_only: Mapped[Optional[bool]]
region_only: Mapped[Optional[bool]]
as_only: Mapped[Optional[bool]]
other_countries: Mapped[Optional[List[str]]]
region: Mapped[str | None]
asn: Mapped[str | None]
score: Mapped[int | None]
latitude: Mapped[float | None]
longitude: Mapped[float | None]
country_only: Mapped[bool | None]
region_only: Mapped[bool | None]
as_only: Mapped[bool | None]
other_countries: Mapped[list[str] | None]

country_code: Mapped[str] = mapped_column(
ForeignKey("country.code"),
init=False,
)
country: Mapped["Country"] = relationship(back_populates="mirrors", init=False)
country: Mapped[Country] = relationship(back_populates="mirrors", init=False)


class Worker(Base):
__tablename__ = "worker"
id: Mapped[UUID] = mapped_column(
elfkuzco marked this conversation as resolved.
Show resolved Hide resolved
init=False, primary_key=True, server_default=text("uuid_generate_v4()")
)
# RSA public key for generating access tokens needed to make request to
# the web server
elfkuzco marked this conversation as resolved.
Show resolved Hide resolved
auth_info: Mapped[str]
elfkuzco marked this conversation as resolved.
Show resolved Hide resolved
last_seen: Mapped[Optional[datetime]]
countries: Mapped[List["Country"]] = relationship(
back_populates="worker", init=False
)
last_seen_on: Mapped[datetime | None]
countries: Mapped[list[Country]] = relationship(back_populates="worker", init=False)


class Test(Base):
Expand All @@ -110,20 +110,22 @@ class Test(Base):
init=False, primary_key=True, server_default=text("uuid_generate_v4()")
)
requested_on: Mapped[datetime]
started_on: Mapped[Optional[datetime]]
status: Mapped[Optional[StatusEnum]] = mapped_column(
started_on: Mapped[datetime | None]
status: Mapped[StatusEnum | None] = mapped_column(
Enum(
native_enum=False,
validate_strings=True,
create_constraint=True,
name="status",
)
)
error: Mapped[Optional[str]]
ip_address: Mapped[Optional[IPv4Address]]
asn: Mapped[Optional[str]]
location: Mapped[Optional[str]]
latency: Mapped[Optional[int]] # milliseconds
download_size: Mapped[Optional[int]] # bytes
duration: Mapped[Optional[int]] # seconds
speed: Mapped[Optional[float]] # bytes per second
error: Mapped[str | None]
isp: Mapped[str | None]
ip_address: Mapped[IPv4Address | None]
asn: Mapped[str | None] # autonomous system based on IP
country: Mapped[str | None] # country based on IP
location: Mapped[str | None] # city based on IP
latency: Mapped[int | None] # milliseconds
download_size: Mapped[int | None] # bytes
duration: Mapped[int | None] # seconds
speed: Mapped[float | None] # bytes per second
9 changes: 4 additions & 5 deletions backend/src/backend/migrations/script.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ Revises: ${down_revision | comma,n}
Create Date: ${create_date}

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
${imports if imports else ""}

# revision identifiers, used by Alembic.
revision: str = ${repr(up_revision)}
down_revision: Union[str, None] = ${repr(down_revision)}
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}


def upgrade() -> None:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
"""set up database models

Revision ID: d45beab913d1
Revision ID: ef3115ef505c
Revises:
Create Date: 2024-06-03 07:46:35.661038
Create Date: 2024-06-03 15:53:20.253276

"""

from typing import Sequence, Union

import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = "d45beab913d1"
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
revision = "ef3115ef505c"
down_revision = None
branch_labels = None
depends_on = None


def upgrade() -> None:
Expand All @@ -37,8 +35,10 @@ def upgrade() -> None:
nullable=True,
),
sa.Column("error", postgresql.CITEXT(), nullable=True),
sa.Column("isp", postgresql.CITEXT(), nullable=True),
sa.Column("ip_address", postgresql.INET(), nullable=True),
sa.Column("asn", postgresql.CITEXT(), nullable=True),
sa.Column("country", postgresql.CITEXT(), nullable=True),
sa.Column("location", postgresql.CITEXT(), nullable=True),
sa.Column("latency", sa.Integer(), nullable=True),
sa.Column("download_size", sa.Integer(), nullable=True),
Expand All @@ -55,7 +55,7 @@ def upgrade() -> None:
nullable=False,
),
sa.Column("auth_info", postgresql.CITEXT(), nullable=False),
sa.Column("last_seen", sa.DateTime(), nullable=True),
sa.Column("last_seen_on", sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint("id", name=op.f("pk_worker")),
)
op.create_table(
Expand All @@ -71,9 +71,9 @@ def upgrade() -> None:
)
op.create_table(
"mirror",
sa.Column("id", postgresql.CITEXT(), nullable=False),
sa.Column("base_url", postgresql.CITEXT(), nullable=False),
sa.Column("enabled", sa.Boolean(), nullable=False),
sa.Column("id", postgresql.CITEXT(), nullable=True),
sa.Column("region", postgresql.CITEXT(), nullable=True),
sa.Column("asn", postgresql.CITEXT(), nullable=True),
sa.Column("score", sa.Integer(), nullable=True),
Expand All @@ -91,7 +91,7 @@ def upgrade() -> None:
["country.code"],
name=op.f("fk_mirror_country_code_country"),
),
sa.PrimaryKeyConstraint("base_url", name=op.f("pk_mirror")),
sa.PrimaryKeyConstraint("id", name=op.f("pk_mirror")),
)
# ### end Alembic commands ###

Expand Down
8 changes: 3 additions & 5 deletions worker/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "mirrors_qa_worker"
requires-python = ">=3.11,<3.13"
requires-python = ">=3.12,<3.13"
description = "mirrors-qa Worker"
readme = "README.md"
authors = [
Expand All @@ -17,7 +17,7 @@ dependencies = [
license = {text = "GPL-3.0-or-later"}
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
]

Expand Down Expand Up @@ -70,8 +70,6 @@ features = ["dev"]
[tool.hatch.envs.test]
features = ["scripts", "test"]

[[tool.hatch.envs.test.matrix]]
python = ["3.10", "3.11"]

[tool.hatch.envs.test.scripts]
run = "inv test --args '{args}'"
Expand Down Expand Up @@ -228,6 +226,6 @@ exclude_lines = [
include = ["src", "tests", "tasks.py"]
exclude = [".env/**", ".venv/**"]
extraPaths = ["src"]
pythonVersion = "3.11"
pythonVersion = "3.12"
typeCheckingMode="strict"
disableBytesTypePromotions = true
Loading