Python Paste

Install

easy_install paste
easy_install pastescript

Create project

paster create myapp

myapp
|-- __init__.py
|-- myapp
|   |-- __init__.py
|   `-- __init__.pyc
|-- myapp.egg-info
|   |-- PKG-INFO
|   |-- SOURCES.txt
|   |-- dependency_links.txt
|   |-- entry_points.txt
|   |-- not-zip-safe
|   |-- paster_plugins.txt
|   `-- top_level.txt
|-- setup.cfg
`-- setup.py

Register your project

 entry_points="""
      [paste.paster_create_template]
      myapp = myapp.myapp:FrameworkTemplate
      """,

/myapp/myapp/__init__.py

from paste.script import templates

class FrameworkTemplate(templates.Template):

    egg_plugins = ['myapp']
    summary = 'Template for creating a basic Framework package'
    required_templates = ['basic_package']
    _template_dir = 'templates'
    use_cheetah = True

cd myapp/myapp
mkdir templates
cd templates
mkdir +package+

python setup.py develop

paster create --list-templates

paster create -t myapp
or later
paster create -t myapp SomeCommand

Templates

Template Structure

myapp
|-- __init__.py
|-- __init__.pyc
|-- myapp
|   |-- __init__.py
|   |-- __init__.pyc
|   `-- templates
|       |-- +package+
|       |   `-- testfile.py_tmpl
|       `-- __init__.py
|-- myapp.egg-info
|   |-- PKG-INFO
|   |-- SOURCES.txt
|   |-- dependency_links.txt
|   |-- entry_points.txt
|   |-- not-zip-safe
|   |-- paster_plugins.txt
|   `-- top_level.txt
|-- setup.cfg
`-- setup.py

paster create -t "myapp"

