Reusando componentes Zope fuera de Zope
(y la web)
Roberto Allende
Menttes / Plone Foundation
rallende@menttes.com
http://robertoallende.com
twitter: robertoallende
 Buildout
 ZODB
 Zope Page Templates
 Adaptadores
Buildout is a Python-based build system for
creating, assembling and deploying applications
from multiple parts, some of which may be non-
Python-based. It lets you create a buildout
configuration and reproduce the same software
later.
Buildout
Tool for working with eggs
Repeatable
Developer oriented
Buildout | Features
$ easy_install zc.buildout
Buildout | Install
$ svn co http://miproyecto
$ python bootstrap.py
$ bin/buildout -v
…
$ bin/miproyecto.py
Buildout | Deploy con buildout
project/
bootstrap.py
buildout.cfg
.installed.cfg
parts/
develop-eggs/
bin/
buildout
miproyecto
eggs/
downloads/
Buildout | Deploy con buildout
[buildout]
index-url = http://pypi.it.uwosh.edu/
parts = instance
zopepy
eggdeps
degraph
extends = http://download.zope.org/Zope2/index/2.13.0a3/versions.cfg
eggs = tl.eggdeps
[instance]
recipe = plone.recipe.zope2instance
user = admin:admin
http-address = 8080
products = ${buildout:directory}/products
Buildout | buildout.cfg
http://buildout.org
Buildout | Mas información
Don’t squeeze your objects into tables:
store them in an object database.
ZODB
Transparent persistence for Python objects
Full ACID-compatible transaction support
History/undo ability
Efficient support for binary large objects (BLOBs)
Pluggable storages
Scalable architecture
ZODB | Features
$ easy_install ZODB3$ easy_install ZODB3
……
$ python$ python
>>> import ZODB>>> import ZODB
ZODB | Instalación
>>> from ZODB.FileStorage import FileStorage>>> from ZODB.FileStorage import FileStorage
>>> from ZODB.DB import DB>>> from ZODB.DB import DB
>>> storage = FileStorage('Data.fs')>>> storage = FileStorage('Data.fs')
>>> db = DB(storage)>>> db = DB(storage)
>>> connection = db.open()>>> connection = db.open()
>>> root = connection.root()>>> root = connection.root()
ZODB | Configuración
>>> root['account-1'] = Account()>>> root['account-1'] = Account()
>>> root['account-2'] = Account()>>> root['account-2'] = Account()
ZODB | Haciendo un objeto persistente
>>> import transaction>>> import transaction
>>> transaction.commit()>>> transaction.commit()
>>> root.keys()>>> root.keys()
['account-1', 'account-2']['account-1', 'account-2']
ZODB | Transactions
http://zodb.orghttp://zodb.org
ZODB | Mas Lectura
Zope Page Template allows you to generateZope Page Template allows you to generate
HTML dynamically.HTML dynamically.
Chameleon compiles templates to Python byte-code. It includes aChameleon compiles templates to Python byte-code. It includes a
complete implementation of the Zope Page Templates (ZPT) language andcomplete implementation of the Zope Page Templates (ZPT) language and
a partial implementation of the Genshi language.a partial implementation of the Genshi language.
ZPT vía Chameleon
ZPT templates are valid XML documentsZPT templates are valid XML documents
It uses namespaces for attributes and tags toIt uses namespaces for attributes and tags to
define the template behaviour.define the template behaviour.
Works on Python 2.4, 2.5 and 2.6, includingWorks on Python 2.4, 2.5 and 2.6, including
Google App EngineGoogle App Engine
PHP, Java, PerlPHP, Java, Perl
ZPT vía Chameleon
$ easy_install Chameleon$ easy_install Chameleon
ZPT vía Chameleon | Install
<table border="1"><table border="1">
<tr<tr tal:repeat="row range(10)"tal:repeat="row range(10)">>
<td<td tal:repeat="column range(10)"tal:repeat="column range(10)">>
<span<span tal:define="x repeat.row.number;tal:define="x repeat.row.number;
y repeat.column.number;y repeat.column.number;
z x * y"z x * y"
tal:replace="string:$x * $y = $z"tal:replace="string:$x * $y = $z">1 * 1 =>1 * 1 =
</span></span>
</td></td>
</tr></tr>
</table></table>
ZPT vía Chameleon | Template loader
from chameleon.zpt import loaderfrom chameleon.zpt import loader
template_path = os.path.join(os.path.dirname(__file__), "..", "templates")template_path = os.path.join(os.path.dirname(__file__), "..", "templates")
template_loader = loader.TemplateLoader(template_path,template_loader = loader.TemplateLoader(template_path,
auto_reload=os.environ['SERVER_SOFTWARE'].startswith('Dev'))auto_reload=os.environ['SERVER_SOFTWARE'].startswith('Dev'))
ZPT vía Chameleon | Ejemplo
def TestHandler(RequestHandler):def TestHandler(RequestHandler):
def get(self):def get(self):
template = template_loader.load("test.pt")template = template_loader.load("test.pt")
self.response.body = template(name="test")self.response.body = template(name="test")
ZPT vía Chameleon | Ejemplo
http://chameleon.repoze.orghttp://chameleon.repoze.org
http://blog.notdot.nethttp://blog.notdot.net
Webapps on App Engine, part 4: TemplatingWebapps on App Engine, part 4: Templating
ZPT vía Chameleon | Mas Lectura
Dynamic adaptation might feel like a typeDynamic adaptation might feel like a type
declaration, but it's not!declaration, but it's not!
It specifies a behavior, not a type; it's dynamic;It specifies a behavior, not a type; it's dynamic;
it's optional.it's optional.
Adapters
class File(object):class File(object):
body = 'foo bar'body = 'foo bar'
class FileSize(object):class FileSize(object):
def __init__(self, context):def __init__(self, context):
self.context = contextself.context = context
def getSize(self):def getSize(self):
return len(self.context.body)return len(self.context.body)
tamano = FileSize(File())tamano = FileSize(File())
print client.request()print client.request()
Adapters | Wrapper
Intrusivo clase baseIntrusivo clase base
Test aisladamenteTest aisladamente
Control factoryControl factory
Colision de nombresColision de nombres
Patches compitenPatches compiten
Lo hace RubyLo hace Ruby
Wrapping es molestoWrapping es molesto
Zope es Cool!Zope es Cool!
Adapters | Comparación con Otros
por Brandon Craig Rhodes
Herencia
oo
xx
xx
xx
Mixin
oo
oo
xx
xx
MonkeyPatch
oo
xx
xx
xx
Adapter
oo
oo
oo
oo
xx
oo
oo
oo
oo
oo
oo
Adapter
a'la Zope
1. Define an interface1. Define an interface
2. Register our adapter2. Register our adapter
3. Request adaptation3. Request adaptation
Adapters | 1, 2, 3
$ easy_install zope.interface$ easy_install zope.interface
$ easy_install zope.component$ easy_install zope.component
Adapters | Install
import zope.interfaceimport zope.interface
class IFile(zope.interface.Interface):class IFile(zope.interface.Interface):
body = zope.interface.Attribute('Contents of the file.')body = zope.interface.Attribute('Contents of the file.')
class ISize(zope.interface.Interface):class ISize(zope.interface.Interface):
def getSize():def getSize():
'Return the size of an object.''Return the size of an object.'
Adapters | Define an interface
from zope.interface.adapter import AdapterRegistryfrom zope.interface.adapter import AdapterRegistry
registry = AdapterRegistry()registry = AdapterRegistry()
registry.register([IFile], ISize, '', FileSize)registry.register([IFile], ISize, '', FileSize)
Adapters | Register our adapterRegister our adapter
>>>>>> def hook(provided, object):def hook(provided, object):
>>>>>> adapter = registry.lookup1(zope.interface.providedBy(object),adapter = registry.lookup1(zope.interface.providedBy(object),
>>>>>> provided, '')provided, '')
>>>>>> return adapter(object)return adapter(object)
>>>>>> from zope.interface.interface import adapter_hooksfrom zope.interface.interface import adapter_hooks
>>>>>> adapter_hooks.append(hook)adapter_hooks.append(hook)
>>> size = ISize(file)>>> size = ISize(file)
>>> size.getSize()>>> size.getSize()
77
Adapters | Request adaptationRequest adaptation
Using the Adapter RegistryUsing the Adapter Registry
http://docs.zope.org/zope3/Book/ifaceschema/human/show.htmlhttp://docs.zope.org/zope3/Book/ifaceschema/human/show.html
Using Grok to walk like a DuckUsing Grok to walk like a Duck
Brandon Rhodes - Pycon08, PloneConf 08Brandon Rhodes - Pycon08, PloneConf 08
Adapters | Mas Lectura
Muchas Gracias
Roberto Allende
http://robertoallende.com
Twitter: robertoallende
rallende@menttes.com

