[Zope-book] CVS: Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7 - Contact.py:1.1 ContactAdd.py:1.1 ContactAddView.py:1.1 ContactCityState.py:1.1 ContactEditView.py:1.1 ContactInfoView.py:1.1 IContact.py:1.1 IPostal.py:1.1 __init__.py:1.1 add.pt:1.1 configure.zcml:1.1 contact.gif:1.1 contact_product_uml.txt:1.1 edit.pt:1.1 info.pt:1.1 products.zcml:1.1 stubpostal.py:1.1

Jim Fulton jim at zope.com
Sun Dec 8 03:44:32 EST 2002


Update of /cvs-repository/Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7
In directory cvs.zope.org:/tmp/cvs-serv13804

Added Files:
	Contact.py ContactAdd.py ContactAddView.py ContactCityState.py 
	ContactEditView.py ContactInfoView.py IContact.py IPostal.py 
	__init__.py add.pt configure.zcml contact.gif 
	contact_product_uml.txt edit.pt info.pt products.zcml 
	stubpostal.py 
Log Message:
Added step 7 to include generation of object events

=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/Contact.py ===

import Persistence
from IContact import IContact

class Contact (Persistence.Persistent):
    """Personal contact information

    Contacts keep track of personal data, such as name, email
    and postal address.  All methods are protected.
    """

    __implements__ = IContact

    def __init__(self, first='', last='', email='', address='', pc=''):
        self.update(first, last, email, address, pc)

    def name(self): 
        return "%s %s" % (self._first, self._last)

    def first(self):
        return self._first

    def last(self):
        return self._last
    
    def email(self):
        return self._email

    def address(self):
        return self._address

    def postal_code(self):
        return self._pc

    def update(self, first=None, last=None, email=None, address=None, pc=None):
        if first is not None:
            self._first = first
        if last is not None:
            self._last = last
        if email is not None:
            self._email = email
        if address is not None:
            self._address = address
        if pc is not None:
            self._pc = pc



=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/ContactAdd.py ===
from Zope.App.OFS.Container.IAdding import IAdding
from Contact import Contact
from Zope.Event import publish
from Zope.Event.ObjectEvent import ObjectCreatedEvent
from Interface import Interface

class IContactAdd(Interface):
    """Add context using IAdding objects
    """

    def add(first, last, email, address, pc):
        """Add a contact initialized from the given arguments
        """

class ContactAdd:
    "Provide a user interface for adding a contact"
    
    # Assert that we can only be applied to IAdding
    __used_for__ = IAdding

    __implements__ = IContactAdd

    def __init__(self, context):
        self.context = context

    def add(self, first, last, email, address, pc):
        contact = Contact()
        publish(self.context.context, ObjectCreatedEvent(contact))
        contact.update(first, last, email, address, pc)
        self.context.add(contact)



=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/ContactAddView.py ===
from Zope.Publisher.Browser.BrowserView import BrowserView
from Zope.App.OFS.Container.IAdding import IAdding
from Zope.ComponentArchitecture import getAdapter
from ContactAdd import IContactAdd

class ContactAddView(BrowserView):
    "Provide a user interface for adding a contact"
    
    # Assert that we can only be applied to IAdding
    __used_for__ = IAdding

    # action method
    def action(self, first, last, email, address, pc):
        "Add a contact"
        getAdapter(self.context, IContactAdd).add(
            first, last, email, address, pc)
        self.request.response.redirect(self.context.nextURL())



=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/ContactCityState.py ===
from IPostal import IPostalLookup, IPostalInfo
from IContact import IContactInfo
from Zope.ComponentArchitecture import getUtility

class ContactCityState:
    "Provide access to city and state information for a contact"

    __implements__ = IPostalInfo

    __used_for__ = IContactInfo

    def __init__(self, contact):
        self._contact = contact
        lookup = getUtility(contact, IPostalLookup)
        info = lookup.lookup(contact.postal_code())
        if info is None:
            self._city, self._state = '', ''
        else:
            self._city, self._state = info.city(), info.state()
        
    def city(self): return self._city

    def state(self): return self._state



=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/ContactEditView.py ===
from Zope.Publisher.Browser.BrowserView import BrowserView
from IContact import IContact
from Zope.Event import publish
from Zope.Event.ObjectEvent import ObjectModifiedEvent

class ContactEditView(BrowserView):
    "Provide a user interface for editing a contact"
    
    # Assert that we can only be applied to IContact
    __used_for__ = IContact

    # action method
    def action(self, first, last, email, address, pc):
        "Edit a contact"
        self.context.update(first, last, email, address, pc)
        publish(self.context, ObjectModifiedEvent(self.context))
        self.request.response.redirect('.')


=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/ContactInfoView.py ===
from Zope.ComponentArchitecture import getAdapter
from IContact import IContactInfo
from IPostal import IPostalInfo

