Skip to content

Commit 9979646

Browse files
authored
requirements: Upgrade fastapi and asyncpg
1 parent 49c357f commit 9979646

File tree

7 files changed

+39
-35
lines changed

7 files changed

+39
-35
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ $ source ./env/bin/activate
1111
$ pip install -r requirements.txt
1212
```
1313

14+
**NOTE:** Python 3.12 is not yet supported.
15+
1416
## Setup
1517

1618
```

app/models.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ async def stats(db, query):
127127
]
128128
)
129129

130-
select = sqlalchemy.select(measurements_stats)
130+
select = sqlalchemy.select(*measurements_stats)
131131
select = select.group_by(
132132
measurements.c.sensor,
133133
measurements.c.source,
@@ -166,8 +166,9 @@ async def create_new_key(db: Database, provider: str) -> str:
166166
@staticmethod
167167
async def get_providers(db: Database) -> List[Tuple[str, int]]:
168168
query = sqlalchemy.select(
169-
[providers.c.provider, sqlalchemy.func.count(providers.c.provider)]
170-
).group_by(providers.c.provider)
169+
providers.c.provider, sqlalchemy.func.count(providers.c.provider)
170+
)
171+
query = query.group_by(providers.c.provider)
171172
query = query.order_by(sqlalchemy.asc(providers.c.provider))
172173
return await db.fetch_all(query)
173174

@@ -187,14 +188,14 @@ async def revoke_all_keys(db: Database, provider: str) -> bool:
187188

188189
@staticmethod
189190
async def get_all_keys(db: Database) -> Set[str]:
190-
query = sqlalchemy.select([providers.c.api_key_hash])
191+
query = sqlalchemy.select(providers.c.api_key_hash)
191192
query = query.order_by(sqlalchemy.asc(providers.c.provider))
192193
keys = await db.fetch_all(query)
193194
return {k[0] for k in keys}
194195

195196
@staticmethod
196197
async def get_provider_for_key(db: Database, api_key_hash: str) -> Union[str, None]:
197-
query = sqlalchemy.select([providers.c.id, providers.c.api_key_hash])
198+
query = sqlalchemy.select(providers.c.id, providers.c.api_key_hash)
198199
query = query.where(providers.c.api_key_hash == api_key_hash)
199200
provider = await db.fetch_one(query)
200201
return provider[0] if provider else None

app/reports.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,11 @@ def get_quality(source):
7171
breakpoint_index = CONCENTRATIONS.index(concentration)
7272
breakpoint = BREAKPOINTS[breakpoint_index]
7373

