~lgs/zcadoc/book

« back to all changes in this revision

Viewing changes to izca-es.txt

  • Committer: Lorenzo Gil Sanchez
  • Date: 2007-12-18 19:09:01 UTC
  • Revision ID: lgs@sicem.biz-20071218190901-ndxv1mrw95v62u3t
Almost done (except for the reference)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1477
1477
Manejador
1478
1478
~~~~~~~~~
1479
1479
 
1480
 
Handlers are subscription adapter factories that don't produce
1481
 
anything.  They do all of their work when called.  Handlers are
1482
 
typically used to handle events.  Handlers are also known as event
1483
 
subscribers or event subscription adapters.
 
1480
Los manejadores son factorias de adaptadores de subscripción que
 
1481
no producen nada. Realizan todo su trabajo cuando son llamados.
 
1482
Los manejadores se utilizan normalmente para tratar eventos. Los
 
1483
manejadores también se conocen como subscriptores de eventos o
 
1484
incluso como adaptadores de subscripción de eventos.
1484
1485
 
1485
 
Event subscribers are different from other subscription adapters in
1486
 
that the caller of event subscribers doesn't expect to interact with
1487
 
them in any direct way.  For example, an event publisher doesn't
1488
 
expect to get any return value.  Because subscribers don't need to
1489
 
provide an API to their callers, it is more natural to define them
1490
 
with functions, rather than classes.  For example, in a
1491
 
document-management system, we might want to record creation times for
1492
 
documents::
 
1486
Los subscriptores de eventos son distintos a los adaptadores de
 
1487
subscripción en cuanto a que el que llama a los subscriptores de
 
1488
eventos no espera interactuar con ellos de manera directa. Por
 
1489
ejemplo, un publicador de eventos no espera recibir ningún valor
 
1490
de retorno. Ya que los subscriptores no necesitan ofrecer una API
 
1491
a los que los llaman, es más natural definirlos con funciones,
 
1492
en vez de con clases. Por ejemplo, en un sistema de gestión
 
1493
documental, podemos querer registrar tiempos de creación para los
 
1494
documentos::
1493
1495
 
1494
1496
  >>> import datetime
1495
1497
 
1496
 
  >>> def documentCreated(event):
1497
 
  ...     event.doc.created = datetime.datetime.utcnow()
1498
 
 
1499
 
In this example, we have a function that takes an event and performs
1500
 
some processing.  It doesn't actually return anything.  This is a
1501
 
special case of a subscription adapter that adapts an event to
1502
 
nothing.  All of the work is done when the adapter "factory" is
1503
 
called.  We call subscribers that don't actually create anything
1504
 
"handlers".  There are special APIs for registering and calling them.
1505
 
 
1506
 
To register the subscriber above, we define a document-created event::
 
1498
  >>> def documentoCreado(evento):
 
1499
  ...     evento.doc.creado = datetime.datetime.utcnow()
 
1500
 
 
1501
En este ejemplo, tenemos una función que recibe un evento y realiza
 
1502
un procesamiento. Realmente no devuelve nada. Este es un caso especial
 
1503
de un adaptador de subscripción que adapta un evento a nada. Todo el
 
1504
trabajo se realiza cuando la "fábrica" del adaptador es invocada.
 
1505
Llamamos "manejadores" a los subscriptores que no crean nada. Hay
 
1506
APIs especiales para registrarlos y llamarlos.
 
1507
 
 
1508
Para registrar el subscriptor anterior definimos un evento de
 
1509
creación de documento::
1507
1510
 
1508
1511
  >>> from zope.interface import Interface
1509
1512
  >>> from zope.interface import Attribute
1510
1513
  >>> from zope.interface import implements
1511
1514
 
1512
 
  >>> class IDocumentCreated(Interface):
 
1515
  >>> class IDocumentoCreado(Interface):
1513
1516
  ...
1514
 
  ...     doc = Attribute("The document that was created")
 
1517
  ...     doc = Attribute("El documento que se creó")
1515
1518
 
1516
 
  >>> class DocumentCreated(object):
 
1519
  >>> class DocumentoCreado(object):
1517
1520
  ...
1518
 
  ...     implements(IDocumentCreated)
 
1521
  ...     implements(IDocumentoCreado)
1519
1522
  ...
1520
1523
  ...     def __init__(self, doc):
1521
1524
  ...         self.doc = doc
1522
1525
 
1523
 
We'll also change our handler definition to:
 
