Skip to content

Conversation

@AryaPhansalkar
Copy link
Contributor

Proposed change

  • Added a new function called list_long_weekends
  • It detects long weekends automatically by combining holidays with the adjacent weekend day.
  • Weekend days are considered according to the country.
  • TestListLongWeekends has been added.

Resolves #2422

Type of change

  • New country/market holidays support (thank you!)
  • Supported country/market holidays update (calendar discrepancy fix, localization)
  • Existing code/documentation/test/process quality improvement (best practice, cleanup, refactoring, optimization)
  • Dependency update (version deprecation/pin/upgrade)
  • Bugfix (non-breaking change which fixes an issue)
  • Breaking change (a code change causing existing functionality to break)
  • New feature (new holidays functionality in general)

Checklist

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 10, 2025

Summary by CodeRabbit

  • New Features
    • Added functionality to identify extended long weekend periods based on holidays, automatically extending holidays to surrounding working days with customizable minimum length thresholds and optional weekend overlap filtering.

Walkthrough

Adds a new public utility function list_long_weekends(instance: HolidayBase, minimum_holiday_length: int = 3, require_weekend_overlap: Optional[bool] = True) in holidays/utils.py, exposes it via __all__, imports _timedelta for date arithmetic, and adds comprehensive tests in tests/test_utils.py.

Changes

Cohort / File(s) Summary of changes
Utilities
holidays/utils.py
Added list_long_weekends(instance: HolidayBase, minimum_holiday_length: int = 3, require_weekend_overlap: Optional[bool] = True) -> list; imported from holidays.calendars.gregorian import _timedelta; updated __all__ to export list_long_weekends. The function extends each holiday to surrounding working days, computes contiguous date blocks, filters by minimum length and optional weekend overlap, and avoids reprocessing overlapping days.
Tests
tests/test_utils.py
Added TestListLongWeekends with multiple scenarios (single/multiple holidays, non-weekend sequences, custom weekend definitions, no-holidays, overlap handling, edge cases). Introduces a MockHolidayBase scaffold and assertions validating returned long-weekend blocks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Potential attention points:

  • Correct use of _timedelta vs. standard timedelta and its implications.
  • Overlap-handling logic and correctness of “already-checked” date tracking.
  • Weekend-detection behavior when require_weekend_overlap is toggled.
  • Test coverage for boundary dates and custom weekend definitions.

