Skip to content

Commit dea56b3

Browse files
authored
Core: Upgrades to SQLAlchemy 2.0
TYPE: Feature LINK: OGC-2945
1 parent 8a1f72e commit dea56b3

File tree

364 files changed

+4754
-6441
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

364 files changed

+4754
-6441
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ repos:
1515
exclude: .pre-commit-config.yaml
1616
- id: pt_structure
1717
- repo: https://github.com/astral-sh/ruff-pre-commit
18-
rev: v0.15.0
18+
rev: v0.15.1
1919
hooks:
2020
- id: ruff-check
2121
args: [ "--fix" ]
@@ -27,15 +27,15 @@ repos:
2727
additional_dependencies:
2828
- flake8-type-checking>=3.0.0
2929
- repo: https://github.com/thibaudcolas/pre-commit-stylelint
30-
rev: v17.1.0
30+
rev: v17.3.0
3131
hooks:
3232
- id: stylelint
3333
files: '^src/.*\.scss'
3434
additional_dependencies:
3535
- stylelint@16.19.1
3636
- stylelint-config-standard-scss@15.0.0
3737
- repo: https://github.com/pre-commit/mirrors-eslint
38-
rev: v10.0.0-rc.2
38+
rev: v10.0.0
3939
hooks:
4040
- id: eslint
4141
files: '^src/.*\.jsx?$'

pyproject.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,7 @@ strict = true
5252
implicit_reexport = true
5353
warn_unreachable = true
5454
warn_return_any = false
55-
# FIXME: remove sqlalchemy when upgrading to SQlAlchemy 2.0
56-
untyped_calls_exclude = "sqlalchemy,pycurl,onegov.core.types,selenium.webdriver.chrome.webdriver"
57-
plugins = "sqlmypy"
55+
untyped_calls_exclude = "pycurl,selenium.webdriver.chrome.webdriver"
5856
mypy_path = "$MYPY_CONFIG_FILE_DIR/src:$MYPY_CONFIG_FILE_DIR/stubs"
5957

6058
[[tool.mypy.overrides]]