1526
También cambiamos nuestra definición del manejador a::
1524
1527
 
1525
 
  >>> def documentCreated(event):
1526
 
  ...     event.doc.created = datetime.datetime.utcnow()
 
1528
  >>> def documentoCreado(evento):
 
1529
  ...     evento.doc.creado = datetime.datetime.utcnow()
1527
1530
 
1528
1531
  >>> from zope.component import adapter
1529
1532
 
1530
 
  >>> @adapter(IDocumentCreated)
1531
 
  ... def documentCreated(event):
1532
 
  ...     event.doc.created = datetime.datetime.utcnow()
1533
 
 
1534
 
This marks the handler as an adapter of `IDocumentCreated` events.
1535
 
 
1536
 
Now we'll register the handler::
 
1533
  >>> @adapter(IDocumentoCreado)
 
1534
  ... def documentoCreado(evento):
 
1535
  ...     evento.doc.creado = datetime.datetime.utcnow()
 
1536
 
 
1537
Esto marca al manejador como un adaptador para los eventos
 
1538
`IDocumentoCreado`.
 
1539
 
 
1540
Ahora registraremos el manejador::
1537
1541
 
1538
1542
  >>> from zope.component import getGlobalSiteManager
1539
1543
  >>> gsm = getGlobalSiteManager()
1540
1544
 
1541
 
  >>> gsm.registerHandler(documentCreated)
 
1545
  >>> gsm.registerHandler(documentoCreado)
1542
1546
 
1543
 
Now, if we can create an event and use the `handle` function to call
1544
 
handlers registered for the event::
 
1547
Ahora, podemos crear un evento y usar la función `handle` para
 
1548
llamar a los manejadores registrados para el evento::
1545
1549
 
1546
1550
  >>> from zope.component import handle
1547
1551
 
1548
 
  >>> handle(DocumentCreated(doc))
1549
 
  >>> doc.created.__class__.__name__
 
1552
  >>> handle(DocumentoCreado(doc))
 
1553
  >>> doc.creado.__class__.__name__
1550
1554
  'datetime'
1551
1555
 
1552
1556
 
1553
1557
Uso de la ZCA en Zope
1554
1558
---------------------
1555
1559
 
1556
 
Zope Component Architecture is used in both Zope 3 and Zope 2.  This
1557
 
chapter go through ZCA usage in Zope.
 
1560
La Arquitectura de Componentes de Zope se usa tanto en Zope 3 como en
 
1561
Zope 2. En este capítulo veremos el uso de la ZCA en Zope.
1558
1562
 
1559
1563
 
1560
1564
ZCML
1561
1565
~~~~
1562
1566
 
1563
 
The Zope Configuration Markup Language (ZCML) is an XML based
1564
 
configuration system for registration of components.  So, instead of
1565
 
using Python API for registration, you can use ZCML.  But to use ZCML,
1566
 
unfortunately, you will be required to install more dependency
1567
 
packages.
 
1567
El Lenguaje de Marcado de Configuración de Zope (ZCML) es un sistema
 
1568
de configuración basado en XML para registrar componentes. Así, en
 
1569
lugar de usar la API Python para los registros, puedes usar ZCML.
 
1570
Pero para usar ZCML, desafortunadamente, necesitas instalar más
 
1571
paquetes de dependencias.
1568
1572
 
1569
 
To install these packages::
 
1573
Para instalar estos paquetes::
1570
1574
 
1571
1575
  $ easy_install "zope.component [zcml]"
1572
1576
 
1573
 
To register an adapter::
1574
 
 
1575
 
  <configure xmlns="http://namespaces.zope.org/zope">
1576
 
 
1577
 
  <adapter
1578
 
      factory=".company.EmployeeSalary"
1579
 
      provides=".interfaces.ISalary"
1580
 
      for=".interfaces.IEmployee"
1581
 
      />
1582
 
 
1583
 
The `provides` and `for` attributes are optional, provided you have
1584
 
declared it in the implementation::
1585
 
 
1586
 
  <configure xmlns="http://namespaces.zope.org/zope">
1587
 
 
1588
 
  <adapter
1589
 
      factory=".company.EmployeeSalary"
1590
 
      />
1591
 
 
1592
 
If you want to register the component as named adapter, you can give a
1593
 
`name` attribute::
1594
 
 
1595
 
 
1596
 
  <configure xmlns="http://namespaces.zope.org/zope">
1597
 
 
1598
 
  <adapter
