Skip to content
This repository has been archived by the owner on Oct 25, 2022. It is now read-only.

Commit

Permalink
putting doctests in a different package
Browse files Browse the repository at this point in the history
  • Loading branch information
gustavofonseca authored and ramalho committed Mar 4, 2011
1 parent 0d4879d commit 8e3580b
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 222 deletions.
75 changes: 2 additions & 73 deletions isis/model/mapper.py
Expand Up @@ -18,81 +18,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""
----------------------
Object-document mapper
----------------------
>>> def text_validator(node, value):
... if value.startswith('Banana'):
... raise BaseException, "You can't start a text with 'Banana'"
...
>>> def colon_validator(node, value):
... for author in value:
... if ',' not in author:
... raise BaseException, "Authors's name must be in 'LastName, FirstName' format"
>>> class Book(Document):
... title = TextProperty(required=True, validator=text_validator)
... authors = MultiTextProperty(required=False, validator=colon_validator)
... pages = TextProperty()
...
>>> class Book2(Document):
... title = TextProperty(required=True, validator=text_validator)
... authors = comp = CompositeTextProperty(required=False, subkeys='fl')
...
Instantiating a Book object::
>>> book1 = Book(title='Godel, Escher, Bach',
... authors=(u'Hofstadter, Douglas',),
... pages='777')
...
>>> book2 = Book2(title='Godel, Escher, Bach',
... authors=u'^lHofstadter^fDouglas')
...
Manipulating its attributes::
>>> book1.title
u'Godel, Escher, Bach'
>>> book1.authors[0]
u'Hofstadter, Douglas'
>>> book1.authors = (u'Hofstadter Douglas',)
Traceback (most recent call last):
...
BaseException: Authors's name must be in 'LastName, FirstName' format
>>> book1.authors[0]
u'Hofstadter, Douglas'
>>> book1.authors += (u'Daiana Rose',)
Traceback (most recent call last):
...
BaseException: Authors's name must be in 'LastName, FirstName' format
>>> book1.authors += (u'Rose, Daiana',)
>>> book1.authors
(u'Hofstadter, Douglas', u'Rose, Daiana')
>>> print book2.authors
[('_', u''), (u'l', u'Hofstadter'), (u'f', u'Douglas')]
>>> book2.authors['f']
u'Douglas'
>>> book2.authors['j']
Traceback (most recent call last):
...
KeyError: 'j'
"""
from ordered import OrderedProperty, OrderedModel
from subfield import CompositeString
from isis.model.subfield import CompositeString

__all__ = ['Document', 'TextProperty', 'MultiTextProperty']
__all__ = ['Document', 'TextProperty', 'MultiTextProperty', 'CompositeTextProperty']


class Document(OrderedModel):
Expand Down
51 changes: 0 additions & 51 deletions isis/model/ordered.py
Expand Up @@ -18,57 +18,6 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""
Em Python os atributos de uma classe são armazenados em um `dict`, portanto
sua ordem não é preservada. Normalmente a ordem não é realmente importante.
Note no exemplo abaixo que a lista devolvida por `dir(l)` não preserva
a ordem em que foram declarados os atributos na classe `Livro`::
>>> class LivroSimples(object):
... titulo = u''
... isbn = u''
... autores = u''
>>> l = LivroSimples()
>>> dir(l) #doctest: +ELLIPSIS
[...'autores', 'isbn', 'titulo'...]
Para gerar formulários automaticamente a partir da classe, é desejável
respeitar a ordem de declaração dos campos. Usando descritores e uma
metaclasse, é possível preservar esta ordem.
>>> class Livro(OrderedModel):
... titulo = OrderedProperty()
... isbn = OrderedProperty()
... autores = OrderedProperty()
>>> l2 = Livro()
>>> l2.titulo = 'O Alienista'
>>> l2.titulo
'O Alienista'
>>> list(l2)
['titulo', 'isbn', 'autores']
>>> for campo in l2: print campo
titulo
isbn
autores
>>> l3 = Livro()
>>> l3.titulo
Traceback (most recent call last):
...
AttributeError: 'Livro' object has no attribute 'titulo'
>>> l4 = Livro(titulo=u'Alice', autores=[u'Carroll', u'Tenniel'], isbn=u'9781234567890')
>>> for campo, valor in l4.iteritems():
... print '%-8s: %s' % (campo, valor)
titulo : Alice
isbn : 9781234567890
autores : [u'Carroll', u'Tenniel']
Os descritores têm um atributo `order` que é inicializado com um contador da
classe `OrderedProperty` incrementado a cada nova instância. A metaclasse usa
este atributo `order` para ordenar uma lista com os nomes dos campos.
"""

from operator import attrgetter

class OrderedProperty(object):
Expand Down
101 changes: 12 additions & 89 deletions isis/model/subfield.py
Expand Up @@ -18,83 +18,6 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.


