Creating template for Python package

From ThemesWiki

Jump to: navigation, search
Python Paste
Official Page
Project Documentation
Download
Source Book
200px-184719494X.jpg
ISBN 978-1-847194-94-7
Publisher Packt Publishing
Author(s) Tarek Ziadé

Contents

[edit] The Template-Based Approach

The boiler-plate code in acme.sql is composed of a tree of folders that create the namespace of a few files in the root folder. To make all packages follow the same structure, a generic code template can be extracted and provided through a code-generation tool. This approach, called generative programming, is very useful at the organization level. It standardizes the way the code is written and makes developers more productive, as they focus on the code they really need to create. This approach is also a good opportunity to prepare a few things in the package such as complex test fixtures that are common to several packages.

There are numerous generative tools available in the community, but the most used is probably Python Paste (http://pythonpaste.org).

[edit] Python Paste

The Python Paste project was partly responsible for the success of frameworks such as Pylons (http://pylonshq.com). Developers are driven by an extensive suite of templates that lets them create applications' skeletons within minutes.

From the official tutorial, this is a three-liner to create a web application and run it:

 $ paster create -t pylons helloworld
 $ cd helloworld

$ paster serve --reload development.ini

The Plone and Zope communities followed this philosophy, and now provide Python Paste templates to generated skeletons as well. ZopeSkel (http://pypi.python.org/pypi/ZopeSkel) is one of them.

Python Paste contains several tools, and the template engine we are interested in is PasteScript. It can be installed with easy_install. It will get all dependencies from the Paste project:

 $ easy_install PasteScript
 Searching for PasteScript
 Reading http://pypi.python.org/simple/PasteScript/
 Reading http://pythonpaste.org/script/
 Best match: PasteScript 1.6.2
 Downloading
 ...
 Processing dependencies for PasteScript
 Searching for PasteDeploy
 ...
 Searching for Paste>=1.3
 ...
 Finished processing dependencies for PasteScript

The paster command will be available with a few default templates than can be listed with the list-templates option of the create command:

 
 $ paster create --list-templates
Available templates:
  basic_package: A basic setuptools-enabled package

paste_deploy: A web application deployed through paste.deploy

The basic_package is almost what acme.sql would have needed to build a namespaced package with a setup.py file. When run, the command line asks a few questions and the corresponding answers will be used to fill the templates:

 $ paster create -t basic_package mypackage
 Selected and implied templates:
  PasteScript#basic_package A basic setuptools-enabled package
 ...
 Enter version (Version (like 0.1)) ['']: 0.1
 Enter description ['']: My package
 Enter long_description ['']: this is the package
 Enter keywords ['']: package is mine
 Enter author (Author name) ['']: Tarek
 Enter author_email (Author email) ['']: tarek@ziade.org
 Enter url (URL of homepage) ['']: http://ziade.org
 Enter license_name (License name) ['']: GPL
 Enter zip_safe [False]:
 Creating template basic_package

...

The resulting structure is a valid, setuptools-compliant, one-level structure:

 $ find mypackage
 mypackage
 mypackage/mypackage
 mypackage/mypackage/__init__.py
 mypackage/setup.cfg

mypackage/setup.py

[edit] Creating Templates

Python Paste, let's call it the paster, can work with the Cheetah template engine for instance (http://cheetahtemplate.org), and feed it with the user input.

To create a new template for the paster, three elements have to be provided:

  • A class derived from paste.script.templates.Template
  • The structure to be created that contains folder and files (Cheetah templates or static files)
  • A setuptools entry point to paste.paster_create_template, to register the class

[edit] Creating the Package Template

Let's create the template that would have been used for acme.sql.

All templates created in this tutorial, including the package are gathered in pbp.skels that is available for your convenience at PyPI. So if you don't want to create your own from scratch, install it:

$ easy_install pbp.skels This section has step-by-step instructions explaining how pbp.skels was created.

To create the package template, the first thing to do is to create a structure for this new package:

 $ mkdir -p pbp.skels/pbp/skels
 $ find pbp.skels
 pbp.skels
 pbp.skels/pbp

pbp.skels/pbp/skels

Then, an __init__.py file with the following code is created in the pbp folder. It tells distutils to make it a namespaced package:

 try:
  __import__('pkg_resources').declare_namespace(__name__)
 except ImportError:
  from pkgutil import extend_path
  __path__ = extend_path(__path__, __name__)

Next, create a setup.py file in the root folder (path_to_pbp_package/pbp.skels/__init__.py) with the right metadata. The correct code for this is shown here:

 from setuptools import setup, find_packages
  version = '0.1.0'
 classifiers = [
  "Programming Language :: Python",
  ("Topic :: Software Development :: "
  "Libraries :: Python Modules")]
 
 setup(name='pbp.skels',
  version=version,
  description=("PasteScript templates for the Expert "
  "Python programming Book."),
  classifiers=classifiers,
  keywords='paste templates',
  author='Tarek Ziade',
  author_email='tarek@ziade.org',
  url='http://atomisator.ziade.org',
  license='GPL',
  packages=find_packages(exclude=['ez_setup']),
  namespace_packages=['pbp'],
  include_package_data=True,
  install_requires=['setuptools',
  'PasteScript'],
  entry_points="""
  # -*- Entry points: -*-
  [paste.paster_create_template]
  pbp_package = pbp.skels.package:Package
  """)

The entry point adds a new template that will be available in the paster.

The next step is to write the Package class in the pbp/skels folder, in a module called package:

 from paste.script.templates import var
 from paste.script.templates import Template
 
 class Package(Template):
  """Package template"""
  _template_dir = 'tmpl/package'
  summary = "A namespaced package with a test environment"
  use_cheetah = True
 
  vars = [
  var('namespace_package', 'Namespace package',
  default='pbp'),
  var('package', 'The package contained',
  default='example'),
  var('version', 'Version', default='0.1.0'),
  var('description',
  'One-line description of the package'),
  var('author', 'Author name'),
  var('author_email', 'Author email'),
  var('keywords', 'Space-separated keywords/tags'),
  var('url', 'URL of homepage'),
  var('license_name', 'License name', default='GPL')
  ]
 
  def check_vars(self, vars, command):
  if not command.options.no_interactive and \
  not hasattr(command, '_deleted_once'):
  del vars['package']
  command._deleted_once = True
  return Template.check_vars(self, vars, command)

This class defines:

  • The folder containing the template structure (_template_dir)
  • A summary of the template that will appear in the paster
  • A flag to indicate if Cheetah is used in the template structure
  • A list of variables, where each variable is composed of a name, a label, and a default value (if needed), which is used by the paster to ask the user at the prompt to enter his or her values
  • A check_vars method that makes sure the package variable will be requested at the prompt

The last thing to do is to create the tmpl/package directory content by copying the one created for acme.sql. All files that contain values to be changed, such as the namespace, have to be suffixed by _tmpl. The values are replaced by ${variable}, where variable is the name of the variable listed in the Package class.

The setup.py file (for instance) becomes setup.py_tmpl and contains:

 from setuptools import setup, find_packages
 import os
 
 version = ${repr($version) or "0.0"}
 long_description = open("README.txt").read()
 classifiers = [
  "Programming Language :: Python",
  ("Topic :: Software Development :: "
  "Libraries :: Python Modules")]
 
 setup(name=${repr($project)},
  version=version,
  description=${repr($description) or $empty},
  long_description=long_description,
  classifiers=classifiers,
  keywords=${repr($keywords) or $empty},
  author=${repr($author) or $empty},
  author_email=${repr($author_email) or $empty},
  url=${repr($url) or $empty},
  license=${repr($license_name) or $empty},
  packages=find_packages(exclude=[ ez_setup ]),
  namespace_packages=[${repr($namespace_package)}],
  include_package_data=True,
  install_requires=[
  setuptools ,
  # -*- Extra requirements: -*-
  ],
  test_suite= nose.collector ,
  test_requires=[ Nose ],
  entry_points=
  # -*- Entry points: -*-
  ,
  )

The repr function will tell Cheetah to add quotes around the string values.

You can use the same technique for all files located in acme.sql to make a template. For instance, the README.txt file is copied to README.txt_tmpl. Then all references to acme.sql are replaced by values defined in the Package class in the vars list.

For instance, getting the full package name is done by:

${namespace_package}.${package}

Last, to use a variable value for a folder name it has to be named with a "+" prefix and suffix. For instance, the namespaced package folder will be called +namespace_package+ and the package folder +package+.

The final structure of pbp.skeles, after the acme.sql has been generalized, will look like this:

 $ cd pbp.skels
 $ find .
 setup.py
 pbp
 pbp/__init__.py
 pbp/skels
 pbp/skels/__init__.py
 pbp/skels/package.py
 pbp/skels/tmpl
 pbp/skels/tmpl/package
 pbp/skels/tmpl/package/README.txt_tmpl
 pbp/skels/tmpl/package/setup.py_tmpl
 pbp/skels/tmpl/package/+namespace_package+
 pbp/skels/tmpl/package/+namespace_package+/__init__.py_tmpl
 pbp/skels/tmpl/package/+namespace_package+/+package+
 pbp/skels/tmpl/package/+namespace_package+/+package+/__init__.py

---

From there, the package can be symlinked to Python's site-packages directory with a develop command, and made available to the paster:

 $ python setup.py develop
 ...

Finished processing dependencies for pbp.skels==0.1.0dev

After the develop command is run, you should find the template listed in paster :

 $ paster create --list-templates
 Available templates:
  basic_package: A basic setuptools-enabled package
  pbp_package: A namespaced package with a test environment
  paste_deploy: A web application ... paste.deploy
 $ paster create -t pbp_package trying.it
 Selected and implied templates:
  pbp.skels#package A namespaced package with a test environment
 
 Variables:
  egg: trying.it
  package: tryingit
  project: trying.it
 Enter namespace_package (Namespace package) ['pbp']: trying
 Enter package (The package contained) ['example']: it
 ...
 Creating template package

...

The generated tree will then contain the structure ready to work with right away.

[edit] Additional References

  • For instructions on Installing Python, click here

[edit] Source

The source of this content is Chapter 5: Installing Scalix of Expert Python Programming by Tarek Ziadé (Packt Publishing, 2008).logo design by Kevin Josh 2010

Executive Editor Sean Lopez own  : SEO Company and provider of Link Building Services and SEO Services

And Like Costumes and Halloween Costumes and criar sites

And Like The Global Information Network and Global Information Network

Personal tools