From 2cd19dfd038762ddf056187533d4e7a77116a47d Mon Sep 17 00:00:00 2001 From: Jens Tirsvad Nielsen Date: Wed, 7 Oct 2026 23:58:37 +0800 Subject: [PATCH] Add project configuration, .gitignore and the package skeleton pyproject.toml declares Python 3.13 or later, an empty runtime dependency list and pytest, ruff and mypy as development tools. The package has constants.py, the one place for constants, and a smoke test keeps the test run green. Task: MIL-001#1 Task: MIL-001#2 Task: MIL-001#3 --- .gitignore | 100 +++++++++++++++++++++++++++++ pyproject.toml | 48 ++++++++++++++ src/turtle_challenges/__init__.py | 7 ++ src/turtle_challenges/constants.py | 15 +++++ tests/__init__.py | 0 tests/test_package.py | 14 ++++ 6 files changed, 184 insertions(+) create mode 100644 .gitignore create mode 100644 pyproject.toml create mode 100644 src/turtle_challenges/__init__.py create mode 100644 src/turtle_challenges/constants.py create mode 100644 tests/__init__.py create mode 100644 tests/test_package.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2e0dd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,100 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Documentation builds (Doxygen writes to build/doxygen, see Doxyfile) +docs/_build/ +doxygen_warnings.log + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Type checkers and linters +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +.ruff_cache/ + +# IDEs and editors +.idea/ +.vscode/ +*.swp +*.swo +.spyderproject +.spyproject +.ropeproject + +# Operating system files +.DS_Store +Thumbs.db +desktop.ini diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..da07083 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,48 @@ +[build-system] +requires = ["setuptools>=77"] +build-backend = "setuptools.build_meta" + +[project] +name = "turtle-challenges" +version = "0.1.0" +description = "Turtle graphics exercises from Udemy's 100 Days of Code Python bootcamp (day 18)." +readme = "README.md" +requires-python = ">=3.13" +license = "AGPL-3.0-only" +license-files = ["LICENSE"] +# Only the standard library is used at run time (turtle needs Tk, see README). +dependencies = [] +classifiers = [ + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.13", + "Topic :: Education", +] + +[project.optional-dependencies] +dev = [ + "mypy>=1.13", + "pytest>=8.3", + "ruff>=0.8", +] + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.pytest.ini_options] +pythonpath = ["src", "."] +testpaths = ["tests"] + +[tool.ruff] +line-length = 88 +target-version = "py313" +src = ["src", "tests"] +# Only the project's own code: the framework submodule and agent skills are not ours. +include = ["src/**/*.py", "tests/**/*.py"] + +[tool.ruff.lint] +select = ["ANN", "B", "E", "F", "I", "N", "SIM", "UP", "W"] + +[tool.mypy] +strict = true +files = ["src", "tests"] +mypy_path = "src" diff --git a/src/turtle_challenges/__init__.py b/src/turtle_challenges/__init__.py new file mode 100644 index 0000000..fda5d58 --- /dev/null +++ b/src/turtle_challenges/__init__.py @@ -0,0 +1,7 @@ +"""! +@file __init__.py +@brief Solutions to the turtle graphics challenges of day 18 of Udemy's +100 Days of Code. + +The challenges are added one milestone at a time; see the README. +""" diff --git a/src/turtle_challenges/constants.py b/src/turtle_challenges/constants.py new file mode 100644 index 0000000..cb2fb0a --- /dev/null +++ b/src/turtle_challenges/constants.py @@ -0,0 +1,15 @@ +"""! +@file constants.py +@brief Every constant of the project, in one place. + +Numbers and names used by the challenges live here and nowhere else, so a +challenge can be tuned (for example the number of dashes) without touching its +drawing code. +""" + +## Title of the turtle window. +WINDOW_TITLE = "Turtle Challenges" + +## Largest value of one color channel; also the turtle color mode, so that +## colors can be given as RGB tuples from 0 to 255. +COLOR_MODE = 255 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_package.py b/tests/test_package.py new file mode 100644 index 0000000..0470738 --- /dev/null +++ b/tests/test_package.py @@ -0,0 +1,14 @@ +import turtle_challenges +from turtle_challenges import constants + + +def test_package_can_be_imported_and_is_documented() -> None: + assert turtle_challenges.__doc__ + + +def test_color_mode_is_the_rgb_range_of_the_course() -> None: + assert constants.COLOR_MODE == 255 + + +def test_window_title_is_not_empty() -> None: + assert constants.WINDOW_TITLE