Suggested reviewers

  • arkid15r
  • PPsyrius
  • KJhellico

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Long weekend Function added" is concise and directly related to the main change in the pull request. It clearly conveys that a new function for long weekends has been introduced, which accurately summarizes the primary contribution of this changeset. While the title could be slightly more specific (e.g., mentioning "list_long_weekends"), it is sufficiently clear for developers scanning the project history to understand the core change.
Linked Issues Check ✅ Passed The pull request addresses the core objectives of linked issue #2422 by implementing a function that detects and combines holidays with adjacent weekends to identify long weekends. The new list_long_weekends function accepts an instance parameter and provides a minimum_holiday_length filter, supporting the issue's goal of helping users plan vacations and breaks. The require_weekend_overlap parameter enables optional control over whether sequences without weekend overlap are included, effectively addressing the issue's request for both standard and "potential" long weekend detection. The implementation delivers the requested functionality with proper testing through TestListLongWeekends, though the specific function name differs slightly (list_long_weekends vs. get_long_weekends as originally described).
Out of Scope Changes Check ✅ Passed All changes in the pull request are directly in scope with the linked issue objectives. The modifications to holidays/utils.py add the new list_long_weekends function and expose it in the public API through all, along with the necessary _timedelta import for date arithmetic. The changes to tests/test_utils.py introduce appropriate test infrastructure (MockHolidayBase) and comprehensive test coverage through TestListLongWeekends. No unrelated code modifications, refactoring, or out-of-scope enhancements were introduced.
Description Check ✅ Passed The pull request description is well-related to the changeset. It clearly explains the new list_long_weekends function, its purpose of detecting long weekends by combining holidays with adjacent weekend days, and mentions that country-specific weekend definitions are considered. The description also notes the addition of TestListLongWeekends and explicitly links to the resolved issue (#2422), providing good context for the changes made.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0eacdcf and fafc47f.

📒 Files selected for processing (2)
  • holidays/utils.py (2 hunks)
  • tests/test_utils.py (3 hunks)
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-09-14T17:17:14.387Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py:209-209
Timestamp: 2025-09-14T17:17:14.387Z
Learning: In tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py, the explicit loop iteration pattern for subdivision-specific holiday checks (like Anniversary Day for TA subdivision) is intentionally preferred over using assertSubdivTa helper methods, as confirmed by PPsyrius.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:47:27.213Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:52-64
Timestamp: 2025-04-05T04:47:27.213Z
Learning: For holiday tests in the vacanza/holidays project, structure tests by individual holidays rather than by years. Each test method should focus on a specific holiday and test it across multiple years (from start_year through 2050) using helper methods like `assertHolidayName`. For fixed holidays, use generators like `(f"{year}-01-01" for year in range(1991, 2051))`. For movable holidays, specify individual dates for specific years followed by a range check.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-03-23T16:59:25.794Z
Learnt from: PPsyrius
PR: vacanza/holidays#2362
File: tests/test_ical.py:31-40
Timestamp: 2025-03-23T16:59:25.794Z
Learning: In the holidays library's `TestIcalExporter` class, initializing `ICalExporter` with `None` is intentional. Using a mock object instead breaks tests because the constructor performs attribute validation with `getattr(self.holidays, "language", None)` which returns a mock with a mock object instead of `None`, causing validation failures. The approach isolates file operation tests from iCal generation logic.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:29:38.042Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:85-86
Timestamp: 2025-04-05T04:29:38.042Z
Learning: For testing holiday implementations in the vacanza/holidays repository, recommend using `from tests.common import CommonCountryTests` as the base class instead of directly using `unittest.TestCase` to maintain consistency with project conventions and leverage common test utilities.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T06:49:06.217Z
Learnt from: PPsyrius
PR: vacanza/holidays#2386
File: tests/countries/test_nepal.py:499-536
Timestamp: 2025-04-05T06:49:06.217Z
Learning: In the holidays project, test files follow a dual testing approach: individual methods test specific holidays across multiple years, while comprehensive year-specific tests (e.g., `test_2025`) verify all holidays for a specific year in a single assertion. Both approaches serve different testing purposes and complement each other.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-09-16T09:44:45.875Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: holidays/countries/hungary.py:46-49
Timestamp: 2025-09-16T09:44:45.875Z
Learning: In the holidays library, using generic variable names like `name` for holiday names within country implementations is acceptable and follows established patterns across other country files, even when the same variable name might be reused for different holidays within the same method.

Applied to files:

  • holidays/utils.py
📚 Learning: 2025-09-04T08:54:35.319Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_albania.py:40-42
Timestamp: 2025-09-04T08:54:35.319Z
Learning: In the vacanza/holidays project test files, extract holiday name strings to local variables only when they are reused multiple times within the same test method (e.g., used in both assertHolidayName and assertNoHolidayName calls). When a holiday name is used only once, keep it inline rather than extracting it to a variable for the sake of consistency.

Applied to files:

  • holidays/utils.py
🧬 Code graph analysis (2)
tests/test_utils.py (2)
holidays/holiday_base.py (1)
  • HolidayBase (57-1304)
holidays/utils.py (1)
  • list_long_weekends (442-491)
holidays/utils.py (2)
holidays/calendars/gregorian.py (1)
  • _timedelta (37-42)
holidays/holiday_base.py (2)
  • get_nth_working_day (1099-1123)
  • _is_weekend (875-882)
🪛 Ruff (0.14.1)
tests/test_utils.py

227-227: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


231-231: Missing return type annotation for special method __init__

Add return type annotation: None

(ANN204)


231-231: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


239-239: Missing return type annotation for special method __contains__

Add return type annotation: bool

(ANN204)


248-248: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


258-258: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


264-264: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


270-270: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


276-276: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


281-281: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


287-287: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


293-293: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)

holidays/utils.py

445-445: Boolean-typed positional argument in function definition

(FBT001)


445-445: Boolean default positional argument in function definition

(FBT002)

🔇 Additional comments (3)
tests/test_utils.py (1)

23-23: LGTM on imports.

The new imports align with the test scaffolding and public API surface.

Also applies to: 32-32

holidays/utils.py (2)

21-21: LGTM on API exposure and import.

Correctly exports the new function and imports the _timedelta helper.

Also applies to: 29-29


447-491: Implementation logic is sound.

The function correctly:

  • Identifies consecutive non-working spans using get_nth_working_day
  • Applies the minimum_holiday_length filter
  • Handles the require_weekend_overlap flag properly using _is_weekend()
  • Prevents duplicate processing via the checked set

The docstring clearly explains parameters and return value. Variable names are descriptive, and the linear control flow is easy to follow.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05d291d and f5f22f8.