1599
 
      factory=".company.EmployeeSalary"
1600
 
      name="salary"
1601
 
      />
1602
 
 
1603
 
Utilities are also registered similarly.
1604
 
 
1605
 
To register an utility::
1606
 
 
1607
 
  <configure xmlns="http://namespaces.zope.org/zope">
1608
 
 
1609
 
  <utility
1610
 
      component=".database.connection"
1611
 
      provides=".interfaces.IConnection"
1612
 
      />
1613
 
 
1614
 
The `provides` attribute is optional, provided you have declared it in
1615
 
the implementation::
1616
 
 
1617
 
  <configure xmlns="http://namespaces.zope.org/zope">
1618
 
 
1619
 
  <utility
1620
 
      component=".database.connection"
1621
 
      />
1622
 
 
1623
 
If you want to register the component as named adapter, you can give a
1624
 
`name` attribute::
1625
 
 
1626
 
 
1627
 
  <configure xmlns="http://namespaces.zope.org/zope">
1628
 
 
1629
 
  <utility
1630
 
      component=".database.connection"
1631
 
      name="Database Connection"
1632
 
      />
1633
 
 
1634
 
Instead of directly using the component, you can also give a factory::
1635
 
 
1636
 
  <configure xmlns="http://namespaces.zope.org/zope">
1637
 
 
1638
 
  <utility
1639
 
      factory=".database.Connection"
 
1577
Para registrar un adaptador::
 
1578
 
 
1579
  <configure xmlns="http://namespaces.zope.org/zope">
 
1580
 
 
1581
  <adapter
 
1582
      factory=".empresa.SalarioEmpleado"
 
1583
      provides=".interfaces.ISalario"
 
1584
      for=".interfaces.IEmpleado"
 
1585
      />
 
1586
 
 
1587
Los atributos `provides` y `for` son opcionales, siempre que los hayas
 
1588
declarado en la implementación::
 
1589
 
 
1590
  <configure xmlns="http://namespaces.zope.org/zope">
 
1591
 
 
1592
  <adapter
 
1593
      factory=".empresa.SalarioEmpleado"
 
1594
      />
 
1595
 
 
1596
Si quieres registrar el componente como un adaptador con nombre,
 
1597
puedes darle un atributo `name`::
 
1598
 
 
1599
 
 
1600
  <configure xmlns="http://namespaces.zope.org/zope">
 
1601
 
 
1602
  <adapter
 
1603
      factory=".empresa.SalarioEmpleado"
 
1604
      name="salario"
 
1605
      />
 
1606
 
 
1607
Las utilidades se registran de forma similar.
 
1608
 
 
1609
Para registrar una utilidad::
 
1610
 
 
1611
  <configure xmlns="http://namespaces.zope.org/zope">
 
1612
 
 
1613
  <utility
 
1614
      component=".basedatos.conexion"
 
1615
      provides=".interfaces.IConexion"
 
1616
      />
 
1617
 
 
1618
El atributo `provides` es opcional, siempre que lo hayas declarado
 
1619
en la implementación::
 
1620
 
 
1621
  <configure xmlns="http://namespaces.zope.org/zope">
 
1622
 
 
1623
  <utility
 
1624
      component=".basedatos.conexion"
 
1625
      />
 
1626
 
 
1627
Si quieres registrar el componente como una utilidad con nombre,
 
1628
puedes darle un atributo `name`::
 
1629
 
 
1630
 
 
1631
  <configure xmlns="http://namespaces.zope.org/zope">
 
1632
 
 
1633
  <utility
 
1634
      component=".basedatos.conexion"
 
1635
      name="Conexión de Base de Datos"
 
1636
      />
 
1637
 
 
1638
En vez de usar directamente el componente, también puedes dar una
 
1639
fábrica::
 
1640
 
 
1641
  <configure xmlns="http://namespaces.zope.org/zope">
 
1642
 
 
1643
  <utility
 
1644
      factory=".basedatos.Conexion"
1640
1645
      />
1641
1646
 
1642
1647
 
1643
1648
Redefiniciones
1644
1649
~~~~~~~~~~~~~~
1645
1650
 
1646
 
When you register components using Python API (``register*`` methods),
1647
 
the last registered component will replace previously registered
1648
 
component, if both are registered with same type of arguments.  For
1649
 
example, consider this example::
 
1651
Cuando registras componentes usando la API de Python (métodos
 
1652
``register*``), el último componente registrado sustituirá el
 
