Open-source project
faif/python-patterns avatar
faif/python-patterns

python-patterns reads as a catalogue, not a library you install

GitHub describes it as A collection of design patterns/idioms in Python. The repository metadata lists Python as its primary language. This article stays within the project description and details documented in the GitHub repository README.

43,027 stars6,985 forksPythonLicense varies

At a glance

What is it?
python-patterns is a directory of design pattern files with no license, an empty dependency list, and a setuptools package list that stops one directory short of the code. Read it as a reference and it earns its place. Install it and you get less than the tables imply.
Who is it for?
python-patterns earns its place as a reading list, not as a dependency. Clone it, open the file for the pattern you are weighing, write your own version, and stay aware that no LICENSE covers copying one verbatim.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

packages = ["patterns"] is the whole install story

`pyproject.toml` builds with `setuptools >= 77.0.3` and declares `packages = ["patterns"]` under `[tool.setuptools]`. That is an explicit list, and no automatic discovery directive sits beside it. The pattern files live one level down, in the directories the README's tables link to: `patterns/creational/abstract_factory.py`, `patterns/structural/decorator.py`, `patterns/behavioral/observer.py`. None of those three directories appears in the package list.

So the artifact and the catalogue are different things. A reader who pip installs the `python-patterns` distribution gets a top-level `patterns` directory with the creational, structural, and behavioral subpackages undeclared, which puts the files themselves outside the built distribution. The README offers no install command and no download link; its tables link straight into the repository, which is the intended way in. For a collection whose entire value is the contents of those files, that is a defensible default, and it should not surprise anyone who expected a pip package to behave like a library.

The declared runtime dependency list is empty (`dependencies=[]`), so nothing here pulls a web framework or numpy into your environment.

The Makefile still says python3.8 while pyproject.toml requires 3.10

The documented way in is the Makefile, and its comment block gives the two setup lines:

bash
python3.8 -m venv venv
source venv/bin/activate

Read the first of those against `requires-python = ">=3.10"` and the comment has aged past the project. The classifiers go further, listing 3.10 through 3.14, so the real floor is 3.10 and the 3.8 above is a leftover. It matters because `checkvenv` runs ahead of every other target and exits with `Venv is not activated!` whenever `$VIRTUAL_ENV` is empty, so a new contributor meets a hard stop before any useful work.

Once inside the venv, two targets carry the setup:

bash
make lock
make pylinter line=88 path=.

`lock` installs pipenv if it is missing, then runs `pipenv lock --dev` and `pipenv sync --dev`. `pylinter` installs black, isort, and flake8 into `venv/bin/` when they are absent, then reformats and lints. The `line := 88` default feeds both the `--line-length` handed to black and the `--max-line-length` handed to flake8, so one variable governs the two tools.

--doctest-modules is enabled but testpaths never reaches the pattern files

The pytest configuration lives in `pyproject.toml`, not in a `pytest.ini` or `setup.cfg`. `addopts` reads `--doctest-modules --randomly-seed=1234 --cov=patterns --cov-report=term-missing`, and two lines below it `testpaths = ["tests"]`.

Those two settings pull in opposite directions. `--doctest-modules` asks pytest to execute the `>>>` examples embedded in Python files, and for a pattern collection that is the most direct check that a snippet still runs. `testpaths` then confines the run to the `tests/` directory, so the modules under `patterns/` are not collected by default. The file records the alternative on the next line as a comment, `#testpaths = ["tests", "patterns"]`.

For a repository whose examples are the product, that makes the examples opt-in to testing. Running pytest from the root gives you `tests/` and a coverage report over `patterns` that shows which pattern files no test ever reached. The fixed seed has a separate job: with `pytest-randomly` in the dev extras, `--randomly-seed=1234` keeps the shuffle reproducible, so a failure you hit locally reruns in the same order for whoever reads it next.

tox is a dev dependency with no tox.ini, and lint.sh has no rule

Tooling is configured in more places than one. The root holds `Pipfile`, `Pipfile.lock`, `pytest_local.ini`, `.travis.yml`, a `lint.sh`, a `config_backup/`, and the `pyproject.toml` that carries the settings pytest actually reads. A comment in that file says the settings are being added from tox.ini, and `tox>=4.25.0` sits in the dev extras, yet no tox.ini appears among the top-level entries.

The split that results is between how you obtain dependencies and how you get checked. `make lock` drives pipenv while the build backend is setuptools, and `make pylinter` runs black, isort, and flake8 with `--max-complexity "18"` and an `--ignore` list covering `E203,E266,E501,W503,F403,F401,E402`. Ignoring F401 and E402 is tuned to this repository in particular. Unused imports and imports placed after code are exactly what a set of standalone pattern snippets produces, so the lint config exists to let the examples keep their shape rather than to police them.

The default `all` target only echoes, and no target shown runs pytest, so the suite is something you start by hand.

No LICENSE file, and no license key in pyproject.toml