📒 Files selected for processing (2)
  • holidays/utils.py (2 hunks)
  • tests/test_utils.py (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-04-05T06:49:06.217Z
Learnt from: PPsyrius
PR: vacanza/holidays#2386
File: tests/countries/test_nepal.py:499-536
Timestamp: 2025-04-05T06:49:06.217Z
Learning: In the holidays project, test files follow a dual testing approach: individual methods test specific holidays across multiple years, while comprehensive year-specific tests (e.g., `test_2025`) verify all holidays for a specific year in a single assertion. Both approaches serve different testing purposes and complement each other.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-08-12T17:16:54.497Z
Learnt from: PPsyrius
PR: vacanza/holidays#2794
File: tests/calendars/test_julian.py:35-36
Timestamp: 2025-08-12T17:16:54.497Z
Learning: In the vacanza/holidays project calendar tests (Thai, Ethiopian, Julian, etc.), the established testing pattern for validation methods is to use simple for loops like `for year in known_data_dict:` followed by `self.assertEqual(expected, actual)` without using unittest's subTest feature. This pattern is consistently maintained across all calendar test files.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:47:27.213Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:52-64
Timestamp: 2025-04-05T04:47:27.213Z
Learning: For holiday tests in the vacanza/holidays project, structure tests by individual holidays rather than by years. Each test method should focus on a specific holiday and test it across multiple years (from start_year through 2050) using helper methods like `assertHolidayName`. For fixed holidays, use generators like `(f"{year}-01-01" for year in range(1991, 2051))`. For movable holidays, specify individual dates for specific years followed by a range check.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-09-10T14:35:54.603Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_brazil.py:28-30
Timestamp: 2025-09-10T14:35:54.603Z
Learning: In the holidays project, the test_no_holidays method should test ALL supported_categories (via categories=CountryClass.supported_categories) rather than just the default PUBLIC category, to ensure comprehensive validation that no holidays exist before start_year across any supported category including OPTIONAL and subdivision categories.

Applied to files:

  • tests/test_utils.py
🧬 Code graph analysis (2)
holidays/utils.py (1)
holidays/holiday_base.py (1)
  • get_nth_working_day (1092-1116)
tests/test_utils.py (1)
holidays/utils.py (1)
  • list_long_weekends (442-487)
🪛 Ruff (0.13.3)
tests/test_utils.py

226-226: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


232-232: Use a regular assert instead of unittest-style assertIsInstance

Replace assertIsInstance(...) with assert ...

(PT009)


233-233: Use a regular assert instead of unittest-style assertTrue

Replace assertTrue(...) with assert ...

(PT009)


237-237: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


241-241: Use a regular assert instead of unittest-style assertIsInstance

Replace assertIsInstance(...) with assert ...

(PT009)


246-246: Use a regular assert instead of unittest-style assertIsInstance

Replace assertIsInstance(...) with assert ...

(PT009)


247-247: Use a regular assert instead of unittest-style assertIsInstance

Replace assertIsInstance(...) with assert ...

(PT009)


248-248: Use a regular assert instead of unittest-style assertIsInstance

Replace assertIsInstance(...) with assert ...

(PT009)


252-252: Use a regular assert instead of unittest-style assertIsInstance

Replace assertIsInstance(...) with assert ...

(PT009)

🔇 Additional comments (1)
holidays/utils.py (1)

21-22: Public API export looks good

Adding list_long_weekends to all aligns with existing naming (list_*).

Comment on lines +223 to +227
financial_files = [
path for path in Path("holidays/financial").glob("*.py") if path.stem != "__init__"
]
self.assertEqual(len(financial_files), len(supported_financial))

Copy link
Contributor

@coderabbitai coderabbitai bot Oct 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Redundant parity check; remove duplicate assertion

You already assert parity at Lines 219-222. Lines 223-227 repeat the same check. Trim the duplicate to keep tests lean.

-        financial_files = [
-            path for path in Path("holidays/financial").glob("*.py") if path.stem != "__init__"
-        ]
-        self.assertEqual(len(financial_files), len(supported_financial))
-
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
financial_files = [
path for path in Path("holidays/financial").glob("*.py") if path.stem != "__init__"
]
self.assertEqual(len(financial_files), len(supported_financial))
🧰 Tools
🪛 Ruff (0.13.3)

226-226: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)

🤖 Prompt for AI Agents
In tests/test_utils.py around lines 223 to 227, there's a duplicate parity
assertion that repeats the check already made at lines 219-222; remove the
redundant block (lines 223-227) so only the original parity assertion remains,
keeping the test lean and avoiding duplicate checks.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the bot says, this section is currently duplicate of the refactored tests above and should be removed

Suggested change
financial_files = [
path for path in Path("holidays/financial").glob("*.py") if path.stem != "__init__"
]
self.assertEqual(len(financial_files), len(supported_financial))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PPsyrius, understood! The duplicate assertion in lines 223-227 should indeed be removed since it repeats the same parity check already performed at lines 219-222. Both count the financial files and verify they match supported_financial, making the second one redundant.

@codecov
Copy link

codecov bot commented Oct 10, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (53853df) to head (fafc47f).

Additional details and impacted files
@@            Coverage Diff            @@
##               dev     #3001   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          306       306           
  Lines        18062     18085   +23     
  Branches      2333      2339    +6     
=========================================
+ Hits         18062     18085   +23     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (2)
tests/test_utils.py (2)

224-228: Remove duplicate parity assertion (already checked above).

