Package: phitoduck-projen
📣 Welcome tophito-projen!⚠️ WarningThis library is in rapid development. Expect breaking API changes.A library of Python-basedprojencomponents that can be used in.projenrc.py.PhilosophiesThis project is working to implement the ideas proposed inthis RFC.For convenience, here are the philosophies laid out in the RFC:#TemplatesAreEvilTemplates get stale over timeA process should exist so that projects are always up to date... but they are helpful:In the overwhelming space of Python software development, starting from an opinionated framework helps learn best practices with minimal cognitive load.... but they often lack desirable features, outside the scope of generating code:Writing/releasing production-worthy code requires infrastructure (i.e. GitHub account/repo). These
tools also have a non-trivial learning curve that should be automated where possible.Automation eliminates avoidable errors caused by manual stepsThe average use should not have to learn the entire Python ecosystem--thanks to abstractions.The advanced user should be able to extend the abstractions; you should not need to "grow out" of the tool.Where possible, we should avoid rebuilding what has already been built/standardized on by the community.The iteration cycle should be fast:developers should be able to run builds locallyprocesses that can be run in parallel should be run in parallel (both locally and in CI)Released software and docs should be immutable. Once packagev0.0.0is out there,
consumers of the software should be able to rely on the fact that it won't disappear and that the behavior
won't change.The tool should be built with both open- and closed-source development in mind.The trunk-based development branching model should have first-class support.Multi-project repositories (mono-repos) have a place in modern software development, and should be supported to an extent (e.g.frontendandbackendprojects, orsrcandiacmight reside in one repository)... but the framework should encourage developers to modularize projects in separate repos as much as possibleQuick startpip install phitoduck-projenCreate and execute a.projenrc.pyExample: Single-package Repository# .projenrc.pyfromphito_projenimportPythonPackagepackage=PythonPackage(name="phitoduck-projen",module_name="phito_projen",install_requires=["projen","jinja2"],version="0.1.0",)package.manifest_in.add_recursive_include("src/","*template*",comment="include template files for rendering components")package.synth()Runningpython .projenrc.pywill yield a nicely organized Python project structured like this:phitoduck-projen/
├── README.md
├── pyproject.toml
├── setup.cfg
├── setup.py
└── src/In this case, thesetup.cfg,setup.pyandpyproject.tomlfiles are set to be read-only.
This is because these config files are meant to be an implementation detail, created by
thePythonPackageabstraction.These read-only files can be modified by calling methods on thePythonPackageinstance,
or changing the parameters passed in. Callingpython .projenrc.pyagain will re-generate
the latestsetup.cfg,setup.pyandpyproject.tomlto reflect the changes.Future (or alternative) versions ofPythonPackagemight use an entirely different package
build system altogether. For example, we could generate only apyproject.tomlfor use withpoetryfor example, or aPipfile, etc., and keep the build/release process the same.This is where the power of projen for platform teams comes in!Because developers can only modify the package via thePythonPackageAPI, we the platform team
can freely swap out the implementation ofPythonPackageso long as we don't break existing
functionality.Example: Sample FastAPI Projectprojenhas a concept of "sample files" and "sample folders". These are files and folders
that are created only if not present.phitoduck-projenprovides a number of sample apps (and other components) that
can be used to create boiler projects with best practices. Here, we create
a Python package containing a sample FastAPI app.# .projenrc.pyfrompython_packageimportPythonPackagefromsamples.fastapi_appimportSampleFastAPIApppackage=PythonPackage(name="phitoduck-projen",module_name="phito_projen",install_requires=["projen","jinja2"],version="0.1.0",)SampleFastAPIApp(project=package)package.synth()Now, runningpython .projenrc.pywould yield something like this:phitoduck-projen
├── pyproject.toml
├── setup.cfg
├── setup.py
└── src
    └── example_pkg
        ├── __init__.py
        ├── config.py
        ├── default_constants.py
        ├── errors.py
        ├── main.py
        ├── types.py
        ├── utilities.py
        └── web/Example: Multi-package RepositoryYou may have a use case that requires having multiple Python packages in a single repository.projenmakes this easy:# .projenrc.pyfromprojenimportProjectfromphito_projen.python_packageimportPythonPackagefromphito_projen.samples.fastapi_appimportSampleFastAPIApprepo=Project(name="demo-project",outdir="demo-project")pkg=PythonPackage(parent=repo,name="example-python-package",module_name="example_pkg",install_requires=["pandas","new-dependency"],additional_extras_require={"test":["pytest"]},version="0.0.0",)pkg_2=PythonPackage(parent=repo,name="another_example-python-package",module_name="example_pkg_2",install_requires=["pandas","new-dependency"],additional_extras_require={"test":["pytest"]},version="0.0.0",)SampleFastAPIApp(project=pkg)repo.synth()Runningpython .projenrc.pywill yield this:demo-project/
├── another_example-python-package
│   ├── pyproject.toml
│   ├── setup.cfg
│   ├── setup.py
│   └── src/  # sample FastAPI files would be in here
└── example-python-package
    ├── pyproject.toml
    ├── setup.cfg
    ├── setup.py
    └── src/Ta-da! 🎉RoadmapReduce barrier to adoption by writing a CLI wizard that generates and invokes a.projenrc.py.Create an abstractCommentableObjectFilebase from whichYamlFile,IniFile,TomlFileandJsoncFilederive.
These will support escape hatches likeprojen'sObjectFile, but will allow for comments as well.Add aSampleSphinx(or simply aSphinx) component that can generate docs for multi-package repos.Add a way to orchestrate builds and releases for multi-package repos.Make these build efficient by parallelizing anything than can be, and skipping any tasks
if their "input files" have not changed.Useprojen's task runner system or write our own to provide aMakefile,Justfile, or other
task runner with useful commands for the project and any component add-ons.Add more samples for items like Metaflow training DAGs with MLFlow, BentoML services, CLI tools with Typer,
infrastructure as code with AWS CDK/Pulumi etc.Add components for thepre-commitframeworkAdd components for config files for code QA tools likepylint,flake8,pytest,black, etc.Add a component for.vscode/settings.jsonthat promps you to fix errors from these tools as you code, rather than having to wait to run a linting task.Investigatecommitizenas a way of automatically bumping package versions and generating changelogs.