class ContactInfoView:
    """Provide an interface for viewing a contact
    """

    __used_for__ = IContactInfo

    def __init__(self, context, request):
        self.context = context
        self.request = request
        
        self.info = getAdapter(context, IPostalInfo)
        
    def city(self):
        return self.info.city()
        
    def state(self):
        return self.info.state()
        


=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/IContact.py ===
from Interface import Interface

class IContactInfo(Interface):
    "Provides access to basic contact information."

    def first():       "Get the first name"
    def last():        "Get the last name"
    def email():       "Get the electronic mail address"
    def address():     "Get the postal address"
    def postal_code(): "Get the postal code"

    def name():
        """Gets the contact name.
        
        The contact name is the first and last name"""

class IContact(IContactInfo):
    "Provides the ability to change contact information."

    def update(first, last, email, address, pc):
        """Modifies contact data
        
        'None' values are ignored.
        """


=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/IPostal.py ===

from Interface import Interface

class IPostalInfo(Interface):
    "Provide information for postal codes"

    def city():
        """Return the city associated with the postal code.

        An empty string is returned if the city is unknown.
        """

    def state():
        """Return the state associated with the postal code.

        An empty string is returned if the state is unknown.
        """

class IPostalLookup(Interface):
    "Provide postal code lookup"

    def lookup(postal_code):
        """Lookup information for a postal code.

        An IPostalInfo is returned if the postal code is known. None is
        returned otherwise.
        """



=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/__init__.py ===



=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/add.pt ===
<html metal:use-macro="views/standard_macros/page">
<head><title>Edit contact</title></head>
<body>
<div metal:fill-slot="body">
Enter the information about the contact.
<form action="action.html" method="post">
<table cellspacing="0" cellpadding="2" border="0">
  <tr><td> First name</td>
      <td><input type="text" name="first" size="40" value="" /> </td>
  </tr>
  <tr><td>Last name</td>
      <td><input type="text" name="last" size="40" value="" /> </td>
  </tr>
  <tr><td>Email</td>
      <td><input type="text" name="email" size="40" value="" /> </td>
  </tr>
  <tr><td>Address</td>
      <td align="left" valign="top">
        <textarea name="address" rows="3" cols="60"></textarea>
      </td>
  </tr>
  <tr>
    <td>Postal Code</td>
    <td><input type="text" name="pc" size="40" value="" />
    </td>
  </tr>
</table>
<input type="submit" name="submit" value=" Save Changes " />
</form></div></body></html>


=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/configure.zcml ===
<zopeConfigure 
    xmlns='http://namespaces.zope.org/zope'
    xmlns:browser='http://namespaces.zope.org/browser'>

<permission
    id="ZopeProducts.Contact.ManageContacts" 
    title="Manage Contacts" />

<content class=".Contact.">
  <implements interface="Zope.App.OFS.Annotation.IAttributeAnnotatable." />
  <factory
      id="ZopeProducts.Contact"
      permission="ZopeProducts.Contact.ManageContacts" />
  <require
      permission="Zope.View"
      interface=".IContact.IContactInfo." />
  <require
      permission="ZopeProducts.Contact.ManageContacts"
      attributes="update" />
</content>

<browser:menuItem menu="add_content" for="Zope.App.OFS.Container.IAdding."
                  title="Personal Contact Information" 
                  action="ZopeProducts.Contact"/>

<adapter
    provides=".ContactAdd.IContactAdd"
    for="Zope.App.OFS.Container.IAdding."
    factory=".ContactAdd."
    />

<browser:view
    name="ZopeProducts.Contact"
    for="Zope.App.OFS.Container.IAdding."
    factory=".ContactAddView."
    permission="ZopeProducts.Contact.ManageContacts" >

  <browser:page name="add.html"       template="add.pt" />
  <browser:page name="action.html" attribute="action" />
</browser:view>

<browser:defaultView for=".IContact.IContactInfo." name="info.html" />

<browser:view
    for=".IContact.IContactInfo."
    name="info.html" 
    template="info.pt"
    class=".ContactInfoView."
    permission="Zope.View" />

<browser:view
    for=".IContact."
    factory=".ContactEditView."
    permission="ZopeProducts.Contact.ManageContacts" >

  <browser:page name="edit.html"       template="edit.pt" />
  <browser:page name="editAction.html" attribute="action" />
</browser:view>

<browser:menuItems menu="zmi_views" for=".IContact.">
  <browser:menuItem title="Edit" action="edit.html"/>
  <browser:menuItem title="View" action="info.html"/>
</browser:menuItems>

<browser:icon name="zmi_icon" for=".IContact." file="contact.gif" />

<content class=".stubpostal.Info">
  <allow interface=".IPostal.IPostalInfo" />
</content>