This repeats the parity check done at Lines 220-223. Trim to avoid double work.

-        financial_files = [
-            path for path in Path("holidays/financial").glob("*.py") if path.stem != "__init__"
-        ]
-        self.assertEqual(len(financial_files), len(supported_financial))
-

244-249: Add a cross‑year boundary test (New Year’s).

Covers spans that start in prior year. Mirrors the feature’s doc intent.

 class TestListLongWeekends(unittest.TestCase):
@@
     def test_no_holidays(self):
         instance = MockHolidayBase([])
         result = list_long_weekends(instance)
         self.assertEqual(result, [])
+
+    def test_cross_year_boundary(self):
+        # US 2024: New Year's Day on Monday yields Sat 2023‑12‑30 to Mon 2024‑01‑01.
+        us = holidays.country_holidays("US", years=2024)
+        result = list_long_weekends(us)
+        self.assertTrue(any(start.year == 2023 and end.year == 2024 for start, end in result))

Based on learnings

Also applies to: 250-259, 260-271, 272-278

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f5f22f8 and 99fb88a.

📒 Files selected for processing (2)
  • holidays/utils.py (2 hunks)
  • tests/test_utils.py (3 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-14T17:17:14.387Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py:209-209
Timestamp: 2025-09-14T17:17:14.387Z
Learning: In tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py, the explicit loop iteration pattern for subdivision-specific holiday checks (like Anniversary Day for TA subdivision) is intentionally preferred over using assertSubdivTa helper methods, as confirmed by PPsyrius.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:47:27.213Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:52-64
Timestamp: 2025-04-05T04:47:27.213Z
Learning: For holiday tests in the vacanza/holidays project, structure tests by individual holidays rather than by years. Each test method should focus on a specific holiday and test it across multiple years (from start_year through 2050) using helper methods like `assertHolidayName`. For fixed holidays, use generators like `(f"{year}-01-01" for year in range(1991, 2051))`. For movable holidays, specify individual dates for specific years followed by a range check.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:29:38.042Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:85-86
Timestamp: 2025-04-05T04:29:38.042Z
Learning: For testing holiday implementations in the vacanza/holidays repository, recommend using `from tests.common import CommonCountryTests` as the base class instead of directly using `unittest.TestCase` to maintain consistency with project conventions and leverage common test utilities.

Applied to files:

  • tests/test_utils.py
🧬 Code graph analysis (2)
tests/test_utils.py (2)
holidays/holiday_base.py (1)
  • HolidayBase (57-1304)
holidays/utils.py (1)
  • list_long_weekends (442-477)
holidays/utils.py (1)
holidays/holiday_base.py (1)
  • get_nth_working_day (1099-1123)
🪛 Ruff (0.14.0)
tests/test_utils.py

227-227: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


231-231: Missing return type annotation for special method __init__

Add return type annotation: None

(ANN204)


231-231: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


239-239: Missing return type annotation for special method __contains__

Add return type annotation: bool

(ANN204)


248-248: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


258-258: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


264-264: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


270-270: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


276-276: Use a regular assert instead of unittest-style assertTrue

Replace assertTrue(...) with assert ...

(PT009)


277-277: Use a regular assert instead of unittest-style assertTrue

Replace assertTrue(...) with assert ...

(PT009)


282-282: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)

holidays/utils.py

444-444: Boolean-typed positional argument in function definition

(FBT001)


444-444: Boolean default positional argument in function definition

(FBT002)

🔇 Additional comments (2)
tests/test_utils.py (1)

279-282: LGTM: empty input returns empty list.

holidays/utils.py (1)

21-21: Public API export looks good.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
tests/test_utils.py (2)

224-228: Remove the duplicate parity assertion.

This repeats the same check from lines 220-223. One assertion is enough.

-        financial_files = [
-            path for path in Path("holidays/financial").glob("*.py") if path.stem != "__init__"
-        ]
-        self.assertEqual(len(financial_files), len(supported_financial))
-

230-234: Fix the mutable default argument.

The weekend={5, 6} default is mutable (Ruff B006). Replace with None and initialize inside the method:

-    def __init__(self, holidays, weekend={5, 6}):
+    def __init__(self, holidays, weekend=None):
         super().__init__()
         self._holidays = set(holidays)
-        self.weekend = weekend
+        self.weekend = weekend if weekend is not None else {5, 6}

Optionally, add type hints for clarity:

-    def __init__(self, holidays, weekend=None):
+    def __init__(self, holidays, weekend=None) -> None:
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 99fb88a and 1ae8ed4.

