11import abc
2+ import inspect
23from pathlib import Path
34from typing import Any , ClassVar
45
@@ -15,16 +16,15 @@ def get_day_from_module(module_name: str) -> int:
1516
1617
1718class ChallengeProtocol (Protocol ):
18- def part_1 (self , input_lines : list [str ]) -> Any :
19- ...
19+ def part_1 (self , input_lines : list [str ]) -> Any : ...
2020
21- def part_2 (self , input_lines : list [str ]) -> Any :
22- ...
21+ def part_2 (self , input_lines : list [str ]) -> Any : ...
2322
2423
2524class BaseChallenge (ChallengeProtocol , abc .ABC ):
2625 """Base class for all challenges."""
2726
27+ year : ClassVar [int ]
2828 day : ClassVar [int ]
2929
3030 def __init__ (
@@ -35,6 +35,7 @@ def __init__(
3535 self ._input_lines : dict [int | None , list [str ]] = {}
3636
3737 def __init_subclass__ (cls , ** kwargs ):
38+ cls .year = cls ._get_year ()
3839 cls .day = cls ._get_day ()
3940
4041 @classmethod
@@ -46,6 +47,17 @@ def _get_day(cls) -> int:
4647 return int (Path (__main__ .__file__ ).parent .name .split ("_" )[1 ])
4748 return get_day_from_module (cls .__module__ )
4849
50+ @classmethod
51+ def _get_year (cls ) -> int :
52+ import __main__
53+
54+ """Return the year of this challenge based on the module name."""
55+ if cls .__module__ == "__main__" : # challenge is run directly
56+ return int (Path (__main__ .__file__ ).parent .parent .name )
57+ # when running pytest it doesn't see parent module name due to relative import
58+ path_to_class = Path (inspect .getfile (cls ))
59+ return int (path_to_class .parent .parent .name )
60+
4961 def get_input_lines (self , part : int | None = None ) -> list [str ]:
5062 """Return the input lines for this challenge. Relative to this file"""
5163 if not self ._input_lines .get (part ):
0 commit comments