Skip to content

Commit 3ff91cc

Browse files
committed
Refactor type hints and improve parameter handling in capacity models; enhance CsvList class methods
1 parent b649c7f commit 3ff91cc

2 files changed

Lines changed: 50 additions & 35 deletions

File tree

ofsc/capacity.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
from typing import Optional, Union, get_origin, get_args
1+
from typing import Optional, Union, get_args, get_origin
22
from urllib.parse import urljoin
3-
import inspect
43

54
import requests
65
from pydantic import BaseModel
76

87
from ofsc.models import CsvList, OFSApi
98

109
from .common import OBJ_RESPONSE, wrap_return
11-
from .models import CapacityRequest, GetCapacityResponse, GetQuotaRequest, GetQuotaResponse
10+
from .models import (
11+
CapacityRequest,
12+
GetCapacityResponse,
13+
GetQuotaRequest,
14+
GetQuotaResponse,
15+
)
1216

1317

1418
def _convert_model_to_api_params(model: BaseModel) -> dict:
@@ -64,7 +68,7 @@ class OFSCapacity(OFSApi):
6468
@wrap_return(response_type=OBJ_RESPONSE, model=GetCapacityResponse)
6569
def getAvailableCapacity(self,
6670
dates: Union[list[str], CsvList, str],
67-
areas: Union[list[str], CsvList, str],
71+
areas: Optional[Union[list[str], CsvList, str]] = None,
6872
categories: Optional[Union[list[str], CsvList, str]] = None,
6973
aggregateResults: Optional[bool] = None,
7074
availableTimeIntervals: str = "all",
@@ -164,3 +168,8 @@ def getQuota(self,
164168
params=params,
165169
)
166170
return response
171+
url,
172+
headers=self.headers,
173+
params=params,
174+
)
175+
return response

ofsc/models.py

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,37 +27,37 @@
2727

2828
class CsvList(BaseModel):
2929
"""Auxiliary model to represent a list of strings as comma-separated values"""
30-
30+
3131
value: str = ""
32-
32+
3333
@classmethod
34-
def from_list(cls, string_list: List[str]) -> 'CsvList':
34+
def from_list(cls, string_list: List[str]) -> "CsvList":
3535
"""Create CsvList from a list of strings
36-
36+
3737
Args:
3838
string_list: List of strings to convert to CSV format
39-
39+
4040
Returns:
4141
CsvList instance with comma-separated values
4242
"""
4343
if not string_list:
4444
return cls(value="")
4545
return cls(value=",".join(string_list))
46-
46+
4747
def to_list(self) -> List[str]:
4848
"""Convert CsvList to a list of strings
49-
49+
5050
Returns:
5151
List of strings split by commas, empty list if value is empty
5252
"""
5353
if not self.value or self.value.strip() == "":
5454
return []
5555
return [item.strip() for item in self.value.split(",") if item.strip()]
56-
56+
5757
def __str__(self) -> str:
5858
"""String representation returns the CSV value"""
5959
return self.value
60-
60+
6161
def __repr__(self) -> str:
6262
"""Representation shows both CSV and list format"""
6363
return f"CsvList(value='{self.value}', list={self.to_list()})"
@@ -989,18 +989,19 @@ class DailyExtractFiles(BaseModel):
989989

