From b175dabe7729ea4bac2d4c8eff164682afb3000a Mon Sep 17 00:00:00 2001 From: Aweryc Date: Mon, 14 Jul 2025 13:00:09 +0300 Subject: [PATCH 1/6] Convenience Functionality for BusinessOpeningHours -check if the business is open at a given time -get the opening hours for a given day --- changes/unreleased/48XX._.toml | 5 + pyproject.toml | 5 + src/telegram/__main__.py | 4 +- src/telegram/_business.py | 89 ++++++++- .../_passport/encryptedpassportelement.py | 1 - src/telegram/_payment/stars/staramount.py | 1 - src/telegram/_utils/datetime.py | 25 +++ src/telegram/_utils/enum.py | 2 +- tests/_utils/test_datetime.py | 54 +++++- tests/test_business_classes.py | 177 ++++++++++++++++++ 10 files changed, 355 insertions(+), 8 deletions(-) create mode 100644 changes/unreleased/48XX._.toml diff --git a/changes/unreleased/48XX._.toml b/changes/unreleased/48XX._.toml new file mode 100644 index 00000000000..fa083bd43a0 --- /dev/null +++ b/changes/unreleased/48XX._.toml @@ -0,0 +1,5 @@ +features = "Added a two methods for BusinessOpeningHours" +[[pull_requests]] +uid = "4326" +author_uid = "Aweryc" +closes_threads = ["4194, 4326"] \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 66589c25b0e..25d18172d19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,12 @@ classifiers = [ "Programming Language :: Python :: 3.13", ] dependencies = [ + "black>=25.1.0", "httpx >=0.27,<0.29", + "pre-commit>=4.2.0", + "pytest>=8.3.5", + "pytz>=2025.2", + "ruff==0.11.9", ] [project.urls] diff --git a/src/telegram/__main__.py b/src/telegram/__main__.py index 7d291b2ae1e..c685c0a389a 100644 --- a/src/telegram/__main__.py +++ b/src/telegram/__main__.py @@ -17,7 +17,7 @@ # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. # pylint: disable=missing-module-docstring -# ruff: noqa: T201, D100, S603, S607 +# ruff: noqa: T201, D100, S607 import subprocess import sys from typing import Optional @@ -28,7 +28,7 @@ def _git_revision() -> Optional[str]: try: - output = subprocess.check_output( + output = subprocess.check_output( # noqa: S603 ["git", "describe", "--long", "--tags"], stderr=subprocess.STDOUT ) except (subprocess.SubprocessError, OSError): diff --git a/src/telegram/_business.py b/src/telegram/_business.py index dd055426654..7846955af7e 100644 --- a/src/telegram/_business.py +++ b/src/telegram/_business.py @@ -21,6 +21,7 @@ import datetime as dtm from collections.abc import Sequence from typing import TYPE_CHECKING, Optional +from zoneinfo import ZoneInfo from telegram._chat import Chat from telegram._files.location import Location @@ -28,7 +29,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg -from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp +from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp, verify_timezone from telegram._utils.types import JSONDict from telegram._utils.warnings import warn from telegram._utils.warnings_transition import ( @@ -494,7 +495,7 @@ class BusinessOpeningHoursInterval(TelegramObject): Examples: A day has (24 * 60 =) 1440 minutes, a week has (7 * 1440 =) 10080 minutes. - Starting the the minute's sequence from Monday, example values of + Starting the minute's sequence from Monday, example values of :attr:`opening_minute`, :attr:`closing_minute` will map to the following day times: * Monday - 8am to 8:30pm: @@ -616,6 +617,90 @@ def __init__( self._freeze() + def get_opening_hours_for_day( + self, date: dtm.date, time_zone: Optional[ZoneInfo] = None + ) -> tuple[tuple[dtm.datetime, dtm.datetime], ...]: + """Returns the opening hours intervals for a specific day as datetime objects. + + .. versionadded:: NEXT.VERSION + + + Objects of this class are comparable in terms of equality. + Two objects of this class are considered equal, if their + :attr:`time_zone_name` and :attr:`opening_hours` are equal. + Args: + date (:obj:`datetime.date`): The date to get opening hours for. + Only the weekday component + is used to determine matching opening intervals. + time_zone (:obj:`zoneinfo.ZoneInfo`, optional): Timezone to use for the returned + datetime objects. If not specified, the returned datetime objects + will be timezone-naive. + + Returns: + tuple[tuple[:obj:`datetime.datetime`, :obj:`datetime.datetime`], ...]: + A tuple of datetime pairs representing opening and closing times for the specified day. + Each pair consists of (opening_time, closing_time). Returns an empty tuple if there are + no opening hours for the given day. + """ + + week_day = date.weekday() + res = [] + + for interval in self.opening_hours: + int_open = interval.opening_time + int_close = interval.closing_time + if int_open[0] == week_day: + res.append( + ( + dtm.datetime( + year=date.year, + month=date.month, + day=date.day, + hour=int_open[1], + minute=int_open[2], + tzinfo=verify_timezone(time_zone), + ), + dtm.datetime( + year=date.year, + month=date.month, + day=date.day, + hour=int_close[1], + minute=int_close[2], + tzinfo=verify_timezone(time_zone), + ), + ) + ) + + return tuple(res) + + def is_open(self, dt: dtm.datetime) -> bool: + """Check if the business is open at the specified datetime. + + .. versionadded:: NEXT.VERSION + + Args: + dt (:obj:`datetime.datetime`): The datetime to check. + If timezone-aware, the check will be performed in that timezone. + If timezone-naive, the check will be performed in the + timezone specified by :attr:`time_zone_name`. + Returns: + :obj:`bool`: True if the business is open at the specified time, False otherwise. + """ + + if dt.tzinfo is None: + dt_utc = dt + else: + dt_utc = dt.astimezone(verify_timezone(ZoneInfo(self.time_zone_name))) + + weekday = dt_utc.weekday() + minute_of_week = weekday * 1440 + dt_utc.hour * 60 + dt_utc.minute + + for interval in self.opening_hours: + if interval.opening_minute <= minute_of_week < interval.closing_minute: + return True + + return False + @classmethod def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessOpeningHours": """See :meth:`telegram.TelegramObject.de_json`.""" diff --git a/src/telegram/_passport/encryptedpassportelement.py b/src/telegram/_passport/encryptedpassportelement.py index c231c51640b..65f88e7a69b 100644 --- a/src/telegram/_passport/encryptedpassportelement.py +++ b/src/telegram/_passport/encryptedpassportelement.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# flake8: noqa: E501 # A library that provides a Python interface to the Telegram Bot API # Copyright (C) 2015-2025 # Leandro Toledo de Souza diff --git a/src/telegram/_payment/stars/staramount.py b/src/telegram/_payment/stars/staramount.py index a8d61b2a118..c78a4aa9aba 100644 --- a/src/telegram/_payment/stars/staramount.py +++ b/src/telegram/_payment/stars/staramount.py @@ -16,7 +16,6 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. -# pylint: disable=redefined-builtin """This module contains an object that represents a Telegram StarAmount.""" diff --git a/src/telegram/_utils/datetime.py b/src/telegram/_utils/datetime.py index 8e6ebdda1b4..bd941b2a5b6 100644 --- a/src/telegram/_utils/datetime.py +++ b/src/telegram/_utils/datetime.py @@ -30,8 +30,11 @@ import contextlib import datetime as dtm import time +import zoneinfo from typing import TYPE_CHECKING, Optional, Union +from telegram.error import TelegramError + if TYPE_CHECKING: from telegram import Bot @@ -224,3 +227,25 @@ def _datetime_to_float_timestamp(dt_obj: dtm.datetime) -> float: if dt_obj.tzinfo is None: dt_obj = dt_obj.replace(tzinfo=dtm.timezone.utc) return dt_obj.timestamp() + + +def verify_timezone( + tz: Optional[Union[dtm.tzinfo, zoneinfo.ZoneInfo]], +) -> Optional[Union[zoneinfo.ZoneInfo, dtm.tzinfo]]: + """ + Verifies that the given timezone is a valid timezone. + """ + + if tz is None: + return None + if isinstance(tz, (dtm.tzinfo, zoneinfo.ZoneInfo)): + return tz + + try: + return zoneinfo.ZoneInfo(tz) + except zoneinfo.ZoneInfoNotFoundError as err: + raise TelegramError( + f"No time zone found with key {tz}. " + f"Make sure to use a valid time zone name and " + f"correct install tzdata (https://pypi.org/project/tzdata/)" + ) from err diff --git a/src/telegram/_utils/enum.py b/src/telegram/_utils/enum.py index 58362870f7e..52e21eb46f5 100644 --- a/src/telegram/_utils/enum.py +++ b/src/telegram/_utils/enum.py @@ -60,7 +60,7 @@ def __str__(self) -> str: # Apply the __repr__ modification and __str__ fix to IntEnum -class IntEnum(_enum.IntEnum): # pylint: disable=invalid-slots +class IntEnum(_enum.IntEnum): """Helper class for int enums where ``str(member)`` prints the value, but ``repr(member)`` gives ``EnumName.MEMBER_NAME``. """ diff --git a/tests/_utils/test_datetime.py b/tests/_utils/test_datetime.py index dfcaca67587..d1b9aaea91d 100644 --- a/tests/_utils/test_datetime.py +++ b/tests/_utils/test_datetime.py @@ -23,6 +23,8 @@ import pytest from telegram._utils import datetime as tg_dtm +from telegram._utils.datetime import verify_timezone +from telegram.error import TelegramError from telegram.ext import Defaults # sample time specification values categorised into absolute / delta / time-of-day @@ -168,7 +170,7 @@ def test_to_timestamp(self): assert tg_dtm.to_timestamp(i) == int(tg_dtm.to_float_timestamp(i)), f"Failed for {i}" def test_to_timestamp_none(self): - # this 'convenience' behaviour has been left left for backwards compatibility + # this 'convenience' behaviour has been left for backwards compatibility assert tg_dtm.to_timestamp(None) is None def test_from_timestamp_none(self): @@ -192,3 +194,53 @@ def test_extract_tzinfo_from_defaults(self, tz_bot, bot, raw_bot): assert tg_dtm.extract_tzinfo_from_defaults(tz_bot) == tz_bot.defaults.tzinfo assert tg_dtm.extract_tzinfo_from_defaults(bot) is None assert tg_dtm.extract_tzinfo_from_defaults(raw_bot) is None + + def test_with_zoneinfo_object(self): + """Test with a valid zoneinfo.ZoneInfo object.""" + tz = zoneinfo.ZoneInfo("Europe/Paris") + result = verify_timezone(tz) + assert result == tz + + def test_with_datetime_tzinfo(self): + """Test with a datetime.tzinfo object.""" + + class CustomTZ(dtm.tzinfo): + def utcoffset(self, dt): + return dtm.timedelta(hours=2) + + def dst(self, dt): + return dtm.timedelta(0) + + tz = CustomTZ() + result = verify_timezone(tz) + assert result == tz + + def test_with_valid_timezone_string(self): + """Test with a valid timezone string.""" + tz = "Asia/Tokyo" + result = verify_timezone(tz) + assert isinstance(result, zoneinfo.ZoneInfo) + assert str(result) == "Asia/Tokyo" + + def test_with_none(self): + """Test with None input.""" + assert verify_timezone(None) is None + + def test_with_invalid_timezone_string(self): + """Test with an invalid timezone string.""" + with pytest.raises(TelegramError, match="No time zone found"): + verify_timezone("Invalid/Timezone") + + def test_with_empty_string(self): + """Test with empty string input.""" + with pytest.raises(TelegramError, match="No time zone found"): + verify_timezone("") + + def test_with_non_timezone_object(self): + """Test with an object that isn't a timezone.""" + with pytest.raises(TelegramError, match="No time zone found"): + verify_timezone(123) # integer + with pytest.raises(TelegramError, match="No time zone found"): + verify_timezone({"key": "value"}) # dict + with pytest.raises(TelegramError, match="No time zone found"): + verify_timezone([]) # empty list diff --git a/tests/test_business_classes.py b/tests/test_business_classes.py index aabf60064c6..afb8f60b765 100644 --- a/tests/test_business_classes.py +++ b/tests/test_business_classes.py @@ -17,6 +17,7 @@ # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. import datetime as dtm +from zoneinfo import ZoneInfo import pytest @@ -589,3 +590,179 @@ def test_equality(self): assert boh1 != boh3 assert hash(boh1) != hash(boh3) + + +class TestBusinessOpeningHoursGetOpeningHoursForDayWithoutRequest: + @pytest.fixture + def sample_opening_hours(self): + # Monday 8am-8:30pm (480-1230) + # Tuesday 24 hours (1440-2879) + # Sunday 12am-11:58pm (8640-10078) + intervals = [ + BusinessOpeningHoursInterval(480, 1230), # Monday 8am-8:30pm + BusinessOpeningHoursInterval(1440, 2879), # Tuesday 24 hours + BusinessOpeningHoursInterval(8640, 10078), # Sunday 12am-11:58pm + ] + return BusinessOpeningHours(time_zone_name="UTC", opening_hours=intervals) + + def test_monday_opening_hours(self, sample_opening_hours): + # Test for Monday + test_date = dtm.date(2023, 11, 6) # Monday + time_zone = ZoneInfo("UTC") + result = sample_opening_hours.get_opening_hours_for_day(test_date, time_zone) + + expected = ( + dtm.datetime(2023, 11, 6, 8, 0, tzinfo=time_zone), + dtm.datetime(2023, 11, 6, 20, 30, tzinfo=time_zone), + ) + + assert result == expected + + def test_tuesday_24_hours(self, sample_opening_hours): + # Test for Tuesday (24 hours) + test_date = dtm.date(2023, 11, 7) # Tuesday + time_zone = ZoneInfo("UTC") + result = sample_opening_hours.get_opening_hours_for_day(test_date, time_zone) + + expected = ( + dtm.datetime(2023, 11, 7, 0, 0, tzinfo=time_zone), + dtm.datetime(2023, 11, 7, 23, 59, tzinfo=time_zone), + ) + + assert result == expected + + def test_sunday_opening_hours(self, sample_opening_hours): + # Test for Sunday + test_date = dtm.date(2023, 11, 12) # Sunday + time_zone = ZoneInfo("UTC") + result = sample_opening_hours.get_opening_hours_for_day(test_date, time_zone) + + expected = ( + dtm.datetime(2023, 11, 12, 0, 0, tzinfo=time_zone), + dtm.datetime(2023, 11, 12, 23, 58, tzinfo=time_zone), + ) + + assert result == expected + + def test_day_with_no_opening_hours(self, sample_opening_hours): + # Test for Wednesday (no opening hours defined) + test_date = dtm.date(2023, 11, 8) # Wednesday + time_zone = ZoneInfo("UTC") + result = sample_opening_hours.get_opening_hours_for_day(test_date, time_zone) + + assert result == () + + def test_multiple_intervals_same_day(self): + # Test with multiple intervals on the same day + intervals = [ + BusinessOpeningHoursInterval(480, 720), # Monday 8am-12pm + BusinessOpeningHoursInterval(900, 1230), # Monday 3pm-8:30pm + ] + opening_hours = BusinessOpeningHours(time_zone_name="UTC", opening_hours=intervals) + + test_date = dtm.date(2023, 11, 6) # Monday + time_zone = ZoneInfo("UTC") + result = opening_hours.get_opening_hours_for_day(test_date, time_zone) + + expected = ( + dtm.datetime(2023, 11, 6, 8, 0, tzinfo=time_zone), + dtm.datetime(2023, 11, 6, 12, 0, tzinfo=time_zone), + dtm.datetime(2023, 11, 6, 15, 0, tzinfo=time_zone), + dtm.datetime(2023, 11, 6, 20, 30, tzinfo=time_zone), + ) + + assert result == expected + + def test_timezone_conversion(self, sample_opening_hours): + # Test that timezone is properly applied + test_date = dtm.date(2023, 11, 6) # Monday + time_zone = ZoneInfo("America/New_York") + result = sample_opening_hours.get_opening_hours_for_day(test_date, time_zone) + + expected = ( + dtm.datetime(2023, 11, 6, 8, 0, tzinfo=time_zone), + dtm.datetime(2023, 11, 6, 20, 30, tzinfo=time_zone), + ) + + assert result == expected + assert result[0].tzinfo == time_zone + assert result[1].tzinfo == time_zone + + def test_no_timezone_provided(self, sample_opening_hours): + # Test when no timezone is provided + test_date = dtm.date(2023, 11, 6) # Monday + result = sample_opening_hours.get_opening_hours_for_day(test_date) + + expected = ( + dtm.datetime(2023, 11, 6, 8, 0, tzinfo=None), + dtm.datetime(2023, 11, 6, 20, 30, tzinfo=None), + ) + + assert result == expected + + +class TestBusinessOpeningHoursIsOpenWithoutRequest: + @pytest.fixture + def sample_opening_hours(self): + # Monday 8am-8:30pm (480-1230) + # Tuesday 24 hours (1440-2879) + # Sunday 12am-11:58pm (8640-10078) + intervals = [ + BusinessOpeningHoursInterval(480, 1230), # Monday 8am-8:30pm UTC + BusinessOpeningHoursInterval(1440, 2879), # Tuesday 24 hours UTC + BusinessOpeningHoursInterval(8640, 10078), # Sunday 12am-11:58pm UTC + ] + return BusinessOpeningHours(time_zone_name="UTC", opening_hours=intervals) + + def test_is_open_during_business_hours(self, sample_opening_hours): + # Monday 10am UTC (within 8am-8:30pm) + dt = dtm.datetime(2023, 11, 6, 10, 0, tzinfo=ZoneInfo("UTC")) + assert sample_opening_hours.is_open(dt) is True + + def test_is_open_at_opening_time(self, sample_opening_hours): + # Monday exactly 8am UTC + dt = dtm.datetime(2023, 11, 6, 8, 0, tzinfo=ZoneInfo("UTC")) + assert sample_opening_hours.is_open(dt) is True + + def test_is_closed_at_closing_time(self, sample_opening_hours): + # Monday exactly 8:30pm UTC (closing time is exclusive) + dt = dtm.datetime(2023, 11, 6, 20, 30, tzinfo=ZoneInfo("UTC")) + assert sample_opening_hours.is_open(dt) is False + + def test_is_closed_outside_business_hours(self, sample_opening_hours): + # Monday 7am UTC (before opening) + dt = dtm.datetime(2023, 11, 6, 7, 0, tzinfo=ZoneInfo("UTC")) + assert sample_opening_hours.is_open(dt) is False + + def test_is_open_24h_day(self, sample_opening_hours): + # Tuesday 3am UTC (24h opening) + dt = dtm.datetime(2023, 11, 7, 3, 0, tzinfo=ZoneInfo("UTC")) + assert sample_opening_hours.is_open(dt) is True + + def test_is_closed_on_day_with_no_hours(self, sample_opening_hours): + # Wednesday (no opening hours) + dt = dtm.datetime(2023, 11, 8, 12, 0, tzinfo=ZoneInfo("UTC")) + assert sample_opening_hours.is_open(dt) is False + + def test_timezone_conversion(self, sample_opening_hours): + # Monday 10am UTC is 6am EDT (should be closed) + dt = dtm.datetime(2023, 11, 6, 6, 0, tzinfo=ZoneInfo("America/New_York")) + assert sample_opening_hours.is_open(dt) is False + + # Monday 10am EDT is 2pm UTC (should be open) + dt = dtm.datetime(2023, 11, 6, 10, 0, tzinfo=ZoneInfo("America/New_York")) + assert sample_opening_hours.is_open(dt) is True + + def test_naive_datetime_uses_business_timezone(self, sample_opening_hours): + # Naive datetime - should be interpreted as UTC (business timezone) + dt = dtm.datetime(2023, 11, 6, 10, 0) # 10am naive + assert sample_opening_hours.is_open(dt) is True + + def test_boundary_conditions(self, sample_opening_hours): + # Sunday 11:58pm UTC (should be open) + dt = dtm.datetime(2023, 11, 12, 23, 57, tzinfo=ZoneInfo("UTC")) + assert sample_opening_hours.is_open(dt) is True + + # Sunday 11:59pm UTC (should be closed) + dt = dtm.datetime(2023, 11, 12, 23, 59, tzinfo=ZoneInfo("UTC")) + assert sample_opening_hours.is_open(dt) is False From 73def0ae6d805584349a3f1b45304c0340c41ee8 Mon Sep 17 00:00:00 2001 From: Aweryc <93672316+Aweryc@users.noreply.github.com> Date: Thu, 17 Jul 2025 11:53:47 +0300 Subject: [PATCH 2/6] Revert enum.py --- src/telegram/_utils/enum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/telegram/_utils/enum.py b/src/telegram/_utils/enum.py index 52e21eb46f5..58362870f7e 100644 --- a/src/telegram/_utils/enum.py +++ b/src/telegram/_utils/enum.py @@ -60,7 +60,7 @@ def __str__(self) -> str: # Apply the __repr__ modification and __str__ fix to IntEnum -class IntEnum(_enum.IntEnum): +class IntEnum(_enum.IntEnum): # pylint: disable=invalid-slots """Helper class for int enums where ``str(member)`` prints the value, but ``repr(member)`` gives ``EnumName.MEMBER_NAME``. """ From 0a70348d9442e9f50881c45c3ee47059b2023d4d Mon Sep 17 00:00:00 2001 From: Aweryc <93672316+Aweryc@users.noreply.github.com> Date: Thu, 17 Jul 2025 11:56:02 +0300 Subject: [PATCH 3/6] Proper re-raise zoneinfo.ZoneInfoNotFoundError --- src/telegram/_utils/datetime.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/telegram/_utils/datetime.py b/src/telegram/_utils/datetime.py index bd941b2a5b6..fb2f0724ba6 100644 --- a/src/telegram/_utils/datetime.py +++ b/src/telegram/_utils/datetime.py @@ -244,7 +244,7 @@ def verify_timezone( try: return zoneinfo.ZoneInfo(tz) except zoneinfo.ZoneInfoNotFoundError as err: - raise TelegramError( + raise zoneinfo.ZoneInfoNotFoundError( f"No time zone found with key {tz}. " f"Make sure to use a valid time zone name and " f"correct install tzdata (https://pypi.org/project/tzdata/)" From 99634d090ea74b6e3124d4228d18aee9a9fb2c31 Mon Sep 17 00:00:00 2001 From: Aweryc <93672316+Aweryc@users.noreply.github.com> Date: Thu, 17 Jul 2025 11:57:09 +0300 Subject: [PATCH 4/6] Update datetime.py --- src/telegram/_utils/datetime.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/telegram/_utils/datetime.py b/src/telegram/_utils/datetime.py index fb2f0724ba6..57aa683c977 100644 --- a/src/telegram/_utils/datetime.py +++ b/src/telegram/_utils/datetime.py @@ -33,8 +33,6 @@ import zoneinfo from typing import TYPE_CHECKING, Optional, Union -from telegram.error import TelegramError - if TYPE_CHECKING: from telegram import Bot From 86540bfcb244f56e8b98383bee7e8367b6d5cc39 Mon Sep 17 00:00:00 2001 From: Aweryc Date: Thu, 17 Jul 2025 12:01:52 +0300 Subject: [PATCH 5/6] Rename change file .toml --- .../unreleased/{48XX._.toml => 4861.HEoGVs2mYXWzqMahi6SEhV.toml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changes/unreleased/{48XX._.toml => 4861.HEoGVs2mYXWzqMahi6SEhV.toml} (100%) diff --git a/changes/unreleased/48XX._.toml b/changes/unreleased/4861.HEoGVs2mYXWzqMahi6SEhV.toml similarity index 100% rename from changes/unreleased/48XX._.toml rename to changes/unreleased/4861.HEoGVs2mYXWzqMahi6SEhV.toml From 6ff094d7baa8e444828b2f60a027161d1151c607 Mon Sep 17 00:00:00 2001 From: Aweryc Date: Thu, 17 Jul 2025 12:06:09 +0300 Subject: [PATCH 6/6] revert pyproject.toml edit 4861.HEoGVs2mYXWzqMahi6SEhV.toml --- changes/unreleased/4861.HEoGVs2mYXWzqMahi6SEhV.toml | 2 +- pyproject.toml | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/changes/unreleased/4861.HEoGVs2mYXWzqMahi6SEhV.toml b/changes/unreleased/4861.HEoGVs2mYXWzqMahi6SEhV.toml index fa083bd43a0..b511be65416 100644 --- a/changes/unreleased/4861.HEoGVs2mYXWzqMahi6SEhV.toml +++ b/changes/unreleased/4861.HEoGVs2mYXWzqMahi6SEhV.toml @@ -2,4 +2,4 @@ features = "Added a two methods for BusinessOpeningHours" [[pull_requests]] uid = "4326" author_uid = "Aweryc" -closes_threads = ["4194, 4326"] \ No newline at end of file +closes_threads = ["4194"] \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 25d18172d19..66589c25b0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,12 +38,7 @@ classifiers = [ "Programming Language :: Python :: 3.13", ] dependencies = [ - "black>=25.1.0", "httpx >=0.27,<0.29", - "pre-commit>=4.2.0", - "pytest>=8.3.5", - "pytz>=2025.2", - "ruff==0.11.9", ] [project.urls]