diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml
index 33f47f541e4..528105a1eec 100644
--- a/.github/workflows/ci-workflow.yml
+++ b/.github/workflows/ci-workflow.yml
@@ -6,7 +6,6 @@ name: Exercises check
on:
push:
branches:
- - master
- main
pull_request:
@@ -19,7 +18,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548
with:
- python-version: 3.11.2
+ python-version: 3.13.5
- name: Download & Install dependencies
run: |
@@ -53,7 +52,7 @@ jobs:
needs: housekeeping
strategy:
matrix:
- python-version: [3.7, 3.8, 3.9, 3.10.6, 3.11.2]
+ python-version: [3.10.6, 3.11.2, 3.12, 3.13.5]
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
@@ -61,12 +60,8 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- - name: Install dataclasses package
- if: ${{ matrix.python-version == '3.6' }}
- run: pip install dataclasses
-
- name: Install pytest
- run: pip install pytest~=7.2.2
+ run: pip install pytest~=8.4.0
- name: Check exercises
run: |
diff --git a/.github/workflows/test-runner.yml b/.github/workflows/test-runner.yml
index f32c41b958a..c009ed1b820 100644
--- a/.github/workflows/test-runner.yml
+++ b/.github/workflows/test-runner.yml
@@ -8,7 +8,7 @@ on:
jobs:
test-runner:
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- name: Run test-runner
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d9c30d85e0a..6ff557f7087 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -32,9 +32,9 @@ Hi. ๐๐ฝ ๐ **We are happy you are here.** ๐&nb
**`exercism/Python`** is one of many programming language tracks on [exercism(dot)org][exercism-website].
This repo holds all the instructions, tests, code, & support files for Python _exercises_ currently under development or implemented & available for students.
-๐ Track exercises support Python `3.7` - `3.11.5`.
+๐ Track exercises support Python `3.10` - `3.13.5`.
Exceptions to this support are noted where they occur.
-๐ Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.11.2`.
+๐ Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.13.5`.
Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree ๐ด .
Concept exercises are constrained to a small set of language or syntax features.
@@ -71,15 +71,14 @@ We're leaving the track contributing docs below for our long-term collaborators
In General
-- Maintainers are happy to review your work and help troubleshoot with you. ๐ ๐
+- Maintainers are happy to review your work and help troubleshoot with you. ๐ ๐ If you need help, comment in the Pull Request/issue. ๐๐ฝโโ๏ธ
+ - **Please wait at least 72 hours before pinging or `@`ing reviewers directly.**
- Requests are reviewed as soon as is practical/possible.
- - (โ ) Reviewers may be in a different timezone โ , or tied up ๐งถ with other tasks.
- - **Please wait at least 72 hours before pinging.**
-- If you need help, comment in the Pull Request/issue. ๐๐ฝโโ๏ธ
+ - (โ ) Keep in mind that reviewers may be in a different timezone โ , or tied up ๐งถ with other tasks.
- If you would like in-progress feedback/discussion, please mark your Pull Request as a **`[draft]`**
- Pull Requests should be focused around a single exercise, issue, or change.
- Pull Request titles and descriptions should make clear **what** has changed and **why**.
- - Please link ๐ to any related issues the PR addresses.
+ - Please link ๐ to any related forum discussions or issues the PR addresses.
- ๐ [ Open an issue ][open-an-issue]๐ and discuss it with ๐งฐ maintainers _**before**_:
- creating a Pull Request making significant or breaking changes.
- for changes across multiple exercises, even if they are typos or small.
@@ -204,13 +203,13 @@ _We know it, and trust us, we are working on fixing it._ But if you see
-This track officially supports Python `3.7 - 3.11.2` for students completing exercises.
-The track `test runner`, `analyzer`, and `representer` run in docker on `python:3.11.2-slim`.
+This track officially supports Python `3.10 - 3.13.5` for students completing exercises.
+The track `test runner`, `analyzer`, and `representer` run in docker on `python:3.13.5-alpine3.22`.
Although the majority of test cases are written using `unittest.TestCase`,
-- All exercises should be written for compatibility with Python `3.7` - `3.11.2`.
-- Version backward _incompatibility_ (_e.g_ an exercise using features introduced in `3.8`, `3.9`, or `3.10`) should be clearly noted in any exercise hints, links, introductions or other notes.
+- All exercises should be written for compatibility with Python `3.10` - `3.13.5`.
+- Version backward _incompatibility_ (_e.g_ an exercise using features introduced in Python `3.10`+ that would not work in Python `3.10`) should be clearly noted in any exercise hints, links, introductions or other notes.
- Here is an example of how the Python documentation handles [version-tagged ๐ท ][version-tagged-language-features] feature introduction.
@@ -231,7 +230,7 @@ Although the majority of test cases are written using `unittest.TestCase`,
- For specifications, refer to [Concept Exercise Anatomy][concept-exercise-anatomy], or [Practice Exercise Anatomy][practice-exercise-anatomy] depending on which type of exercise you are contributing to.
-- **Practice exercise**, descriptions and instructions come from a centralized, cross-track [problem specifications][problem-specifications] repository.
+- **Practice exercise** descriptions and instructions come from a centralized, cross-track [problem specifications][problem-specifications] repository.
- Any updates or changes need to be proposed/approved in `problem-specifications` first.
- If Python-specific changes become necessary, they need to be appended to the canonical instructions by creating a `instructions.append.md` file in this (`exercism/Python`) repository.
diff --git a/README.md b/README.md
index f3d083aab42..fd9be64f715 100644
--- a/README.md
+++ b/README.md
@@ -34,9 +34,9 @@ Hi. ๐๐ฝ ๐ **We are happy you are here.** ๐&nb
**`exercism/Python`** is one of many programming language tracks on [exercism(dot)org][exercism-website].
This repo holds all the instructions, tests, code, & support files for Python _exercises_ currently under development or implemented & available for students.
-๐ Track exercises support Python `3.7` - `3.11.5`.
+๐ Track exercises support Python `3.10` - `3.13.5`.
Exceptions to this support are noted where they occur.
-๐ Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.11.5`.
+๐ Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.13.5`.
Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree ๐ด .
Concept exercises are constrained to a small set of language or syntax features.
@@ -84,7 +84,7 @@ _Thoughtful suggestions will likely result in faster & more enthusiastic respons
## Python Software and Documentation
-**Copyright ยฉ 2001-2025 Python Software Foundation. All rights reserved.**
+**Copyright ยฉ 2001-2026 Python Software Foundation. All rights reserved.**
Python software and documentation are licensed under the [PSF License Agreement][psf-license].
diff --git a/docs/ABOUT.md b/docs/ABOUT.md
index 6177394a518..8f06e20267a 100644
--- a/docs/ABOUT.md
+++ b/docs/ABOUT.md
@@ -20,14 +20,14 @@ Code can be written and executed from the command line, in an interactive interp
The [zen of Python (PEP 20)][the zen of python] and [What is Pythonic?][what is pythonic] lay out additional philosophies and perspectives on the language.
-Tests and tooling for this track currently support `3.7` - `3.11.2` (_tests_) and [`Python 3.11.2`][311-new-features] (_tooling_).
-It is highly recommended that students upgrade to at least `Python 3.8`, as some features used by this track may not be supported in earlier versions.
+Tests and tooling for this track currently support `3.10` - `3.13.5` (_tests_) and [`Python 3.13.5`][313-new-features] (_tooling_).
+It is highly recommended that students upgrade to at least `Python 3.10`, as some features used by this track may not be supported in earlier versions.
That being said, most of the exercises will work with `Python 3.6+`, or even earlier versions.
But we don't guarantee support for versions not listed under [Active Python Releases][active-python-releases].
We will try to note when a feature is only available in a certain version.
-Complete documentation for the current release of Python (3.11.x) can be found at [docs.python.org][python docs].
+Complete documentation for the current release of Python (3.13.x) can be found at [docs.python.org][python docs].
- [Python Tutorial][python tutorial]
- [Python Library Reference][python library reference]
@@ -37,8 +37,8 @@ Complete documentation for the current release of Python (3.11.x) can be found a
- [Python Glossary of Terms][python glossary of terms]
-[311-new-features]: https://docs.python.org/3/whatsnew/3.11.html
-[active-python-releases]: https://www.python.org/downloads/
+[313-new-features]: https://docs.python.org/3/whatsnew/3.13.html
+[active-python-releases]: https://devguide.python.org/versions/#full-chart
[duck typing]: https://en.wikipedia.org/wiki/Duck_typing
[dynamic typing in python]: https://stackoverflow.com/questions/11328920/is-python-strongly-typed
[editors for python]: https://djangostars.com/blog/python-ide/
@@ -49,16 +49,16 @@ Complete documentation for the current release of Python (3.11.x) can be found a
[peps]: https://www.python.org/dev/peps/
[psf membership]: https://www.python.org/psf/membership/
[psf]: https://www.python.org/psf/
-[python docs]: https://docs.python.org/3/
-[python faqs]: https://docs.python.org/3/faq/index.html
+[python docs]: https://docs.python.org/3.13/
+[python faqs]: https://docs.python.org/3.13/faq/index.html
[python for beginners]: https://www.python.org/about/gettingstarted/
[python glossary of terms]: https://docs.python.org/3/glossary.html
-[python how tos]: https://docs.python.org/3/howto/index.html
+[python how tos]: https://docs.python.org/3.13/howto/index.html
[python is used extensively]: https://www.python.org/about/apps/
-[python language reference]: https://docs.python.org/3/reference/index.html
-[python library reference]: https://docs.python.org/3/library/index.html
-[python tutorial]: https://docs.python.org/3/tutorial/index.html
-[significant indentation]: https://docs.python.org/3/reference/lexical_analysis.html#indentation
+[python language reference]: https://docs.python.org/3.13/reference/index.html
+[python library reference]: https://docs.python.org/3.13/library/index.html
+[python tutorial]: https://docs.python.org/3.13/tutorial/index.html
+[significant indentation]: https://docs.python.org/3.13/reference/lexical_analysis.html#indentation
[the zen of python]: https://www.python.org/dev/peps/pep-0020/
[type hints]: https://docs.python.org/3/library/typing.html
[what is pythonic]: https://blog.startifact.com/posts/older/what-is-pythonic.html
diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md
index 7be6910710d..d70d15153f7 100644
--- a/docs/INSTALLATION.md
+++ b/docs/INSTALLATION.md
@@ -14,24 +14,25 @@ Some quick links into the documentation by operating system:
- [Windows][windows] Additionally, this Microsoft article on [installing Python on windows][python-on-windows] is helpful.
- [Unix & Linux Systems][unix-and-linux] (_these largely work for MacOS as well_)
-- [MacOS][macos] : **This is outdated.**
- We recommend reviewing some of the methods outlined in the Real Python article [Installing Python][installing-python] or the articles by Brett Cannon linked above.
+- [MacOS][macos]
+ We also recommend reviewing some of the methods outlined in the Real Python article [Installing Python][installing-python] or the articles by Brett Cannon linked above.
-Exercism tests and tooling currently support `3.7` - `3.11.5` (_tests_) and [`Python 3.11.5`][311-new-features] (_tooling_).
+
+Exercism tests and tooling currently support `3.10` - `3.13.5` (_tests_) and [`Python 3.13.5`][313-new-features] (_tooling_).
Exceptions to this support are noted where they occur.
Most of the exercises will work with `Python 3.6+`, or even earlier versions.
But we don't guarantee support for versions not listed under [Active Python Releases][active-python-releases].
-Please refer to the [Python 3.11.x documentation][3.11 docs] for what is currently supported.
+Please refer to the [Python 3.13.x documentation][3.13 docs] for what is currently supported.
-[3.11 docs]: https://docs.python.org/3.11/
-[311-new-features]: https://docs.python.org/3/whatsnew/3.11.html
+[3.13 docs]: https://docs.python.org/3.13/
+[313-new-features]: https://docs.python.org/3/whatsnew/3.13.html
[Python-three downloads]: https://www.python.org/downloads/
[active-python-releases]: https://www.python.org/downloads/
[helpful guide]: https://realpython.com/installing-python/
-[installing-python]: https://realpython.com/installing-python/#what-your-options-are_1
+[installing-python]: https://realpython.com/installing-python/
[macos]: https://docs.python.org/3/using/mac.html
[python-m-pip]: https://snarky.ca/why-you-should-use-python-m-pip/
[python-on-windows]: https://docs.microsoft.com/en-us/windows/python/beginners
diff --git a/docs/LEARNING.md b/docs/LEARNING.md
index d71a95455cc..4a85339a936 100644
--- a/docs/LEARNING.md
+++ b/docs/LEARNING.md
@@ -13,14 +13,19 @@ Below you will find some additional jumping-off places to start your learning jo
- [Python Documentation Tutorial][Python Documentation Tutorial]
+- [Stanford Code in Place Course][code in place]
+- [Stanford Code in Place Self-Guided][cip self guided]
- [Automate the Boring Stuff with Python (_book_)][automate the boring stuff]
-- [Automate the Boring Stuff Videos (_covers first 15 book chapters_)][automate the videos]
+- [Automate the Boring Stuff with Python Workbook (_exercises_)][automate the boring stuff workbook]
+- [Think Python][Think Python]
+- [Beyond the Basic Stuff with Python][beyond the basics]
+- [Beyond the Basic Stuff with Python Video][beyond the basics video]
+- [Python Programming Exercises, Gently Explained][PPEG]
+- [Python for Non-Programmers][python-for-non-programmers]
- [Learn X in Y minutes (where X = Python3)][Learn X in Y minutes]
- [Python at Free Code Camp][python at free code camp]
+- [Python at Khan Academy][python at kahn academy]
- [Intro to Python (_python-course.eu_)][python-course.eu]
-- [Think Python][Think Python]
-- [Python for Non-Programmers][python-for-non-programmers]
-- [Python 4 Everyone][python4everyone]
- [Googles Python Class][googles python class]
- [Microsoft's Python Learning Path][MS Python]
- [Introduction to Computer Science and Programming in Python (MIT)][mitocw600]
@@ -30,14 +35,19 @@ Below you will find some additional jumping-off places to start your learning jo
[CS50P]: https://pll.harvard.edu/course/cs50s-introduction-programming-python?delta=0
[Learn X in Y minutes]: https://learnxinyminutes.com/docs/python3/
[MS Python]: https://docs.microsoft.com/en-us/learn/paths/python-language/
+[PPEG]: https://inventwithpython.com/pythongently/
[Python Documentation Tutorial]: https://docs.python.org/3/tutorial/index.html
-[Python at Free Code Camp]: https://www.freecodecamp.org/learn/scientific-computing-with-python/
-[Think Python]: http://www.greenteapress.com/thinkpython/html/index.html
-[automate the boring stuff]: https://automatetheboringstuff.com/2e/
-[automate the videos]: https://www.youtube.com/watch?v=1F_OgqRuSdI&list=PL0-84-yl1fUnRuXGFe_F7qSH1LEnn9LkW
-[googles python class]: https://developers.google.com/edu/python/introduction
+[Python at Free Code Camp]: https://www.freecodecamp.org/learn/python-v9/
+[Think Python]: https://allendowney.github.io/ThinkPython/
+[automate the boring stuff workbook]: https://automatetheboringstuff.com/#toc
+[automate the boring stuff]: https://automatetheboringstuff.com/#toc
+[beyond the basics video]: https://www.youtube.com/watch?v=kSrnLbioN6w
+[beyond the basics]: https://inventwithpython.com/beyond/
+[cip self guided]: https://codeinplace.stanford.edu/public/studenthome
+[code in place]: https://codeinplace.stanford.edu/
+[googles python class]: https://developers.google.com/edu/python
[mitocw600]: https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-0001-introduction-to-computer-science-and-programming-in-python-fall-2016/
+[python at kahn academy]: https://www.khanacademy.org/computing/intro-to-python-fundamentals
[python-course.eu]: https://python-course.eu/python-tutorial/
[python-for-non-programmers]: https://store.lerner.co.il/python-for-non-programmers-live
-[python4everyone]: https://www.py4e.com/
[wikipython]: https://en.wikipedia.org/wiki/Python_(programming_language)
diff --git a/docs/PROBLEM-SOLVING.md b/docs/PROBLEM-SOLVING.md
index 198b9ea5ef9..47a99e8a8ab 100644
--- a/docs/PROBLEM-SOLVING.md
+++ b/docs/PROBLEM-SOLVING.md
@@ -8,9 +8,9 @@ Below are some community-sourced articles, videos, and books that can help you d
- Free Code Camp offers a good overview article on [How to Think Like a Programmer - Lessons in Problem-Solving][free-code-camp-think-like-a-programmer].
-- Kurtis Pykes writing for Towards Data Science has a nice [hands-on tutorial for problem-solving][Kurtis Pykes: Hands-on Tutorial - How to Improve Your Problem-Solving Skills as A Programmer].
-- UC Berkeley has a nice PDF summary of [G. Polya's Problem Solving Techniques][g-polya-how-to-solve-it-summary].
+- Jeremy Howard, founder of fast.ai has a nice summary of [G. Polya's Problem Solving Techniques][g-polya-how-to-solve-it-summary].
- Originally written in 1945 as guidance for tackling complicated math problems,[G. Polya's How To Solve It][g-polya-how-to-solve-it] (full book) is still _excellent_ advice for problem-solving in general.
+- Kurtis Pykes writing for Towards Data Science has a nice [hands-on tutorial for problem-solving][Kurtis Pykes: Hands-on Tutorial - How to Improve Your Problem-Solving Skills as A Programmer].
- Mentioned in the Free Code Camp Article, V. Anton Spraul's [Think Like a Programmer: An Introduction to Creative Problem Solving][v-anton-spraul-think-like-a-programmer] is a more modern and programming-focused take on the same general methods Polya outlines for mathematics.
- [Felienne Hermans][felienne-hermans] is more focused on _how_ people learn the art of coding and how that maps to learning in general.
She has written [The Programmers Brian][programmers-brain-free-online], with strategies for reading code better, thinking about code clearly, writing better code, and becoming a better code collaborator.
@@ -32,8 +32,8 @@ Membership (paid) information is available at [acm(dot)org][association-for-comp
[felienne-hermans-programming-is-writing-is-programming]: https://www.youtube.com/watch?v=uO3a4HIBDU4
[felienne-hermans]: https://www.felienne.com/
[free-code-camp-think-like-a-programmer]: https://www.freecodecamp.org/news/how-to-think-like-a-programmer-lessons-in-problem-solving-d1d8bf1de7d2/
-[g-polya-how-to-solve-it-summary]: https://math.berkeley.edu/~gmelvin/polya.pdf
-[g-polya-how-to-solve-it]: https://press.princeton.edu/books/paperback/9780691164076/how-to-solve-it
+[g-polya-how-to-solve-it-summary]: https://gist.github.com/jph00/d60301884c56fe063101a7cc6193b3af
+[g-polya-how-to-solve-it]: https://archive.org/details/howtosolveit0000gpol_c0p2/page/n9/mode/2up
[paul-vickers-how-to-think-like-a-programmer]: https://www.researchgate.net/publication/236270907_How_to_Think_like_a_Programmer_Problem_Solving_for_the_Bewildered
[programmers-brain-free-online]: https://www.manning.com/books/the-programmers-brain#toc
[programmers-brain-manning]: https://www.manning.com/books/the-programmers-brain
diff --git a/docs/RESOURCES.md b/docs/RESOURCES.md
index ea8527592ab..f04fcf601d0 100644
--- a/docs/RESOURCES.md
+++ b/docs/RESOURCES.md
@@ -5,24 +5,26 @@
- [The Docs on pip][pip]
- [Tall, Snarky Canadian (_The Blog of Core Python Developer Brett Cannon_)][Tall, Snarky Canadian]
- [Practical Python][practical python]
-- [Python 3 Module of the Week (PyMOTW-3)][pymotw-3]
-- [Beyond the Basic Stuff with Python][Beyond the Basic Stuff with Python]
-- [The Big Book of Small Python Projects][The Big Book of Small Python Projects]
- [Data Structures and Information Retrieval in Python][Data Structures and Information Retrieval in Python]
-- [python practice projects][python practice projects]
-- [Python Courses eu][python-course.eu main]
-- [Fluent Python Notebooks][fluent-notebooks]
+- [Fluent Python, 2nd Edition][Fluent Python 2] (_you might be able to find free access through a library or online_)
+- [Fluent Python Notebooks][fluent-notebooks] (_these are based on the first edition, but still really good_)
+- [The Big Book of Small Python Projects][The Big Book of Small Python Projects]
+- [Practice Python Projects][practice python projects]
+- [Dataquest: Python Projects for Beginners][Python projects for beginners]
+- [Mouse vs Python (Mike Driscoll's blog)][mouse vs python]
+- [Simon Willison's Weblog][simon willison]
-[Beyond the Basic Stuff with Python]: https://inventwithpython.com/beyond/
[Data Structures and Information Retrieval in Python]: https://allendowney.github.io/DSIRP/
[Practical Python]: https://dabeaz-course.github.io/practical-python/
+[Python projects for beginners]: https://www.dataquest.io/blog/python-projects-for-beginners/
[Tall, Snarky Canadian]: https://snarky.ca/
[The Big Book of Small Python Projects]: http://inventwithpython.com/bigbookpython/
[The Python Library Reference]: https://docs.python.org/3/library/index.html
+[fluent python 2]: https://www.oreilly.com/library/view/fluent-python-2nd/9781492056348/
[fluent-notebooks]: https://github.com/AllenDowney/fluent-python-notebooks
+[mouse vs python]: https://www.blog.pythonlibrary.org/
[pip]: https://pip.pypa.io/en/stable/user_guide/
-[pymotw-3]: https://pymotw.com/3/
+[practice python projects]: https://learnbyexample.github.io/practice_python_projects/preface.html
[python docs]: https://docs.python.org/3/
-[python practice projects]: http://pythonpracticeprojects.com/
-[python-course.eu main]: https://python-course.eu/
+[simon willison]: https://simonwillison.net/
diff --git a/docs/TOOLS.md b/docs/TOOLS.md
index bacb8626aaa..11713826c14 100644
--- a/docs/TOOLS.md
+++ b/docs/TOOLS.md
@@ -15,6 +15,7 @@ If you have an editor, IDE, tool, or plugin recommendation, we encourage you to
- [Environments](#virtual-environments)
- [Venv](#creating-a-virtual-environment-with-venv)
- [Conda](#creating-a-virtual-environment-using-conda)
+ - [uv](#uv)
- [Virtual Environment Wrapper](#virtual-environment-wrapper)
- [Editors and IDEs](#editors-and-ides)
- [Visual Studio Code](#visual-studio-code)
@@ -30,9 +31,9 @@ If you have an editor, IDE, tool, or plugin recommendation, we encourage you to
Before you start exploring, make sure that you have a recent version of Python installed.
-The Exercism web platform currently supports `Python 3.7 - 3.11.5` (_exercises and tests_) and `Python 3.11.5` (_tooling_).
-Our online test runner currently uses `pytest 7.2.2` and `pytest-subtests 0.11.0`.
-Our online analyzer uses `pylint 2.17.7`.
+The Exercism web platform currently supports `Python 3.10 - 3.13.5` (_exercises and tests_) and `Python 3.13.5` (_tooling_).
+Our online test runner currently uses `pytest 8.4.0` and `pytest-subtests 0.14.2`.
+Our online analyzer uses `pylint 4.0.4`.
Using different versions of `Python`, `pytest`, or `pylint` locally might give you different results than the website.
For more information, please refer to [Installing Python locally][Installing Python locally].
@@ -45,10 +46,16 @@ Python virtual environments offer lightweight runtime and package isolation.
Different environments can hold different versions of the Python runtime together with any project or library dependencies.
This helps avoid bugs and incompatibilities caused by upgrading a library for one project that "breaks" a dependency in a different one.
-There are two major *virtual environment* tools in use today, the Python standard library [`venv`][venv] and the third-party [`conda env`][condaenv], using the [`conda`][conda] package manager and (_usually_) the Anaconda Python distribution.
-Both of are straightforward to use and/or install.
+There are many *virtual environment* and *virtual environment-like* tools in use today, and a growing movement to use [inline script metadata][PEP723], [dev containers][dev containers], or [docker][docker] instead of virtual environments.
+It is important to try out different strategies and find one that suits your development style and project needs.
+Don't assume that the strategies here are one-size-fits all, or are your only options.
+For a more general rundown of tools not covered here, check out [this blog post by Bas Nijholt][bas nihholt] and stay curious.
-Additionally, [`PyEnv`][pyenv] and [virtualenvwrapper][virtualenvwrapper] are tools that can help to manage multiple versions of Python and multiple Python environments on the same machine.
+
+There are three major *virtual environment* tools we'll cover here, the Python standard library [`venv`][venv], the third-party [`conda env`][condaenv], using the [`conda`][conda] package manager and (_usually_) the Anaconda Python distribution, and the third-party `pip` + `venv` replacement [`uv`][uv].
+All three are fairly straightforward to use and/or install.
+
+Additionally, [`PyEnv`][pyenv], [`Poetry`][poetry], and [virtualenvwrapper][virtualenvwrapper] are tools that can help to manage multiple versions of Python and multiple Python environments on the same machine.
@@ -208,6 +215,19 @@ Executing transaction: done
+### UV
+
+Working on Projects with uv: [uv][uv-docs]
+
+`uv` is a Python package + project management tool from [Astral][astral] written in [Rust][rust programming language].
+It was designed to replace `pip`, `venv`, `poetry`, and other Python packaging/dependency management tools.
+Unlike `Conda` or `Mamba`, uv is specialized/tailored to only Python.
+ However, uv does support building Python extension modules written in other languages such as Fortran.
+Astral is also the developer of the popular [Ruff][ruff] linter and [TY][ty], a static type checker for Python type hints, both written in Rust.
+
+
+Rather than go into detail here, the [UV documentation][uv documentation] is your best source for installation and setup.
+
### Virtual Environment wrapper
Documents and background: [virtualenvwrapper][virtualenvwrapper].
@@ -369,14 +389,19 @@ You can also [develop plugins][sublime plugin development] of your own for the e
[Installing Python locally]: https://exercism.org/docs/tracks/Python/installation
[MS Python extension]: https://marketplace.visualstudio.com/items?itemName=ms-python.python
+[PEP723]: https://packaging.python.org/en/latest/specifications/inline-script-metadata/#inline-script-metadata
[anaconda]: https://www.anaconda.com/products/individual
+[astral]: https://astral.sh/about
[atom]: https://atom.io/
+[bas nihholt]: https://www.nijho.lt/post/python-environments/
[conda command ref]: https://docs.conda.io/projects/conda/en/latest/commands.html#conda-vs-pip-vs-virtualenv-commands
[conda-cheatsheet]: https://docs.conda.io/projects/conda/en/latest/_downloads/843d9e0198f2a193a3484886fa28163c/conda-cheatsheet.pdf
[conda-docs]: https://docs.conda.io/projects/conda/en/latest/user-guide/index.html
[conda]: https://docs.conda.io/projects/conda/en/latest/index.html
[condaenv]: https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html
+[dev containers]: https://andypickup.com/developing-in-python-with-dev-containers-part-1-setup-f1aeb89cbfed
[docker in vscode]: https://code.visualstudio.com/docs/containers/overview
+[docker]: https://www.docker.com/blog/containerized-python-development-part-1/
[emacs at fullstack python]: https://www.fullstackpython.com/emacs.html
[emacs setup at real python]: https://realpython.com/emacs-the-best-python-editor
[emacs wiki python programming]: https://www.emacswiki.org/emacs/PythonProgrammingInEmacs#h5o-4
@@ -390,6 +415,7 @@ You can also [develop plugins][sublime plugin development] of your own for the e
[linting python in vscode]: https://code.visualstudio.com/docs/python/linting
[miniconda]: https://docs.conda.io/en/latest/miniconda.html
[opensource spacemacs guide]: https://opensource.com/article/19/12/spacemacs
+[poetry]: https://github.com/python-poetry/poetry
[pycharm config venv]: https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html
[pycharm database tools]: https://www.jetbrains.com/help/pycharm/relational-databases.html
[pycharm debug configuration]: https://www.jetbrains.com/help/pycharm/run-debug-configuration-py-test.html
@@ -407,6 +433,8 @@ You can also [develop plugins][sublime plugin development] of your own for the e
[python testing in vscode]: https://code.visualstudio.com/docs/python/testing
[python web dev in vscode]: https://code.visualstudio.com/docs/python/tutorial-django
[rtorr vim cheat sheet]: https://vim.rtorr.com/
+[ruff]: https://docs.astral.sh/ruff/
+[rust programming language]: https://rust-lang.org/
[spacemacs github repo]: https://github.com/syl20bnr/spacemacs
[spacemacs official docs]: https://github.com/syl20bnr/spacemacs#documentation
[spacemacs python layer]: https://www.spacemacs.org/layers/+lang/python/README.html
@@ -434,6 +462,10 @@ You can also [develop plugins][sublime plugin development] of your own for the e
[sublime support docs]: https://www.sublimetext.com/support
[sublime text 4]: https://www.sublimetext.com/
[sublime text at real python]: https://realpython.com/setting-up-sublime-text-3-for-full-stack-python-development/
+[ty]: https://docs.astral.sh/ty/
+[uv documentation]: https://docs.astral.sh/uv/getting-started/
+[uv-docs]: https://docs.astral.sh/uv/guides/projects/#working-on-projects
+[uv]: https://github.com/astral-sh/uv
[venv wrapper tutorial]: https://virtualenvwrapper.readthedocs.io/en/latest/plugins.html#plugins
[venv]: https://docs.python.org/3.9/tutorial/venv.html
[vim cheat sheet]: https://vimsheet.com/
diff --git a/exercises/practice/acronym/acronym_test.py b/exercises/practice/acronym/acronym_test.py
index 984deef60d2..a10f2bf3dc2 100644
--- a/exercises/practice/acronym/acronym_test.py
+++ b/exercises/practice/acronym/acronym_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/acronym/canonical-data.json
-# File last updated on 2023-07-20
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class AcronymTest(unittest.TestCase):
+
def test_basic(self):
self.assertEqual(abbreviate("Portable Network Graphics"), "PNG")
diff --git a/exercises/practice/affine-cipher/affine_cipher_test.py b/exercises/practice/affine-cipher/affine_cipher_test.py
index f6d7c106c33..db265953691 100644
--- a/exercises/practice/affine-cipher/affine_cipher_test.py
+++ b/exercises/practice/affine-cipher/affine_cipher_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/affine-cipher/canonical-data.json
-# File last updated on 2023-07-20
+# File last updated on 2026-02-19
import unittest
@@ -11,6 +11,7 @@
class AffineCipherTest(unittest.TestCase):
+
def test_encode_yes(self):
self.assertEqual(encode("yes", 5, 7), "xbt")
diff --git a/exercises/practice/alphametics/alphametics_test.py b/exercises/practice/alphametics/alphametics_test.py
index 6279b805c59..30e54813093 100644
--- a/exercises/practice/alphametics/alphametics_test.py
+++ b/exercises/practice/alphametics/alphametics_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/alphametics/canonical-data.json
-# File last updated on 2023-07-20
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class AlphameticsTest(unittest.TestCase):
+
def test_puzzle_with_three_letters(self):
self.assertEqual(solve("I + BB == ILL"), {"I": 1, "B": 9, "L": 0})
diff --git a/exercises/practice/bob/bob_test.py b/exercises/practice/bob/bob_test.py
index 755d5c935e4..46410fa62ba 100644
--- a/exercises/practice/bob/bob_test.py
+++ b/exercises/practice/bob/bob_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/bob/canonical-data.json
-# File last updated on 2025-01-10
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class BobTest(unittest.TestCase):
+
def test_stating_something(self):
self.assertEqual(response("Tom-ay-to, tom-aaaah-to."), "Whatever.")
diff --git a/exercises/practice/book-store/book_store_test.py b/exercises/practice/book-store/book_store_test.py
index 87b0051faa2..d25bdc5a25b 100644
--- a/exercises/practice/book-store/book_store_test.py
+++ b/exercises/practice/book-store/book_store_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/book-store/canonical-data.json
-# File last updated on 2023-07-20
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class BookStoreTest(unittest.TestCase):
+
def test_only_a_single_book(self):
basket = [1]
self.assertEqual(total(basket), 800)
diff --git a/exercises/practice/circular-buffer/circular_buffer_test.py b/exercises/practice/circular-buffer/circular_buffer_test.py
index eb0663cf503..031d970fabc 100644
--- a/exercises/practice/circular-buffer/circular_buffer_test.py
+++ b/exercises/practice/circular-buffer/circular_buffer_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/circular-buffer/canonical-data.json
-# File last updated on 2023-07-20
+# File last updated on 2026-02-19
import unittest
@@ -12,6 +12,7 @@
class CircularBufferTest(unittest.TestCase):
+
def test_reading_empty_buffer_should_fail(self):
buf = CircularBuffer(1)
with self.assertRaises(BufferError) as err:
diff --git a/exercises/practice/connect/connect_test.py b/exercises/practice/connect/connect_test.py
index e7303d35131..9214cda9800 100644
--- a/exercises/practice/connect/connect_test.py
+++ b/exercises/practice/connect/connect_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/connect/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class ConnectTest(unittest.TestCase):
+
def test_an_empty_board_has_no_winner(self):
game = ConnectGame(
""". . . . .
diff --git a/exercises/practice/diamond/diamond_test.py b/exercises/practice/diamond/diamond_test.py
index 6a3a2295098..448f65d5326 100644
--- a/exercises/practice/diamond/diamond_test.py
+++ b/exercises/practice/diamond/diamond_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/diamond/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class DiamondTest(unittest.TestCase):
+
def test_degenerate_case_with_a_single_a_row(self):
result = ["A"]
self.assertEqual(rows("A"), result)
diff --git a/exercises/practice/difference-of-squares/difference_of_squares_test.py b/exercises/practice/difference-of-squares/difference_of_squares_test.py
index aa7271907ac..3536a20f8f8 100644
--- a/exercises/practice/difference-of-squares/difference_of_squares_test.py
+++ b/exercises/practice/difference-of-squares/difference_of_squares_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/difference-of-squares/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -12,6 +12,7 @@
class DifferenceOfSquaresTest(unittest.TestCase):
+
def test_square_of_sum_1(self):
self.assertEqual(square_of_sum(1), 1)
diff --git a/exercises/practice/diffie-hellman/diffie_hellman_test.py b/exercises/practice/diffie-hellman/diffie_hellman_test.py
index e24c4e742a1..f6a2a9c1cfd 100644
--- a/exercises/practice/diffie-hellman/diffie_hellman_test.py
+++ b/exercises/practice/diffie-hellman/diffie_hellman_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/diffie-hellman/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -12,11 +12,12 @@
class DiffieHellmanTest(unittest.TestCase):
+
def test_private_key_is_greater_than_1_and_less_than_p(self):
for prime in [5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]:
with self.subTest(f"prime={prime}"):
key = private_key(prime)
- self.assertTrue(1 < key < prime, msg=f"{key} out of range, expected to be >1 and <{prime}") # fmt: skip
+ self.assertTrue(1 < key < prime, msg=f"{key} out of range, expected to be >1 and <{prime}") # fmt: skip
def test_private_key_is_random(self):
"""
@@ -30,19 +31,19 @@ def test_can_calculate_public_key_using_private_key(self):
p = 23
g = 5
private_key = 6
- self.assertEqual(8, public_key(p, g, private_key, )) # fmt: skip
+ self.assertEqual(8, public_key(p, g, private_key, )) # fmt: skip
def test_can_calculate_public_key_when_given_a_different_private_key(self):
p = 23
g = 5
private_key = 15
- self.assertEqual(19, public_key(p, g, private_key, )) # fmt: skip
+ self.assertEqual(19, public_key(p, g, private_key, )) # fmt: skip
def test_can_calculate_secret_using_other_party_s_public_key(self):
p = 23
their_public_key = 19
my_private_key = 6
- self.assertEqual(2, secret(p, their_public_key, my_private_key, )) # fmt: skip
+ self.assertEqual(2, secret(p, their_public_key, my_private_key, )) # fmt: skip
def test_key_exchange(self):
p = 23
diff --git a/exercises/practice/etl/etl_test.py b/exercises/practice/etl/etl_test.py
index d6eed70a574..ef24e9af484 100644
--- a/exercises/practice/etl/etl_test.py
+++ b/exercises/practice/etl/etl_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/etl/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class EtlTest(unittest.TestCase):
+
def test_single_letter(self):
legacy_data = {1: ["A"]}
data = {"a": 1}
diff --git a/exercises/practice/food-chain/food_chain_test.py b/exercises/practice/food-chain/food_chain_test.py
index 0cd42356ab1..4ce21d81339 100644
--- a/exercises/practice/food-chain/food_chain_test.py
+++ b/exercises/practice/food-chain/food_chain_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/food-chain/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class FoodChainTest(unittest.TestCase):
+
def test_fly(self):
self.assertEqual(
recite(1, 1),
diff --git a/exercises/practice/forth/forth_test.py b/exercises/practice/forth/forth_test.py
index 1489bbd7df0..848da9ed2f9 100644
--- a/exercises/practice/forth/forth_test.py
+++ b/exercises/practice/forth/forth_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/forth/canonical-data.json
-# File last updated on 2024-11-04
+# File last updated on 2026-02-19
import unittest
@@ -11,6 +11,7 @@
class ForthTest(unittest.TestCase):
+
def test_parsing_and_numbers_numbers_just_get_pushed_onto_the_stack(self):
self.assertEqual(evaluate(["1 2 3 4 5"]), [1, 2, 3, 4, 5])
diff --git a/exercises/practice/game-of-life/game_of_life_test.py b/exercises/practice/game-of-life/game_of_life_test.py
index b62b74407cb..24f89e6f73c 100644
--- a/exercises/practice/game-of-life/game_of_life_test.py
+++ b/exercises/practice/game-of-life/game_of_life_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/game-of-life/canonical-data.json
-# File last updated on 2026-01-26
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class GameOfLifeTest(unittest.TestCase):
+
def test_empty_matrix(self):
matrix = []
expected = []
diff --git a/exercises/practice/go-counting/go_counting_test.py b/exercises/practice/go-counting/go_counting_test.py
index aec80a1b369..036e3c26fd7 100644
--- a/exercises/practice/go-counting/go_counting_test.py
+++ b/exercises/practice/go-counting/go_counting_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/go-counting/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -13,6 +13,7 @@
class GoCountingTest(unittest.TestCase):
+
def test_black_corner_territory_on_5x5_board(self):
board = Board([" B ", " B B ", "B W B", " W W ", " W "])
stone, territory = board.territory(x=0, y=1)
diff --git a/exercises/practice/grade-school/grade_school_test.py b/exercises/practice/grade-school/grade_school_test.py
index 30d91c6c57d..638c776474a 100644
--- a/exercises/practice/grade-school/grade_school_test.py
+++ b/exercises/practice/grade-school/grade_school_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/grade-school/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class GradeSchoolTest(unittest.TestCase):
+
def test_roster_is_empty_when_no_student_is_added(self):
school = School()
expected = []
diff --git a/exercises/practice/grains/grains_test.py b/exercises/practice/grains/grains_test.py
index 177f91faa1a..bd924723348 100644
--- a/exercises/practice/grains/grains_test.py
+++ b/exercises/practice/grains/grains_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/grains/canonical-data.json
-# File last updated on 2023-09-27
+# File last updated on 2026-02-19
import unittest
@@ -11,6 +11,7 @@
class GrainsTest(unittest.TestCase):
+
def test_grains_on_square_1(self):
self.assertEqual(square(1), 1)
diff --git a/exercises/practice/luhn/luhn_test.py b/exercises/practice/luhn/luhn_test.py
index 58234eb7d55..7d26c9ae02f 100644
--- a/exercises/practice/luhn/luhn_test.py
+++ b/exercises/practice/luhn/luhn_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/luhn/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class LuhnTest(unittest.TestCase):
+
def test_single_digit_strings_can_not_be_valid(self):
self.assertIs(Luhn("1").valid(), False)
diff --git a/exercises/practice/pig-latin/pig_latin_test.py b/exercises/practice/pig-latin/pig_latin_test.py
index 1217d6883f9..10c2f76419d 100644
--- a/exercises/practice/pig-latin/pig_latin_test.py
+++ b/exercises/practice/pig-latin/pig_latin_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/pig-latin/canonical-data.json
-# File last updated on 2025-01-10
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class PigLatinTest(unittest.TestCase):
+
def test_word_beginning_with_a(self):
self.assertEqual(translate("apple"), "appleay")
diff --git a/exercises/practice/pov/pov_test.py b/exercises/practice/pov/pov_test.py
index 2436ebc2db9..0399300eac0 100644
--- a/exercises/practice/pov/pov_test.py
+++ b/exercises/practice/pov/pov_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/pov/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class PovTest(unittest.TestCase):
+
def test_results_in_the_same_tree_if_the_input_tree_is_a_singleton(self):
tree = Tree("x")
expected = Tree("x")
diff --git a/exercises/practice/prime-factors/prime_factors_test.py b/exercises/practice/prime-factors/prime_factors_test.py
index 4f6865036e5..a1d5d4d2fbb 100644
--- a/exercises/practice/prime-factors/prime_factors_test.py
+++ b/exercises/practice/prime-factors/prime_factors_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/prime-factors/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class PrimeFactorsTest(unittest.TestCase):
+
def test_no_factors(self):
self.assertEqual(factors(1), [])
diff --git a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py
index f82066ca274..4cbca167cb9 100644
--- a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py
+++ b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/rail-fence-cipher/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -11,6 +11,7 @@
class RailFenceCipherTest(unittest.TestCase):
+
def test_encode_with_two_rails(self):
self.assertMultiLineEqual(encode("XOXOXOXOXOXOXOXOXO", 2), "XXXXXXXXXOOOOOOOOO")
diff --git a/exercises/practice/rotational-cipher/rotational_cipher_test.py b/exercises/practice/rotational-cipher/rotational_cipher_test.py
index ca22735ef9b..9c226ace3f1 100644
--- a/exercises/practice/rotational-cipher/rotational_cipher_test.py
+++ b/exercises/practice/rotational-cipher/rotational_cipher_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/rotational-cipher/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class RotationalCipherTest(unittest.TestCase):
+
def test_rotate_a_by_0_same_output_as_input(self):
self.assertEqual(rotate("a", 0), "a")
diff --git a/exercises/practice/sgf-parsing/sgf_parsing_test.py b/exercises/practice/sgf-parsing/sgf_parsing_test.py
index c33a5dbecff..35e08d66dfe 100644
--- a/exercises/practice/sgf-parsing/sgf_parsing_test.py
+++ b/exercises/practice/sgf-parsing/sgf_parsing_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/sgf-parsing/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -11,6 +11,7 @@
class SgfParsingTest(unittest.TestCase):
+
def test_empty_input(self):
input_string = ""
with self.assertRaises(ValueError) as err:
diff --git a/exercises/practice/swift-scheduling/swift_scheduling_test.py b/exercises/practice/swift-scheduling/swift_scheduling_test.py
index 08ed2485b9c..234f7feec0d 100644
--- a/exercises/practice/swift-scheduling/swift_scheduling_test.py
+++ b/exercises/practice/swift-scheduling/swift_scheduling_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/swift-scheduling/canonical-data.json
-# File last updated on 2025-06-25
+# File last updated on 2026-02-19
import unittest
@@ -10,6 +10,7 @@
class SwiftSchedulingTest(unittest.TestCase):
+
def test_now_translates_to_two_hours_later(self):
self.assertEqual(
delivery_date("2012-02-13T09:00:00", "NOW"), "2012-02-13T11:00:00"
diff --git a/exercises/practice/triangle/triangle_test.py b/exercises/practice/triangle/triangle_test.py
index b279c83c325..d4f7269e398 100644
--- a/exercises/practice/triangle/triangle_test.py
+++ b/exercises/practice/triangle/triangle_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/triangle/canonical-data.json
-# File last updated on 2023-07-19
+# File last updated on 2026-02-19
import unittest
@@ -12,6 +12,7 @@
class EquilateralTriangleTest(unittest.TestCase):
+
def test_all_sides_are_equal(self):
self.assertIs(equilateral([2, 2, 2]), True)
@@ -29,6 +30,7 @@ def test_sides_may_be_floats(self):
class IsoscelesTriangleTest(unittest.TestCase):
+
def test_last_two_sides_are_equal(self):
self.assertIs(isosceles([3, 4, 4]), True)
@@ -58,6 +60,7 @@ def test_sides_may_be_floats(self):
class ScaleneTriangleTest(unittest.TestCase):
+
def test_no_sides_are_equal(self):
self.assertIs(scalene([5, 4, 6]), True)
diff --git a/exercises/practice/variable-length-quantity/variable_length_quantity_test.py b/exercises/practice/variable-length-quantity/variable_length_quantity_test.py
index e059f82ee3f..7404128a882 100644
--- a/exercises/practice/variable-length-quantity/variable_length_quantity_test.py
+++ b/exercises/practice/variable-length-quantity/variable_length_quantity_test.py
@@ -1,6 +1,6 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/variable-length-quantity/canonical-data.json
-# File last updated on 2025-08-28
+# File last updated on 2026-02-19
import unittest
@@ -11,6 +11,7 @@
class VariableLengthQuantityTest(unittest.TestCase):
+
def test_zero(self):
self.assertEqual(encode([0x0]), [0x0])
diff --git a/exercises/shared/.docs/help.md b/exercises/shared/.docs/help.md
index ef95bd6193b..f4114f8b2cb 100644
--- a/exercises/shared/.docs/help.md
+++ b/exercises/shared/.docs/help.md
@@ -3,13 +3,13 @@
Below are some resources for getting help if you run into trouble:
- [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources.
+- [Python Community Forums](https://discuss.python.org/) help, PEP discussion, core Python committers, and more.
- [The Exercism Community on Discord](https://exercism.org/r/discord)
+- [The Exercism Community Discussion Forums](https://forum.exercsim.org)
- [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community.
- [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners.
- [#python on Libera.chat](https://www.python.org/community/irc/) this is where the core developers for the language hang out and get work done.
-- [Python Community Forums](https://discuss.python.org/)
- [Free Code Camp Community Forums](https://forum.freecodecamp.org/)
-- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help)
- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually.
Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already.
diff --git a/exercises/shared/.docs/representations.md b/exercises/shared/.docs/representations.md
index 8439ca9aab4..ec803d01dc8 100644
--- a/exercises/shared/.docs/representations.md
+++ b/exercises/shared/.docs/representations.md
@@ -7,7 +7,7 @@ The [Python representer][representer] processes and normalizes student solutions
- For troubleshooting purposes, `representation.out` includes starting AST, edited AST, and a code representation with normalizations applied.
- Removals:
- - typehints
+ - typehints (_including typehints in dataclasses, see Normalizations below_)
- `print()` statements
- `if __name__ == __main__` blocks
- comments
@@ -28,6 +28,8 @@ The [Python representer][representer] processes and normalizes student solutions
- **1e2+1_23e0+4.4e-1** --> 100.0 + 123.0 + 0.44 #223.44
- **7e6+7e5+5e4+9.98e2+4.45_779e-1** -->7000000.0 + 700000.0 + 50000.0 + 998.0 + 0.445779 #7750998.445779
- **(7e6+7e5+5e4+9.98e1+4.457_79e-1)+(1e2+1.23e1+4.444_23e-1)*1*j** --> (7000000.0 + 700000.0 + 50000.0 + 99.8 + 0.445779 + (100.0 + 12.3 + 0.444423) * 1j) #7750100.245779+112.744423j
+ - functions and classes that have empty bodies after docstring removal have `pass` assigned to the body.
+ - dataclasses that have type hinted but unassigned data members have those data members assigned `None` as a value. See the docstring starting on line 153 of normalizer.py for more details.
[representer]: https://github.com/exercism/python-representer/tree/main/representer
[python-ast]: https://docs.python.org/3/library/ast.html#module-ast
diff --git a/pylintrc b/pylintrc
index 09795978bc4..4c362789429 100644
--- a/pylintrc
+++ b/pylintrc
@@ -2,373 +2,345 @@
# This pylintrc file contains a best-effort configuration to uphold the
# best-practices and style for the Python track of exercism.org.
#
-# It is based on the Google pylintrc & the Google Python style guide:
-# https://google.github.io/styleguide/pyguide.html,
-# https://google.github.io/styleguide/pylintrc
+# It is based on the default pylint rc with enabled extensions, and is the same
+# pylintrc file used in our generic Analyzer.
#
-# Additions & alterations to the Google Style guide are noted in
+# Additions & alterations to the base configuration are noted in
# the Exercism Python Track contributing guide:
# https://github.com/exercism/python/blob/main/CONTRIBUTING.md
###########################################################################
-[MASTER]
+[MAIN]
-# Files or directories to be skipped. They should be base names, not paths.
+analyse-fallback-blocks=no
+clear-cache-post-run=yes
+extension-pkg-allow-list=
+extension-pkg-whitelist=
ignore=third_party
-
-# Files or directories matching the regex patterns are skipped. The regex
-# matches against base names, not paths.
-ignore-patterns=
-
-# Pickle collected data for later comparisons.
-persistent=no
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-# Use multiple processes to speed up Pylint.
jobs=4
-
-# Allow loading of arbitrary C extensions. Extensions are imported into the
-# active Python interpreter and may run arbitrary code.
+limit-inference-results=100
unsafe-load-any-extension=no
+persistent=no
+prefer-stubs=no
+recursive=no
+# Specify a score threshold under which the program will exit with error.
+fail-under=10
-[MESSAGES CONTROL]
-
-# Only show warnings with the listed confidence levels. Leave empty to show
-# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
-confidence=
-
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time (only on the command line, not in the configuration file where
-# it should appear only once). See also the "--disable" option for examples.
-#enable=
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifiers separated by comma (,) or put this
-# option multiple times (only on the command line, not in the configuration
-# file where it should appear only once).You can also use "--disable=all" to
-# disable everything first and then re-enable specific checks. For example, if
-# you want to run only the similarities checker, you can use "--disable=all
-# --enable=similarities". If you want to run only the classes checker, but have
-# no Warning level messages displayed, use"--disable=all --enable=classes
-# --disable=W"
-# As of Pylint 2.6+, the following options are not supported, so they're commented out:
-#
-# misplaced-comparison-constant
-# relative-import
-# input-builtin
-# inconsistent-return-statements
-# no-absolute-import
-# raising-string
-# round-builtin
-
-disable=arguments-differ,
- attribute-defined-outside-init,
- fixme,
- global-statement,
- implicit-str-concat-in-sequence,
- import-error,
- import-self,
- locally-disabled,
- no-else-break,
- no-else-continue,
- no-else-raise,
- no-else-return,
- no-member,
- no-name-in-module,
- signature-differs,
- suppressed-message,
- too-many-boolean-expressions,
- too-many-branches,
- too-many-locals,
- too-many-public-methods,
- too-many-return-statements,
- too-many-statements,
- unnecessary-pass,
- unused-argument,
- useless-suppression
-
-
-[REPORTS]
-
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html. You can also give a reporter class, eg
-# mypackage.mymodule.MyReporterClass.
-output-format=colorized
-
-# Tells whether to display a full report or only the messages
-reports=no
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Template used to display messages. This is a python new-style format string
-# used to format the message information. See doc for all details
-#msg-template=
+# List of plugins (as comma separated values of python module names) to load,
+# usually to register additional checkers.
+load-plugins = pylint.extensions.bad_builtin,
+ # pylint.extensions.code_style,
+ pylint.extensions.comparison_placement,
+ pylint.extensions.consider_refactoring_into_while_condition,
+ # pylint.extensions.docparams,
+ pylint.extensions.dunder,
+ pylint.extensions.eq_without_hash,
+ pylint.extensions.for_any_all,
+ # pylint.extensions.mccabe,
+ pylint.extensions.no_self_use,
+ pylint.extensions.overlapping_exceptions,
+ pylint.extensions.private_import,
+ pylint.extensions.redefined_loop_name,
+ pylint.extensions.set_membership,
[BASIC]
-# Good variable names which should always be accepted, separated by a comma
-good-names=main,_
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=x,y,i,l
-
-# Colon-delimited sets of names that determine each other's naming style when
-# the name regexes allow several styles.
-name-group=
-
-# Include a hint for the correct naming format with invalid-name
-include-naming-hint=no
+module-naming-style=snake_case
+const-naming-style=UPPER_CASE
+variable-naming-style=snake_case
+function-naming-style=snake_case
+argument-naming-style=snake_case
+attr-naming-style=snake_case
+class-naming-style=PascalCase
+class-attribute-naming-style=any
+class-const-naming-style=UPPER_CASE
+method-naming-style=snake_case
+inlinevar-naming-style=snake_case
+
+# Include a hint for the correct naming format with invalid-name.
+include-naming-hint=yes
+
+# Bad variable names which should always be refused, separated by a comma.
+bad-names=x,
+ y,
+ i,
+ l,
+ a,
+ b,
+ j,
+ o,
+ z
+
+# Good variable names which should always be accepted, separated by a comma.
+good-names=main,
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
-property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl
-
-# Regular expression matching correct function names
-function-rgx=^(?:(?PsetUp|tearDown|setUpModule|tearDownModule)|(?P_?[A-Z][a-zA-Z0-9]*)|(?P_?[a-z][a-z0-9_]*))$
-
-# Regular expression matching correct variable names
-variable-rgx=^[a-z][a-z0-9_]*$
+# These decorators are taken in consideration only for invalid-name.
+property-classes=abc.abstractproperty,
+ cached_property.cached_property,
+ cached_property.threaded_cached_property,
+ cached_property.cached_property_with_ttl,
+ cached_property.threaded_cached_property_with_ttl
-# Regular expression matching correct constant names
-const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
-
-# Regular expression matching correct attribute names
-attr-rgx=^_{0,2}[a-z][a-z0-9_]*$
-
-# Regular expression matching correct argument names
-argument-rgx=^[a-z][a-z0-9_]*$
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=5
-# Regular expression matching correct class attribute names
-class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
+# Bad variable names regexes, separated by a comma. If names match any regex,
+# they will always be refused
+bad-names-rgxs=^.{1,2}$
-# Regular expression matching correct inline iteration names
-inlinevar-rgx=^[a-z][a-z0-9_]*$
+# Good variable names regexes, separated by a comma. If names match any regex,
+# they will always be accepted
+good-names-rgxs=
-# Regular expression matching correct class names
-class-rgx=^_?[A-Z][a-zA-Z0-9]*$
-# Regular expression matching correct module names
-module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$
+[CLASSES]
-# Regular expression matching correct method names
-method-rgx=(?x)^(?:(?P_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P_{0,2}[a-z][a-z0-9_]*))$
+check-protected-access-in-special-methods=no
+defining-attr-methods=__init__,
+ __new__,
+ setUp
-# Regular expression which should only match function or class names that do
-# not require a docstring.
-no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$
+exclude-protected=_asdict,
+ _fields,
+ _replace,
+ _source,
+ _make
-# Minimum line length for functions/classes that require docstrings, shorter
-# ones are exempt.
-docstring-min-length=10
+valid-classmethod-first-arg=cls,
+ class_
+valid-metaclass-classmethod-first-arg=mcs
-[TYPECHECK]
-# List of decorators that produce context managers, such as
-# contextlib.contextmanager. Add to this list to register other decorators that
-# produce valid context managers.
-contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
+[DESIGN]
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
+max-args=5
+max-attributes=7
+max-bool-expr=5
+max-branches=12
+max-locals=15
+max-parents=7
+max-positional-arguments=5
+max-public-methods=20
+max-returns=6
+max-statements=50
+min-public-methods=2
-# List of module names for which member attributes should not be checked
-# (useful for modules/projects where namespaces are manipulated during runtime
-# and thus existing member attributes cannot be deduced by static analysis. It
-# supports qualified module names, as well as Unix pattern matching.
-ignored-modules=
-# List of class names for which member attributes should not be checked (useful
-# for classes with dynamically set attributes). This supports the use of
-# qualified names.
-ignored-classes=optparse.Values,thread._local,_thread._local
+[EXCEPTIONS]
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E1101 when accessed. Python regular
-# expressions are accepted.
-generated-members=
+# Exceptions that will emit a warning when caught.
+overgeneral-exceptions=StandardError,
+ Exception,
+ BaseException
[FORMAT]
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
# Maximum number of characters on a single line.
max-line-length=120
-# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt
-# lines made too long by directives to pytype.
-
# Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=(?x)(
- ^\s*(\#\ )??$|
- ^\s*(from\s+\S+\s+)?import\s+.+$)
+ignore-long-lines=(?x)(^\s*(\#\ )??$|^\s*(from\s+\S+\s+)?import\s+.+$)
-# Allow the body of an if to be on the same line as the test if there is no
-# else.
+# Maximum number of lines in a module.
+max-module-lines=99999
+
+single-line-class-stmt=no
single-line-if-stmt=yes
-# List of optional constructs for which whitespace checking is disabled. `dict-
-# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
-# `trailing-comma` allows a space between comma and closing bracket: (a, ).
-# `empty-line` allows space-only lines.
-# no-space-check=
-# Maximum number of lines in a module
-max-module-lines=99999
+[IMPORTS]
-# String used as indentation unit. Currently 4, consistent with
-# PEP 8.
-indent-string=' '
+# Allow explicit reexports by alias from a package __init__.
+allow-reexport-from-package=no
-# Number of spaces of indent required inside a hanging or continued line.
-indent-after-paren=4
+# Allow wildcard imports from modules that define __all__.
+allow-wildcard-with-all=no
-# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
-expected-line-ending-format=
+# Deprecated modules which should not be used, separated by a comma.
+deprecated-modules=regsub,
+ TERMIOS,
+ Bastion,
+ rexec,
+ sets
+# Force import order to recognize a module as part of a third party library.
+known-third-party=enchant,
+ absl
-[MISCELLANEOUS]
+[LOGGING]
-# List of note tags to take in consideration, separated by a comma.
-notes=TODO
+# The type of string formatting that logging methods do. `old` means using %
+# formatting, `new` is for `{}` formatting.
+logging-format-style=old
+# Logging modules to check that the string format arguments are in logging
+# function parameter format.
+logging-modules=logging,absl.logging
-[STRING]
-# This flag controls whether inconsistent-quotes generates a warning when the
-# character used as a quote delimiter is used inconsistently within a module.
-check-quote-consistency=yes
+[MESSAGES CONTROL]
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
+# UNDEFINED.
+confidence=HIGH,
+ CONTROL_FLOW,
+ INFERENCE,
+ INFERENCE_FAILURE,
+ UNDEFINED
+
+# Disable the message, report, category or checker with the given id(s).
+disable=raw-checker-failed,
+ locally-disabled,
+ suppressed-message,
+ arguments-differ,
+ fixme,
+ line-too-long,
+ global-statement,
+ import-error,
+ no-member,
+ signature-differs,
+ too-many-locals,
+ too-many-public-methods,
+ too-many-return-statements,
+ too-many-statements,
+ unnecessary-pass
-[VARIABLES]
+# Include some helpful details on errors messages for naming rules:
+include-naming-hint = yes
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-# A regular expression matching the name of dummy variables (i.e. expectedly
-# not used).
-dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_)
+[METHOD_ARGS]
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
+# List of qualified names (i.e., library.method) which require a timeout
+# parameter e.g. 'requests.api.get,requests.api.post'
+timeout-methods=requests.api.delete,
+ requests.api.get,
+ requests.api.head,
+ requests.api.options,
+ requests.api.patch,
+ requests.api.post,
+ requests.api.put,
+ requests.api.request
-# List of strings which can identify a callback function by name. A callback
-# name must start or end with one of those strings.
-callbacks=
-# List of qualified module names which can have objects that can redefine
-# builtins.
-redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools
+[MISCELLANEOUS]
+check-fixme-in-docstring=no
+notes=TODO
-[LOGGING]
-# Logging modules to check that the string format arguments are in logging
-# function parameter format
-logging-modules=logging,absl.logging
+[REFACTORING]
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
-[SIMILARITIES]
+# Complete name of functions that never returns. When checking for
+# inconsistent-return-statements if a never returning function is called then
+# it will be considered as an explicit return statement and no message will be
+# printed.
+never-returning-functions=sys.exit,argparse.parse_error
-# Minimum lines number of a similarity.
-min-similarity-lines=4
+# Let 'consider-using-join' be raised when the separator to join on would be
+# non-empty (resulting in expected fixes of the type: ``"- " + " -
+# ".join(items)``)
+suggest-join-with-non-empty-separator=yes
-# Ignore comments when computing similarities.
-ignore-comments=yes
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
+[REPORTS]
-# Ignore imports when computing similarities.
-ignore-imports=no
+reports=no
[SPELLING]
-# Spelling dictionary name. Available dictionaries: none. To make it working
-# install python-enchant package.
-spelling-dict=
-
-# List of comma separated words that should not be checked.
-spelling-ignore-words=
+# Limits count of emitted suggestions for spelling mistakes.
+max-spelling-suggestions=4
-# A path to a file that contains private dictionary; one word per line.
-spelling-private-dict-file=
+# List of comma separated words that should be considered directives if they
+# appear at the beginning of a comment and should not be checked.
+spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
-# Tells whether to store unknown words to indicated private dictionary in
-# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
-[IMPORTS]
+[STRING]
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,
- TERMIOS,
- Bastion,
- rexec,
- sets
+check-quote-consistency=yes
+check-str-concat-over-line-jumps=yes
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
+[VARIABLES]
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
+allow-global-unused-variables=yes
+dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_)
+ignored-argument-names=_.*|^ignored_|^unused_
+redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools
-# Force import order to recognize a module as part of the standard
-# compatibility libraries.
-known-standard-library=
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
-# Force import order to recognize a module as part of a third party library.
-known-third-party=enchant, absl
+[TYPECHECK]
-[CLASSES]
+# List of decorators that produce context managers, such as
+# contextlib.contextmanager. Add to this list to register other decorators that
+# produce valid context managers.
+contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,
- __new__,
- setUp
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=
-# List of member names, which should be excluded from the protected access
-# warning.
-exclude-protected=_asdict,
- _fields,
- _replace,
- _source,
- _make
+# Tells whether to warn about missing members when the owner of the attribute
+# is inferred to be None.
+ignore-none=yes
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls,
- class_
+# This flag controls whether pylint should warn about no-member and similar
+# checks whenever an opaque object is returned when inferring. The inference
+# can return multiple potential results while evaluating a Python object, but
+# some branches might not be evaluated, which results in partial inference. In
+# that case, it might be useful to still emit no-member and other checks for
+# the rest of the inferred objects.
+ignore-on-opaque-inference=yes
-# List of valid names for the first argument in a metaclass class method.
-valid-metaclass-classmethod-first-arg=mcs
+# List of symbolic message names to ignore for Mixin members.
+ignored-checks-for-mixins=no-member,
+ not-async-context-manager,
+ not-context-manager,
+ attribute-defined-outside-init
+
+# List of class names for which member attributes should not be checked (useful
+# for classes with dynamically set attributes). This supports the use of
+# qualified names.
+ignored-classes=optparse.Values,thread._local,_thread._local
+# Show a hint with possible names when a member name was not found. The aspect
+# of finding the hint is based on edit distance.
+missing-member-hint=yes
-[EXCEPTIONS]
+# The maximum edit distance a name should have in order to be considered a
+# similar match for a missing member name.
+missing-member-hint-distance=1
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=StandardError,
- Exception,
- BaseException
+# The total number of similar names that should be taken in consideration when
+# showing a hint for a missing member.
+missing-member-max-choices=1
+
+# Regex pattern to define which classes are considered mixins.
+mixin-class-rgx=.*[Mm]ixin
+
+# List of decorators that change the signature of a decorated function.
+signature-mutators=
diff --git a/requirements-generator.txt b/requirements-generator.txt
index d472d158b9b..7385618bb4f 100644
--- a/requirements-generator.txt
+++ b/requirements-generator.txt
@@ -1,6 +1,9 @@
-black<=22.3.0
-flake8~=5.0.4
-Jinja2~=3.1.2
-python-dateutil==2.8.1
-markupsafe==2.0.1
-tomli>=1.1.0; python_full_version < '3.11.2'
+Jinja2~=3.1.6
+black<=25.1.0
+flake8~=7.3.0
+markupsafe==3.0.2
+pytest-subtests~=0.14.2
+pytest~=8.4.0
+python-dateutil~=2.9.0
+requests~=2.32.4
+tomli>=2.2.1; python_full_version < '3.11.2'
diff --git a/requirements.txt b/requirements.txt
index 712608f8550..6d2f03a4e7d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,7 @@
-flake8~=5.0.4
-pylint~=2.17.1
-black<=22.3.0
-yapf~=0.32.0
-tomli>=1.1.0; python_full_version < '3.11.2'
+black<=25.1.0
+yapf~=0.43.0
+flake8~=7.3.0
+pylint ~=4.0.4
+pytest~=8.4.0
+pytest-subtests~=0.14.2
+tomli>=2.2.1; python_full_version < '3.11.2'