/pyproject

Common files for pyproject based projects

Primary LanguagePython

About
=====

TurnKey Linux Python toolkit template, with two example commands:

1) example # dummy example command that parses options
2) prog # prints 'prog' not implemented

Features
========

* leverage common infrastructure (pyproject-common):

  - pyproject.py Python module for wrapper cli
  - shared base Makefiles
  - shred utility scripts

* integrated help support
  (e.g., command docstrings are automatically interpreted by wrapper)

* debian packaging support

* flexible toolkit execution syntax::

    # lists available commands
    project
    
    # runs pylib/cmd_command.py:main()
    project command arg1 arg2 ...
    project-command arg1 arg2 ...
    
    # if only one command available, this will run it
    project arg1 arg2

* wrapper environment setup

  - automatically sets up pylib into your python path 
  - automatically sets up libexec into your PATH

* versioning support

  Looks for version in the following places (by order):

  1) <INSTALL_PATH>/version.txt (if it exists)
  2) debian/changelog (if it exists - parsed with dpkg-parsechangelog)
  3) `autoversion HEAD`

To print out program version:
	project --version

* integrated profiler support

  project -p subcommand args...

  project-subcommand --profile args...

* integrated debugging support

  project -d subcommand args...

  project-subcommand --debug args..

Usage
=====

* initialization::

    cp -a pyproject newproject
    cd newproject && make init

* update packaging files

  eg. debian/control with descriptions and dependencies

* remove example dummy commands?

  pylib/cmd_printargs.py

  pylib/cmd_prog.py

* add programs to the toolkit as pylib/cmd_<subcmd>.py

* Makefile help usage

  make || make help

* update links (when you have added or removed commands)

  make updatelinks

  Remember, you can run toolkit commands like this::

    pylib/cmd_<subcmd>.py arg1 arg2 ...
    <progname>-<subcmd> arg1 arg2 ...
    <progname> <subcmd> arg1 arg2 ...
  
* documentation / integrated help

  Usage:
  <progname> # prints high level overview of programs + help
  <progname>-<command> -h # extended help
  
  Notes:
  
  - The first line of a cmd_* module docstring is the short usage desc.
  - commands that have a usage() function, support the -h flag for
    extended help.
  - The help module defines a usage decorator for convenience.  
  
  Example usage (see cmd_printargs for an example)::
  
      import help
      @help.usage(__doc__)
      def usage():
          print "Syntax: foo"
  
  Advanced:
  
  Normally, the order of the commands printed by <progname> is determined
  by their sort order. If you want to manually tweak with the order, then
  list the desired order in wrapper.CliWrapper.COMMANDS_USAGE_ORDER.
  
  Empty string values COMMANDS_USAGE_ORDER symbolize empty lines/seperators.
  
* install::

    make install prefix=...  # prefix defaults to /usr/local

* uninstall::

    make uninstall	         # prefix defaults to /usr/local

* tag the latest commit as a versioned release:

  # this will ask you for a tag message (which may include release notes)
  # and create a tag signed by your GPG key
  git-tag -s v1.0.1
  
  (if available, use of git-tag-release is recommended)

Makefile extension mechanism
============================

pyproject-common's Makefiles (pyproject.mk and debian-rules.mk)
are designed to be configurable and extendable with *define* based hooks
which are set BEFORE including the shared Makefile because target
prerequisites are evaluated at include time::

    <target>/pre  # rules before default body (default: empty)
    <target>/post # rules after default body (default: empty)

    <target>/deps # override default dependencies for a rule
    <target>/deps/extra # extra dependencies for rule (default: empty)

Special case - if you want to override built in built-in rules for a target,
you'll need to define them AFTER including the shared Makefile::

    <target>/body # body of rules (default: defined, but can be overridden)

To override built-in variables you'll need to define them AFTER the include.

Most pyprojects don't need to extend the default Makefiles, but
extending and overriding default behavior is occasionally needed to
satisfy special use cases (e.g., connagent and opus).

For example::

    $ cd opus
    $ cat Makefile
    PATH_INSTALL_TEMPLATES = $(PATH_INSTALL)/templates
    
    define help/post
            @echo
            @echo "templates                        # make templates/generated"
    endef
    
    templates:
            cd templates && ./generate.py
    
    build/deps/extra = templates
    
    define install/post
            install -d $(PATH_INSTALL_TEMPLATES)
            cp -a templates/generated $(PATH_INSTALL_TEMPLATES)
    endef
    
    .PHONY: templates
    
    PYPROJECT_SHARE_PATH ?= /usr/share/pyproject
    include $(PYPROJECT_SHARE_PATH)/pyproject.mk
    
Makefile API
============

pyproject.mk::

        INSTALL_SUID   # if not empty string, install program suid
        INSTALL_NODOC  # if not empty string, compile without docstrings

        EXTENDABLE_TARGETS = help build install uninstall clean

debian-rules.mk::

        EXTENDABLE_TARGETS = build clean binary-indep binary-arch