<utility
    factory=".stubpostal.Lookup" 
    provides=".IPostal.IPostalLookup"
    permission="Zope.Public" />

<adapter
    factory=".ContactCityState."
    provides=".IPostal.IPostalInfo" 
    for=".IContact.IContactInfo"
    permission="Zope.Public" />

</zopeConfigure>


=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/contact.gif ===
  <Binary-ish file>

=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/contact_product_uml.txt ===

                           <<utility>>
                           ----------
                           | Lookup |
                           ----------
                              |
                              o IPostalLookup
           o IPostalInfo      ^
           |                  : 
      <<adapter>>             :
  --------------------        :
  | ContactCityState |- - - - +
  --------------------
    :
    :
    :
    :                                       <<view>>
    v IContactInfo                         -------------------
    o<- - - - - - - - - - - - - - - - - - -| ContactInfoView |
    ^                                      --------^----------
    :                                              V
    :                                              |
    :                                              | <<page template>>
    :                    <<page template>>        -----------
    :                    -----------              | info.pt |
    :                    | edit.pt |              -----------
    :                    -----------
    :                      |
    :                      ^ <<view>>
    : IContact     --------V----------
    o<- - - - - - -| ContactEditView |
    |              -------------------
    |                               
  -----------                                 
  | Contact |                                 
  -----------                                 


Key:

  o           Interface (catalysis style)
  
  ^
  V           Aggregation
  
  
  <- - - +    Dependency
         :


  o<- - -o    Interface B specializes interface A
  A      B

         
  <<name>>    Stereotype
  
  --------    
  | name |    Class
  --------
  


=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/edit.pt ===
<html metal:use-macro="views/standard_macros/page">
<head><title>Edit contact</title></head>
<body>
<div metal:fill-slot="body">
Enter the information about the contact.
<form action="editAction.html" method="post">
<table cellspacing="0" cellpadding="2" border="0">
  <tr><td> First name</td>
      <td><input type="text" name="first" size="40" value=""
           tal:attributes="value context/first" /> </td>
  </tr>
  <tr><td>Last name</td>
      <td><input type="text" name="last" size="40" value=""
           tal:attributes="value context/last" /> </td>
  </tr>
  <tr><td>Email</td>
      <td><input type="text" name="email" size="40" value=""
           tal:attributes="value context/email" /> </td>
  </tr>
  <tr><td>Address</td>
      <td align="left" valign="top">
        <textarea name="address" rows="3" cols="60"
         tal:content="context/address"></textarea>
      </td>
  </tr>
  <tr>
    <td>Postal Code</td>
    <td><input type="text" name="pc" size="40" value=""
       tal:attributes="value context/postal_code" />
    </td>
  </tr>
</table>
<input type="submit" name="submit" value=" Save Changes " />
</form></div></body></html>


=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/info.pt ===
<html metal:use-macro="views/standard_macros/page">
<head><title>Contact Information</title></head>
<body>
<div metal:fill-slot="body">
  <table border="0">
  <caption>Contact information</caption>
  <tbody>
    <tr><td>Name:</td>
        <td><span tal:replace="context/first">First</span>
            <span tal:replace="context/last">Last</span></td>
    </tr>
    <tr><td>Address:</td>
        <td tal:content="context/address">Mailing address here</td>
    </tr>
    <tr><td>Email:</td>
        <td tal:content="context/email">foo at bar.com</td>
    </tr>
    <tr><td>City:</td>
        <td tal:content="view/city | default">City</td>
    </tr>
    <tr><td>State:</td>
        <td tal:content="view/state | default">State</td>
    </tr>
    
  </tbody>
  </table>
</div></body></html>


=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/products.zcml ===
<zopeConfigure
    xmlns='http://namespaces.zope.org/zope'
    xmlns:security='http://namespaces.zope.org/security'
    xmlns:zmi='http://namespaces.zope.org/zmi'
    xmlns:browser='http://namespaces.zope.org/browser'
>
<!-- add include directives for products here -->
<include package="Zope.Contact" file="Contact.zcml"/>

</zopeConfigure>


=== Added File Docs/ZopeComponentArchitecture/PythonProgrammerTutorial/Chapter1/Step7/stubpostal.py ===
# Stub postal utility implemantation
from IPostal import IPostalLookup, IPostalInfo

class Info:

    __implements__ = IPostalInfo

    def __init__(self, city, state):
        self._city, self._state = city, state

    def city(self): return self._city

    def state(self): return self._state

class Lookup:

    __implements__ = IPostalLookup
    
    _data = {
        '22401': ('Fredericksburg', 'Virginia'),
        '44870': ('Sandusky', 'Ohio'),
        '90051': ('Los Angeles', 'California'),
        }

    def lookup(self, postal_code):
        data = self._data.get(postal_code)
        if data: return Info(*data)





More information about the Zope-book mailing list