📒 Files selected for processing (2)
  • holidays/utils.py (2 hunks)
  • tests/test_utils.py (3 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-09-14T17:17:14.387Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py:209-209
Timestamp: 2025-09-14T17:17:14.387Z
Learning: In tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py, the explicit loop iteration pattern for subdivision-specific holiday checks (like Anniversary Day for TA subdivision) is intentionally preferred over using assertSubdivTa helper methods, as confirmed by PPsyrius.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:47:27.213Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:52-64
Timestamp: 2025-04-05T04:47:27.213Z
Learning: For holiday tests in the vacanza/holidays project, structure tests by individual holidays rather than by years. Each test method should focus on a specific holiday and test it across multiple years (from start_year through 2050) using helper methods like `assertHolidayName`. For fixed holidays, use generators like `(f"{year}-01-01" for year in range(1991, 2051))`. For movable holidays, specify individual dates for specific years followed by a range check.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-03-23T16:59:25.794Z
Learnt from: PPsyrius
PR: vacanza/holidays#2362
File: tests/test_ical.py:31-40
Timestamp: 2025-03-23T16:59:25.794Z
Learning: In the holidays library's `TestIcalExporter` class, initializing `ICalExporter` with `None` is intentional. Using a mock object instead breaks tests because the constructor performs attribute validation with `getattr(self.holidays, "language", None)` which returns a mock with a mock object instead of `None`, causing validation failures. The approach isolates file operation tests from iCal generation logic.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:29:38.042Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:85-86
Timestamp: 2025-04-05T04:29:38.042Z
Learning: For testing holiday implementations in the vacanza/holidays repository, recommend using `from tests.common import CommonCountryTests` as the base class instead of directly using `unittest.TestCase` to maintain consistency with project conventions and leverage common test utilities.

Applied to files:

  • tests/test_utils.py
🧬 Code graph analysis (2)
tests/test_utils.py (2)
holidays/holiday_base.py (1)
  • HolidayBase (57-1304)
holidays/utils.py (1)
  • list_long_weekends (442-480)
holidays/utils.py (1)
holidays/holiday_base.py (2)
  • get_nth_working_day (1099-1123)
  • is_weekend (1148-1158)
🪛 Ruff (0.14.0)
tests/test_utils.py

227-227: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


231-231: Missing return type annotation for special method __init__

Add return type annotation: None

(ANN204)


231-231: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


239-239: Missing return type annotation for special method __contains__

Add return type annotation: bool

(ANN204)


248-248: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


258-258: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


264-264: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


270-270: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


276-276: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


281-281: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)

holidays/utils.py

444-444: Boolean-typed positional argument in function definition

(FBT001)


444-444: Boolean default positional argument in function definition

(FBT002)

🔇 Additional comments (1)
tests/test_utils.py (1)

243-281: Good test coverage of core scenarios.

The tests cover the main cases well: basic long weekends, multiple holidays, the inclusion flag, custom weekends, and empty input.

Consider adding an edge case test for long weekends that span year boundaries (e.g., Dec 31 + Jan 1) if you want even more thorough coverage, but what's here is solid.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
holidays/utils.py (1)

442-446: Fix the function signature: import date, use plain bool, make parameter keyword-only.

Three issues here:

  1. Critical: The return type should be list[list[date]], but date isn't imported. Add it to line 26.
  2. Optional[bool] is redundant—bool can't be None. Use bool directly.
  3. The boolean parameter should be keyword-only to prevent accidental positional usage.

Apply these changes:

-from datetime import timedelta
+from datetime import date, timedelta
 def list_long_weekends(
     instance: HolidayBase,
+    *,
     minimum_holiday_length: int = 3,
-    require_weekend_overlap: Optional[bool] = True,
+    require_weekend_overlap: bool = True,
-) -> list:
+) -> list[list[date]]:
tests/test_utils.py (1)

243-281: Consider strengthening the test suite with invariant checks and edge cases.

The current tests validate the happy path well. Adding a few defensive checks would make the suite more robust:

  1. Invariant assertion: Verify that all returned blocks satisfy length >= minimum_holiday_length (currently hardcoded as 3 in tests).
  2. Cross-year boundary: Add a test where a long weekend spans Dec 31 → Jan 1 to confirm the function handles year transitions correctly.
  3. Invalid subdivision: Mirror the test_invalid_country_subdivision_raises_not_implemented pattern from TestCountryHolidays if applicable.

Example additions:

def test_minimum_length_invariant(self):
    holidays = [date(2025, 7, 4), date(2025, 12, 26)]
    instance = MockHolidayBase(holidays)
    result = list_long_weekends(instance)
    # Verify all blocks are >= 3 days
    self.assertTrue(all(len(block) >= 3 for block in result))

def test_cross_year_boundary(self):
    # Jan 1, 2024 (Monday) → weekend Sat-Sun Dec 30-31, 2023
    holidays = [date(2024, 1, 1)]
    instance = MockHolidayBase(holidays)
    result = list_long_weekends(instance)
    # Verify at least one block spans years
    self.assertTrue(any(block[0].year != block[-1].year for block in result if block))
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ae8ed4 and 0eacdcf.