990990
class CapacityRequest(BaseModel):
991991
"""Request model for capacity queries with CsvList support for string arrays
992-
992+
993993
Accepts list[str], CsvList, or str for string array parameters but converts internally to CsvList
994994
"""
995+
995996
aggregateResults: Optional[bool] = None
996-
areas: CsvList
997+
areas: Optional[CsvList] = None
997998
availableTimeIntervals: str = "all"
998999
calendarTimeIntervals: str = "all"
9991000
categories: Optional[CsvList] = None
10001001
dates: CsvList
10011002
fields: Optional[CsvList] = None
1002-
1003-
@field_validator('areas', 'categories', 'dates', 'fields', mode='before')
1003+
1004+
@field_validator("areas", "categories", "dates", "fields", mode="before")
10041005
@classmethod
10051006
def convert_to_csvlist(cls, v):
10061007
"""Convert list[str], CsvList, str, or dict to CsvList"""
@@ -1013,24 +1014,26 @@ def convert_to_csvlist(cls, v):
10131014
elif isinstance(v, str):
10141015
# Handle string input as CSV
10151016
return CsvList(value=v)
1016-
elif isinstance(v, dict) and 'value' in v:
1017+
elif isinstance(v, dict) and "value" in v:
10171018
# Handle dict from JSON deserialization
1018-
return CsvList(value=v['value'])
1019+
return CsvList(value=v["value"])
10191020
else:
1020-
raise ValueError(f"Expected list[str], CsvList, str, dict with 'value' key, or None, got {type(v)}")
1021-
1021+
raise ValueError(
1022+
f"Expected list[str], CsvList, str, dict with 'value' key, or None, got {type(v)}"
1023+
)
1024+
10221025
def get_areas_list(self) -> List[str]:
10231026
"""Get areas as a list of strings"""
10241027
return self.areas.to_list()
1025-
1028+
10261029
def get_categories_list(self) -> List[str]:
10271030
"""Get categories as a list of strings"""
10281031
return self.categories.to_list() if self.categories is not None else []
1029-
1032+
10301033
def get_dates_list(self) -> List[str]:
10311034
"""Get dates as a list of strings"""
10321035
return self.dates.to_list()
1033-
1036+
10341037
def get_fields_list(self) -> List[str]:
10351038
"""Get fields as a list of strings"""
10361039
return self.fields.to_list() if self.fields is not None else []
@@ -1076,7 +1079,7 @@ class GetCapacityResponse(BaseModel):
10761079

10771080
class QuotaAreaItem(BaseModel):
10781081
"""Model for quota area items with quota-specific fields"""
1079-
1082+
10801083
label: Optional[str] = None
10811084
name: Optional[str] = None
10821085
maxAvailable: Optional[int] = None
@@ -1092,7 +1095,7 @@ class QuotaAreaItem(BaseModel):
10921095

10931096
class QuotaResponseItem(BaseModel):
10941097
"""Model for individual quota response item by date"""
1095-
1098+
10961099
date: str
10971100
areas: List[QuotaAreaItem] = []
10981101

@@ -1105,9 +1108,10 @@ class GetQuotaResponse(BaseModel):
11051108

11061109
class GetQuotaRequest(BaseModel):
11071110
"""Request model for quota queries with comprehensive parameters
1108-
1111+
11091112
Accepts list[str] or CsvList for string array parameters but converts internally to CsvList
11101113
"""
1114+
11111115
aggregateResults: Optional[bool] = None
11121116
areas: Optional[CsvList] = None
11131117
categories: Optional[CsvList] = None
@@ -1116,8 +1120,8 @@ class GetQuotaRequest(BaseModel):
11161120
intervalLevel: Optional[bool] = None
11171121
returnStatuses: Optional[bool] = None
11181122
timeSlotLevel: Optional[bool] = None
1119-
1120-
@field_validator('areas', 'categories', 'dates', mode='before')
1123+
1124+
@field_validator("areas", "categories", "dates", mode="before")
11211125
@classmethod
11221126
def convert_to_csvlist(cls, v):
11231127
"""Convert list[str], CsvList, str, or dict to CsvList"""
@@ -1130,20 +1134,22 @@ def convert_to_csvlist(cls, v):
11301134
elif isinstance(v, str):
11311135
# Handle string input as CSV
11321136
return CsvList(value=v)
1133-
elif isinstance(v, dict) and 'value' in v:
1137+
elif isinstance(v, dict) and "value" in v:
11341138
# Handle dict from JSON deserialization
1135-
return CsvList(value=v['value'])
1139+
return CsvList(value=v["value"])
11361140
else:
1137-
raise ValueError(f"Expected list[str], CsvList, str, dict with 'value' key, or None, got {type(v)}")
1138-
1141+
raise ValueError(
1142+
f"Expected list[str], CsvList, str, dict with 'value' key, or None, got {type(v)}"
1143+
)
1144+
11391145
def get_areas_list(self) -> List[str]:
11401146
"""Get areas as a list of strings"""
11411147
return self.areas.to_list() if self.areas is not None else []
1142-
1148+
11431149
def get_categories_list(self) -> List[str]:
11441150
"""Get categories as a list of strings"""
11451151
return self.categories.to_list() if self.categories is not None else []
1146-
1152+
11471153
def get_dates_list(self) -> List[str]:
11481154
"""Get dates as a list of strings"""
11491155
return self.dates.to_list()

0 commit comments

Comments
 (0)