{"id":20202675,"url":"https://github.com/devsjc/python-project-structure","last_synced_at":"2025-07-19T04:02:54.247Z","repository":{"id":190448260,"uuid":"682647685","full_name":"devsjc/python-project-structure","owner":"devsjc","description":"Information on how to structure a python project, based on the Hexagonal Architecture pattern ","archived":false,"fork":false,"pushed_at":"2023-08-24T16:19:49.000Z","size":15,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-10T14:11:33.688Z","etag":null,"topics":["guide","hexagonal-architecture","project-layout","project-structure","pyproject-toml","python","src-layout","template"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devsjc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-24T16:09:27.000Z","updated_at":"2023-08-24T17:28:52.000Z","dependencies_parsed_at":"2023-08-24T18:31:38.574Z","dependency_job_id":null,"html_url":"https://github.com/devsjc/python-project-structure","commit_stats":null,"previous_names":["devsjc/python-project-structure"],"tags_count":0,"template":true,"template_full_name":null,"purl":"pkg:github/devsjc/python-project-structure","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devsjc%2Fpython-project-structure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devsjc%2Fpython-project-structure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devsjc%2Fpython-project-structure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devsjc%2Fpython-project-structure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devsjc","download_url":"https://codeload.github.com/devsjc/python-project-structure/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devsjc%2Fpython-project-structure/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265886965,"owners_count":23844317,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["guide","hexagonal-architecture","project-layout","project-structure","pyproject-toml","python","src-layout","template"],"created_at":"2024-11-14T04:57:53.674Z","updated_at":"2025-07-19T04:02:54.190Z","avatar_url":"https://github.com/devsjc.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch2 align=\"center\"\u003e\nMODERN PYTHON MICROSERVICE\n\u003cbr\u003e\n\u003cbr\u003e\nTemplate for creating src-layout PEP628 compliant hexagonal python microservice.\u003c/h2\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n\u003ca href=\"https://github.com/devsjc/python-project-structure/graphs/contributors\" alt=\"Contributors\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/contributors/devsjc/python-project-structure?style=for-the-badge\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/devsjc/python-project-structure/actions/workflows/ci.yml\"\u003e\n    \u003cimg alt=\"GitHub Workflow Status (with branch)\" src=\"https://img.shields.io/github/actions/workflow/status/devsjc/python-project-structure/ci.yml?branch=main\u0026style=for-the-badge\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/devsjc/python-project-structure/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/issues/devsjc/python-project-structure?style=for-the-badge\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/devsjc/python-project-structure/tags\"\u003e\n    \u003cimg alt=\"GitHub tag (latest SemVer pre-release)\" src=\"https://img.shields.io/github/v/tag/openclimatefix/package-name?include_prereleases\u0026sort=semver\u0026style=for-the-badge\"\u003e\u003c/a\u003e\n\u003ca href=\"https://pypi.org/project/package-name\"\u003e\n    \u003cimg alt=\"PyPI tag (latest SemVer pre-release)\" src=\"https://img.shields.io/pypi/v/package-name?style=for-the-badge\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\n\nRepo containing a template for creating a modern Python microservice. The template is designed to contain the important\nparts of a Hexagonal python microservice, with a minimal dockerfile and a CI workflow that builds and tests the service.\nIt uses modern python standards, such as pyproject.toml and src-layout, and is designed to be easily extended. The\ncontents of this README are an example of what you might expect to find in a well-documented service.\n\n## Running the service\n\nDepending on the source and sink you choose to read and write data from, environment variables will need to be set.\nThe program will inform you of missing env vars, but you can also check the \n[config](src/nwp_consumer/internal/config/config.py) for the given module.\n\n### CLI\n\nWhether running via Docker or the Python package, available commands can be found with the command `help` or the \n`--help` flag. For example:\n\n```shell\n$ package-name --help\n# or\n$ docker run ghcr.io/user/package-name:latest --help\n```\n\n## Ubiquitous Language\n\nThe following terms are used throughout the codebase and documentation. They are defined here to avoid ambiguity.\n\n- ***Ubiquitous Language*** - The language describing terms relevant to the bounded context of the service. These are\n high-level business descriptions of the function of the application, not code-specific terms.\n\n\n## Repository structure\n\nProduced using [exa](https://github.com/ogham/exa):\n```shell\n$ exa --tree --git-ignore -F -I \"*init*|test*.*\"\n```\n\n```yml\n./\n├── Containerfile # Dockerfile for building the image\n├── pyproject.toml # The build configuration for the service\n├── README.md\n└── src/\n   ├── package_name/ # The python package\n   │  ├── cmd/\n   │  │  └── main.py # The entrypoint for the service\n   │  └── internal/ # Packages internal to the service. Akin to 'lib' folder\n   │     ├── config/\n   │     │  └── config.py # Configuration for the service\n   │     ├── models.py\n   │     ├── outputs/ # Holds subpackages for each data sink\n   │     └── service/ # Contains the business logic and use-cases of the application\n\n```\n\n`package-name` is structured following principles from the hexagonal architecture pattern. In brief, this means a clear \nseparation between the application's business logic - it's **Core** - and the **Actors** that are external to it. In \nthis package, the core of the service is in `internal/service/` and the actors are in `internal/inputs/` and \n`internal/outputs/`. The service logic has no knowledge of the external actors, instead defining interfaces that the \nactors must implement. These are found in `internal/models.py`. The actors are then responsible for implementing these \ninterfaces, and are *dependency-injected* in at runtime. This allows the service to be easily tested and extended. See\n[further reading](#further-reading) for more information.\n\n## Local development\n\nClone the repository and create and activate a new python virtualenv for it. `cd` to the repository root.\n\nInstall the [Python](#python-requirements) dependencies as shown in the section\nbelow.\n\n### Python requirements\n\nInstall the required python dependencies (including dev dependencies) and make it editable with\n\n```shell\n$ pip install -e .[dev] \n```\n\nThis looks for requirements specified in the `pyproject.toml` file.\n\n\u003cdetails\u003e\n    \u003csummary\u003eWhere is the requirements.txt file?\u003c/summary\u003e\n\nThere is no `requirements.txt` file. Instead, the project uses setuptool's pyproject.toml integration to specify \ndependencies. This is a new feature of setuptools and pip, and is the \n[recommended way](https://packaging.python.org/en/latest/tutorials/packaging-projects/) to specify dependencies.\nSee [the setuptools guide](https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html) and\n[the PEP621 specification](https://packaging.python.org/en/latest/specifications/declaring-project-metadata)\nfor more information, as well as [Further Reading](#further-reading).\n\u003c/details\u003e\n\n### Running tests\n\nEnsure you have installed the [Python requirements](#python-requirements).\n\nRun the unit tests with\n\n```shell\n$ python -m unittest discover -s src/package_name -p \"test_*.py\"\n```\n\nand the integration tests with\n\n```shell\n$ python -m unittest discover -s test_integration -p \"test_*.py\"\n```\n\nSee [further reading](#further-reading) for more information on the `src` directory structure.\n\n\n### Linting and autoformatting\n\nThis project uses [Ruff](https://github.com/charliemarsh/ruff) for linting and autoformatting.\nIt can be run whilst developing via\n\n```shell\n$ ruff check --watch --fix src\n```\n\n\n---\n\n## Further reading\n\nOn packaging a python project using setuptools and pyproject.toml:\n- The official [PyPA packaging guide](https://packaging.python.org/en/latest/tutorials/packaging-projects/).\n- A [step-by-step practical guide](https://godatadriven.com/blog/a-practical-guide-to-setuptools-and-pyproject-toml/)\non the *godatadriven* blog.\n- The pyproject.toml\n[metadata specification](https://packaging.python.org/en/latest/specifications/declaring-project-metadata).\n\nOn hexagonal architecture:\n- A [concrete example](https://medium.com/towards-data-engineering/a-concrete-example-of-the-hexagonal-architecture-in-python-d821213c6fb9)\nusing Python.\n- An [overview of the fundamentals](https://medium.com/ssense-tech/hexagonal-architecture-there-are-always-two-sides-to-every-story-bc0780ed7d9c) \nincorporating Typescript \n- Another [example](https://medium.com/@matiasvarela/hexagonal-architecture-in-go-cfd4e436faa3) using Go.\n\nOn the directory structure:\n- The official [PyPA discussion](https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/) on \nsrc and flat layouts.\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevsjc%2Fpython-project-structure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevsjc%2Fpython-project-structure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevsjc%2Fpython-project-structure/lists"}