1653
componente registrado anteriormente, si los dos se registran con
 
1654
los mismos tipos de argumentos. Por ejemplo, imagina este ejemplo::
1650
1655
 
1651
1656
  >>> from zope.interface import Attribute
1652
1657
  >>> from zope.interface import Interface
1691
1696
  >>> getAdapter(a, IP) #doctest: +ELLIPSIS
1692
1697
  <AP object at ...>
1693
1698
 
1694
 
  If you register another adapter, the existing one will be replaced:
 
1699
Si registras otro adaptador, el ya hay será sustituido::
1695
1700
 
1696
1701
  >>> gsm.registerAdapter(AP2)
1697
1702
 
1698
1703
  >>> getAdapter(a, IP) #doctest: +ELLIPSIS
1699
1704
  <AP2 object at ...>
1700
1705
 
1701
 
But when registering components using ZCML, the second registration
1702
 
will raise a conflict error.  This is a hint for you, otherwise there
1703
 
is a chance for overriding registration by mistake.  This may lead to
1704
 
hard to track bugs in your system.  So, using ZCML is a win for the
1705
 
application.
 
1706
Pero cuando se registran componente usando ZCML, el segundo registro
 
1707
causará un error de conflicto. Esto es una ayuda para tí, si no,
 
1708
cabría la posibilidad de que sustituyas los registros por error. Esto
 
1709
podría hacer que sea dificil de encontrar errores en tu sistema. Así,
 
1710
usar ZCML es un avance para la aplicación.
1706
1711
 
1707
 
Sometimes you will be required to override existing registration.
1708
 
ZCML provides ``includeOverrides`` directive for this.  Using this,
1709
 
you can write your overrides in a separate file::
 
1712
A veces es necesario sustituir registros existentes. ZCML ofrece una
 
1713
directiva ``includeOverrides`` para esto. Usándola, puedes escribir
 
1714
sustituciones en un fichero aparte::
1710
1715
 
1711
1716
  <includeOverrides file="overrides.zcml" />
1712
1717
 
1713
1718
 
1714
 
NameChooser
1715
 
~~~~~~~~~~~
1716
 
 
1717
 
Location: `zope.app.container.contained.NameChooser`
1718
 
 
1719
 
This is an adapter for choosing a unique name for an object inside a
1720
 
container.
1721
 
 
1722
 
The registration of adapter is like this::
 
1719
NameChooser (Elejidor de nombres)
 
1720
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
1721
 
 
1722
Situación: `zope.app.container.contained.NameChooser`
 
1723
 
 
1724
Este es un adaptador para elejir un nombre único para un objeto dentro
 
1725
de un contenedor.
 
1726
 
 
1727
El registro del adaptador es así::
1723
1728
 
1724
1729
  <adapter
1725
1730
      provides=".interfaces.INameChooser"
1727
1732
      factory=".contained.NameChooser"
1728
1733
      />
1729
1734
 
1730
 
From the registration, you can see that the adaptee is a
1731
 
``IWriteContainer`` and the adapter provides ``INameChooser``.
 
1735
A partir del registro, puedes ver que el adaptado es un 
 
1736
``IWriteContainer`` y el adaptador ofrece ``INameChooser``.
1732
1737
 
1733
 
This adapter provides a very convenient functionality for Zope
1734
 
programmers.  The main implementations of ``IWriteContainer`` in
1735
 
Zope 3 are ``zope.app.container.BTreeContainer`` and
1736
 
``zope.app.folder.Folder``.  Normally you will be inheriting from
1737
 
these implementations for creating your own container classes.
1738
 
Suppose there is no interface called ``INameChooser`` and
1739
 
adapter, then you will be required to implement this functionality
1740
 
for every implementations separately.
 
1738
Este adaptador ofrece una funcionalidad muy útil para los programadores
 
1739
de Zope. Las principales implementaciones de ``IWriteContainer`` en
 
1740
Zope 3 son ``zope.app.container.BTreeContainer`` y
 
1741
``zope.app.folder.Folder``. Normalmente heredarás de estas
 
1742
implementaciones al crear tus propias clases de contenedores. Supón
 
1743
que no hay interfaz llamada ``INameChooser`` ni adaptador, entonces
 
1744
tendrás que implementar esta funcionalidad para cada implementación
 
1745
de forma separada.
1741
1746
 
1742
1747
 
1743
1748
LocationPhysicallyLocatable