Skip to content

enerqi/python-skeleton

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Python-Skeleton

Command line utility for creating a python project skeleton. Requires python 3 to run.

Examples:

python3 python-new-project.py myproject --app  # create a new application based project in ./myproject
python3 python-new-project.py /path/to/myproject --lib   # create a library project in /path/to/myproject
python3 python-new-project.py myproject --app --force  # create the new project overwriting any existing skeleton files

Notes

Libraries vs Applications

Libraries specify abstract dependencies (including dev-packages) in setup.py but may use Pipenv to create a virtual env. Applications specify exact dependencies in a Pipfile + Pipfile.lock that are checked into the source code. A setup.py file is not needed as there need not be any packaging.

Virtual Environment

It's easy to get library/tool version mismatches when not working in an isolated environment on a development machine. It is more feasible to install globally if using something like jails/docker.

  • Pipenv is the latest python tooling for creating virtual environments and dealing with dependencies.
  • Anaconda is a tool for creating isolated environment management. Virtualenv could also be used but anaconda has better support for building non-python code. When using Pipenv you probably are not going to need it, though pipenv might be able to use an arbritrary environment.
  • pip and virtualenv can be avoided when using Pipenv - pipenv uses them in its implementation.
  • pip-tools is a good option for carefully managing production and development dependencies if not using pipenv.

A Pipfile and Pipfile.lock should not be committed to the project for library based projects - only abstract dependencies should be specified in the setup.py for libraries.

Import Style

Prefer absolute imports, otherwise I find at least one of flask or pytest or the editor/IDE have some import problem. Pep-008 recommends absolute imports or maybe explicit relative imports. Implicit relative imports are removed from python 3.

import mypkg.sibling
import mypkg.sibling as sibling
from mypkg import sibling
from mypkg.sibling import example
from . import sibling  # relative
from .sibling import example  # relative

Tool config

Most tools (e.g. coverage, pytest, flake8, mypy) now allow their config to go in the one file setup.cfg instead of requiring their own file (e.g. mypy.ini, .flake, and pytest.ini).

Pytest

[tool:pytest]
addopts = --doctest-modules --ignore build

MyPy

[mypy]
python_version = 3.6
ignore_missing_imports = true

Makes mypy quiet when it finds 3rd party code that does not have any type annotations.

Running 'main' type python files (if part of package)

Running something like app/main.py within a project results in import errors as the main file does not know it is part of a package. Both setting the PYTHONPATH and doing sys.path.insert stuff seems ugly. See Stackoverflow.

A shell script per runnable main file seems a reasonable approach, for example:

#!/bin/bash
BASEDIR=$(dirname "$0")
PYTHONPATH=$BASEDIR python3 app/main.py

Coverage reports on tests

Install the python dependency pytest-cov into the virtual environment. See pytest --help. For example, to run coverage in html or xml on mymodule and submodules.

pytest --cov-report=html|xml --cov=mymodule or pytest --cov=mymodule to print to terminal.

Type hint linting and documentation

If using python3 and specificaly python3.5+ we can use type hints, that at least serves as minimal documentation and provides some support for type driven development / domain modelling.

The MyPy project is a linter that will try to check those types statically. It is however, an alpha status project, despite being > 5 years old.

Enabling doctests in combination with pytest & flask

Putting this pytest conftest.py file in the main package directory(s) to fix this pytest/doctest/flask combination issue.

"""Pytest configuration module to fix pytest/doctest-discovery/flask interaction issue."""
import importlib


def pytest_configure():
    patch_flask_for_doctest()


def patch_flask_for_doctest():
    """
    Patch flask magic objects to keep them from raising
    RuntimeErrors during doctest discovery.
    https://github.com/pallets/flask/issues/1680
    """
    flask = importlib.import_module('flask')
    object.__setattr__(flask.request, '__wrapped__', None)
    object.__setattr__(flask.session, '__wrapped__', None)
    object.__setattr__(flask.current_app, '__wrapped__', None)

Releases

No releases published

Packages

No packages published