maa4
|-- __init__.py
|-- maa4
|   |-- __init__.py
|   `-- testfile.py
|-- maa4.egg-info
|   |-- PKG-INFO
|   |-- SOURCES.txt
|   |-- dependency_links.txt
|   |-- entry_points.txt
|   |-- not-zip-safe
|   |-- paster_plugins.txt
|   `-- top_level.txt
|-- setup.cfg
`-- setup.py

Template Variables

*Based on the http://pythonpaste.org/script/developer.html#templates we add few more options to our init file. *required_templates = ['basic_package'] means that basic_package template will be run before ours. *You specify a list of variables.

from paste.script import templates
vars = [
        templates.var('version', 'Version (like 0.1)'),
        templates.var('description', 'One-line description of the package'),
        templates.var('long_description', 'Multi-line description (in reST)'),
        templates.var('keywords', 'Space-separated keywords/tags'),
        templates.var('author', 'Author name'),
        templates.var('author_email', 'Author email'),
        templates.var('url', 'URL of homepage'),
        templates.var('license_name', 'License name'),
        templates.var('zip_safe', 'True/False: if the package can be distributed as a .zip file',
            default=False),
    ]

class FrameworkTemplate(templates.Template):

    egg_plugins = ['MyApp']
    summary = 'Template for creating a basic Framework package'
    required_templates = ['basic_package']
    _template_dir = 'template'
    use_cheetah = True
    vars=vars

${package}
${author}

#This file was created by ${author}.
from ${package}.myfiles import myprogramfile

Customize the template

class FrameworkTemplate(templates.Template):

    egg_plugins = ['MyApp']
    summary = 'Template for creating a basic Framework package'
    required_templates = ['basic_package']
    _template_dir = 'template'
    use_cheetah = True
    vars=vars

    #Customizing question
    from paste.script import command
    def pre(self, command, output_dir, vars):
        vars['myquestion']=command.challenge('Please Enter A Name:','done',True)

    from paste.script import command
    def pre(self, command, output_dir, vars):
        vars['myquestion']=[]
        while 1:
            question=command.challenge('Please Enter A Name:','done',True)
            if question=='done':
                break
            #Do what every you want with the new response below.
            vars['myquestion'].append(question)

Cheetah and custom Templates

#Please refer to cheetah docs for exact syntax

#if not 'txt' in vars['myurl']
#  exec raise SkipTemplate

from Cheetah.Template import Template
#Provide source filename of where the file is:
source_filename = os.path.join(os.path.dirname(__file__), 'somefolder/somefile.py_tmpl')
#Fill in the template file
content = Template(file=source_filename, searchList=[vars])
#Create a file, by passing the filename and content
command.ensure_file(os.path.join(vars['package'], filename), str(content))

Create Automatic rst Syntax

myoproject documentation
========================

#repeat $len($project) + 14
=#slurp
#end repeat

$project documentation

Commands

Create a command

from paste.script import command

class MyCommand(command.Command):

    max_args = 1
    min_args = 1

    usage = "NAME"
    summary = "Say hello!"
    group_name = "My Package Name"

    parser = command.Command.standard_parser(verbose=True)
    parser.add_option('--goodbye',
                      action='store_true',
                      dest='goodbye',
                      help="Say 'Goodbye' instead")

    def command(self):
        name = self.args[0]
        if self.verbose:
            print "Got name: %r" % name
        if self.options.goodbye:
            print "Goodbye", name
        else:
            print "Hello", name

Attributes

 min_args = 0
 max_args = 1
or
 min_args = 1
 max_args = 1

Group Name

paster

Commands:
  create          Create the file layout for a Python distribution
  grep            Search project for symbol
  help            Display help
  make-config     Install a package and create a fresh config file/directory
  points          Show information about entry points
  post            Run a request for the described application
  request         Run a request for the described application
  serve           Serve the described application
  setup-app       Setup an application, given a config file

TurboGears2:
  crud            Generate CRUD interface based on model
  migrate         Sqlalchemy migration
  quickstart      Create a new TurboGears 2 project.
  tginfo          Show TurboGears 2 related projects and their versions

pylons:
  controller      Create a Controller and accompanying functional test
  restcontroller  Create a REST Controller and accompanying functional test
  shell           Open an interactive shell with the Pylons app loaded

group_name = 'TurboGears2'

add option

 parser.add_option('-o', '--output-dir',
                      dest='output_dir',
                      metavar='DIR',
                      default='.',
                      help="Write put the directory into DIR (default current directory)")

output_dir = os.path.join(self.options.output_dir, 'somefolder')

def command(self)

paste.script.checkperms
paste.script.command
paste.script.copydir
paste.script.filemaker
paste.script.templates
paste.script.testapp
paste.script.util.secret

parse PKG-INFO

import pkg_resources
for ep in pkg_resources.iter_entry_points(
    'paste.app_factory','main'):
    print ep
    dir(ep)

from paste.script import pluginlib
import os, sys
egg_info_dir = pluginlib.find_egg_info_dir(os.getcwd())
plugins= os.path.splitext(os.path.basename(egg_info_dir))[0]
print os.path.splitext(os.path.basename(egg_info_dir))[0]
dist= pluginlib.get_distro(plugins)
if dist.has_metadata('PKG-INFO'):
    data=dist.get_metadata('PKG-INFO')

for add_info in pluginlib.parse_lines(data):
    print add_info

Entry Point

paste.paster_command

[paste.paster_command]
    mycommand = mypackage.mycommand:MyCommand

echo "mygreatnewapplication" >> ./sometg2app.egg-info/paster_plugins.txt
or
echo "modwsgideploy" >> ./myapp.egg-info/paster_plugins.txt

paster

paste.global_paster_command

[paste.global_paster_command]
    myglobal = mypackage.myglobal:MyGlobalCommand

Installing package

setup.py

Package and upload to PYPI

python setup.py sdist
or
python setup.py sdist --formats=gztar,zip

python setup.py register
python setup.py sdist upload

MANIGEST.in

recursive-include somefolder *.txt *.py *_tmpl *.wsgi
or
recursive-include templates *.txt *.py *_tmpl *.wsgi
or
recursive-include somefolder2 *.txt *.py *_tmpl *.wsgi

check your long_description

$ python setup.py --long-description | rst2html > /dev/null

It will displays warnings and errors.

python setup.py check --restructuredtext

setuptools required

#Gets setuptools
try:
    from setuptools import setup, find_packages
except ImportError:
    from ez_setup import use_setuptools
    use_setuptools()
    from setuptools import setup, find_packages

wget http://peak.telecommunity.com/dist/ez_setup.py

Troubleshooting entry points

from pkg_resources import *
for i in iter_entry_points("paste.paster_command"):
    print i

    [paste.paster_command]
        modwsgi_deploy = modwsgideploy.commands:ModwsgiCommand

load_entry_point("modwsgideploy", "paste.paster_command", "modwsgi_deploy")

*Try running it:

load_entry_point("modwsgideploy", "paste.paster_command", "modwsgi_deploy")()
or
load_entry_point("modwsgideploy", "paste.paster_command", "modwsgi_deploy")('someoption').command()

(10:28:29 AM) luca1: I'm trying to implement a paster create -t "mytemplate" , as one of the questions I need to as after license, project owner etc is "enter filename:" ; I need it to be in a loop. so enter filename 1:   , enter filename 2, enter filename 3 until "done" is passed... How do I do that.
(10:28:36 AM) sanjiv_ [n=sanjiv-c@59.180.154.228] entered the room.
(10:29:16 AM) sanjiv left the room (quit: Nick collision from services.).
(10:29:18 AM) luca1: I've been told I can do: while f != "done":
(10:29:18 AM) luca1:     files.append(f)
(10:29:18 AM) luca1:     f = self.ask("Enter file or 'done':")    something like thatwhile 1:
(10:29:18 AM) luca1:     f = self.ask("Enter file or 'done':")
(10:29:18 AM) luca1:     if f == 'done':
(10:29:18 AM) luca1:         break
(10:29:18 AM) luca1:     files.append(f)
(10:29:18 AM) luca1:  But where do I paste this code?
(10:29:27 AM) kumar: btw, for anyones interest, luca1 is working on a manual for creating custom paste commands here: http://lucasmanual.com/mywiki/Paste
(10:29:38 AM) sanjiv_ is now known as sanjiv
(10:29:58 AM) luca1: http://lucasmanual.com/mywiki/Paste#head-8ef91046e3015539e95435f0c1bcc434d7f41f78
(10:30:26 AM) luca1: Above is how I overload the template questions... But How do I create a loop with my list of files?
(10:30:40 AM) anilm [n=anilm@64.90.184.79.static.nyinternet.net] entered the room.
(10:33:07 AM) kumar: luca1 the piece you are missing so far is a custom command -- this should get you started: http://pythonpaste.org/script/developer.html
(10:34:09 AM) luca1: So you are saying I should do:
(10:34:09 AM) luca1: setup(...     entry_points="""     [paste.paster_command]     mycommand = mypackage.mycommand:MyCommand
(10:34:52 AM) luca1: then...
(10:34:52 AM) luca1: from paste.script import command  class MyCommand(command.Command):      max_args = 1     min_args = 1
(10:35:22 AM) luca1: and do my asking in here?
(10:35:22 AM) luca1:  def command(self):         name = self.args[0]         if self.verbose:
(10:35:27 AM) luca1:   f = self.ask("Enter file or 'done':")    something like thatwhile 1:
(10:35:36 AM) kumar: yes
(10:36:14 AM) luca1: how do I run the command now? paster create -t "myapp" --enterfiles   ?
(10:36:16 AM) kumar: self.challenge("enter file") not ask()
(10:37:11 AM) luca1: what is the difference between ask and challenge?
(10:37:27 AM) kumar: I think there is no ask, sorry, just my bad memory
(10:37:42 AM) luca1: I see.
(10:38:31 AM) luca1: So is above how I run my command? paster create -t "myapp" --enterfiles
(10:39:07 AM) kumar: have a read through those docs again
(10:39:15 AM) kumar: paster mycommand
(10:39:17 AM) kumar: is how you run it
(10:39:48 AM) kumar: but plugging into paster create is a little different.  I'm not sure where the docs are for that
(10:42:25 AM) luca1: so... I have to install the template first, then I can use my command? How do I get to "paster mycommand" part?
(10:44:43 AM) kumar: the same way you got your templates to show up in the list, from the manual you are working on
(10:44:47 AM) luca1: What my goal is to use "paster create -t"mytemplate"  which would create a project file that somebody would be working on. As part of that project creation I need to have a list of files entered.
(10:44:54 AM) kumar: except this time you need the new entry point mycommand = ...
(10:45:02 AM) kumar: then run python setup.py develop again
(10:45:12 AM) kumar: and it will appear as paster mycommand
(10:45:24 AM) luca1: I see...
(10:46:06 AM) kumar: if you want to customize paster create that is a little different
(10:46:08 AM) luca1: So I guess do I use paster mycommand to create the project folder, or paster create ....?
(10:47:00 AM) whit [n=whit@adsl-156-6-60.bna.bellsouth.net] entered the room.
(10:47:28 AM) luca1: If the only way to get my project folder the way I need it then I guess I have to do just that.? Unless I can do it from my command?
(10:48:11 AM) kumar: if you want to customize paster create then you'll have to go back to working in the Template class
(10:48:28 AM) luca1: ok
(10:50:06 AM) kumar: read the code in paste.script.templates to learn more about that, or read the code in pylons.util.PylonsTemplate to see an example of how paster create -t "pylons" works
(10:50:20 AM) luca1: So from above I can use paste to either create me project folders or add commands which will do xyz..? Right...
(10:50:20 AM) luca1: So we go back to original question, how do I customize paster create template/ template class to ask a question in a loop until I get "done"
(10:51:28 AM) kumar: the answer is put self.challenger(...) in the pre() method of your Template class, I think
(10:51:58 AM) kumar: you'll have to experiment with it and you will want to read the code in paste.script.templates.Template since I don't see any docs on it
(10:52:33 AM) luca1: Where was the second example? http://pylonshq.com/project/pylonshq/browser/pylons/templates/default_project
(10:53:05 AM) kumar: here: http://pylonshq.com/project/pylonshq/browser/pylons/util.py#L148
(10:54:07 AM) luca1: From here http://wiki.pylonshq.com/display/pylonscookbook/Creating+Templates+For+The+paster+create+Command I will use :
(10:54:07 AM) luca1: class ArtProjectTemplate(Template):         _template_dir = 'templates/default_project'         summary = 'Art project template'         vars = vars
(10:54:38 AM) luca1: I'll try to put the self.challenge after vars and see if that will work.
(10:57:51 AM) luca1: From the util..py.. You are correct def pre seems to be  a way to go.. I wonder if there is a post..? I would like to ask for files after everything else is filled.
(10:57:52 AM) luca1: ?
(10:58:05 AM) rhymes left the room (quit: "Ex-Chat").
(10:58:31 AM) kumar: yes, there is a post.  read through paste.script.templates.Template -- that is the best way to understand what is available to you ;)
(11:02:06 AM) luca1: where would that be again? Somewhere here ? http://svn.pythonpaste.org/Paste/trunk/paste/
(11:10:53 AM) gldnspud [n=gldnspud@74-61-143-162.bel.clearwire-dns.net] entered the room.
(11:14:28 AM) luca1: ?
(11:46:42 AM) cmlenz left the room (quit: ).
(11:49:09 AM) luca1: /usr/lib/python2.4/site-packages/paste/script/templates.py it is..
(11:50:07 AM) luca1: Thanks for the Information Kumar! I will give it a try some time this week... Appreciate it! Thanks.

Link References

MyWiki: PythonPaste (last edited 2009-12-02 23:05:13 by LukaszSzybalski)