Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce custom exceptions [WIP] #1328

Draft
wants to merge 5 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions holidays/calendars/thai.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from functools import lru_cache
from typing import Optional

from holidays.exceptions import CalendarError

# Manual Assign to avoid circular import
KHMER_CALENDAR = "KHMER_CALENDAR"
THAI_CALENDAR = "THAI_CALENDAR"
Expand Down Expand Up @@ -202,8 +204,8 @@ def __verify_calendar(calendar):
Verify calendar type.
"""
if calendar not in {KHMER_CALENDAR, THAI_CALENDAR}:
raise ValueError(
f"Unknown calendar name: {calendar}. Use `KHMER_CALENDAR` or `THAI_CALENDAR`."
raise CalendarError(
f"Unknown calendar name: {calendar}. Use KHMER_CALENDAR or THAI_CALENDAR."
)

@lru_cache()
Expand Down
8 changes: 3 additions & 5 deletions holidays/countries/israel.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from datetime import timedelta as td

from holidays.calendars import _HebrewLunisolar
from holidays.exceptions import YearOutOfRangeError
from holidays.holiday_base import HolidayBase


Expand All @@ -24,11 +25,8 @@ def _add_with_eve(self, name: str, dt: date) -> None:
self._add_holiday(name, dt)

def _populate(self, year):
if year <= 1947:
return None

if year >= 2101:
raise NotImplementedError
if year < 1948 or year > 2100:
raise YearOutOfRangeError("Year must be in 1948 - 2100 range.")

super()._populate(year)

Expand Down
3 changes: 2 additions & 1 deletion holidays/countries/japan.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from holidays.calendars import _get_nth_weekday_of_month
from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC, MON
from holidays.exceptions import YearOutOfRangeError
from holidays.helpers import _normalize_tuple
from holidays.holiday_base import HolidayBase

Expand All @@ -41,7 +42,7 @@ class Japan(HolidayBase):

def _populate(self, year):
if year < 1949 or year > 2099:
raise NotImplementedError
raise YearOutOfRangeError("Year must be in 1949 - 2099 range.")

super()._populate(year)
observed_dates = set()
Expand Down
42 changes: 42 additions & 0 deletions holidays/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# python-holidays
# ---------------
# A fast, efficient Python library for generating country, province and state
# specific sets of holidays on the fly. It aims to make determining whether a
# specific date is a holiday as fast and flexible as possible.
#
# Authors: dr-prodigy <[email protected]> (c) 2017-2023
# ryanss <[email protected]> (c) 2014-2017
# Website: https://github.com/dr-prodigy/python-holidays
# License: MIT (see LICENSE file)


class BaseError(Exception):
"""Base exception."""


class CalendarError(BaseError):
"""Calendar not recognized exception."""


class InvalidDateError(BaseError):
"""Invalid date type or format exception."""


class EntityDoesNotExist(BaseError):
"""Entity not supported exception."""


class CountryDoesNotExist(EntityDoesNotExist):
"""Country not supported exception."""


class FinancialDoesNotExist(EntityDoesNotExist):
"""Financial not supported exception."""


class SubdivisionDoesNotExist(BaseError):
"""Subdivision not supported exception."""


class YearOutOfRangeError(BaseError):
"""Year out of range error."""
6 changes: 3 additions & 3 deletions holidays/groups/christian.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from holidays.calendars import GREGORIAN_CALENDAR, JULIAN_CALENDAR
from holidays.constants import JAN, FEB, MAR, APR, JUN, JUL, AUG, SEP, NOV, DEC
from holidays.exceptions import CalendarError


class ChristianHolidays:
Expand Down Expand Up @@ -66,9 +67,8 @@ def __verify_calendar(calendar):
Verify calendar type.
"""
if calendar not in {GREGORIAN_CALENDAR, JULIAN_CALENDAR}:
raise ValueError(
f"Unknown calendar name: {calendar}. "
"Use `GREGORIAN_CALENDAR` or `JULIAN_CALENDAR`."
raise CalendarError(
f"Unknown calendar name: {calendar}. Use GREGORIAN_CALENDAR or JULIAN_CALENDAR."
)

@property
Expand Down
4 changes: 2 additions & 2 deletions holidays/groups/international.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ def _add_childrens_day(self, name, variation="JUN"):
return self._add_holiday(name, NOV, 20)
else:
raise ValueError(
f"Unknown variaton name: {variation}. "
"This entry currently supports `JUN` and `NOV` variation only."
f"Unknown variation name: {variation}. "
"This entry currently supports JUN and NOV variations only."
)

def _add_columbus_day(self, name):
Expand Down
19 changes: 12 additions & 7 deletions holidays/holiday_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from dateutil.parser import parse

from holidays.constants import HOLIDAY_NAME_DELIMITER, MON, TUE, WED, THU, FRI, SAT, SUN
from holidays.exceptions import InvalidDateError, SubdivisionDoesNotExist
from holidays.helpers import _normalize_tuple

DateArg = Union[date, Tuple[int, int]]
Expand Down Expand Up @@ -275,10 +276,14 @@ def __init__(
if not isinstance(self, HolidaySum):
if subdiv and subdiv not in set(self.subdivisions + self._deprecated_subdivisions):
if hasattr(self, "market"):
error = f"Market '{self.market}' does not have subdivision " f"'{subdiv}'"
error_message = (
f"Market '{self.market}' does not have subdivision " f"'{subdiv}'"
)
arkid15r marked this conversation as resolved.
Show resolved Hide resolved
else:
error = f"Country '{self.country}' does not have subdivision " f"'{subdiv}'"
raise NotImplementedError(error)
error_message = (
f"Country '{self.country}' does not have subdivision " f"'{subdiv}'"
arkid15r marked this conversation as resolved.
Show resolved Hide resolved
)
raise SubdivisionDoesNotExist(error_message)

if subdiv and subdiv in self._deprecated_subdivisions:
warnings.warn(
Expand Down Expand Up @@ -358,7 +363,7 @@ def __contains__(self, key: object) -> bool:
"""

if not isinstance(key, (date, datetime, float, int, str)):
raise TypeError(f"Cannot convert type '{type(key)}' to date.")
raise InvalidDateError(f"Cannot convert type '{type(key)}' to date.")

return dict.__contains__(cast("Mapping[Any, Any]", self), self.__keytransform__(key))

Expand Down Expand Up @@ -425,7 +430,7 @@ def __keytransform__(self, key: DateLike) -> date:
try:
dt = parse(key).date()
except (OverflowError, ValueError):
raise ValueError(f"Cannot parse date from string '{key}'")
raise InvalidDateError(f"Cannot parse date from string '{key}'")

# Check all other types.
elif isinstance(key, datetime): # Key type is derived from `datetime`.
Expand All @@ -440,7 +445,7 @@ def __keytransform__(self, key: DateLike) -> date:
dt = datetime.fromtimestamp(key, timezone.utc).date()

else: # Key type is not supported.
raise TypeError(f"Cannot convert type '{type(key)}' to date.")
raise InvalidDateError(f"Cannot convert type '{type(key)}' to date.")

# Automatically expand for `expand=True` cases.
if self.expand and dt.year not in self.years:
Expand Down Expand Up @@ -758,7 +763,7 @@ def get_named(
if any((holiday_name_lower == name[: len(holiday_name)].lower() for name in names))
]

raise AttributeError(f"Unknown lookup type: {lookup}")
raise ValueError(f"Unknown lookup type: {lookup}")

def pop(
self,
Expand Down
50 changes: 25 additions & 25 deletions holidays/locale/en_US/LC_MESSAGES/JP.po
Original file line number Diff line number Diff line change
Expand Up @@ -17,122 +17,122 @@ msgstr ""
"X-Generator: Poedit 3.2.2\n"

#. The Crown Prince marriage ceremony.
#: ./holidays/countries/japan.py:31 ./holidays/countries/japan.py:34
#: ./holidays/countries/japan.py:32 ./holidays/countries/japan.py:35
msgid "結婚の儀"
msgstr "The Crown Prince Marriage Ceremony"

#. State Funeral of Emperor Shōwa.
#: ./holidays/countries/japan.py:32
#: ./holidays/countries/japan.py:33
msgid "大喪の礼"
msgstr "Emperor Shōwa Funeral Ceremony"

#. Enthronement ceremony.
#: ./holidays/countries/japan.py:33
#: ./holidays/countries/japan.py:34
msgid "即位礼正殿の儀"
msgstr "Enthronement Ceremony"

#. Enthronement day.
#: ./holidays/countries/japan.py:36
#: ./holidays/countries/japan.py:37
msgid "天皇の即位の日"
msgstr "Emperor's Enthronement Day"

#. Enthronement ceremony.
#: ./holidays/countries/japan.py:37
#: ./holidays/countries/japan.py:38
msgid "即位礼正殿の儀が行われる日"
msgstr "Emperor's Enthronement Day"

#. New Year's Day.
#: ./holidays/countries/japan.py:50
#: ./holidays/countries/japan.py:51
msgid "元日"
msgstr "New Year's Day"

#. Coming of Age Day.
#: ./holidays/countries/japan.py:55
#: ./holidays/countries/japan.py:56
msgid "成人の日"
msgstr "Coming of Age Day"

#. Foundation Day.
#: ./holidays/countries/japan.py:64
#: ./holidays/countries/japan.py:65
msgid "建国記念の日"
msgstr "Foundation Day"

#. Emperor's Birthday.
#: ./holidays/countries/japan.py:68 ./holidays/countries/japan.py:75
#: ./holidays/countries/japan.py:158
#: ./holidays/countries/japan.py:69 ./holidays/countries/japan.py:76
#: ./holidays/countries/japan.py:159
msgid "天皇誕生日"
msgstr "Emperor's Birthday"

#. Vernal Equinox Day.
#: ./holidays/countries/japan.py:71
#: ./holidays/countries/japan.py:72
msgid "春分の日"
msgstr "Vernal Equinox Day"

#. Greenery Day.
#: ./holidays/countries/japan.py:78 ./holidays/countries/japan.py:89
#: ./holidays/countries/japan.py:79 ./holidays/countries/japan.py:90
msgid "みどりの日"
msgstr "Greenery Day"

#. Showa Day.
#: ./holidays/countries/japan.py:81
#: ./holidays/countries/japan.py:82
msgid "昭和の日"
msgstr "Showa Day"

#. Constitution Day.
#: ./holidays/countries/japan.py:85
#: ./holidays/countries/japan.py:86
msgid "憲法記念日"
msgstr "Constitution Day"

#. Children's Day.
#: ./holidays/countries/japan.py:92
#: ./holidays/countries/japan.py:93
msgid "こどもの日"
msgstr "Children's Day"

#. Marine Day.
#: ./holidays/countries/japan.py:104
#: ./holidays/countries/japan.py:105
msgid "海の日"
msgstr "Marine Day"

#. Mountain Day.
#: ./holidays/countries/japan.py:113
#: ./holidays/countries/japan.py:114
msgid "山の日"
msgstr "Mountain Day"

#. Respect for the Aged Day.
#: ./holidays/countries/japan.py:119
#: ./holidays/countries/japan.py:120
msgid "敬老の日"
msgstr "Respect for the Aged Day"

#. Autumnal Equinox Day.
#: ./holidays/countries/japan.py:127
#: ./holidays/countries/japan.py:128
msgid "秋分の日"
msgstr "Autumnal Equinox"

#. Physical Education Day.
#: ./holidays/countries/japan.py:136
#: ./holidays/countries/japan.py:137
msgid "体育の日"
msgstr "Physical Education Day"

#. Sports Day.
#: ./holidays/countries/japan.py:133
#: ./holidays/countries/japan.py:134
msgid "スポーツの日"
msgstr "Sports Day"

#. Culture Day.
#: ./holidays/countries/japan.py:151
#: ./holidays/countries/japan.py:152
msgid "文化の日"
msgstr "Culture Day"

#. Labor Thanksgiving Day.
#: ./holidays/countries/japan.py:154
#: ./holidays/countries/japan.py:155
msgid "勤労感謝の日"
msgstr "Labor Thanksgiving Day"

#. Substitute Holiday.
#: ./holidays/countries/japan.py:173
#: ./holidays/countries/japan.py:174
msgid "振替休日"
msgstr "Substitute Holiday"

#. National Holiday.
#: ./holidays/countries/japan.py:184
#: ./holidays/countries/japan.py:185
msgid "国民の休日"
msgstr "National Holiday"
Loading