74-
index = (
75-
(breakpoint[1] - breakpoint[0]) / (concentration[1] - concentration[0])
76-
) * (source.pm2dot5_average - concentration[0]) + breakpoint[0]
74+
index = int(
75+
((breakpoint[1] - breakpoint[0]) / (concentration[1] - concentration[0]))
76+
* (source.pm2dot5_average - concentration[0])
77+
+ breakpoint[0]
78+
)
7779
index_breakpoint = next(
7880
(b for b in BREAKPOINTS if index <= b[1]),
7981
BREAKPOINTS[-1],

app/schemas.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -124,37 +124,37 @@ def to_orm(self, provider):
124124
return _dict
125125

126126
class Config:
127-
orm_mode = True
127+
from_attributes = True
128128

129129

130130
@dataclass
131131
class QueryParams:
132-
source: str = Query(
132+
source: Optional[str] = Query(
133133
None,
134134
title="Source",
135135
description="Include measurements from this source only",
136136
)
137-
start: datetime = Query(
137+
start: Optional[datetime] = Query(
138138
None,
139139
title="Start",
140140
description="Include measurements after this date and time",
141141
)
142-
end: datetime = Query(
142+
end: Optional[datetime] = Query(
143143
None,
144144
title="End",
145145
description="Include measurements before this date and time",
146146
)
147-
longitude: float = Query(
147+
longitude: Optional[float] = Query(
148148
None,
149149
title="Longitude",
150150
description="Target longitude coordinate",
151151
)
152-
latitude: float = Query(
152+
latitude: Optional[float] = Query(
153153
None,
154154
title="Latitude",
155155
description="Target latitude coordinate",
156156
)
157-
distance: float = Query(
157+
distance: Optional[float] = Query(
158158
None,
159159
title="Distance",
160160
description="Include measurements that are this kilometers far from the target",
@@ -174,7 +174,7 @@ class Provider(BaseModel):
174174
)
175175

176176
class Config:
177-
orm_mode = True
177+
from_attributes = True
178178

179179

180180
class APIKey(BaseModel):
@@ -233,7 +233,7 @@ class Report(BaseModel):
233233
title="Latitude",
234234
description="Target latitude coordinate",
235235
)
236-
quality: Quality = Field(
236+
quality: Optional[Quality] = Field(
237237
None,
238238
title="Quality",
239239
description="Quality according to AQI",

app/service.py

+9-11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# You should have received a copy of the GNU Affero General Public License
1414
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1515

16+
from contextlib import asynccontextmanager
1617
from fastapi import FastAPI, Depends
1718
from fastapi.middleware.cors import CORSMiddleware
1819
from fastapi.security.api_key import APIKey
@@ -25,7 +26,14 @@
2526
from .authentication import validate_api_key, validate_master_key
2627

2728

28-
app = FastAPI()
29+
@asynccontextmanager
30+
async def lifespan(app: FastAPI):
31+
await db.connect()
32+
yield
33+
await db.disconnect()
34+
35+
36+
app = FastAPI(lifespan=lifespan)
2937
app.add_middleware(
3038
CORSMiddleware,
3139
allow_origins=["*"],
@@ -35,16 +43,6 @@
3543
)
3644

3745

38-
@app.on_event("startup")
39-
async def startup():
40-
await db.connect()
41-
42-
43-
@app.on_event("shutdown")
44-
async def shutdown():
45-
await db.disconnect()
46-
47-
4846
@app.post("/api/v1/providers", response_model=schemas.APIKey)
4947
async def create_provider(
5048
provider: schemas.Provider, key: APIKey = Depends(validate_master_key)

requirements.txt

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
fastapi==0.94.1
1+
fastapi==0.114.1
22
httpx==0.23.3
33
uvicorn==0.21.0
44
gunicorn==20.1.0
@@ -9,8 +9,9 @@ black==23.1.0
99
aiosqlite==0.18.0
1010
databases==0.7.0
1111
SQLAlchemy==1.4.46
12-
asyncpg==0.27.0
13-
psycopg2-binary==2.9.5
12+
asyncpg==0.29.0
13+
psycopg2-binary==2.9.9
1414
alembic==1.10.2
1515
geopy==2.3.0
16-
pytest-dependency==0.5.1
16+
pytest-dependency==0.5.1
17+
pydantic==2.9.1

tests/service.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"co2": 1000.0,
4444
"longitude": -57.521369,
4545
"latitude": -25.194156,
46-
"recorded": "2020-10-24T20:47:57.370721+00:00",
46+
"recorded": "2020-10-24T20:47:57.370721Z",
4747
},
4848
{
4949
"sensor": "nullable",
@@ -59,7 +59,7 @@
5959
"co2": None,
6060
"longitude": -57.521369,
6161
"latitude": -25.194156,
62-
"recorded": "2020-10-24T20:47:57.370721+00:00",
62+
"recorded": "2020-10-24T20:47:57.370721Z",
6363
},
6464
{
6565
"sensor": "test",
@@ -75,7 +75,7 @@
7575
"co2": 200.0,
7676
"longitude": -57.521369,
7777
"latitude": -25.194156,
78-
"recorded": "2020-10-24T20:47:57.370721+00:00",
78+
"recorded": "2020-10-24T20:47:57.370721Z",
7979
},
8080
]
8181
aqi = [

0 commit comments

Comments
 (0)