Reusando componentes Zope fuera de Zope

  • 1.
    Reusando componentes Zopefuera de Zope (y la web) Roberto Allende Menttes / Plone Foundation rallende@menttes.com http://robertoallende.com twitter: robertoallende
  • 2.
     Buildout  ZODB Zope Page Templates  Adaptadores
  • 3.
    Buildout is aPython-based build system for creating, assembling and deploying applications from multiple parts, some of which may be non- Python-based. It lets you create a buildout configuration and reproduce the same software later. Buildout
  • 4.
    Tool for workingwith eggs Repeatable Developer oriented Buildout | Features
  • 5.
  • 6.
    $ svn cohttp://miproyecto $ python bootstrap.py $ bin/buildout -v … $ bin/miproyecto.py Buildout | Deploy con buildout
  • 7.
  • 8.
    [buildout] index-url = http://pypi.it.uwosh.edu/ parts= instance zopepy eggdeps degraph extends = http://download.zope.org/Zope2/index/2.13.0a3/versions.cfg eggs = tl.eggdeps [instance] recipe = plone.recipe.zope2instance user = admin:admin http-address = 8080 products = ${buildout:directory}/products Buildout | buildout.cfg
  • 9.
  • 10.
    Don’t squeeze yourobjects into tables: store them in an object database. ZODB
  • 11.
    Transparent persistence forPython objects Full ACID-compatible transaction support History/undo ability Efficient support for binary large objects (BLOBs) Pluggable storages Scalable architecture ZODB | Features
  • 12.
    $ easy_install ZODB3$easy_install ZODB3 …… $ python$ python >>> import ZODB>>> import ZODB ZODB | Instalación
  • 13.
    >>> from ZODB.FileStorageimport FileStorage>>> from ZODB.FileStorage import FileStorage >>> from ZODB.DB import DB>>> from ZODB.DB import DB >>> storage = FileStorage('Data.fs')>>> storage = FileStorage('Data.fs') >>> db = DB(storage)>>> db = DB(storage) >>> connection = db.open()>>> connection = db.open() >>> root = connection.root()>>> root = connection.root() ZODB | Configuración
  • 14.
    >>> root['account-1'] =Account()>>> root['account-1'] = Account() >>> root['account-2'] = Account()>>> root['account-2'] = Account() ZODB | Haciendo un objeto persistente
  • 15.
    >>> import transaction>>>import transaction >>> transaction.commit()>>> transaction.commit() >>> root.keys()>>> root.keys() ['account-1', 'account-2']['account-1', 'account-2'] ZODB | Transactions
  • 16.
  • 17.
    Zope Page Templateallows you to generateZope Page Template allows you to generate HTML dynamically.HTML dynamically. Chameleon compiles templates to Python byte-code. It includes aChameleon compiles templates to Python byte-code. It includes a complete implementation of the Zope Page Templates (ZPT) language andcomplete implementation of the Zope Page Templates (ZPT) language and a partial implementation of the Genshi language.a partial implementation of the Genshi language. ZPT vía Chameleon
  • 18.
    ZPT templates arevalid XML documentsZPT templates are valid XML documents It uses namespaces for attributes and tags toIt uses namespaces for attributes and tags to define the template behaviour.define the template behaviour. Works on Python 2.4, 2.5 and 2.6, includingWorks on Python 2.4, 2.5 and 2.6, including Google App EngineGoogle App Engine PHP, Java, PerlPHP, Java, Perl ZPT vía Chameleon
  • 19.
    $ easy_install Chameleon$easy_install Chameleon ZPT vía Chameleon | Install
  • 20.
    <table border="1"><table border="1"> <tr<trtal:repeat="row range(10)"tal:repeat="row range(10)">> <td<td tal:repeat="column range(10)"tal:repeat="column range(10)">> <span<span tal:define="x repeat.row.number;tal:define="x repeat.row.number; y repeat.column.number;y repeat.column.number; z x * y"z x * y" tal:replace="string:$x * $y = $z"tal:replace="string:$x * $y = $z">1 * 1 =>1 * 1 = </span></span> </td></td> </tr></tr> </table></table> ZPT vía Chameleon | Template loader
  • 21.
    from chameleon.zpt importloaderfrom chameleon.zpt import loader template_path = os.path.join(os.path.dirname(__file__), "..", "templates")template_path = os.path.join(os.path.dirname(__file__), "..", "templates") template_loader = loader.TemplateLoader(template_path,template_loader = loader.TemplateLoader(template_path, auto_reload=os.environ['SERVER_SOFTWARE'].startswith('Dev'))auto_reload=os.environ['SERVER_SOFTWARE'].startswith('Dev')) ZPT vía Chameleon | Ejemplo
  • 22.
    def TestHandler(RequestHandler):def TestHandler(RequestHandler): defget(self):def get(self): template = template_loader.load("test.pt")template = template_loader.load("test.pt") self.response.body = template(name="test")self.response.body = template(name="test") ZPT vía Chameleon | Ejemplo
  • 23.
    http://chameleon.repoze.orghttp://chameleon.repoze.org http://blog.notdot.nethttp://blog.notdot.net Webapps on AppEngine, part 4: TemplatingWebapps on App Engine, part 4: Templating ZPT vía Chameleon | Mas Lectura
  • 24.
    Dynamic adaptation mightfeel like a typeDynamic adaptation might feel like a type declaration, but it's not!declaration, but it's not! It specifies a behavior, not a type; it's dynamic;It specifies a behavior, not a type; it's dynamic; it's optional.it's optional. Adapters
  • 25.
    class File(object):class File(object): body= 'foo bar'body = 'foo bar' class FileSize(object):class FileSize(object): def __init__(self, context):def __init__(self, context): self.context = contextself.context = context def getSize(self):def getSize(self): return len(self.context.body)return len(self.context.body) tamano = FileSize(File())tamano = FileSize(File()) print client.request()print client.request() Adapters | Wrapper
  • 26.
    Intrusivo clase baseIntrusivoclase base Test aisladamenteTest aisladamente Control factoryControl factory Colision de nombresColision de nombres Patches compitenPatches compiten Lo hace RubyLo hace Ruby Wrapping es molestoWrapping es molesto Zope es Cool!Zope es Cool! Adapters | Comparación con Otros por Brandon Craig Rhodes Herencia oo xx xx xx Mixin oo oo xx xx MonkeyPatch oo xx xx xx Adapter oo oo oo oo xx oo oo oo oo oo oo Adapter a'la Zope
  • 27.
    1. Define aninterface1. Define an interface 2. Register our adapter2. Register our adapter 3. Request adaptation3. Request adaptation Adapters | 1, 2, 3
  • 28.
    $ easy_install zope.interface$easy_install zope.interface $ easy_install zope.component$ easy_install zope.component Adapters | Install
  • 29.
    import zope.interfaceimport zope.interface classIFile(zope.interface.Interface):class IFile(zope.interface.Interface): body = zope.interface.Attribute('Contents of the file.')body = zope.interface.Attribute('Contents of the file.') class ISize(zope.interface.Interface):class ISize(zope.interface.Interface): def getSize():def getSize(): 'Return the size of an object.''Return the size of an object.' Adapters | Define an interface
  • 30.
    from zope.interface.adapter importAdapterRegistryfrom zope.interface.adapter import AdapterRegistry registry = AdapterRegistry()registry = AdapterRegistry() registry.register([IFile], ISize, '', FileSize)registry.register([IFile], ISize, '', FileSize) Adapters | Register our adapterRegister our adapter
  • 31.
    >>>>>> def hook(provided,object):def hook(provided, object): >>>>>> adapter = registry.lookup1(zope.interface.providedBy(object),adapter = registry.lookup1(zope.interface.providedBy(object), >>>>>> provided, '')provided, '') >>>>>> return adapter(object)return adapter(object) >>>>>> from zope.interface.interface import adapter_hooksfrom zope.interface.interface import adapter_hooks >>>>>> adapter_hooks.append(hook)adapter_hooks.append(hook) >>> size = ISize(file)>>> size = ISize(file) >>> size.getSize()>>> size.getSize() 77 Adapters | Request adaptationRequest adaptation
  • 32.
    Using the AdapterRegistryUsing the Adapter Registry http://docs.zope.org/zope3/Book/ifaceschema/human/show.htmlhttp://docs.zope.org/zope3/Book/ifaceschema/human/show.html Using Grok to walk like a DuckUsing Grok to walk like a Duck Brandon Rhodes - Pycon08, PloneConf 08Brandon Rhodes - Pycon08, PloneConf 08 Adapters | Mas Lectura
  • 33.