The goodies of zope, pyramid, and plone (2)

Preview:

DESCRIPTION

8 goodies you can take away, in any web or non web python project.

Citation preview

The goodies that Zope begatPyramid, Plone, buildout + more

Dylan Jay @djay75

Who am I?Dylan JayCore Plone Contributor1995 First web app (ISAPI)1999 Built first e-commerce site (zope)2003 Built first startup (IntroVino)2004 Started PretaWeb/PretaGov (Plone0

Reasons for this talkHistory"Those who don't learn from history are doomed to add it as a feature of their framework"

Better choicesThere is no perfect framework, only a perfect mess when you pick wrong

ReuseGoodies you might not be using yet

The goodies1. Traversal2. ZODB3. ZTK Adapters4. Sprints5. Pyramid6. Buildout7. Plone + the customisation cliff8. Diazo9. RobotFramework - RobotSuite

Python family tree(web)

Zope (1996-)

ZTK (BlueBream) (2004-)

Pylons/TurboGears (2005-2010)Django (2005-)

Flask (2010-)

RoR (2004-) Plone (1999-)

BFG (2008-2010)

CGI (1993-)

httpd (1990-)

NikolaPyramid (2010-)

Zope - wtf was that about?Back in 1996 ● webserver = path to file● cgi = path to script + args● OO - was very big● Jim Fulton was on a

plane

traversal = path to object + '/' + method zope = zope object publishing environment

Goodie #1 - Traversalresponse = traverse(root, HTTP_PATH.split('/'), request)

def traverse(context, path, request): if len(path) == 0: return context(request) elif len(path) == 1: view_method = getattr( context, path[0] ) return view_method(request) else:

sub_context = context[ path[0] ] return traverse( sub_context, path[1:], request)

Traversal - why?

Good for CMSplugins cooperating webappscomplex apps

Traversal Routes

/A/B/C/myaction/myaction/id123

distributedcentrally defined

Good for relational single use apps

Goodie #2: ZODB● Want to store something non relational?● Want to store something non key-value?● Got complex object structures?

Use Object persistence

ZODB: The piss easy DB$ easyinstall ZODB

db = DB( FileStorage.FileStorage('./Data.fs') )connection = db.open()dbroot = connection.root()

transaction.commit()db.close()

dbroot['a_number'] = 3dbroot['a_string'] = 'Gift'dbroot['a_list'] = [1, 2, 3, 5, 7, 12]dbroot['a_dictionary'] = { 1918: 'Red Sox', 1919: 'Reds' }dbroot['deeply_nested'] = { 1918: [ ('Red Sox', 4), ('Cubs', 2) ], 1919: [ ('Reds', 5), ('White Sox', 3) ],}

ZODB: simple but powerful● transactions - multiversion concurrency

control (MVCC)● scalability across a network (using ZEO)● replication (using ZRS or relstorage)● history/undo● transparently pluggable storage● built-in caching● Blob support

Goodie #3: Adapters

Adapters: why?● Solves how to plug complex software

together● Better than Object Orientation● Perfect for overridable software● Perfect for plugin architecture● ZTK - ZCA - Zope3 == Adapters

ZTK Adaptersclass IUSPlug(zope.interface): prongs = Attribute("""number of prongs""")

class Motox(object): implements(IUSPlug) prongs = 2

class INZPlug(zope.interface): prongs = Attribute("""number of prongs""")

OO - not so crash hotAdapters = Interface -> Factory -> Interfacee.g. IRSSFeed -> RSS2Tweets -> ITwitterFeedTraversal = (MultiAdapter) Context (Interface. from path) Request (Interface. from request) name (last part of url)-> BrowserView class (Factory) -> BrowserView

ZTK Adapters

class ACPowerAdapter(object): implements(INZPlug) adapts(IUSPlug) def __init__(self, plug):

self.prongs = plug.prongs + 1self.voltage = 240

registry.registerAdapter(ACPowerAdapter)

ZTK Adapters>>> myphone = MotoX()>>> myphone.prongs == 3False>>> adaptedphone = INZPlug(myphone)>>> adaptedphone.prongs == 3True

http://www.muthukadan.net/docs/zca.html

Goodie #4: Sprints“The practice of using sprints for open source software development was pioneered by the Zope Corporation in the early days of the Zope 3 project. Between January 2002 and January 2006, more than 30 Zope 3 sprints had taken place.[citation needed]”

Plone Pacific Rim Sprint 14-15 Sept

Goodie #5 Pyramid

Zope (1996-)

ZTK (BlueBream) (2004-)

Pylons/TurboGears (2005-2010)Django (2005-)

Flask (2010-)

RoR (2004-) Plone (1999-)

BFG (2008-2010)

CGI (1993-)

httpd (1990-)

NikolaPyramid (2010-)

Pyramid: It's micro!from wsgiref.simple_server import make_serverfrom pyramid.view import view_configfrom pyramid.config import Configurator

if __name__ == '__main__': config = Configurator() config.add_route('hello', '/hello/{name}') config.scan() app = config.make_wsgi_app() server = make_server('0.0.0.0', 8080, app) server.serve_forever()

@view_config(route_name='hello', renderer='json')def hello_world(request): return {'content':'Hello %(name)s!' % request.matchdict}

Pyramid: worst name ever

Pyramid (the structure) Pyramid (the framework)

Start big - End small Start small - End big

Ancient Best of breed

Unchanging over time Extensible & Flexible

Pyramid: a "micro & more" Framework● a declarative authorization system● extensibility: aggregate Pyramid application

configuration from multiple sources● separate I18N translation string factories● reuse: "Interface" based view/subscriber

registrations● optionally map URLs to code using traversal

Pyramid: routes vs. traversal: why not both?from wsgiref.simple_server import make_serverfrom pyramid.config import Configuratorfrom pyramid.response import Response

class Resource(dict): pass

def get_root(request): return Resource({'a': Resource({'b': Resource({'c': Resource()})})})

def hello_world_of_resources(context, request): output = "Here's a resource and its children: %s" % context return Response(output)

if __name__ == '__main__': config = Configurator(root_factory=get_root) config.add_view(hello_world_of_resources, context=Resource) app = config.make_wsgi_app() server = make_server('0.0.0.0', 8080, app) server.serve_forever()

Goodie #6: buildout

buildout - what you get if you put make, puppet, python, pip, virtualenv into a blender

Buildout● uses recipes - python packages that know

how to build other things○ like puppet

● automated dependencies○ like Make

● recipes download and install python packages into your environment○ like PIP/easy_install

● everything gets installed into a local directory isolated from your system○ like virtualenv

Buildout is like...

you need it when- you’re on tour (deploy different places)- very different components

Goodie #7: Plone300+ core contributors400+ plugins1000+ commits/month5-8 sprints per year1 Plone foundation1-2 CVE's/year

Plone

Plone step 1: Install

wget --no-check-certificate https://launchpad.net/plone/4.3/4.3.1/+download/Plone-4.3.1-UnifiedInstaller.tgz

# Extract the downloaded filetar -xf Plone-4.3-UnifiedInstaller.tgz

# Go the folder containing installer scriptcd Plone-4.3-UnifiedInstaller

# Run script./install.sh standalone

cd ~/Plone/zinstancebin/instance fg

Plone: #2 Add content

Plone Step 2: Add content

Plone Step 3: Add plugins

$ nano buildout.cfg

[instance]...eggs = Products.PloneFormGen collective.recaptcha

$ bin/buildout$ bin/instance fg

Plone Step 4: Theme it

Framework vs CMS

start with a blank page start with fully featured site

build up customise down

good for "app" sites good for "content" sites others can edit

Framework CMS

startup tool agency tool

risk reinventing the wheel risk hitting customisation cliff

dev has full control shared control, editors, admin, dev, themer

Content Editor Site Admin

Separation of concerns

Backend devFrontend dev / Themer

Integrator

Reviewer

Developers blog

Integrator

Static site generator

An app/startup

Backend devFrontend dev / Themer

Django/Pyramid

Simple Blog

Content Editor

PluginsThemes

Simple CMS e.g. Wordpress

Large content site

PluginsThemes

Frontend dev / Themer

Content Editor Site Admin

Integrator

Reviewer

Enterprise CMS

Web consultancy

Plugins

Frontend dev / Themer

Content Editor

Site Admin

Integrator CMS/Framework

The customisation cliff

Framework

CMS

Goodie #8: Diazo- Ultimate in code - html seperation- templates without altering your html - allows designer to work on html while you work on the code - round trip

Diazo.org1. app with very simple html - "content"2. create mockups in html of how you want the pages to really look - "theme"3. create a rules.xml.4. Compile it to single XSLT file,5. execute it in middleware

Goodie #9: RobotFramework

what you get when you put python, selenum and BDD into a blender

RobotFramework

RobotFramework● Not invented by Plone/Zope (Nokia did)● but robotsuite was● Used to test Plone● Automated screenshots for user manuals

Thanks

Dylan Jay (pretagov.com.au)

Recommended