"""
-----------------
Subfield parsing
-----------------
>>> expand('John Tenniel^rillustrator')
[('_', 'John Tenniel'), ('r', 'illustrator')]
All subfields are stripped of trailing whitespace::
>>> expand('John Tenniel ^rillustrator ')
[('_', 'John Tenniel'), ('r', 'illustrator')]
Subfield keys are case-insensitive, and always converted to lower case::
>>> expand('John Tenniel^Rillustrator')
[('_', 'John Tenniel'), ('r', 'illustrator')]
Even if there is no main subfield, the '_' key is returned::
>>> expand('^1one^2two^3three')
[('_', ''), ('1', 'one'), ('2', 'two'), ('3', 'three')]
---------------
Abnormal cases
---------------
Empty field::
>>> expand('')
[('_', '')]
Empty subfields::
>>> expand('aa^1^2c') # empty subfield ^1, middle position
[('_', 'aa'), ('1', ''), ('2', 'c')]
>>> expand('aa^1b^2') # empty subfield ^2, last position
[('_', 'aa'), ('1', 'b'), ('2', '')]
Subfield keys are limited to a-z and 0-9. Invalid keys are ignored,
and the subfield delimiter is appended to the previous subfield::
>>> expand('John Tenniel^!illustrator')
[('_', 'John Tenniel^!illustrator')]
>>> expand('John Tenniel^rillustrator^')
[('_', 'John Tenniel'), ('r', 'illustrator^')]
>>> expand('John Tenniel^rillustrator^^')
[('_', 'John Tenniel'), ('r', 'illustrator^^')]
To reduce the damage from duplicate delimiters in the middle of the
field, a space is added after each pair. Otherwise the example below
would seem to have an ^i subfield with the content "llustrator".
Keeping the duplicate delimiters together makes it easier to find
and fix these problems later::
>>> expand('John Tenniel^^illustrator')
[('_', 'John Tenniel^^ illustrator')]
----------------------------
Controlled subfield parsing
----------------------------
When a subkeys parameter is passed, only subfield markers with those keys
are expanded::
>>> expand('John Tenniel^rillustrator', subkeys='r')
[('_', 'John Tenniel'), ('r', 'illustrator')]
>>> expand('John Tenniel^xillustrator', subkeys='r')
[('_', 'John Tenniel^xillustrator')]
>>> expand('John Tenniel^rillustrator', subkeys='')
[('_', 'John Tenniel^rillustrator')]
"""

import re

MAIN_SUBFIELD_KEY = '_'
Expand Down Expand Up @@ -132,32 +55,32 @@ class CompositeString(object):
''' Represent an Isis field, with subfields, using
Python native datastructures
>>> pythonic_author = CompositeString('John Tenniel^xillustrator',
... subkeys='x')
>>> print pythonic_author
[('_', u'John Tenniel'), (u'x', u'illustrator')]
>>> author = CompositeString('John Tenniel^xillustrator',
... subkeys='x')
>>> unicode(author)
u'John Tenniel^xillustrator'
'''

def __init__(self, isis_string, subkeys=None, encoding=DEFAULT_ENCODING):
if not isinstance(isis_string, basestring):
raise Invalid('%r value must be unicode or str instance' % isis_string)
def __init__(self, isis_raw, subkeys=None, encoding=DEFAULT_ENCODING):
if not isinstance(isis_raw, basestring):
raise Invalid('%r value must be unicode or str instance' % isis_raw)

isis_string = isis_string.decode(encoding)
self.expanded = expand(isis_string, subkeys)
self.__isis_raw = isis_raw.decode(encoding)
self.__expanded = expand(self.__isis_raw, subkeys)

def __getitem__(self, key):
for subfield in self.expanded:
for subfield in self.__expanded:
if subfield[0] == key:
return subfield[1]
else:
raise KeyError(key)

def __unicode__(self):
return unicode(self.expanded)
return self.__isis_raw

def __str__(self):
return str(self.expanded)
return str(self.__isis_raw)


def test():
Expand Down
Empty file added isis/model/tests/__init__.py
Empty file.
83 changes: 83 additions & 0 deletions isis/model/tests/test_mapper.py
@@ -0,0 +1,83 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

"""
----------------------
Object-document mapper
----------------------
>>> def text_validator(node, value):
... if value.startswith('Banana'):
... raise BaseException, "You can't start a text with 'Banana'"
...
>>> def colon_validator(node, value):
... for author in value:
... if ',' not in author:
... raise BaseException, "Authors's name must be in 'LastName, FirstName' format"
>>> class Book(Document):
... title = TextProperty(required=True, validator=text_validator)
... authors = MultiTextProperty(required=False, validator=colon_validator)
... pages = TextProperty()
...
>>> class Book2(Document):
... title = TextProperty(required=True, validator=text_validator)
... authors = comp = CompositeTextProperty(required=False, subkeys='fl')
...
Instantiating a Book object::
>>> book1 = Book(title='Godel, Escher, Bach',
... authors=(u'Hofstadter, Douglas',),
... pages='777')
...
>>> book2 = Book2(title='Godel, Escher, Bach',
... authors=u'^lHofstadter^fDouglas')
...
Manipulating its attributes::
>>> book1.title
u'Godel, Escher, Bach'
>>> book1.authors[0]
u'Hofstadter, Douglas'
>>> book1.authors = (u'Hofstadter Douglas',)
Traceback (most recent call last):
...
BaseException: Authors's name must be in 'LastName, FirstName' format
>>> book1.authors[0]
u'Hofstadter, Douglas'
>>> book1.authors += (u'Daiana Rose',)
Traceback (most recent call last):
...
BaseException: Authors's name must be in 'LastName, FirstName' format
>>> book1.authors += (u'Rose, Daiana',)
>>> book1.authors
(u'Hofstadter, Douglas', u'Rose, Daiana')
>>> print book2.authors
^lHofstadter^fDouglas
>>> book2.authors['f']
u'Douglas'
>>> book2.authors['j']
Traceback (most recent call last):
...
KeyError: 'j'
"""
from isis.model.mapper import Document
from isis.model.mapper import TextProperty, MultiTextProperty, CompositeTextProperty

def test():
import doctest
doctest.testmod()

if __name__=='__main__':
test()

0 comments on commit 8e3580b

Please sign in to comment.