Getting started

When creating a project, the following steps are taken:

Creating the project

Create a project directory

~ $ export PROJECT=documentation
~ $ mkdir -p $PROJECTS/$PROJECT
~ $ cd $PROJECTS/$PROJECT
~ $ export PROJECT_DIR=`pwd`

Git init

Initialise the repository

~/projects/documentation $ git init
~/projects/documentation $ printf '# %s\n\n' "$PROJECT" > README.md
~/projects/documentation $ git add README.md
~/projects/documentation $ git commit -S -m "Initial commit"

Note

The ‘-S’ is used to sign the commit

gitflow

Enabling git-flow can be done either via git-flow

~ $ git-flow init -d

or manually

~/projects/documentation $ git flow init \
-p feature/ \
-b bugfix/ \
-r release/ \
-x hotfix/ \
-s support/

Using git-flow keeps the trunk branch in a pristine state while the monkies do their thing…

The original project files can now be copied over into a feature branch…

~/projects/documentation $ git flow feature start 'requirements-and-configuration'
~/projects/documentation $ mkdir "$PROJECT_DIR/docs"
~/projects/documentation $ cp -r $ORIGINAL_DIR/* $PROJECT_DIR/docs
~/projects/documentation $ cp -r $ORIGINAL_DIR/{.project,.pydevproject,.settings} .
~/projects/documentation $ git add *
~/projects/documentation $ git commit -S -m "Requirements and configuration

Initial documentation guides used to get thus far.
"
~/projects/documentation $ git flow feature finish requirements-and-configuration

pyproject

Add the pyproject.toml configuration.

Using ‘poetry init –help’, 4 options are required to initialise a ‘pyproject’

  • name

  • description

  • author

  • python

First, export these to the environment:

~/projects/documentation $ export NAME=devdocs
~/projects/documentation $ export DESCRIPTION="Ongoing base documentation"
~/projects/documentation $ export AUTHOR="`git config user.name` <`git config user.email`>"
~/projects/documentation $ export PYTHON=`python -c 'import sys; print(f"^{sys.version_info[0]}.{sys.version_info[1]}")'`
~/projects/documentation $ poetry init -n --name $NAME --description "$DESCRIPTION" --author "$AUTHOR" --python $PYTHON

then install and enter a virtual envrionment shell:

~/projects/documentation $ poetry install
Installing dependencies from lock file
~/projects/documentation $ poetry shell
(devdocs-...-py3.10) user@localhost $

Directory layout

There are three main choices for the project directory structure (or two, dependingon where your research has taken you):

  1. root_dir/project_name

    Python source files are placed under ‘project_name’ folder

    Possibly the most common layout given the ease of which developers can get started.

    The disadvantages to using this approach however, is everything is bundled under ‘project_name’. This leads to a situation where the ‘MANIFEST.in’ is used to control project files and can require careful management.

  2. root_dir/src/project_name

    Python source files are placed under ‘src/project_name’

    Possibly the second most common layout.

    The advantages to using this type of layout is ease of separation. For example, tests can be isolted from the package itself and used in extras.

    Which lends itself to easily adding ‘extra’s, these can be either packages located off the ‘src’ node, or just as easily a git submodule.

  3. root_dir/src/main/python/project_name

    Python source files are placed under ‘src/main/python/project_name’

    Possibly the most uncommon layout (and one the author hadn’t even heard of until a few months ago).

    The discovery of this type of layout was the conclusion of several months research into using various build tools.

    PyBuilder is the offending package responsible for even considering this type of layout, combined with a view on being able to use Maven for managing resources other than python source files.

    Thus, one can probably tell, this is the layout of choice.

    It provides all the advantages of the ‘src’ style layout, with additional capabilities for integrating different languages with ease.

    Combined with Maven and the extension eco system of plugins thus afforded, the possibility of using configuration based descriptors to generate boiler plate code is granted.

    It also provides future proofing, in regards that should the need arise to use a different language (such as C for optimisations, or Java), the layout is already prepared for statically compiled languages.

Create source tree

~/projects/documentation $ mkdir -p src/main/python/$NAME
~/projects/documentation $ printf '""".. currentmodule:: %s\n\n' $NAME > \
src/main/python/$NAME/__init__.py

Note

This has left the ‘__init__’ in an unparsable state…

Add header/meta information

Using sphinx directives some meta information will be added:

~/projects/documentation $ printf '.. versionadded:: 0.1.0
.. codeauthor:: %s <%s>\n"""\n\n' \
   "` git config user.name`" \
   "`git config user.email`" \
>> src/main/python/$NAME/__init__.py
~/projects/documentation $ printf '__authors__ = (\n    "%s <%s>"\n)\n\n' "` git config user.name`" \
   "`git config user.email`" \
>> src/main/python/$NAME/__init__.py
~/projects/documentation $ today=$(date "+%F")
~/projects/documentation $ printf '__updated__ = "%s"\n\n' $today \
>> src/main/python/$NAME/__init__.py

This adds the following directives/metadata:

  1. ‘currentmodule’ used by sphinx to determine what module it is

  2. ‘versionadded’ used by sphinx to determine when the module was added

  3. ‘__authors__’ standard python header indicating the module author

  4. ‘__updated__’ when the file was last updated

    This can usually be configured through the IDE to automatcially update on file changes.

Last entry

Finally we add the __all__ attribute to the module:

~/projects/documentation $ printf '__all__ = [""]\n\n' >> src/main/python/$NAME/__init__.py

Keeping the namespace is always a good idea, ergo what the above does

Check package exists

To finish, enter a python shell and import the package:

>>> import devdocs  
Traceback (most recent call last):
...
ModuleNotFoundError: No module named 'devdocs'

Oops!

The pyproject.toml hasn’t had the packages entry defined.

Open ‘pyproject.toml’ and under the ‘[tool.poetry]’ add the following:

packages = [
{ include = “devdocs”, from = “src/main/python” }
]

Note

The above doctest is marked to “skip” as it will only fail on the initially.

Once the package is installed, this exception will not be raised.

Update poetry:

~/projects/documentation $ poetry update
~/projects/documentation $ poetry install
Installing dependencies from lock file

Installing the current project: devdocs (0.1.0)

Looking at the result of git status, the ‘poetry.lock’ file is showing.

This needs to be ignored, add poetry.lock to the entry to the global ignore file.

Check again

>>> import devdocs
...

See also

6. Modules

An explanation to what ‘__all__’ is