📒 Files selected for processing (2)
  • holidays/utils.py (2 hunks)
  • tests/test_utils.py (3 hunks)
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-09-16T09:44:45.875Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: holidays/countries/hungary.py:46-49
Timestamp: 2025-09-16T09:44:45.875Z
Learning: In the holidays library, using generic variable names like `name` for holiday names within country implementations is acceptable and follows established patterns across other country files, even when the same variable name might be reused for different holidays within the same method.

Applied to files:

  • holidays/utils.py
📚 Learning: 2025-09-04T08:54:35.319Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_albania.py:40-42
Timestamp: 2025-09-04T08:54:35.319Z
Learning: In the vacanza/holidays project test files, extract holiday name strings to local variables only when they are reused multiple times within the same test method (e.g., used in both assertHolidayName and assertNoHolidayName calls). When a holiday name is used only once, keep it inline rather than extracting it to a variable for the sake of consistency.

Applied to files:

  • holidays/utils.py
📚 Learning: 2025-09-14T17:17:14.387Z
Learnt from: PPsyrius
PR: vacanza/holidays#2881
File: tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py:209-209
Timestamp: 2025-09-14T17:17:14.387Z
Learning: In tests/countries/test_saint_helena_ascension_and_tristan_da_cunha.py, the explicit loop iteration pattern for subdivision-specific holiday checks (like Anniversary Day for TA subdivision) is intentionally preferred over using assertSubdivTa helper methods, as confirmed by PPsyrius.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:47:27.213Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:52-64
Timestamp: 2025-04-05T04:47:27.213Z
Learning: For holiday tests in the vacanza/holidays project, structure tests by individual holidays rather than by years. Each test method should focus on a specific holiday and test it across multiple years (from start_year through 2050) using helper methods like `assertHolidayName`. For fixed holidays, use generators like `(f"{year}-01-01" for year in range(1991, 2051))`. For movable holidays, specify individual dates for specific years followed by a range check.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-03-23T16:59:25.794Z
Learnt from: PPsyrius
PR: vacanza/holidays#2362
File: tests/test_ical.py:31-40
Timestamp: 2025-03-23T16:59:25.794Z
Learning: In the holidays library's `TestIcalExporter` class, initializing `ICalExporter` with `None` is intentional. Using a mock object instead breaks tests because the constructor performs attribute validation with `getattr(self.holidays, "language", None)` which returns a mock with a mock object instead of `None`, causing validation failures. The approach isolates file operation tests from iCal generation logic.

Applied to files:

  • tests/test_utils.py
📚 Learning: 2025-04-05T04:29:38.042Z
Learnt from: PPsyrius
PR: vacanza/holidays#2416
File: tests/countries/test_turkmenistan.py:85-86
Timestamp: 2025-04-05T04:29:38.042Z
Learning: For testing holiday implementations in the vacanza/holidays repository, recommend using `from tests.common import CommonCountryTests` as the base class instead of directly using `unittest.TestCase` to maintain consistency with project conventions and leverage common test utilities.

Applied to files:

  • tests/test_utils.py
🧬 Code graph analysis (2)
holidays/utils.py (1)
holidays/holiday_base.py (2)
  • get_nth_working_day (1099-1123)
  • is_weekend (1148-1158)
tests/test_utils.py (2)
holidays/holiday_base.py (1)
  • HolidayBase (57-1304)
holidays/utils.py (1)
  • list_long_weekends (442-500)
🪛 Ruff (0.14.1)
holidays/utils.py

445-445: Boolean-typed positional argument in function definition

(FBT001)


445-445: Boolean default positional argument in function definition

(FBT002)

tests/test_utils.py

227-227: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


231-231: Missing return type annotation for special method __init__

Add return type annotation: None

(ANN204)


231-231: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


239-239: Missing return type annotation for special method __contains__

Add return type annotation: bool

(ANN204)


248-248: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


258-258: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


264-264: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


270-270: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


276-276: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)


281-281: Use a regular assert instead of unittest-style assertEqual

Replace assertEqual(...) with assert ...

(PT009)

Comment on lines +457 to +459
require_weekend_overlap:
Whether to include consecutive holidays that do not contain any weekend days.
Defaults to True.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Param description seems reversed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the param name is changed I changed its default value to True and made changes to the code wherever required.

require_weekend_overlap makes more sense with its default value being True.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean that the description "Whether to include consecutive holidays that do not contain any weekend days" can be understood as "If True, include consecutive holidays that do not contain..."

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
require_weekend_overlap:
Whether to include consecutive holidays that do not contain any weekend days.
Defaults to True.
require_weekend_overlap:
Whether to include only consecutive holidays that overlap with a weekend.
Defaults to True.

@sonarqubecloud
Copy link