setup.cfg

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ install_requires =
9898
kerberos
9999
lazy-object-proxy
100100
ldap3
101-
libres>=0.10.2,<1
101+
libres>=1
102102
libsass
103103
lingua-language-detector
104104
lxml
@@ -156,7 +156,7 @@ install_requires =
156156
# so we don't end up locked into Python <3.14
157157
setuptools<80
158158
sortedcontainers
159-
sqlalchemy<2
159+
sqlalchemy>=2
160160
sqlalchemy-utils
161161
sqlparse
162162
stripe==12.5.1
@@ -208,7 +208,6 @@ mypy =
208208
onegov-cloud[test]
209209
pytest-xdist
210210
sortedcontainers-stubs
211-
sqlalchemy-stubs
212211
types-babel
213212
types-beautifulsoup4
214213
types-bleach
@@ -339,3 +338,7 @@ select = TC0,TC1
339338
per_file_ignores =
340339
*.pyi: TC
341340
tests/**.py: TC
341+
type_checking_sqlalchemy_enabled = true
342+
type_checking_sqlalchemy_mapped_dotted_names =
343+
onegov.core.orm.mixins.dict_property
344+
onegov.core.orm.mixins.content.dict_property

src/onegov/activity/collections/activity.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,8 @@ def query(self) -> Query[ActivityT]:
335335

336336
if self.filter.tags:
337337
query = query.filter(
338-
model_class._tags.has_any( # type:ignore[attr-defined]
339-
array(self.filter.tags))) # type:ignore[call-overload]
338+
model_class._tags.has_any(array(self.filter.tags))
339+
)
340340

341341
if self.filter.states:
342342
query = query.filter(
@@ -414,7 +414,7 @@ def query(self) -> Query[ActivityT]:
414414
filters_applied = True
415415
o = o.filter(or_(
416416
*(
417-
Occasion.age.overlaps( # type:ignore[attr-defined]
417+
Occasion.age.overlaps(
418418
func.int4range(min_age, max_age + 1))
419419
for min_age, max_age in self.filter.age_ranges
420420
)
@@ -434,19 +434,18 @@ def query(self) -> Query[ActivityT]:
434434

435435
if self.filter.dateranges:
436436
filters_applied = True
437-
o = o.filter(Occasion.active_days.op('&&')(array( # type:ignore
438-
tuple(
437+
o = o.filter(Occasion.active_days.op('&&')(array(
439438
dt.toordinal()
440439
for start, end in self.filter.dateranges
441440
for dt in sedate.dtrange(start, end)
442-
)))
441+
))
443442
)
444443

445444
if self.filter.weekdays:
446445
filters_applied = True
447446
o = o.filter(
448-
Occasion.weekdays.op('<@')(array( # type:ignore[call-overload]
449-
self.filter.weekdays)))
447+
Occasion.weekdays.op('<@')(array(self.filter.weekdays))
448+
)
450449

451450
if self.filter.available:
452451
filters_applied = True
@@ -515,7 +514,7 @@ def used_tags(self) -> set[str]:
515514
base = self.query_base().with_entities(
516515
func.skeys(self.model_class._tags).label('keys'))
517516

518-
query = select(func.array_agg(column('keys')))
517+
query = select(func.array_agg(column('keys'))) # type: ignore[var-annotated]
519518
query = query.select_from(base.subquery())
520519

521520
tags = self.session.execute(query.distinct()).scalar()
@@ -597,7 +596,7 @@ def available_weeks(
597596
if not period:
598597
return
599598

600-
weeknumbers = {n[:2] for n in self.session.execute(text("""
599+
weeknumbers_weeks = {n[:2] for n in self.session.execute(text("""
601600
SELECT DISTINCT
602601
EXTRACT(week FROM start::date),
603602
EXTRACT(week FROM "end"::date)
@@ -607,13 +606,13 @@ def available_weeks(
607606
WHERE period_id = :period_id
608607
"""), {'period_id': period.id})}
609608

610-
weeknumbers = {
609+
weeknumbers_weeks = {
611610
tuple(
612611
range(int(start), int(end) + 1)
613-
) for start, end in weeknumbers
612+
) for start, end in weeknumbers_weeks
614613
}
615614

616-
weeknumbers = {week for weeks in weeknumbers for week in weeks}
615+
weeknumbers = {week for weeks in weeknumbers_weeks for week in weeks}
617616

618617
weeks = sedate.weekrange(period.execution_start, period.execution_end)
619618

@@ -636,4 +635,4 @@ def available_ages(self) -> tuple[int, int] | None:
636635

637636
ages = self.session.execute(query).first()
638637

639-
return ages and ages or None
638+
return ages._tuple() if ages else None

src/onegov/activity/collections/booking.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def booking_count(
103103

104104
return self.count(
105105
usernames=(username, ),
106-
periods=periods.scalar_subquery(),
106+
periods=periods.scalar_subquery(), # type: ignore[arg-type]
107107
states=states
108108
)
109109

src/onegov/activity/collections/invoice.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def add( # type:ignore[override]
132132
optimistic: bool = False
133133
) -> BookingPeriodInvoice:
134134

135-
invoice = BookingPeriodInvoice( # type: ignore[misc]
135+
invoice = BookingPeriodInvoice(
136136
id=uuid4(),
137137
period_id=period_id or self.period_id,
138138
user_id=user_id or self.user_id)

src/onegov/activity/collections/volunteer.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
from datetime import date, datetime
1414
from onegov.activity.models import BookingPeriod, BookingPeriodMeta
1515
from onegov.activity.models.volunteer import VolunteerState
16-
from sqlalchemy.orm import Query, Session
16+
from sqlalchemy.engine import Result
17+
from sqlalchemy.orm import Session
1718
from uuid import UUID
1819
from typing import NamedTuple
1920
from typing import Self, TypeAlias
@@ -91,11 +92,11 @@ def model_class(self) -> type[Volunteer]:
9192
def period_id(self) -> UUID | None:
9293
return self.period and self.period.id or None
9394

94-
def report(self) -> Query[ReportRow]:
95+
def report(self) -> Result[ReportRow]:
9596
stmt = as_selectable_from_path(
9697
module_path('onegov.activity', 'queries/volunteer-report.sql'))
9798

98-
query = select(stmt.c).where(stmt.c.period_id == self.period_id)
99+
query = select(*stmt.c).where(stmt.c.period_id == self.period_id)
99100

100101
return self.session.execute(query)
101102

src/onegov/activity/iso20022.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
from __future__ import annotations
22

33
import re
4-
from math import isclose
5-
64
import stdnum.ch.esr as esr
75

86
from collections import defaultdict
@@ -108,10 +106,11 @@ def state(self) -> str:
108106
if self.duplicate:
109107
return 'duplicate'
110108

111-
if isclose(self.confidence, 1):
109+
if self.confidence == 1:
112110
return 'success'
113111

114-
if isclose(self.confidence, 0.5):
112+
# NOTE: This value is never calculated we set it exactly
113+
if self.confidence == 0.5: # noqa: RUF069
115114
return 'warning'
116115

117116
return 'unknown'
@@ -284,7 +283,7 @@ def items(period_id: UUID | None = None) -> Query[ActivityInvoiceItem]:
284283
username_by_ref = dict(q2.with_entities(
285284
InvoiceReference.reference,
286285
User.username
287-
))
286+
).tuples())
288287

289288
# Get the items matching the given period
290289
q3 = items(period_id=period_id).outerjoin(InvoiceReference).with_entities(

src/onegov/activity/matching/score.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def get_is_organiser_child(booking: Booking) -> bool:
188188
.filter(Activity.id.in_(
189189
session.query(Occasion.activity_id)
190190
.filter(Occasion.period_id == booking.period_id)
191-
.scalar_subquery() # type: ignore[attr-defined]
191+
.scalar_subquery()
192192
))
193193
}
194194

@@ -281,11 +281,9 @@ def get_group_score(booking: Booking) -> float:
281281
)
282282

283283
group_scores = {
284-
r.group_code:
285-
max(.5, .7 - 0.1 * (r.count - 2))
286-
+ unique_score_modifier(r.group_code)
287-
288-
for r in query
284+
group_code: max(.5, .7 - 0.1 * (count - 2))
285+
+ unique_score_modifier(group_code)
286+
for group_code, count in query
289287
}
290288

291289
return group_scores.get(booking.group_code, 0)

0 commit comments

Comments
 (0)