Skip to content

Commit 3514139

Browse files
committed
refactor: normalize spacing
1 parent 3545801 commit 3514139

23 files changed

Lines changed: 85 additions & 81 deletions

AGENTS.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@
1919
- Reuse or extend existing schema modules before creating new top-level packages.
2020
- Follow existing async patterns with `AsyncSession`, explicit return types, and Pydantic schemas.
2121
- Use vertical spacing to separate logical steps inside functions. Keep related statements together, but add a blank line when moving between setup, validation, branching, and side effects.
22-
- Prefer readable spacing over dense blocks. Short guard clauses, temporary assignments, and context-manager branches should usually be visually separated the way `papyrus/services/email.py` is structured.
22+
- Prefer readable spacing over dense blocks. Short guard clauses, temporary assignments, and context-manager branches should usually be visually separated the way `papyrus/services/email.py` and `papyrus/services/auth/` are structured.
23+
- Treat any multiline statement or block as a visual boundary inside a function. If one adjacent statement is multiline and both sides are real code, separate the two statements with a blank line.
24+
- Apply that rule to multiline conditionals, loops, `with` blocks, `try` blocks, multiline calls, multiline literals, and multiline return values. Treat `if` / `elif` / `else` as one block.
25+
- Do not add a blank line just because a docstring appears above the first statement in a function. The multiline-block rule applies between code statements, not between a docstring and the first line of code.
26+
- Add a blank line between query execution and result extraction, especially around `session.execute(...)` and subsequent `scalar*()` reads.
27+
- Add a blank line before persistence and side-effect boundaries such as `session.add(...)`, `send_email(...)`, `commit()`, redirects, and returned result objects when they start a new phase of the function.
28+
- Keep tightly coupled short sequences together when they are clearly one step. Do not add spacing mechanically when it makes a two-line operation harder to read.
29+
- Prefer extra spacing around state transitions and persistence boundaries rather than packing setup, branching, and writes into a single block.
2330
- When adding a new router module, register it in `papyrus/api/routes/__init__.py`.
2431
- Avoid adding dependencies unless the user explicitly asks for them.
2532
- Keep changes scoped. Do not refactor unrelated areas as part of a focused fix.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ uv run alembic upgrade head
2525
Run the server:
2626

2727
```bash
28-
uv run uvicorn papyrus.main:app --reload
28+
uv run uvicorn papyrus.main:app --reload --port 8080
2929
```
3030

3131
Generate local PowerSync keys for auth testing:

