2024 Advent of Code
The countdown has now begun for Advent of Code and it’s time to start getting ready for the challenges ahead.
This year I’m breaking from my usual tactic of trying to learn a new language and instead I’ll be using a language I’ve used before albeit one which I now have more experience with. So this year, my language of choice will be 🥁🥁🥁 Python.
I last used Python for AoC in 2021, it got me to 31 🌟 before I ran out of steam. At the time the project was very much like a hack project, I didn’t have a build pipeline, use a test framework or any linting tools. So this time I’m going to start as I have in the last couple of years and get a process in place ready for solving the puzzles.
Getting set up
A little while ago I created a barebones-python repo that I could use for creating new python projects, I even blogged about it. The bad news is I haven’t touched this in over 12 months so the versions are no longer the latest. This is an opportunity though, I can take that project as a base and then “upgrade” it. In reality, this upgrade should be simple as there is no code in the barebones project but we shall see.
As always, my very first step is to create my public GitHub repo, this years repo will be unimaginatively titled 2024-advent-of-code.
Cloning the git repo
This is standard but the URL I use isn’t, this is because of the Git setup on my machine. I’ve been meaning to write about this each AoC period and then promptly forget for 12 months, this year might be the year though 🙄.
1╰─❯ git clone git@github-andrewfitzy:andrewfitzy/2024-advent-of-code.git
Copying barebones
For this step I’m going to take the lazy approach of cloning barebones-python and copying all but the .git
folder, README.md
file and requirements*.txt
files into the 2024-advent-of-code repo. I will then have my 2024 repo ready to be updated.
1╰─❯ cp .github .gitignore .pre-commit-config.yaml LICENSE pyproject.toml requirements-dev.in requirements.in src tests ../2024-advent-of-code
2cp: .github is a directory (not copied).
3cp: src is a directory (not copied).
4cp: tests is a directory (not copied).
cp
couldn’t copy directories and subfiles as I missed a flag 😖
1╰─❯ cp -R .github src tests ../2024-advent-of-code
Thankyou StackOverflow.
The upgrades
The barebones repo has a bunch of versioned dependencies, for this exercise I will make the following changes:
As Is | Action | To Be |
---|---|---|
Python 3.11 | Upgrade | Python 3.13.0 |
ruff 0.1.0 | Upgrade | ruff 0.8.0 |
Black 23.9.1 | Remove | |
iSort 5.12.0 | Upgrade | iSort 5.13.2 |
pytest 7.4.2 | Upgrade | pytest 8.3.3 |
pytest-cov 4.1.0 | Upgrade | pytest-cov 6.0.0 |
Pre-commit 3.5.0 | Upgrade | Pre-commit 4.0.1 |
pip 24.2 | Replace | uv 0.5.4 |
Python First step is to create my virtual environment for Python 3.13
1╰─❯ pyenv install 3.13.0
2
3╰─❯ pyenv virtualenv 3.13.0 2024-aoc
4
5╰─❯ pyenv activate 2024-aoc
I use zsh, oh-my-zsh and Powerlevel10k so that I can easily see which virtual environment I have activated at any point in time:
From the barebones repo, there are a couple of places that need updating to cope with python 3.11:
.github/workflows/build-and-test-project.yml
, here we need to set the GitHub build process to use 3.13.pyproject.toml
, here theruff
spec needs updating to set the target Python version to 3.13.
Now that Python is done, we can get on with the other dependencies.
ruff
ruff is used for linting and formatting but is super quick compared to many of the other linting tools as it’s written in Rust. To upgrade the version of ruff
, we need to update the version defined in requirements-dev.in
and also in the .pre-commit-config.yaml
file.
As we are using ruff
we can also use the formatting function to prettify the code, to do this we need to make 2 changes. Firstly, add format
config to pyproject.toml
specifying some of fhe formatting elements that come with Black which we want to keep. Secondly, adding a ruff-format
configuration to the .pre-commit-config.yaml
file so that we can check formatting on commit.
Black
With ruff
installed, there is no need for Black. So the removal path for this library is:
- Remove
black
fromrequirements-dev.in
- Remove
black
from the.pre-commit-config.yaml
file
iSort
iSort keeps our imports in order across files so that they are consistent. There is some configuration in ruff
for iSort
but in this project I will keep them separate, this is partly due to not having the time to investigate the iSort
options in ruff
. iSort
does need an update though so to achieve this:
- Update the
iSort
version inrequirements-dev.in
- Update the
iSort
version in.pre-commit-config.yaml
pytest and pytest-cov
The upgrade of pytest and pytest-cov are simple ones, update the version of each in requirements-dev.in
.
pre-commit
I’m a pre-commit
fanboy, it does lots of the jobs engineering teams have been struggling with applying consistently for years in an easy to use way. The minimum update is to change the version in requirements-dev.in
, however there is also a minimum_pre_commit_version
in .pre-commit-config.yaml
which can also be changed. I don’t think this will have an impact on the project so I’ll leave it as-is for now.
uv
The barebones project doesn’t have a Makefile
. To better replace pip
with uv, I’ll create a makefile so that I don’t forget the uv
command and regress to using pip
.
I will also want uv
to install the dependencies when the GitHub actions are running, to do this a new section needs to be added ot the .github/workflows/build-and-test-project.yml
file so that uv
can be prepended to the pip install
line
Code setup
In theory that is the environment set up. I want my repo to be more representative of my AoC workflow though so there are just a couple of extra things to do. I’ll create a day_xx
namespace in /src
and /tests
, this will hold the template files that I can copy each day prior to creating the day’s solution.
One important note for any participant in AoC is that the puzzle inputs should not be committed to git, this has been requested several times by the creators of AoC. To prevent me accidentally doing this, I’ll add input*.txt
to my .gitignore
but only after I’ve done the first commit.
The final bit of setup is to create a file that will duplicate the day_xx
folder for each day that I am attempting to solve. Again I will be lazy here and copy the one from my 2021 repo.
Testing and committing
With all this done, I first need to test the local configuration:
1╰─❯ make test
2pytest --cov-fail-under=80 --cov=src/ --cov-report=term-missing --cov-report=xml
3================================================================== test session starts ===================================================================
4platform darwin -- Python 3.13.0, pytest-8.3.3, pluggy-1.5.0
5rootdir: /Users/andrew.fitzpatrick/Personal/git/2024-advent-of-code
6configfile: pyproject.toml
7testpaths: tests/
8plugins: cov-6.0.0
9collected 2 items
10
11tests/day_xx/test_task_01.py . [ 50%]
12tests/day_xx/test_task_02.py . [100%]
13
14---------- coverage: platform darwin, python 3.13.0-final-0 ----------
15Name Stmts Miss Cover Missing
16-----------------------------------------------------
17src/day_xx/task_01.py 2 0 100%
18src/day_xx/task_02.py 2 0 100%
19-----------------------------------------------------
20TOTAL 4 0 100%
21
222 empty files skipped.
23Coverage XML written to file coverage.xml
24
25Required test coverage of 80% reached. Total coverage: 100.00%
26
27=================================================================== 2 passed in 0.06s ====================================================================
Great, all tests have passed. Next test is of the pre-commit hooks, after installing the hooks they should kick in when trying to commit the project files
1╰─❯ pre-commit install
2pre-commit installed at .git/hooks/pre-commit
3
4╰─❯ git add --all
5
6╰─❯ git commit -a
7ruff.....................................................................Passed
8ruff-format..............................................................Failed
9- hook id: ruff-format
10- files were modified by this hook
11
12╰─❯ git commit -a
13ruff.....................................................................Passed
14ruff-format..............................................................Passed
15isort....................................................................Failed
16- hook id: isort
17- files were modified by this hook
18
19Fixing /Users/andrew.fitzpatrick/Personal/git/2024-advent-of-code/tests/day_xx/test_task_01.py
20Fixing /Users/andrew.fitzpatrick/Personal/git/2024-advent-of-code/tests/day_xx/test_task_02.py
21
22╰─❯ git commit -a
23ruff.....................................................................Passed
24ruff-format..............................................................Passed
25isort....................................................................Passed
26[main 1222a03] Initial commit, barebones needed for AoC 2024
27 22 files changed, 273 insertions(+), 5 deletions(-)
It took three attempts but I was able to commit my changes locally. After a quick push to main the GitHub workflow kicked in, and we can see that the first build passes:
Next stop, 1st December and first Advent of Code challenge.