Nothing in this repository states a license. No `LICENSE` file appears among the top-level entries, `pyproject.toml` carries no `license` key and no Trove classifier for one, and no licensing note appears in the README. The only license in play is the one covering code you write yourself.

That is a real constraint on a collection of copy-and-paste code. The README frames each entry as a file you can point at, and its opening note asks you to think about why you are choosing a certain pattern rather than how to implement it. Neither instruction touches the other question, which is whether you may put that file into your codebase. Nothing inside the directory answers it either, since no per-file header is described.

Treat the repository as readable reference material rather than as a dependency. Read the file, write your own version, keep the result in your own tree. If you plan to vendor or redistribute anything from `patterns/`, ask first, because `faif` is listed as the sole maintainer in `pyproject.toml` and nobody else can answer.

GoF plus nine patterns with no stated provenance

The three tables cover the Gang of Four catalogue and then keep going. Alongside the classics you find `3-tier`, `mvc`, `front_controller`, `catalog`, `servant`, `borg`, `lazy_evaluation`, `chaining_method`, and a second `iterator` row marked as an alt. impl. pointing at `iterator_alt.py`. None of those nine come from the original design patterns book, and the README says nothing about where the borrowings came from or who to credit.

The book's own warning is the other thing worth carrying across, that each pattern has its own trade-offs and the reason for choosing one matters more than the mechanics of implementing it. In a catalogue of twenty-odd runnable files that is easy to state and harder to act on, because no entry tells you what a pattern costs. The `borg` row, for instance, is one line long and reads as a singleton with shared-state among instances, with nothing about what shared state costs in tests or under threads.

For the reference itself, the book is the real alternative. Its pseudocode is language-neutral and arrives in no Python at all, which is the gap this repository fills. Read both when a decision is on the table.

3-tier and mvc are listed side by side and differ only in strictness

Two structural entries sit next to each other and the distinction deserves a second read. `3-tier` is given as data<->business logic<->presentation separation with strict relationships, and `mvc` as model<->view<->controller with non-strict relationships. Strictness is the whole difference the table offers, which is thin ground for a decision that governs how much of your code is allowed to reach across layers.

The rest of the structural table is compressed the same way. `adapter` is defined by a white-list of methods, `facade` as one class used as an API to a number of others, `proxy` as an object that funnels operations to something else. Each is a link to one file, and each file is the documentation. There is no prose page, no before-and-after, and no test showing a pattern inside a codebase that is doing actual work.

The mermaid diagrams above each table carry less than they appear to. The structural graph draws a client reaching a facade over three subsystems, a client reaching an adapter over a legacy service, and a client reaching a proxy. Ten patterns are listed in that table and three are drawn. Read the tables, not the pictures.

Version 0.1.0 with no GitHub releases, and a push on 2026-09-24

`pyproject.toml` says `version = "0.1.0"` and the repository has no GitHub releases, so there is no tag to diff against and no changelog to read. The last push was on 2026-09-24, which tells you the files on `master` are being edited and tells you nothing about what sits on PyPI.

That gap is the practical upgrade cost. The version has not moved to reflect the commits behind it, so a reader who installs the published artifact and a reader who clones `master` can be looking at different code under one name. For a documentation collection the difference is small, but it is the difference between a snippet that ran against the current release of a library and one that did not, and the file listing gives you no way to tell which you hold.

The dev extras are the other thing to check before starting. `black>=25.1.0`, `mypy`, `pyupgrade`, `codespell`, `tox>=4.25.0`, and `pytest>=6.2.0` all sit in the optional `dev` group, so preparing to contribute means pulling the entire formatting and testing toolchain first.

Editorial conclusion

python-patterns earns its place as a reading list, not as a dependency. Clone it, open the file for the pattern you are weighing, write your own version, and stay aware that no LICENSE covers copying one verbatim. Treat the Makefile as the entry point and disregard its python3.8 comment, since pyproject.toml requires 3.10. Before you start, check three things in the files themselves: whether the pattern you want is one of the nine that did not come from the Gang of Four, whether the snippet still runs against the library versions you actually use, and whether you can point pytest at patterns/ yourself, since testpaths = ["tests"] leaves the embedded doctests uncollected by default.

Frequently asked questions

What are patterns in coding?

In this repository they are grouped as creational, structural, and behavioral, and every entry is one Python file linked from a table row. The project describes itself as a collection of design patterns and idioms in Python rather than a framework of its own.

What is a pattern and example?

Each table row pairs a pattern name with a one-line description and a link to the file that implements it, such as decorator described as wrapping functionality with other functionality in order to affect outputs. The linked file is the worked example.

How do I set up python-patterns for local work?

The Makefile comment gives `python3.8 -m venv venv` and `source venv/bin/activate`, followed by the targets `make lock` and `make pylinter line=88 path=.`. The 3.8 in that comment is stale, because pyproject.toml sets requires-python to >=3.10.

Official sources

  1. Official README
  2. Project repository