Skip to content

Commit

Permalink
Iron out type-checking and formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel-Therrien-Beslogic committed May 8, 2024
1 parent 3a67abb commit a7d19dd
Show file tree
Hide file tree
Showing 15 changed files with 452 additions and 288 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# You can run this locally with `pre-commit run [--all]`
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v4.6.0
hooks:
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
Expand All @@ -14,7 +14,7 @@ repos:
- id: check-case-conflict
# You can run this locally with `ruff format && ruff check`
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.4 # must match canopeum_backend/requirements-dev.txt
rev: v0.4.3 # must match canopeum_backend/requirements-dev.txt
hooks:
# Run the linter.
- id: ruff
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from django.db import connection
from django.utils import timezone

from canopeum_backend import settings
import canopeum_backend.settings
from canopeum_backend.models import (
Announcement,
Asset,
Expand Down Expand Up @@ -42,8 +42,8 @@ def create_posts_for_site(site):
# Create a post for the site
post = Post.objects.create(
site=site,
body=f"""{site.name} has planted {random.randint(100, 1000)} new trees today.
Let's continue to grow our forest!""", # noqa: S311
body=f"{site.name} has planted {random.randint(100, 1000)} new trees today." # noqa: S311
+ "Let's continue to grow our forest!",
share_count=share_count,
)
# Change created_at date since it is auto-generated on create
Expand Down Expand Up @@ -72,7 +72,12 @@ def handle(self, *args, **kwargs):
self.stdout.write("Erasing existing data...")
assets_to_delete = Asset.objects.all().exclude(asset="site_img.png")
for asset in assets_to_delete:
path = Path(settings.BASE_DIR) / "canopeum_backend" / "media" / asset.asset.name
path = (
Path(canopeum_backend.settings.BASE_DIR)
/ "canopeum_backend"
/ "media"
/ asset.asset.name
)
path.unlink(missing_ok=True)
call_command("flush", "--noinput")
cursor.execute("SET FOREIGN_KEY_CHECKS = 0;")
Expand Down Expand Up @@ -106,7 +111,9 @@ def handle(self, *args, **kwargs):
def create_fertilizer_types(self):
fertilizer_types = [["Synthetic", "Synthetique"], ["Innoculant", "Innoculant"]]
for _ in fertilizer_types:
Fertilizertype.objects.create(name=FertilizertypeInternationalization.objects.create(en=_[0], fr=_[1]))
Fertilizertype.objects.create(
name=FertilizertypeInternationalization.objects.create(en=_[0], fr=_[1])
)

def create_mulch_layer_types(self):
mulch_layer_types = [
Expand All @@ -118,7 +125,9 @@ def create_mulch_layer_types(self):
["Corn husk", "Feuille de maïs"],
]
for _ in mulch_layer_types:
Mulchlayertype.objects.create(name=MulchlayertypeInternationalization.objects.create(en=_[0], fr=_[1]))
Mulchlayertype.objects.create(
name=MulchlayertypeInternationalization.objects.create(en=_[0], fr=_[1])
)

def create_tree_types(self):
tree_types = [
Expand Down Expand Up @@ -222,7 +231,9 @@ def create_tree_types(self):
]

for _ in tree_types:
Treetype.objects.create(name=TreespeciestypeInternationalization.objects.create(en=_[0], fr=_[1]))
Treetype.objects.create(
name=TreespeciestypeInternationalization.objects.create(en=_[0], fr=_[1])
)

def create_site_types(self):
site_types = [
Expand All @@ -234,10 +245,14 @@ def create_site_types(self):
]

for _ in site_types:
Sitetype.objects.create(name=SitetypeInternationalization.objects.create(en=_[0], fr=_[1]))
Sitetype.objects.create(
name=SitetypeInternationalization.objects.create(en=_[0], fr=_[1])
)

def create_assets(self):
seeding_images_path = Path(settings.BASE_DIR) / "canopeum_backend" / "seeding" / "images"
seeding_images_path = (
Path(canopeum_backend.settings.BASE_DIR) / "canopeum_backend" / "seeding" / "images"
)
image_file_names = (
"site_img1.png",
"site_img2.jpg",
Expand All @@ -262,47 +277,49 @@ def create_users(self):
User.objects.create_user(
username="admin",
email="[email protected]",
password="Adminbeslogic!", # noqa: S106 MOCK_PASSWORD
password="Adminbeslogic!", # noqa: S106 # MOCK_PASSWORD
is_staff=True,
is_superuser=True,
role=Role.objects.get(name="MegaAdmin"),
)
User.objects.create_user(
username="TyrionLannister",
email="[email protected]",
password="tyrion123", # noqa: S106 MOCK_PASSWORD
password="tyrion123", # noqa: S106 # MOCK_PASSWORD
role=Role.objects.get(name="SiteManager"),
)
User.objects.create_user(
username="DaenerysTargaryen",
email="[email protected]",
password="daenerys123", # noqa: S106 MOCK_PASSWORD
password="daenerys123", # noqa: S106 # MOCK_PASSWORD
role=Role.objects.get(name="SiteManager"),
)
User.objects.create_user(
username="JonSnow",
email="[email protected]",
password="jon123", # noqa: S106 MOCK_PASSWORD
password="jon123", # noqa: S106 # MOCK_PASSWORD
role=Role.objects.get(name="SiteManager"),
)
User.objects.create_user(
username="OberynMartell",
email="[email protected]",
password="oberyn123", # noqa: S106 MOCK_PASSWORD
password="oberyn123", # noqa: S106 # MOCK_PASSWORD
role=Role.objects.get(name="SiteManager"),
)
User.objects.create_user(
username="NormalUser",
email="[email protected]",
password="normal123", # noqa: S106 MOCK_PASSWORD
password="normal123", # noqa: S106 # MOCK_PASSWORD
role=Role.objects.get(name="User"),
)

def create_canopeum_site(self):
site = Site.objects.create(
name="Canopeum",
is_public=True,
site_type=Sitetype.objects.get(name=SitetypeInternationalization.objects.get(en="Parks")),
site_type=Sitetype.objects.get(
name=SitetypeInternationalization.objects.get(en="Parks")
),
coordinate=Coordinate.objects.create(
dms_latitude="45°30'06.1\"N",
dms_longitude="73°34'02.3\"W",
Expand All @@ -322,8 +339,9 @@ def create_canopeum_site(self):
),
image=Asset.objects.first(),
announcement=Announcement.objects.create(
body="We currently have 20000 healthy seedlings of different species, ready to be planted at any time!"
+ "Please click the link below to book your favorite seedlings on our website",
body="We currently have 20000 healthy seedlings of different species, ready to "
+ "be planted at any time! Please click the link below to book your favorite "
+ "seedlings on our website",
link="https://www.canopeum-pos.com",
),
)
Expand All @@ -349,7 +367,7 @@ def create_canopeum_site(self):
name="First Batch",
site=site,
created_at=timezone.now(),
size=100,
size="100",
sponsor="Beslogic Inc.",
soil_condition="Good",
total_number_seed=100,
Expand All @@ -365,16 +383,18 @@ def create_other_sites(self):
site_2 = Site.objects.create(
name="Maple Grove Retreat",
is_public=True,
site_type=Sitetype.objects.get(name=SitetypeInternationalization.objects.get(en="Parks")),
site_type=Sitetype.objects.get(
name=SitetypeInternationalization.objects.get(en="Parks")
),
coordinate=Coordinate.objects.create(
dms_latitude="46°48'33.6\"N",
dms_longitude="71°18'40.0\"W",
dd_latitude=46.8093,
dd_longitude=-71.3111,
address="123 Forest Trail, Quebec City, QC G1P 3X4",
),
description="""Maple Grove Retreat is a serene escape nestled in the outskirts of Quebec City,
offering a lush forested area with scenic maple groves.""",
description="Maple Grove Retreat is a serene escape nestled in the outskirts of "
+ "Quebec City, offering a lush forested area with scenic maple groves.",
size="1500",
research_partnership=True,
visible_map=True,
Expand All @@ -386,11 +406,9 @@ def create_other_sites(self):
),
image=Asset.objects.get(asset__contains="site_img2"),
announcement=Announcement.objects.create(
body="""
Maple Grove Retreat is excited to announce our upcoming Maple Syrup Festival!
Join us on March 15th for a day of maple syrup tastings, nature hikes,
and family fun. Learn more on our website.
""",
body="Maple Grove Retreat is excited to announce our upcoming Maple Syrup "
+ "Festival! Join us on March 15th for a day of maple syrup tastings, "
+ "nature hikes, and family fun. Learn more on our website.",
link="https://www.maplegroveretreat.com/events/maple-syrup-festival",
),
)
Expand All @@ -399,16 +417,18 @@ def create_other_sites(self):
site_3 = Site.objects.create(
name="Lakeside Oasis",
is_public=True,
site_type=Sitetype.objects.get(name=SitetypeInternationalization.objects.get(en="Parks")),
site_type=Sitetype.objects.get(
name=SitetypeInternationalization.objects.get(en="Parks")
),
coordinate=Coordinate.objects.create(
dms_latitude="48°36'05.0\"N",
dms_longitude="71°18'27.0\"W",
dd_latitude=48.6014,
dd_longitude=-71.3075,
address="456 Lakeview Road, Lac-Saint-Jean, QC G8M 1R9",
),
description="""Lakeside Oasis offers a tranquil retreat by the shores of Lac-Saint-Jean,
with pristine waters and breathtaking sunsets.""",
description="Lakeside Oasis offers a tranquil retreat by the shores of "
+ "Lac-Saint-Jean, with pristine waters and breathtaking sunsets.",
size="800",
research_partnership=False,
visible_map=True,
Expand All @@ -420,8 +440,10 @@ def create_other_sites(self):
),
image=Asset.objects.get(asset__contains="site_img3"),
announcement=Announcement.objects.create(
body="""Escape to Lakeside Oasis! Our cozy cabins are now open for winter bookings. Enjoy ice fishing,
snowshoeing, and warm campfires by the lake. Book your stay today!""",
body="Escape to Lakeside Oasis! "
+ "Our cozy cabins are now open for winter bookings. "
+ "Enjoy ice fishing, snowshoeing, and warm campfires by the lake. "
+ "Book your stay today!",
link="https://www.lakesideoasis.com/winter-getaway",
),
)
Expand All @@ -430,16 +452,18 @@ def create_other_sites(self):
site_4 = Site.objects.create(
name="Evergreen Trail",
is_public=False,
site_type=Sitetype.objects.get(name=SitetypeInternationalization.objects.get(en="Parks")),
site_type=Sitetype.objects.get(
name=SitetypeInternationalization.objects.get(en="Parks")
),
coordinate=Coordinate.objects.create(
dms_latitude="46°12'30.0\"N",
dms_longitude="74°35'30.0\"W",
dd_latitude=46.2083,
dd_longitude=-74.5917,
address="789 Trailhead Way, Mont-Tremblant, QC J8E 1T7",
),
description="""Evergreen Trail invites you to explore the rugged beauty of Mont-Tremblant's wilderness,
with winding trails and majestic evergreen forests.""",
description="Evergreen Trail invites you to explore the rugged beauty of "
+ "Mont-Tremblant's wilderness, with winding trails and majestic evergreen forests.",
size="1200",
research_partnership=True,
visible_map=True,
Expand All @@ -451,10 +475,10 @@ def create_other_sites(self):
),
image=Asset.objects.get(asset__contains="site_img4"),
announcement=Announcement.objects.create(
body="""Discover the wonders of Evergreen Trail!
Our guided nature walks are now available every weekend.
Immerse yourself in nature and learn about the diverse
flora and fauna of Mont-Tremblant.""",
body="Discover the wonders of Evergreen Trail!"
+ "Our guided nature walks are now available every weekend."
+ "Immerse yourself in nature and learn about the diverse"
+ "flora and fauna of Mont-Tremblant.",
link="https://www.evergreentrail.com/guided-walks",
),
)
Expand Down
50 changes: 37 additions & 13 deletions canopeum_backend/canopeum_backend/models.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
from datetime import datetime, timedelta
from typing import ClassVar
from typing import TYPE_CHECKING, ClassVar

