Skip to content

Commit 371e485

Browse files
authored
Add Holidays service (#13)
1 parent 2b02b29 commit 371e485

File tree

5 files changed

+217
-0
lines changed

5 files changed

+217
-0
lines changed

src/abstract_api/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from .avatars import Avatars
44
from .email_validation import EmailValidation
5+
from .holidays import Holidays
56
from .iban_validation import IBANValidation
67
from .ip_geolocation import IPGeolocation
78
from .phone_validation import PhoneValidation
@@ -10,6 +11,7 @@
1011
__all__: Final[list[str]] = [
1112
"Avatars",
1213
"EmailValidation",
14+
"Holidays",
1315
"IBANValidation",
1416
"IPGeolocation",
1517
"PhoneValidation",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from typing import Final
2+
3+
from .holidays import Holidays
4+
from .holidays_response import HolidaysResponse
5+
6+
__all__: Final[list[str]] = [
7+
"Holidays",
8+
"HolidaysResponse"
9+
]
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from abstract_api.bases import BaseService
2+
from abstract_api.exceptions import ResponseParseError
3+
4+
from .holidays_response import HolidaysResponse
5+
6+
7+
class Holidays(BaseService):
8+
"""AbstractAPI Holidays service.
9+
10+
Used to get the public, local, religious, and other holidays of a
11+
particular country.
12+
13+
Attributes:
14+
_subdomain: Holidays service subdomain.
15+
"""
16+
_subdomain: str = "holidays"
17+
18+
def lookup(
19+
self,
20+
country: str,
21+
year: int | None = None,
22+
month: int | None = None,
23+
day: int | None = None
24+
) -> HolidaysResponse:
25+
"""Gets the list of holidays of a particular country.
26+
27+
Can get the public, local, religious, and other holidays.
28+
29+
Args:
30+
country: The country’s two-letter ISO 3166-1 alpha-2 code.
31+
year: The year to get the holiday(s) from. Note that this is
32+
optional on paid plans and required on free plans, and if left
33+
blank it will default to the current year.
34+
month: The month to get the holiday(s) from, in the format
35+
of 1-12 (e.g., 1 is January, 2 is February, etc.).
36+
Note that this is optional on paid plans and required on
37+
free plans, and if left blank it will default to the current
38+
month.
39+
day: The day to get the holiday(s) from, in the format of 1-31.
40+
Note that this is optional on paid plans and required on free
41+
plans, and if left blank it will default to the current day.
42+
43+
Returns:
44+
HolidaysResponse representing API call response.
45+
"""
46+
response = self._service_request(
47+
country=country,
48+
year=year,
49+
month=month,
50+
day=day
51+
)
52+
53+
try:
54+
holidays_response = HolidaysResponse(response=response)
55+
except Exception as e:
56+
raise ResponseParseError(
57+
"Failed to parse response as HolidaysResponse"
58+
) from e
59+
60+
return holidays_response
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
from typing import TYPE_CHECKING
2+
3+
import requests
4+
5+
from abstract_api.bases import JSONResponse
6+
7+
from .response_fields import RESPONSE_FIELDS
8+
9+
10+
class Holiday:
11+
"""Holiday entity in VAT Holidays response."""
12+
13+
def __init__(
14+
self,
15+
name: str,
16+
name_local: str,
17+
language: str,
18+
description: str,
19+
country: str,
20+
location: str,
21+
type: str,
22+
date: str,
23+
date_year: str,
24+
date_month: str,
25+
date_day: str,
26+
week_day: str
27+
) -> None:
28+
"""Initializes a new Holiday."""
29+
self._name = name
30+
self._name_local = name_local
31+
self._language = language
32+
self._description = description
33+
self._country = country
34+
self._location = location
35+
self._type = type
36+
self._date = date
37+
self._date_year = date_year
38+
self._date_month = date_month
39+
self._date_day = date_day
40+
self._week_day = week_day
41+
42+
@property
43+
def name(self) -> str:
44+
"""The name of the holiday."""
45+
return self._name
46+
47+
@property
48+
def name_local(self) -> str:
49+
"""The local name of the holiday."""
50+
return self._name_local
51+
52+
@property
53+
def language(self) -> str:
54+
"""The language in which name_local is in."""
55+
return self._language
56+
57+
@property
58+
def description(self) -> str:
59+
"""A short description or additional details on the holiday.
60+
61+
Such as the holiday is a part of a long weekend.
62+
"""
63+
return self._description
64+
65+
@property
66+
def country(self) -> str:
67+
"""The country in which the holiday occurs.
68+
69+
Returned directly from the request.
70+
"""
71+
return self._country
72+
73+
@property
74+
def location(self) -> str:
75+
"""The location or region in which the holiday occurs.
76+
77+
If the holiday is that specific.
78+
"""
79+
return self._location
80+
81+
@property
82+
def type(self) -> str:
83+
"""The type of holiday it is.
84+
85+
(e.g., public holiday, religious holiday, etc.).
86+
"""
87+
return self._type
88+
89+
@property
90+
def date(self) -> str:
91+
"""The date on which the holiday occurs."""
92+
return self._date
93+
94+
@property
95+
def date_year(self) -> str:
96+
"""The year in which the holiday occurs."""
97+
return self._date_year
98+
99+
@property
100+
def date_month(self) -> str:
101+
"""The month in which the holiday occurs."""
102+
return self._date_month
103+
104+
@property
105+
def date_day(self) -> str:
106+
"""The day in which the holiday occurs."""
107+
return self._date_day
108+
109+
@property
110+
def week_day(self) -> str:
111+
"""The day of the week on which the holiday occurs.
112+
113+
(Monday, Tuesday, Wednesday, etc.).
114+
"""
115+
return self._week_day
116+
117+
118+
class HolidaysResponse(JSONResponse):
119+
"""Holidays service response."""
120+
121+
def __init__(self, response: requests.models.Response) -> None:
122+
"""Initializes a new VATValidationResponse."""
123+
super().__init__(response)
124+
self._response_fields = RESPONSE_FIELDS
125+
126+
if self.meta.body_json is not None:
127+
holidays = []
128+
for c in self.meta.body_json:
129+
if TYPE_CHECKING:
130+
assert isinstance(c, dict)
131+
holidays.append(Holiday(**c))
132+
self._holidays = frozenset(holidays)
133+
134+
@property
135+
def holidays(self) -> frozenset[Holiday]:
136+
"""The returned holidays."""
137+
return self._get_response_field("holidays")
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""Response fields of Holidays service endpoint."""
2+
3+
4+
# The response body does not contain 'holidays' field. This is just to be
5+
# able to initialize and use the response in a Pythonic way and conform with
6+
# other parts of the code.
7+
RESPONSE_FIELDS: frozenset[str] = frozenset({
8+
"holidays"
9+
})

0 commit comments

Comments
 (0)