Comment on lines +457 to +459
require_weekend_overlap:
Whether to include consecutive holidays that do not contain any weekend days.
Defaults to True.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
require_weekend_overlap:
Whether to include consecutive holidays that do not contain any weekend days.
Defaults to True.
require_weekend_overlap:
Whether to include only consecutive holidays that overlap with a weekend.
Defaults to True.

Comment on lines +223 to +227
financial_files = [
path for path in Path("holidays/financial").glob("*.py") if path.stem != "__init__"
]
self.assertEqual(len(financial_files), len(supported_financial))

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the bot says, this section is currently duplicate of the refactored tests above and should be removed

Suggested change
financial_files = [
path for path in Path("holidays/financial").glob("*.py") if path.stem != "__init__"
]
self.assertEqual(len(financial_files), len(supported_financial))

import pytest

import holidays
from holidays.holiday_base import HolidayBase
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from holidays.holiday_base import HolidayBase
from holidays.calendars.gregorian import FRI, SAT, SUN
from holidays.holiday_base import HolidayBase

Comment on lines +231 to +234
def __init__(self, holidays, weekend={5, 6}):
super().__init__()
self._holidays = set(holidays)
self.weekend = weekend
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def __init__(self, holidays, weekend={5, 6}):
super().__init__()
self._holidays = set(holidays)
self.weekend = weekend
def __init__(self, holidays: set[date], weekend: set[int] | None = None) -> None:
super().__init__()
self._holidays = set(holidays)
self.weekend = weekend or {SAT, SUN}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would apply the same approach here as in test_holiday_base - country stubs with the necessary sets of holidays and weekends.

Comment on lines +239 to +240
def __contains__(self, d):
return d in self._holidays
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def __contains__(self, d):
return d in self._holidays
def __contains__(self, day):
return day in self._holidays

Comment on lines +243 to +293
class TestListLongWeekends(unittest.TestCase):
def test_simple_long_weekend(self):
holidays = [date(2025, 7, 4)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance)
self.assertEqual(result, [[date(2025, 7, 4), date(2025, 7, 5), date(2025, 7, 6)]])

def test_multiple_holidays(self):
holidays = [date(2025, 7, 4), date(2025, 12, 26)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance)
expected = [
[date(2025, 7, 4), date(2025, 7, 5), date(2025, 7, 6)],
[date(2025, 12, 26), date(2025, 12, 27), date(2025, 12, 28)],
]
self.assertEqual(result, expected)

def test_three_holidays_no_weekend(self):
holidays = [date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance)
self.assertEqual(result, [])

def test_three_holidays_included_with_flag(self):
holidays = [date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance, require_weekend_overlap=False)
self.assertEqual(result, [[date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]])

def test_custom_weekend(self):
holidays = [date(2025, 4, 10)]
instance = MockHolidayBase(holidays, weekend={4, 5})
result = list_long_weekends(instance)
self.assertEqual(result, [[date(2025, 4, 10), date(2025, 4, 11), date(2025, 4, 12)]])

def test_no_holidays(self):
instance = MockHolidayBase([])
result = list_long_weekends(instance)
self.assertEqual(result, [])

def test_no_weekend_overlap(self):
holidays = [date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance, require_weekend_overlap=False)
self.assertEqual(result, [[date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]])

def test_holidays_less_than_three_days(self):
holidays = [date(2025, 5, 3)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance)
self.assertEqual(result, [])
Copy link
Collaborator

@PPsyrius PPsyrius Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did change this to use a common helper method, merge some similar test cases and add some missing ones (the ones which has long weekends straddling across 2 years, as well as real country and financial holidays examples)