import pytz
from django.contrib.auth.models import AbstractUser
from django.db import models
from rest_framework.request import Request as drf_Request

# Pyright won't be able to infer all types here, see:
# https://github.com/typeddjango/django-stubs/issues/579
# https://github.com/typeddjango/django-stubs/issues/1264
# For now we have to rely on the mypy plugin


class RoleName(models.TextChoices):
USER = "User"
SITEMANAGER = "SiteManager"
MEGAADMIN = "MegaAdmin"

def from_string(self, value):
if value == self.MEGAADMIN:
return self.MEGAADMIN
if value == self.SITEMANAGER:
return self.SITEMANAGER
return self.USER
@classmethod
def from_string(cls, value: str):
try:
return cls(value)
except ValueError:
return cls.USER


class Role(models.Model):
Expand All @@ -34,8 +40,11 @@ class User(AbstractUser):
unique=True,
)
USERNAME_FIELD = "email"
REQUIRED_FIELDS: ClassVar[list[str]] = [] # type: ignore
role = models.ForeignKey(Role, models.RESTRICT, null=False, default=1) # type: ignore
REQUIRED_FIELDS: ClassVar[list[str]] = []
role = models.ForeignKey[Role, Role](Role, models.RESTRICT, null=False, default=1)
# Missing "id" in "Model" or some base "User" class?
if TYPE_CHECKING:
id: int


