Package: hellopymsdl
PYMSDL_TemplatePYMSDL(PYthon Maven Standard Directory Layout)templateis a
PythonPoetrytemplate inspired from
theMaven Standard Directory Layout.WARNING Prerequisites:Python >= 3.10.1Poetry >= 1.1.0Since there are some existing limitations, it is strongly advised to read
theProject organizationpart before theProject commandsone.Note:this template is configured in order to work withPoetry.if you want to use another layout thanMaven Standard Directory Layout,
you can change theproject structureas explained in thepyproject.toml & project.py filespart.Table of contentsQuickstartCreate a new project1. Click on Use this template2. Fork this template3. Clone/download this templatePrepare your environmentTest your setupManage your projectLet's devProject organizationpyproject.toml & project.py filesMaven Standard Directory Layout with pythonSources & Resources directories configurationWARNING: LimitationsA. Use root package names with suffixB. Use namespace package as root packageC. Don't fully respect the Maven Standard Directory LayoutProject commandsClean projectRun moduleRun toxRun linterRun testsRun type checkRun mutationBuildWheel archiveSource DistributionDelivery(on https://pypi.org/)DockerDev environmentBuild the pymsdl:devenv docker imageRun the pymsdl:devenv environmentDocker application image deliveryBuild your docker imageRun your docker imagePush your docker imageWorkflowsCIOn_releaseWeekly_checksQuickstartCreate a new projectThere are several ways to use this template for your project:1. Click onUse this templateCreate a new project from theUse this templatebutton is the
standard way for a new GitHub project from a template.See:Creating a repository from a templateNote:You have to be logged in2. Fork this templateCreate a new project by forking the template is the "old way" to work with templates on GitHub.However, there are some differences between "fork" and "use template"
explainedherewhich can help you about your choice.See:About forks3. Clone/download this templateThis is a way to use if you are creating a new project but, you are not working on GitHub.Prepare your environmentPYMSDL template requiresPython >= 3.10.1andPoetry >= 1.1.0.If your environment is not ready yet, a docker ready to work environment is provided
(seeDev environment).In order to simplify your pipeline evolution and local use, this template provides you a python script with basic
management commands. See:Project commands.You have to run this command line in order to download your project dependencies:./project.pyload_depsTest your setupPYMSDL template provides a simple sample project namedhellopymsdl. You can test your setup by running this command
line:./project.pytestManage your projectSince this template usePoetryyou have to learn eachpoetry command.Moreover, this template provides you a python script with basic management commands.
See:Project commandsNoteProject commandssamples should work on the providedhellopymsdlsimple sample
project.Let's devOnce previous steps are done you can start your developments by respecting the content
ofProject organizationpart.Project organizationpyproject.toml & project.py filesThepyproject.tomlfile is used in order to describe and deliver correctly your project.See:PEP 517 – A build-system independent format for source treesPEP 518 – Specifying Minimum Build System Requirements for Python ProjectsPEP 621 – Storing project metadata in pyproject.tomlPEP 660 – Editable installs for pyproject.toml based builds (wheel based)Poetry pyproject.toml detailsMoreover, this template provides theproject.pyfile which is a command line wrapper in order to
simplify the project evolution (seeProject commands).When you start a new project from this template,YOU DON'T HAVE TO UPDATE THEPROJECT.PYFILE,
until you switch fromPoetryto another tool.In order to set your project properties, you just have to update thepyproject.toml.Note:If you don't want to use theMaven Standard Directory Layout,
you can reconfigure the project structure by replacing each/src/main/...or/src/test/...by your structure in
thepyproject.tomlfile.Maven Standard Directory Layout with pythonSources & Resources directories configurationThis template attempts to reach
theMaven Standard Directory Layoutfor python.That's why you will find the following directory structure:src/main/python:Should contains your application sourcessrc/main/resources:Should contains your application resourcessrc/test/python:Should contains your applicationtestsourcessrc/test/resources:Should contains your applicationtestresourcesSourcesandresourcesdirectories must be in
yourPYTHONPATH.However, if you don't want to configure your PYTHONPATH, you can use the providedRun modulecommand.Note:if you are using IDE likePycharm, it meanssrc/main/pythonandsrc/main/resourcesmust be marked asSources Root(Right click on these directories > Mark directory as > Sources Root)andsrc/test/pythonandsrc/test/resourcesmust be marked asTest Sources Root(Right click on these directories > Mark directory as > Test Sources Root).Note:Due to aPoetrylimitation, using  installation with edit mode
(pip install -e .) in order to avoid thePYTHONPATHconfiguration will not work and fail
with:build backend is missing the 'build_editable' ... Consider using a build backend that supports PEP 660.WARNING: LimitationsPython resources MUST be located in a python package (i.e.: directory containing an__init__.pyfile). (You can see
that like a java classpath.)Since a package sources cannot be split in several directories, each package insrc/main/python,src/main/resources,src/test/pythonandsrc/test/resourcesdirectories must be different. In case of conflict, the
package from the first directory found in
yourPYTHONPATHwill be used.So if you want to respect theMaven Standard Directory Layoutthere are several suggestions:A. Use root package names with suffixUse root package names with suffixes like this:<My_Root_Package_Name>for sources (insrc/main/python)<My_Root_Package_Name>_rsrcfor resources (insrc/main/resources)<My_Root_Package_Name>_testfor test sources (insrc/test/python)<My_Root_Package_Name>_test_rsrcfor test resources (insrc/test/resources)Project structure example:<My_Project>|-...|-src|-main||-python|||-<MY_ROOT_PACKAGE_NAME>|||-__init__.py|||-...||-resources||-<MY_ROOT_PACKAGE_NAME>_rsrc||-__init__.py||-...|-test|-python||-<MY_ROOT_PACKAGE_NAME>_test||-__init__.py||-...|-resources|-<MY_ROOT_PACKAGE_NAME>_test_rsrc|-__init__.py|-...Note:since root package names are different (_rsrc,_test,_test_rsrcsuffixes) it cannot exist conflict
between packages insrc/main/python,src/main/resources,src/test/pythonandsrc/test/resources.Note:_rsrc,_test,_test_rsrcare just suggested suffixes you can use your own suffixes.B. Use namespace package as root packageIf you really want a common root package name, you can use anamespace packageas root. Thisnamespace packagemust
contain packages without conflict between sources and resources directories.Reminder: A namespace package doesn't contain any source or__init__.pyfile.Project structure with namespace package as root package example:<My_Project>|-...|-src|-main||-python|||-<MY_ROOT_NAMESPACE_PACKAGE_NAME>|||-<MY_PACKAGE_NAME>||||-__init__.py||||-...|||-...||-resources||-<MY_ROOT_NAMESPACE_PACKAGE_NAME>||-<MY_PACKAGE_NAME>_rsrc|||-__init__.py|||-...||-...|-test|-python||-<MY_ROOT_NAMESPACE_PACKAGE_NAME>||-<MY_PACKAGE_NAME>_test|||-__init__.py|||-...||-...|-resources|-<MY_ROOT_NAMESPACE_PACKAGE_NAME>|-<MY_PACKAGE_NAME>_test_rsrc||-__init__.py||-...|-...C. Don't fully respect the Maven Standard Directory LayoutIf you are not agree with the previous suggestions, you can remove thesrc/main/resources,src/test/pythonandsrc/test/resourcesdirectories and put your resources and tests directly into thesrc/main/pythondirectory.Note:if you do that, your tests will be included during your project/package installation (not only in the source
distribution as it is suggested in the best practices).Project commandsProject commands are available from theproject.pypython file.If you take a look at this file, you will see that it contains:A sharedproject_propertiesvariablewhich contains all project properties.A command line wrapper:this wrapper is designed in order to be used locally and in your deployment scripts (like
CI/CD).Indeed, by using it, if you want to update you "project tools" (sample: switching from poetry to setuptools) you just
have to update this script but not all your pipeline.Moreover, this wrapper manage the projectPYTHONPATHfor you.Command wrapper man:PROJECTCOMMANDSWRAPPER:

Usage:pythonproject.py<COMMAND_1><arg1_1...>...<COMMAND_N><argN_1...>Note:Inordertogetthewrappedcommandhelp,youcantrypythonproject.py<command>--help

Availablecommandsare:load_depsInstallalldependencies(devincluded)cleanRemovedirectoriesgeneratedbythe"build"commands(like'sdist'or'wheel')runRunmodulewhichcanbeintheprojectstructurewithouthavingtoconfigurethePYTHONPATHtoxRuntoxlintRunlintertestRunconfiguredunitteststypingRuntypingcheckermutRunmutationtestswheelBuildWheelarchivesdistBuildsdistarchiveuploadUploadavailabledeliveriesNote:Using--helpargument on a command or if an error occurs, the message will be from the wrapped command
line.Load dependencies./project.pyload_depsorpythonproject.pyload_depsClean project./project.pycleanorpythonproject.pycleanNote:Remove dist directory and test cache directories.Run modulePYMSDL template provides you a run python module command line (even in theproject packages) without having to
configure yourPYTHONPATH:./project.pyrun-m<MODULE_NAME>orpythonproject.pyrun-m<MODULE_NAME>Note:theruncommand is like opening python in your poetry virtual environment and the project structure
configured in yourPYTHONPATH.Moreover, your openedpythonwill work from the current directory (not from theproject.pyone).Examples:- Open apython consolefrom the current directory:./project.py runNote:<PATH_TO_PROJECT.PY> runwill open a python console in your current directory not in theproject.pyone.- Runmoduleexample:./project.pyrun-mhellopymsdl.__main__Run the__main__.pymodule fromhellopymsdlpackage.- Runpackageexample:./project.pyrun-mhellopymsdlNote:your package MUST contains a__main__.pymodule.- Runmodulefrom path example:./project.pyrunsrc/main/python/hellopymsdl/__main__.pyRun the__main__.pymodule fromhellopymsdlpackage.WARNING: the path is from the commandCWDif not absolute.- Runpackagefrom path example:./project.pyrunsrc/main/python/hellopymsdlNote:your package MUST contains a__main__.pymodule.WARNING: the path is from the commandCWDif not absolute.- Runmodulewith arguments example (using --args string parameter):./project.pyrun-mhellopymsdl.__main__--arg1--arg2=my_arg2...Run toxPYMSDL template usestoxin order to manage your tests (unit tests, lint, etc.)./project.pytoxorpythonproject.pytoxNote:You will find thetoxconfiguration in thepyproject.tomlfile
([tool.tox]section).The defaulttoxconfiguration provides the followingenvlist:pylint:Executes the configured lintercovclean:Cleans the coverage reportspy310:Executes the configured test runner under python 3.10report:Generates console, html and xml reportsmutation:Executes mutation testing and generate reportsMoreover, the provided configuration runs each test on INSTALLED packages (Not on the given sources even if obviously
the installed packages depends on the given sources). The goal is to test definitive installed versions.Run linter./project.pylintorpythonproject.pylintNote:jsonandtxtreports will be available inbuild/reports/lint.Note:By default this template usespylintas linter. You will find the linter
configuration in thepyproject.tomlfile ([tool.pylint....]sections).Note:This command usestoxbut only in order to call the linter.Run testsThis project is configured to execute tests withPytest:./project.pytestorpythonproject.pytestNote:html,jsonandxmlreports will be available inbuild/reports/coverage.Note:If you change the project structure, don't forget to update the[tool.pytest.ini_options]section from
thepyproject.tomlfile.Note:This command usestoxbut only in order to run your tests.Run type checkPYMSDL template provides a static type checker by usingmypy.See:PEP 484 – Type HintsPEP 526 – Syntax for Variable Annotations./project.pytypingorpythonproject.pytypingNote:Reports will be available inbuild/reports/typing.Note:If you change the project structure, don't forget to update thepyproject.tomlfile
([tool.tox]and[tool.mypy]sections).Note:This command usestoxbut only in order to call the type checker (by default:mypy).Run mutationThis template provides mutation testing by usingmutmut:./project.pymutorpythonproject.pymutNote:htmlreport will be available inbuild/reports/mutation.Note:If you change the project structure, don't forget to update thepyproject.tomlfile.Note:This command usestoxbut only in order to run your tests.BuildWheel archive./project.pywheelorpythonproject.pywheelSource Distribution archiveIf you need a source distribution (sdist) archive:./project.pysdistorpythonproject.pysdistDelivery(onhttps://pypi.org/)./project.pyuploadorpythonproject.pyuploadNote:Obviously, this command must be executed after theBuildone.DockerWARNING This part requiresdockerto be installedDev environmentIf you haven't a python/poetry environment installed, PYMSDL template provides you a "ready to work" Dockerfile:Build the pymsdl:devenv docker imagedockerbuild-tpymsdl:devenv-1.0.0-fdocker/devenv/Dockerfile.Run the pymsdl:devenv environmentdockerrun--rm-it--namepymsdl-dev-env-v${PWD}:/apppymsdl:devenv-1.0.0It opens ashon a well configured python/poetry environment.Note:you have to use the volume (-v) option in order to mount your project files into the container/appdirectory. This is useful for staying up to date with your updates.Now, you are ready to work (seeQuickstart).Docker application image deliveryNote:this step isuselessif you are working on a python package/Library/Framework to share (ie, not
an application) because in these cases you want to publish your sdist or/and wheel archive(s).Build your docker imagePYMSDL template provides a Dockerfile in order to build an image for your application based on a generatedwheeldistribution (See:Dockerfile)).Note:this Dockerfile is a "generic" one in order to provide a starting docker image distribution solution. You
can (/should) update (/rewrite) it in order to adapt it to your application (see:Best practices for writing Dockerfiles).Build image command:dockerbuild\-fdocker/app/Dockerfile\-t<DOCKER_IMG_NAME>:<VERSION>\--build-argwheel_name=<WHEEL_NAME>\--build-argentrypoint=<ENTRYPOINT_VALUE>\--build-argcmd=<CMD_VALUE>\.Where:<DOCKER_IMG_NAME>: Is your docker image name<VERSION>: Is your docker image version<WHEEL_NAME>:[REQUIRED]Is thewheelarchive name to install from thedistdirectory<ENTRYPOINT_VALUE>:[OPTIONAL: default ispython]Is the docker file ENTRYPOINT<CMD_VALUE>:[OPTIONAL: default cmd is empty]Is the dockerfile CMDNote:Obviously, this command must be executed after theWheel archiveone.Note:Using anentrypointwith an emptycmdprovides the possibility for the end user to usecmdas your
project parameters (argv). Moreover, you can usecmdin order to define your default project parameters.Example with the providedhellopymsdlsample application:First we create a wheel archive with./project.py wheel.Note:yourdistdirectory can contain several versions (/wheelarchives)- Build docker image frompython entry pointexample:Thehellopymsdlproject provides anhelloentry point (See:pyproject.toml).dockerbuild\-fdocker/app/Dockerfile\-thellopymsdl:2.9.10\--build-argwheel_name=hellopymsdl-2.9.10-py3-none-any.whl\--build-argentrypoint=hello\.- Build docker image frommoduleexample:dockerbuild\-fdocker/app/Dockerfile\-thellopymsdl:2.9.10\--build-argwheel_name=hellopymsdl-2.9.10-py3-none-any.whl\--build-argentrypoint="python -m hellopymsdl.__main__"\.Run the__main__.pymodule fromhellopymsdlpackage.- Build docker image frompackageexample:Thehellopymsdlproject provided anhelloentry point (See:pyproject.toml).dockerbuild\-fdocker/app/Dockerfile\-thellopymsdl:2.9.10\--build-argwheel_name=hellopymsdl-2.9.10-py3-none-any.whl\--build-argentrypoint="python -m hellopymsdl"\.Note:your package MUST contains a__main__.pymodule.- Build docker image withoutentrypointbuild-arg:if you don't define theentrypointbuild-arg, the default one ispython. So if you run your image
without any argument (orcmdbuild-arg) it will open a python console in an environment where your project is
installedTrick:If you want to build the last updated wheel (not the last version but the last built archive) you can use--build-arg wheel_name=$(ls -1At dist/ | head -1)Run your docker imageOnce your docker image is ready, you can run itdockerrun--rm<DOCKER_IMG_NAME>:<VERSION>Where:<DOCKER_IMG_NAME>: Is your docker image name<VERSION>: Is your docker image versionExample with the providedhellopymsdlsample application:docker run --rm --name hellopymsdl hellopymsdl:2.9.10Note:Since we used only theentrypointbuild-arg in our previous samples, if you have to pass arguments (argv)
to your project you can do it directly like this:docker run --rm --name hellopymsdl hellopymsdl:2.9.10 arg-1 arg-2 ... arg-NMoreover, you can define default values for your project parameters. To do that, you have to use thecmdbuild-arg
like this:dockerbuild\-fdocker/app/Dockerfile\-thellopymsdl:2.9.10\--build-argwheel_name=hellopymsdl-2.9.10-py3-none-any.whl\--build-argentrypoint=hello\--build-argcmd="arg-1 arg-2 ... arg-N"\.Note:You can override the defaultcmdby using the previous command line sample.Push your docker imageIn order to push your image into a repository (likeDocker Hub), you will have to use thedocker pushcommand line.SeeDocker repositoriesWorkflowsThe PYMSDL template provides a simpleGitHub Actionsworkflow in order to check
and manage your project (See:.github).CIThis workflow is executed onpull_requestorpush on main. It aims to check your project quality. To do that the
following steps are executed:Build archivesLintUnit testsMutation testsCheck dependencies vulnerabilitiesSee:ci.ymlNote:if you want to reuse thebadge for
your project, don't forget to update the link.On_releaseThis workflow is used in order to publish your project intopypi.By default, PYMSDL template try to publish your project intopypiwhen you publish a new release.Note:APYPI_API_TOKENsecret must be configured as pipy API key
(See:pypi api token).WARNING:pypidoesn't allow to override an existing package version. You have to update your
project version in thepyproject.tomlfile to a not existing one before publish a new release.
Otherwise, the workflow will fail.Note:This workflow doesn't execute tests again because released version should be onmainbranch and this
branch is configured to be protected (only pull requests can be merged on it which implies theCI workflowis
executed first).See:on_release.yml.Note:if you want to reuse thebadge for your
project, don't forget to update the link.You can find thehellopymsdlsample project publishedhereNote:it means you can runpip install hellopymsdl.Weekly_checksThis workflow is provided in order to do scheduled checks.By default, PYMSDL template weekly checks your project dependencies in order to detect vulnerabilities even if you are
not working on you project (i.e.:CI workflowis not executed).See:weekly_checks.yml.Note:if you want to reuse thebadge for your project, don't forget to update the link.