Suggested change
class TestListLongWeekends(unittest.TestCase):
def test_simple_long_weekend(self):
holidays = [date(2025, 7, 4)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance)
self.assertEqual(result, [[date(2025, 7, 4), date(2025, 7, 5), date(2025, 7, 6)]])
def test_multiple_holidays(self):
holidays = [date(2025, 7, 4), date(2025, 12, 26)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance)
expected = [
[date(2025, 7, 4), date(2025, 7, 5), date(2025, 7, 6)],
[date(2025, 12, 26), date(2025, 12, 27), date(2025, 12, 28)],
]
self.assertEqual(result, expected)
def test_three_holidays_no_weekend(self):
holidays = [date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance)
self.assertEqual(result, [])
def test_three_holidays_included_with_flag(self):
holidays = [date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance, require_weekend_overlap=False)
self.assertEqual(result, [[date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]])
def test_custom_weekend(self):
holidays = [date(2025, 4, 10)]
instance = MockHolidayBase(holidays, weekend={4, 5})
result = list_long_weekends(instance)
self.assertEqual(result, [[date(2025, 4, 10), date(2025, 4, 11), date(2025, 4, 12)]])
def test_no_holidays(self):
instance = MockHolidayBase([])
result = list_long_weekends(instance)
self.assertEqual(result, [])
def test_no_weekend_overlap(self):
holidays = [date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance, require_weekend_overlap=False)
self.assertEqual(result, [[date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]])
def test_holidays_less_than_three_days(self):
holidays = [date(2025, 5, 3)]
instance = MockHolidayBase(holidays)
result = list_long_weekends(instance)
self.assertEqual(result, [])
class TestListLongWeekends(unittest.TestCase):
def assertLongWeekendsEqual( # noqa: N802
self,
holidays,
expected,
weekend=None,
minimum_holiday_length=3,
*,
require_weekend_overlap=True,
):
instance = MockHolidayBase(holidays, weekend=weekend or {SAT, SUN})
result = list_long_weekends(
instance,
minimum_holiday_length=minimum_holiday_length,
require_weekend_overlap=require_weekend_overlap,
)
self.assertEqual(result, expected)
def test_long_weekend_single(self):
self.assertLongWeekendsEqual(
[date(2025, 7, 4)],
[[date(2025, 7, 4), date(2025, 7, 5), date(2025, 7, 6)]],
)
def test_long_weekend_multiple(self):
self.assertLongWeekendsEqual(
[date(2025, 7, 4), date(2025, 12, 26)],
[
[date(2025, 7, 4), date(2025, 7, 5), date(2025, 7, 6)],
[date(2025, 12, 26), date(2025, 12, 27), date(2025, 12, 28)],
],
)
def test_long_weekend_require_weekend_overlap(self):
self.assertLongWeekendsEqual(
[date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)],
[],
)
self.assertLongWeekendsEqual(
[date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)],
[[date(2025, 3, 4), date(2025, 3, 5), date(2025, 3, 6)]],
require_weekend_overlap=False,
)
def test_long_weekend_custom_weekend(self):
self.assertLongWeekendsEqual(
[date(2025, 4, 10)],
[[date(2025, 4, 10), date(2025, 4, 11), date(2025, 4, 12)]],
weekend={FRI, SAT},
)
def test_long_weekend_no_holidays(self):
self.assertLongWeekendsEqual(
[],
[],
)
def test_long_weekend_custom_minimum_length(self):
self.assertLongWeekendsEqual(
[date(2025, 8, 11), date(2025, 8, 12), date(2025, 12, 5)],
[[date(2025, 8, 9), date(2025, 8, 10), date(2025, 8, 11), date(2025, 8, 12)]],
minimum_holiday_length=4,
)
def test_long_weekend_across_years(self):
self.assertLongWeekendsEqual(
[date(2024, 1, 1)],
[[date(2023, 12, 30), date(2023, 12, 31), date(2024, 1, 1)]],
)
self.assertLongWeekendsEqual(
[date(2021, 12, 31)],
[[date(2021, 12, 31), date(2022, 1, 1), date(2022, 1, 2)]],
)
def test_long_weekend_real_country_holidays_data(self):
self.assertEqual(
list_long_weekends(country_holidays("AU", subdiv="NSW", years=2024)),
[
[date(2023, 12, 30), date(2023, 12, 31), date(2024, 1, 1)],
[date(2024, 1, 26), date(2024, 1, 27), date(2024, 1, 28)],
[date(2024, 3, 29), date(2024, 3, 30), date(2024, 3, 31), date(2024, 4, 1)],
[date(2024, 6, 8), date(2024, 6, 9), date(2024, 6, 10)],
[date(2024, 10, 5), date(2024, 10, 6), date(2024, 10, 7)],
],
)
def test_long_weekend_real_financial_holidays_data(self):
self.assertEqual(
list_long_weekends(financial_holidays("XNSE", years=2024)),
[
[date(2024, 1, 26), date(2024, 1, 27), date(2024, 1, 28)],
[date(2024, 3, 8), date(2024, 3, 9), date(2024, 3, 10)],
[date(2024, 3, 23), date(2024, 3, 24), date(2024, 3, 25)],
[date(2024, 3, 29), date(2024, 3, 30), date(2024, 3, 31)],
[date(2024, 6, 15), date(2024, 6, 16), date(2024, 6, 17)],
[date(2024, 11, 1), date(2024, 11, 2), date(2024, 11, 3)],
[date(2024, 11, 15), date(2024, 11, 16), date(2024, 11, 17)],
],
)

Comment on lines +442 to +446
def list_long_weekends(
instance: HolidayBase,
minimum_holiday_length: int = 3,
require_weekend_overlap: Optional[bool] = True,
) -> list:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def list_long_weekends(
instance: HolidayBase,
minimum_holiday_length: int = 3,
require_weekend_overlap: Optional[bool] = True,
) -> list:
def list_long_weekends(
instance: HolidayBase, *, minimum_holiday_length: int = 3, require_weekend_overlap: bool = True
) -> list[list[date]]:

To make boolean parameters keyword-only in new code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add get_long_weekends() function to find holiday-based long weekends

3 participants