Skip to content

Commit 557a646

Browse files
authored
improve date introspection to work with example like adventofcode/202… (#96)
1 parent a7c5824 commit 557a646

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

aocd/get.py

+25-3
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@ def get_day_and_year():
9797
"""
9898
pattern_year = r"201[5-9]|202[0-9]"
9999
pattern_day = r"2[0-5]|1[0-9]|[1-9]"
100+
pattern_path = re.escape(os.sep) + re.escape(os.sep).join([r"20\d\d", r"[0-2]?\d", r".*\.py$"])
101+
visited = []
102+
103+
def giveup(msg):
104+
log.info("introspection failure")
105+
for fname in visited:
106+
log.info("stack crawl visited %s", fname)
107+
return AocdError(msg)
108+
100109
for frame in traceback.extract_stack():
101110
filename = frame[0]
102111
linetxt = frame[-1] or ""
@@ -112,6 +121,7 @@ def get_day_and_year():
112121
"aocd" not in linetxt,
113122
"ipykernel" in filename,
114123
]
124+
visited.append(filename)
115125
if not any(reasons_to_skip_frame):
116126
log.debug("stack crawl found %s", filename)
117127
abspath = os.path.abspath(filename)
@@ -126,6 +136,18 @@ def get_day_and_year():
126136
if abspath and re.search(pattern_day, abspath):
127137
basename = os.path.basename(abspath)
128138
break
139+
elif re.search(pattern_path, filename):
140+
year = day = None
141+
for part in filename.split(os.sep):
142+
if not part.isdigit():
143+
continue
144+
if len(part) == 4:
145+
year = int(part)
146+
elif 1 <= len(part) <= 2:
147+
day = int(part)
148+
if year is not None and day is not None:
149+
log.debug("year=%s day=%s filename=%s", year, day, filename)
150+
return day, year
129151
log.debug("skipping frame %s", filename)
130152
else:
131153
import __main__
@@ -135,10 +157,10 @@ def get_day_and_year():
135157
year = most_recent_year()
136158
return day, year
137159
log.debug("non-interactive")
138-
raise AocdError("Failed introspection of filename")
160+
raise giveup("Failed introspection of filename")
139161
years = {int(year) for year in re.findall(pattern_year, abspath)}
140162
if len(years) > 1:
141-
raise AocdError("Failed introspection of year")
163+
raise giveup("Failed introspection of year")
142164
year = years.pop() if years else None
143165
basename_no_years = re.sub(pattern_year, "", basename)
144166
try:
@@ -152,4 +174,4 @@ def get_day_and_year():
152174
log.debug("year=%s day=%s", year or "?", day)
153175
return day, year
154176
log.debug("giving up introspection for %s", abspath)
155-
raise AocdError("Failed introspection of day")
177+
raise giveup("Failed introspection of day")

aocd/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.3.0"
1+
__version__ = "1.3.1"

tests/test_date_introspection.py

+11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
import pytest
24

35
from aocd.exceptions import AocdError
@@ -61,3 +63,12 @@ def test_ipynb_fail_no_numbers_in_ipynb_filename(mocker):
6163
mocker.patch("aocd.get.get_ipynb_path", "puzzle.py")
6264
with pytest.raises(AocdError("Failed introspection of filename")):
6365
get_day_and_year()
66+
67+
68+
def test_no_numbers_in_py_filename_but_date_in_abspath(mocker):
69+
fname = os.sep.join(["adventofcode", "2022", "02", "main.py"])
70+
fake_stack = [(fname, 1, "<test>", "from aocd import data")]
71+
mocker.patch("aocd.get.traceback.extract_stack", return_value=fake_stack)
72+
day, year = get_day_and_year()
73+
assert day == 2
74+
assert year == 2022

0 commit comments

Comments
 (0)