Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
308e4fc
Fix type issues and missing imports
Heliodex Sep 8, 2026
c911936
Remove unneeded type error ignore comments
Heliodex Sep 8, 2026
fc1b5a7
Remove more unnecessary type ignore comments
Heliodex Sep 8, 2026
047abb8
Improve GET request context parameter typing
Heliodex Sep 8, 2026
d55ee1b
Improved variable type hints
Heliodex Sep 8, 2026
313a31f
Remove always-true nested if statements
Heliodex Sep 8, 2026
6514132
Fix timezone time formatting
Heliodex Sep 8, 2026
9ac7de3
Correct venv configuration for Pyright
Heliodex Sep 8, 2026
dab0db9
Improved type hinting and parameters
Heliodex Sep 8, 2026
13e9f69
Assertions for ensuring user properties exist
Heliodex Sep 8, 2026
bee4703
Fix default Ari ship status checking
Heliodex Sep 8, 2026
9e117f4
Add `or` to prevent runtime type errors
Heliodex Sep 8, 2026
604eedc
Add type ignore directive comments for remaining type errors in both ty
Heliodex Sep 8, 2026
4e31ee1
Configuration for Pyrefly
Heliodex Sep 8, 2026
8f346ac
More variable type hinting
Heliodex Sep 8, 2026
d0472d0
Improve variable default values
Heliodex Sep 8, 2026
a3ca796
More assertions for structure checking
Heliodex Sep 8, 2026
6a639cd
More ignore comments for all type checkers
Heliodex Sep 8, 2026
9acba1a
Merge branch 'main' into heliodex/typing
Heliodex Sep 8, 2026
bd0046c
Merge pull request #6 from hackclub/heliodex/typing
Heliodex Sep 8, 2026
a302d6b
More Ruff formatting
Heliodex Sep 8, 2026
6868b92
Add more buttoms to the homepage footer
KavyanshKhaitan2 Sep 8, 2026
bc8715a
Import sorting
Heliodex Sep 8, 2026
e66032a
Merge branch 'main' of https://github.com/hackclub/twisted
Heliodex Sep 8, 2026
d2fb002
Remove unused imports
Heliodex Sep 8, 2026
e729c75
Add another link to the homepage 'Heliodex'
KavyanshKhaitan2 Sep 8, 2026
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
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,10 @@ dependencies = [

[tool.ruff.lint.per-file-ignores]
"*/migrations/*.py" = ["RUF012"]

[tool.pyright]
venvPath = "."
venv = ".venv"

[tool.pyrefly]
infer-with-first-use = false
1 change: 0 additions & 1 deletion twisted/common/admin.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@

# Register your models here.
1 change: 0 additions & 1 deletion twisted/common/models.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@

# Create your models here.
1 change: 0 additions & 1 deletion twisted/common/tests.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@

# Create your tests here.
6 changes: 3 additions & 3 deletions twisted/mysite/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,9 @@
ARI_SIGNING_SECRET = os.environ.get("ARI_SIGNING_SECRET")
# Separate from ARI_SIGNING_SECRET: signs deliveries Ari sends to us (Settings -> Webhooks),
# not requests we send to Ari.
ARI_WEBHOOK_SECRET = os.environ.get('ARI_WEBHOOK_SECRET')
ARI_WEBHOOK_SECRET = os.environ.get("ARI_WEBHOOK_SECRET")


# Slack
SLACK_TOKEN = os.environ.get('SLACK_TOKEN')
SLACK_LOG_CHANNEL = os.environ.get('SLACK_LOG_CHANNEL')
SLACK_TOKEN = os.environ.get("SLACK_TOKEN")
SLACK_LOG_CHANNEL = os.environ.get("SLACK_LOG_CHANNEL")
1 change: 0 additions & 1 deletion twisted/twisted_site/admin.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@

# Register your models here.
21 changes: 11 additions & 10 deletions twisted/twisted_site/ari.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import json
import time
from collections.abc import Iterable
from typing import Literal
from typing import Any, Literal

import requests
from django.conf import settings
Expand Down Expand Up @@ -83,13 +83,13 @@ def send_ship(ship: ProjectShip):

untracked_time = 0
if ship.project.project_type == "hardware":
for journal in ship.project.journals.filter(type="untracked"):
for journal in ship.project.journals.filter(type="untracked"): # pyrefly: ignore[missing-attribute]
untracked_time += journal.reduced_minutes

maker = {
"email": ship.project.user.email,
"name": ship.project.user.profile.slack_username,
"slack_id": ship.project.user.profile.slack_id,
"email": ship.project.user.email, # pyrefly: ignore[missing-attribute]
"name": ship.project.user.profile.slack_username, # pyrefly: ignore[missing-attribute]
"slack_id": ship.project.user.profile.slack_id, # pyrefly: ignore[missing-attribute]
"program_hours": untracked_time / 60,
}

Expand All @@ -112,9 +112,9 @@ def send_ship(ship: ProjectShip):
}