papyrus/api/deps.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ async def get_current_auth_session(
6565
result = await db.execute(
6666
select(AuthSession).options(selectinload(AuthSession.user)).where(AuthSession.session_id == session_uuid)
6767
)
68+
6869
auth_session = result.scalar_one_or_none()
6970

7071
if auth_session is None or auth_session.user_id != user_uuid:

papyrus/api/routes/auth.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def _public_callback_url(request: Request, route_name: str) -> str:
5555

5656
route_parts = urlsplit(route_url)
5757
public_parts = urlsplit(public_base_url.rstrip("/"))
58+
5859
return urlunsplit(
5960
(
6061
public_parts.scheme,
@@ -110,6 +111,7 @@ async def google_oauth_start(
110111
redirect_uri=redirect_uri,
111112
callback_uri=_public_callback_url(request, "google_oauth_callback"),
112113
)
114+
113115
return RedirectResponse(url=authorization_url, status_code=status.HTTP_302_FOUND)
114116

115117

@@ -133,6 +135,7 @@ async def google_oauth_callback(
133135
state_token=state,
134136
error=error,
135137
)
138+
136139
return RedirectResponse(url=redirect_url, status_code=status.HTTP_302_FOUND)
137140

138141

@@ -215,6 +218,7 @@ async def start_google_link(
215218
redirect_uri=request.redirect_uri,
216219
callback_uri=_public_callback_url(http_request, "google_oauth_callback"),
217220
)
221+
218222
return AuthorizationUrlResponse(authorization_url=authorization_url)
219223

220224

papyrus/api/routes/books.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ async def batch_create_books(
193193
updated_at=datetime.now(UTC),
194194
)
195195
)
196+
196197
return BatchCreateResponse(created=created, errors=[])
197198

198199

papyrus/api/routes/goals.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
def _example_goal(goal_id: UUID | None = None) -> Goal:
2222
"""Create an example goal for responses."""
2323
today = date.today()
24+
2425
return Goal(
2526
goal_id=goal_id or uuid4(),
2627
title="Read 12 books this year",

papyrus/api/routes/series.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ async def get_series(
7777
) -> SeriesWithBooks:
7878
"""Return detailed information about a series with its books."""
7979
base = _example_series(series_id)
80+
8081
return SeriesWithBooks(
8182
series_id=base.series_id,
8283
name=base.name,

papyrus/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ def normalize_debug(cls, value: bool | str) -> bool:
6565

6666
if normalized in truthy:
6767
return True
68+
6869
if normalized in falsy:
6970
return False
7071

papyrus/core/security.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ def create_powersync_token(user_id: str, expires_delta: timedelta | None = None)
153153
def get_powersync_jwks() -> dict[str, list[dict[str, Any]]]:
154154
settings = get_settings()
155155
jwk = RSAAlgorithm.to_jwk(_get_powersync_public_key(), as_dict=True)
156+
156157
jwk.update(
157158
{
158159
"kid": settings.powersync_jwt_key_id,

papyrus/services/auth/_core.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,12 @@ async def _create_session_for_user(
6868
expires_at=_now() + timedelta(days=get_settings().refresh_token_expire_days),
6969
last_seen_at=_now(),
7070
)
71+
7172
session.add(auth_session)
7273
user.last_login_at = _now()
7374
await session.flush()
74-
7575
access_token = create_access_token({"sub": str(user.user_id), "sid": str(auth_session.session_id)})
76+
7677
return AuthResult(
7778
access_token=access_token,
7879
refresh_token=refresh_token,
@@ -102,6 +103,7 @@ async def _revoke_user_sessions(session: AsyncSession, user_id: UUID) -> None:
102103
result = await session.execute(
103104
select(AuthSession).where(AuthSession.user_id == user_id, AuthSession.revoked_at.is_(None))
104105
)
106+
105107
for auth_session in result.scalars():
106108
auth_session.revoked_at = _now()
107109

@@ -120,6 +122,7 @@ async def _create_exchange_code(
120122
avatar_url: str | None = None,
121123
) -> str:
122124
plain_code = generate_opaque_token()
125+
123126
session.add(
124127
AuthExchangeCode(
125128
code_hash=hash_opaque_token(plain_code),
@@ -135,6 +138,7 @@ async def _create_exchange_code(
135138
expires_at=_now() + timedelta(minutes=get_settings().auth_exchange_code_expire_minutes),
136139
)
137140
)
141+
138142
await session.flush()
139143
return plain_code
140144

@@ -164,6 +168,7 @@ async def _issue_email_action_token(
164168
expires_minutes: int,
165169
) -> str:
166170
plain_token = generate_opaque_token()
171+
167172
session.add(
168173
EmailActionToken(
169174
user_id=user_id,
@@ -172,6 +177,7 @@ async def _issue_email_action_token(
172177
expires_at=_now() + timedelta(minutes=expires_minutes),
173178
)
174179
)
180+
175181
await session.flush()
176182
return plain_token
177183

@@ -206,6 +212,7 @@ def _default_display_name(identity: GoogleIdentity | None = None, email: str | N
206212

207213
def _build_api_url(path: str) -> str | None:
208214
public_base_url = get_settings().public_base_url
215+
209216
if public_base_url is None:
210217
return None
211218

@@ -223,10 +230,12 @@ def _verification_email_body(token: str) -> str:
223230
]
224231

225232
if verify_url is not None:
226-
lines.extend([
227-
"",
228-
f"Submit this token to: {verify_url}",
229-
])
233+
lines.extend(
234+
[
235+
"",
236+
f"Submit this token to: {verify_url}",
237+
]
238+
)
230239

231240
return "\n".join(lines)
232241

@@ -240,9 +249,11 @@ def _password_reset_email_body(token: str) -> str:
240249
]
241250

242251
if reset_url is not None:
243-
lines.extend([
244-
"",
245-
f"Submit this token and your new password to: {reset_url}",
246-
])
252+
lines.extend(
253+
[
254+
"",
255+
f"Submit this token and your new password to: {reset_url}",
256+
]
257+
)
247258

248259
return "\n".join(lines)

0 commit comments

Comments
 (0)