auto-rest-api 0.1.5__py3-none-any.whl → 0.1.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
auto_rest/app.py CHANGED
@@ -44,9 +44,12 @@ async def logging_middleware(request: Request, call_next: callable) -> Response:
44
44
  "ip": request.client.host,
45
45
  "port": request.client.port,
46
46
  "method": request.method,
47
- "endpoint": f"{request.url.path}?{request.url.query}",
47
+ "endpoint": request.url.path,
48
48
  }
49
49
 
50
+ if request.url.query:
51
+ request_meta["endpoint"] += "?" + request.url.query
52
+
50
53
  # Execute handling logic
51
54
  try:
52
55
  response = await call_next(request)
auto_rest/cli.py CHANGED
@@ -35,7 +35,7 @@ import logging.config
35
35
  from argparse import ArgumentParser, HelpFormatter
36
36
  from pathlib import Path
37
37
 
38
- __all__ = ["configure_cli_logging", "create_cli_parser"]
38
+ __all__ = ["configure_cli_logging", "create_cli_parser", "VERSION"]
39
39
 
40
40
  VERSION = importlib.metadata.version("auto-rest-api")
41
41
 
auto_rest/handlers.py CHANGED
@@ -188,21 +188,42 @@ def create_list_records_handler(engine: DBEngine, table: Table) -> Callable[...,
188
188
  """
189
189
 
190
190
  interface = create_interface(table)
191
- columns = tuple(table.columns.keys())
191
+ interface_opt = create_interface(table, mode="optional")
192
+ col_names = tuple(table.columns.keys())
192
193
 
193
194
  async def list_records_handler(
194
195
  response: Response,
195
196
  session: DBSession = Depends(create_session_iterator(engine)),
197
+ filters: interface_opt = Depends(),
196
198
  _limit_: int = Query(0, ge=0, description="The maximum number of records to return."),
197
199
  _offset_: int = Query(0, ge=0, description="The starting index of the returned records."),
198
- _order_by_: Optional[Literal[*columns]] = Query(None, description="The field name to sort by."),
199
- _direction_: Literal["asc", "desc"] = Query("asc", description="Sort results in 'asc' or 'desc' order.")
200
+ _order_by_: Optional[Literal[*col_names]] = Query(None, description="The field name to sort by."),
201
+ _direction_: Literal["asc", "desc"] = Query("asc", description="Sort results in 'asc' or 'desc' order."),
200
202
  ) -> list[interface]:
201
203
  """Fetch a list of records from the database.
202
204
 
203
205
  URL query parameters are used to enable filtering, ordering, and paginating returned values.
204
206
  """
205
207
 
208
+ query = select(table)
209
+
210
+ # Fetch data per the request parameters
211
+ for param, value in filters:
212
+ if value is not None:
213
+ column = getattr(table.c, param)
214
+ if value.lower() == "_null_":
215
+ query = query.filter(column.is_(None))
216
+
217
+ else:
218
+ query = query.filter(column.ilike(f"%{value}%"))
219
+
220
+ if _limit_ > 0:
221
+ query = query.offset(_offset_).limit(_limit_)
222
+
223
+ if _order_by_ is not None:
224
+ direction = {'desc': desc, 'asc': asc}[_direction_]
225
+ query = query.order_by(direction(_order_by_))
226
+
206
227
  # Determine total record count
207
228
  total_count_query = select(func.count()).select_from(table)
208
229
  total_count = await execute_session_query(session, total_count_query)
@@ -214,17 +235,8 @@ def create_list_records_handler(engine: DBEngine, table: Table) -> Callable[...,
214
235
  response.headers["x-order-by"] = str(_order_by_)
215
236
  response.headers["x-order-direction"] = str(_direction_)
216
237
 
217
- # Fetch data per the request parameters
218
- query = select(table)
219
- if _limit_ > 0:
220
- query = query.offset(_offset_).limit(_limit_)
221
-
222
- if _order_by_ is not None:
223
- direction = {'desc': desc, 'asc': asc}[_direction_]
224
- query = query.order_by(direction(_order_by_))
225
-
226
- result = await execute_session_query(session, query)
227
- return [row._mapping for row in result.all()]
238
+ # noinspection PyTypeChecker
239
+ return await execute_session_query(session, query)
228
240
 
229
241
  return list_records_handler
230
242
 
@@ -257,7 +269,7 @@ def create_get_record_handler(engine: DBEngine, table: Table) -> Callable[..., A
257
269
  return get_record_handler
258
270
 
259
271
 
260
- def create_post_record_handler(engine: DBEngine, table: Table) -> Callable[..., Awaitable[PydanticModel]]:
272
+ def create_post_record_handler(engine: DBEngine, table: Table) -> Callable[..., Awaitable[None]]:
261
273
  """Create a function for handling POST requests against a record in the database.
262
274
 
263
275
  Args:
@@ -276,7 +288,7 @@ def create_post_record_handler(engine: DBEngine, table: Table) -> Callable[...,
276
288
  ) -> None:
277
289
  """Create a new record in the database."""
278
290
 
279
- query = insert(table).values(**data.dict())
291
+ query = insert(table).values(**data.model_dump())
280
292
  await execute_session_query(session, query)
281
293
  await commit_session(session)
282
294
 
auto_rest/models.py CHANGED
@@ -32,7 +32,7 @@ connection and session handling are configured accordingly.
32
32
  import asyncio
33
33
  import logging
34
34
  from pathlib import Path
35
- from typing import Callable
35
+ from typing import AsyncGenerator, Callable, Generator
36
36
 
37
37
  import yaml
38
38
  from sqlalchemy import create_engine, Engine, MetaData, URL
@@ -169,7 +169,7 @@ def create_db_metadata(engine: DBEngine) -> MetaData:
169
169
  return metadata
170
170
 
171
171
 
172
- def create_session_iterator(engine: DBEngine) -> Callable[[], DBSession]:
172
+ def create_session_iterator(engine: DBEngine) -> Callable[[], Generator[Session, None, None] | AsyncGenerator[AsyncSession, None]]:
173
173
  """Create a generator for database sessions.
174
174
 
175
175
  Returns a synchronous or asynchronous function depending on whether
@@ -185,12 +185,12 @@ def create_session_iterator(engine: DBEngine) -> Callable[[], DBSession]:
185
185
  """
186
186
 
187
187
  if isinstance(engine, AsyncEngine):
188
- async def session_iterator() -> AsyncSession:
188
+ async def session_iterator() -> AsyncGenerator[AsyncSession, None]:
189
189
  async with AsyncSession(bind=engine, autocommit=False, autoflush=True) as session:
190
190
  yield session
191
191
 
192
192
  else:
193
- def session_iterator() -> Session:
193
+ def session_iterator() -> Generator[Session, None, None]:
194
194
  with Session(bind=engine, autocommit=False, autoflush=True) as session:
195
195
  yield session
196
196
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: auto-rest-api
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Automatically map database schemas and deploy per-table REST API endpoints.
5
5
  License: GPL-3.0-only
6
6
  Keywords: Better,HPC,automatic,rest,api
@@ -0,0 +1,14 @@
1
+ auto_rest/__init__.py,sha256=9ICmv2urSoAo856FJylKdorF19UsUGc4eyORYLptf1Q,69
2
+ auto_rest/__main__.py,sha256=VkLZ9j1Q9I0isYvO0Bj1HHCQ9Ew_r5O7a0Dn4fUi5Lo,2233
3
+ auto_rest/app.py,sha256=1R8niLADFPI9Zpegdrpt9ITFMHaIj0E6tsgF59dRr38,3190
4
+ auto_rest/cli.py,sha256=k07_ucmsxholhiikL41VgrAEPKHX3_ay-qGvRvmQwxA,6250
5
+ auto_rest/handlers.py,sha256=QgiVnNxxi_LWon5pb0CktV347EPD1kcahSW726vAreA,13350
6
+ auto_rest/interfaces.py,sha256=WB_0eMDjGF8DpnDN9INHqo7u4x3aklvzAYK4t3JwC7s,3779
7
+ auto_rest/models.py,sha256=g_oLzgxl39WfNWzf3yAu4_HiPF5ht30yydjsGfB4pJA,6017
8
+ auto_rest/queries.py,sha256=2e6f_S4n1xvaSY8rYJG-koDmqiXHreOIRUteRuqZlv8,3058
9
+ auto_rest/routers.py,sha256=SZoOugauKdCk2Kqzzp9o6tGENusAsP1-YP-6Aam53tc,5636
10
+ auto_rest_api-0.1.6.dist-info/LICENSE.md,sha256=zFRw_u1mGSOH8GrpOu0L1P765aX9fB5UpKz06mTxAos,34893
11
+ auto_rest_api-0.1.6.dist-info/METADATA,sha256=Cv0Zw-T0nGfp9TpK-Hw0d6NQICOwtURzyifpwi3tM9k,2914
12
+ auto_rest_api-0.1.6.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
13
+ auto_rest_api-0.1.6.dist-info/entry_points.txt,sha256=zFynmBrHyYo3Ds0Uo4-bTFe1Tdr5mIXV4dPQOFb-W1w,53
14
+ auto_rest_api-0.1.6.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- auto_rest/__init__.py,sha256=9ICmv2urSoAo856FJylKdorF19UsUGc4eyORYLptf1Q,69
2
- auto_rest/__main__.py,sha256=VkLZ9j1Q9I0isYvO0Bj1HHCQ9Ew_r5O7a0Dn4fUi5Lo,2233
3
- auto_rest/app.py,sha256=AnBb2jt0yMxTLj_ICWB1mXLgu2pchjlapfdIk2CwNsQ,3128
4
- auto_rest/cli.py,sha256=3emee1GrUkQZ-DVAboy5O65jPE0vwmdcy-wfaxh2kBs,6239
5
- auto_rest/handlers.py,sha256=gwMiE5TKA65nrMizQ472A5iCNmYK7B7vlFDWL0Vrphw,12943
6
- auto_rest/interfaces.py,sha256=WB_0eMDjGF8DpnDN9INHqo7u4x3aklvzAYK4t3JwC7s,3779
7
- auto_rest/models.py,sha256=pi97l2PsDqjhW52tAIAZKx6bl2QvC-q5kM5OsVP3V_M,5887
8
- auto_rest/queries.py,sha256=2e6f_S4n1xvaSY8rYJG-koDmqiXHreOIRUteRuqZlv8,3058
9
- auto_rest/routers.py,sha256=SZoOugauKdCk2Kqzzp9o6tGENusAsP1-YP-6Aam53tc,5636
10
- auto_rest_api-0.1.5.dist-info/LICENSE.md,sha256=zFRw_u1mGSOH8GrpOu0L1P765aX9fB5UpKz06mTxAos,34893
11
- auto_rest_api-0.1.5.dist-info/METADATA,sha256=cgh43Yv81K8gaf9B-mAAiWX72VnJAGGuQHWa7Qi5-K4,2914
12
- auto_rest_api-0.1.5.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
13
- auto_rest_api-0.1.5.dist-info/entry_points.txt,sha256=zFynmBrHyYo3Ds0Uo4-bTFe1Tdr5mIXV4dPQOFb-W1w,53
14
- auto_rest_api-0.1.5.dist-info/RECORD,,