journals = []
orm_journals: Iterable[Journal] = ship.project.journals.all()
orm_journals: Iterable[Journal] = ship.project.journals.all() # pyrefly: ignore[missing-attribute]
for journal in orm_journals:
content = f"# Journal type: {journal.get_type_display()}\n\n{journal.content}"
content = f"# Journal type: {journal.get_type_display()}\n\n{journal.content}" # ty:ignore[unresolved-attribute] # pyright: ignore[reportAttributeAccessIssue]
journals.append(
{
"at": journal.created_at.isoformat(),
Expand Down Expand Up @@ -146,7 +146,7 @@ def send_ship(ship: ProjectShip):


def get_project_status(project: Project):
r = send_request("GET", endpoint=f"/status?external_id=twisted-{project.id}")
r = send_request("GET", endpoint=f"/status?external_id=twisted-{project.id}") # ty:ignore[unresolved-attribute] # pyright: ignore[reportAttributeAccessIssue]
_resp = r.content
r.raise_for_status()
return r.json()
Expand All @@ -163,14 +163,15 @@ def get_project_status(project: Project):
}


def ship_passes_from_status(status: dict | None) -> tuple[str, str]:
def ship_passes_from_status(status: dict[str, Any] | None) -> tuple[str, str]:
"""Maps an ARI /status response into (first_pass_status, second_pass_status),
using the PROJECT_SHIP_STATUSES vocabulary (pending/approved/rejected/requested_changes)."""
if not status:
return "pending", "pending"

phase = status.get("phase")
decision = _ARI_DECISION_TO_SHIP_STATUS.get(status.get("decision"), "pending")
raw_decision = status.get("decision", "pending")
decision = _ARI_DECISION_TO_SHIP_STATUS.get(raw_decision, "pending")

if phase == "second_pass":
return decision, "pending"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,34 @@


class Migration(migrations.Migration):

dependencies = [
('twisted_site', '0030_alter_journal_minutes_worked_and_more'),
("twisted_site", "0030_alter_journal_minutes_worked_and_more"),
]

operations = [
migrations.CreateModel(
name='ProfileStaffPermissions',
name="ProfileStaffPermissions",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('superuser', models.BooleanField(default=False)),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("superuser", models.BooleanField(default=False)),
],
),
migrations.AddField(
model_name='profile',
name='staff_permissions',
field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='twisted_site.profilestaffpermissions'),
model_name="profile",
name="staff_permissions",
field=models.OneToOneField(
default=None,
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="twisted_site.profilestaffpermissions",
),
),
]
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,54 @@


class Migration(migrations.Migration):

dependencies = [
('twisted_site', '0031_profilestaffpermissions_profile_staff_permissions'),
("twisted_site", "0031_profilestaffpermissions_profile_staff_permissions"),
]

operations = [
migrations.AddField(
model_name='profilestaffpermissions',
name='manage_announcements',
model_name="profilestaffpermissions",
name="manage_announcements",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='profilestaffpermissions',
name='manage_fulfillments',
model_name="profilestaffpermissions",
name="manage_fulfillments",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='profilestaffpermissions',
name='manage_pathways',
model_name="profilestaffpermissions",
name="manage_pathways",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='profilestaffpermissions',
name='manage_review',
model_name="profilestaffpermissions",
name="manage_review",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='profilestaffpermissions',
name='manage_shop',
model_name="profilestaffpermissions",
name="manage_shop",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='profilestaffpermissions',
name='view_auditlogs',
model_name="profilestaffpermissions",
name="view_auditlogs",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='profilestaffpermissions',
name='view_pathways',
model_name="profilestaffpermissions",
name="view_pathways",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='profilestaffpermissions',
name='view_review',
model_name="profilestaffpermissions",
name="view_review",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='profilestaffpermissions',
name='view_users',
model_name="profilestaffpermissions",
name="view_users",
field=models.BooleanField(default=False),
),
]
Loading
Loading