class Announcement(models.Model):
Expand Down Expand Up @@ -101,7 +110,9 @@ class Coordinate(models.Model):


class Fertilizertype(models.Model):
name = models.ForeignKey("FertilizertypeInternationalization", models.DO_NOTHING, blank=True, null=True)
name = models.ForeignKey(
"FertilizertypeInternationalization", models.DO_NOTHING, blank=True, null=True
)


class FertilizertypeInternationalization(models.Model):
Expand All @@ -110,7 +121,9 @@ class FertilizertypeInternationalization(models.Model):


class Mulchlayertype(models.Model):
name = models.ForeignKey("MulchlayertypeInternationalization", models.DO_NOTHING, blank=True, null=True)
name = models.ForeignKey(
"MulchlayertypeInternationalization", models.DO_NOTHING, blank=True, null=True
)


class MulchlayertypeInternationalization(models.Model):
Expand Down Expand Up @@ -195,7 +208,9 @@ class Sitetreespecies(models.Model):


class Sitetype(models.Model):
name = models.ForeignKey("SitetypeInternationalization", models.DO_NOTHING, blank=True, null=True)
name = models.ForeignKey(
"SitetypeInternationalization", models.DO_NOTHING, blank=True, null=True
)


class SitetypeInternationalization(models.Model):
Expand All @@ -209,7 +224,9 @@ class TreespeciestypeInternationalization(models.Model):


class Treetype(models.Model):
name = models.ForeignKey(TreespeciestypeInternationalization, models.DO_NOTHING, blank=True, null=True)
name = models.ForeignKey(
TreespeciestypeInternationalization, models.DO_NOTHING, blank=True, null=True
)


class Widget(models.Model):
Expand All @@ -226,3 +243,10 @@ class Like(models.Model):
class Internationalization(models.Model):
en = models.TextField(db_column="EN", blank=True, null=True)
fr = models.TextField(db_column="FR", blank=True, null=True)


class Request(drf_Request):
"""A custom Request type to use for parameter annotations."""

# Override with our own User model
user: User # pyright: ignore[reportIncompatibleMethodOverride]
Loading

0 comments on commit a7d19dd

Please sign in to comment.