Package pyperry :: Module base :: Class Base
[frames] | no frames]

Class Base

source code

object --+
         |
        Base

The Base class for all models using pyperry.

Base defines the functionality of a pyperry model. All models should inherit (directly or indirectly) from Base. For a basic overview of usage, check out the docs on the pyperry module.

Configuration Overview

Configuration is done through various class methods on the model. These could be set anywhere, but conventionally they are set in a config method on the class. This method is run when a class is created with the newly created class as an argument. Thus, configuration can be done like this:

   class Animal(pyperry.base.Base):
       def config(cls):
           cls.attributes 'id', 'name', 'mammal'
           cls.configure('read', type='bertrpc')
           cls.add_middleware('read', MyMiddleware, config1='val')

           cls.has_many('friendships', class_name='Friendship')

           cls.scope('mammal', where={ 'mammal': true })

Any class configuration can be done in this method.

Querying

Queries can be built by chaining calls to scopes or query methods. For example:

   Person.where({ 'first_name': 'Bob' }).order('last_name')

This generates a query for all Person objects with the first name "Bob" ordered by their last name. Each query method returns a new Relation object with the new query parameters applied. This allows the continued chaining.

A Relation object is a sequence-like object behaving much like a list. The query will be run the first time the object is treated like a list, and the records will be used for the expression. For example:

   query = Animal.where({ 'type': 'Platypus' })

   # Array comprehensions and for loops
   for animal in query:
       print animal.name + " is a platypus.  They don't do much."

   # Compares type and attributes of objects for equality
   object in query
   object not in query

   # Indexing, slicing, step slicing
   query[0]
   query[0:3]
   query[0:3:2]

   # Other
   len(query)

In this example the query is executed before running the for loop, and all subsequent calls use that result. Queries will not be run until you need them so unused queries don't hurt performance. If you would like to force a query to run and retreive the records in a list object use the Relation.all() method, or to receive the object itself in single result queries use the Relation.first() method.

Persistence

Pyperry provides an interface for creating, updating, and deleting models when a write adapter is configured. A model can be initialized as a "new" record (default) or a "stored" record and is determined by the new_record attribute. This changes the behavior of the save operation. A "new" record is created and a "stored" record is updated. Also, a "new" record cannot be deleted as it does not yet exist in the database. See the individual persistence methods for more information

Scopes

Scopes allow you to specify prebuilt views of your data. Scopes, like query methods, can be applied simply by chaining calls on instances of Relation or the Base class. Scopes are created through the scope() class method (conventionally within the _config method):

   cls.scope('ordered', order='type, name')
   cls.scope('platypus', where={ 'type': 'platypus' })
   cls.scope('perrys', where={ 'name': 'perry' })
   cls.scope('agentp', cls.perrys().platypus())

These scopes can now be used in queries along with query methods and chained together to make powerful queries:

   # Ordered animals with type 'platypus' named 'perry'
   Animal.ordered().agentp()

Scopes can also accept arguments by defining a lambda or function to be called when the scope is invoked:

   @cls.scope
   def name_is(rel, name):
       return rel.where({ 'name': name })

   # This can also be written:
   cls.scope('name_is', lambda(rel, name): rel.where({ 'name': name }))

   # This allows:
   Animal.name_is('perry')

Associations

Associations allow you to define foreign key relationships between two models, the target (model on which the association is defined) and the source (model from which the data will come). There are two basic kinds of associations: has and belongs. A has relationship means the foreign_key lives on the source model. A belongs relationship means the foreign_key lives on target model.

Imagine a blog. A blog has many articles and an article belongs to an author. You might model this structure with Blog, Article and Person classes. Associations are conventionally defined in the _config method for each class, but to save space we'll just show the association definition for each class:

   Blog.has_many('articles', class_name='Article')
   Article.belongs_to('blog', class_name='Blog')
   Article.belongs_to('author', class_name='Person')

Assuming you have an instance of Blog called blog you could then reference these associations like this:

   # An ordered list of articles on this blog
   articles = blog.authors().ordered()
   # The author of the first article
   articles[0].author()

Note that the has_many association returns a Relation object allowing you to apply query methods and scopes to the association before executing the query.

For more information on Associations see the individual association methods.

Nested Classes
  __metaclass__
The Metaclass for Base
Instance Methods
 
__init__(self, attributes={}, new_record=True, **kwargs)
Initialize a new pyperry object with attributes
source code
 
reload(self)
Refetch the attributes for this object from the read adapter
source code
 
frozen(self)
Returns True if this instance is frozen and cannot be saved.
source code
 
freeze(self)
Marks this instance as being frozen, which will cause all future writes and deletes to fail.
source code
 
__repr__(self)
Return a string representation of the object
source code
 
__eq__(self, compare)
Compare equality of an object by its attributes
source code

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __sizeof__, __str__, __subclasshook__

    Attribute access
 
__getitem__(self, key)
Adds dict like attribute reading
source code
 
__setitem__(self, key, value)
Adds dict like attribute writing
source code
 
__getattr__(self, key)
Dynamic attribute / association reading
source code
 
__setattr__(self, key, value)
Dynamic attribute setting
source code
 
pk_attr(self)
A shortcut method from retrieving the name of this model's primary key attribute.
source code
 
pk_value(self)
A shortcut method for retrieving the value stored in this model's primary key attribute.
source code
    Persistence
 
set_attributes(self, attributes)
Set the attributes of the object using the provided dictionary.
source code
 
save(self)
Save the current value of the model's data attributes through the write adapter.
source code
 
update_attributes(self, attributes=None, **kwargs)
Update the attributes with the given dictionary or keywords and save the model.
source code
 
delete(self)
Removes this model from the data store
source code
Class Methods
 
fetch_records(cls, relation)
Execute query using relation on the read adapter stack
source code
 
__configmodel__(cls) source code
    Configuration
 
configure(cls, adapter_type, config=None, **kwargs)
Method for setting adapter configuration options.
source code
 
add_middleware(cls, adapter_type, klass, options=None, **kwargs)
Add a middleware to the given adapter
source code
 
add_processor(cls, adapter_type, klass, options=None, **kwargs)
Add a processor to the given adapter
source code
 
adapter(cls, adapter_type)
Returns the adapter specified by adapter_type
source code
 
define_attributes(cls, *attributes)
Define available attributes for a model.
source code
 
attributes(cls, *attributes)
Define available attributes for a model.
source code
 
primary_key(cls)
Returns the attribute name of the model's primary key.
source code
 
set_primary_key(cls, attr_name)
Set the name of the primary key attribute for the model.
source code
    Scoping
 
relation(cls)
A base instance of Relation for this model.
source code
 
current_scope(cls)
Base instance of Relation after default scopes are applied.
source code
 
scoped(cls)
Unique instance of Relation to build queries on.
source code
 
default_scope(cls, *args, **kwargs)
Add a default scoping for this model.
source code
 
unscoped(cls, function)
Execute function without default scopes
source code
 
scope(cls, name_or_func, *args, **kwargs)
Defines a scope on the given model.
source code
    Association Declaration
 
belongs_to(cls, id, **kwargs)
Create a belongs association
source code
 
has_many(cls, id, **kwargs)
Create has collection association
source code
 
has_one(cls, id, **kwargs)
Create singular has association
source code
Class Variables
  adapter_config = {}
  defined_associations = {}
  defined_attributes = set([])
Properties

Inherited from object: __class__

Method Details

__init__(self, attributes={}, new_record=True, **kwargs)
(Constructor)

source code 

Initialize a new pyperry object with attributes

Uses attributes dictionary to set attributes on a new instance. Only keys that have been defined for the model will be set. Defaults to a new record but can be overriden with new_record param. You can also use kwargs to specify the attributes.

Parameters:
  • attributes - dictionary of attributes to set on the new instance
  • new_record - set new_record flag to True or False.
Overrides: object.__init__

__getitem__(self, key)
(Indexing operator)

source code 

Adds dict like attribute reading

Allows:

   person['id']
   person['name']

Developer Note: This method of accessing attributes is used internally and should never be overridden by subclasses.

Parameters:
  • key - name of the attribute to get
Raises:
  • KeyError - If key is not a defined attribute.

__setitem__(self, key, value)
(Index assignment operator)

source code 

Adds dict like attribute writing

Allows:

   animal['name'] = 'Perry'
   animal['type'] = 'Platypus'
Parameters:
  • key - name of the attribute to set
  • value - value to set key attribute to
Raises:
  • KeyError - If key is not a defined attribute.

__getattr__(self, key)
(Qualification operator)

source code 

Dynamic attribute / association reading

Properties or Methods are not created for attributes or associations, and are instead handled by this method. This allows a model to override the default behavior of attribute or association access by creating a property or method (respectively) of the same name.

Allows:

   animal.name
   animal.friends()
Parameters:
  • key - name of the attribute attempting to be accessed
Raises:
  • AttributeError - if key is not a defined attribute or association.

__setattr__(self, key, value)

source code 

Dynamic attribute setting

Properties are not created for setting attributes. This method allows setting any defined attributes through the standard writer interface.

Allows:

   animal.name = "Perry"
   animal.type = "Platypus
Parameters:
  • key - name of the attribute to set
  • value - value to set the key attribute to
Overrides: object.__setattr__

set_attributes(self, attributes)

source code 

Set the attributes of the object using the provided dictionary.

Only attributes defined using define_attributes will be set.

Parameters:
  • attributes - dictionary of attributes

save(self)

source code 

Save the current value of the model's data attributes through the write adapter.

If the save succeeds, the model's saved attribute will be set to True. Also, if a read adapter is configured, the models data attributes will be refreshed to ensure that you have the current values.

If the save fails, the model's errors will be set to a dictionary containing error messages and the saved attribute will be set to False.

Returns:
Returns True on success or False on failure

update_attributes(self, attributes=None, **kwargs)

source code 

Update the attributes with the given dictionary or keywords and save the model.

Has the same effect as calling:

   obj.set_attributes(attributes)
   obj.save()

Requires either attributes or keyword arguments. If both are provicded, attributes will be used and kwargs will be ignored.

Parameters:
  • attributes - dictionary of attributes to set
  • kwargs - Optionally use keyword syntax instead of attributes
Returns:
Returns True on success or False on failure

delete(self)

source code 

Removes this model from the data store

If the call succeeds, the model will be marked as frozen and calling frozen on the model will return True. Once a model is frozen, an exception will be raised if you attempt to call one of the persistence methods on it.

If the call fails, the model's errors attribute will be set to a dictionary of error messages describing the error.

Returns:
True on success or False on failure

configure(cls, adapter_type, config=None, **kwargs)
Class Method

source code 

Method for setting adapter configuration options.

Accepts a dictionary argument or keyword arguments, but not both. Configuration specified will be merged with all previous calls to configure for this adapter_type

Parameters:
  • adapter_type - specify the type of adapter ('read' or 'write')
  • config - dictionary of configuration parameters
  • kwargs - alternate specification of configuration

add_middleware(cls, adapter_type, klass, options=None, **kwargs)
Class Method

source code 

Add a middleware to the given adapter

Interface for appending a middleware to an adapter stack. For more information on middlewares see docs on pyperry.adapter.abstract_adapter.AbstractAdapter.

Parameters:
  • adapter_type - specify type of adapter ('read' or 'write')
  • klass - specify the class to use as the middleware
  • options - specify an options dictionary to pass to middleware
  • kwargs - specify options with keyword arguments instead of options.

add_processor(cls, adapter_type, klass, options=None, **kwargs)
Class Method

source code 

Add a processor to the given adapter

Interface for adding a processor to the adapter stack. Processors come before the middleware in the adapter stack. For more information on processors see docs on pyperry.adapter.abstract_adapter.AbstractAdapter.

Parameters:
  • adapter_type - specify type of adapter ('read' or 'write')
  • klass - specify the class to use as the processor
  • options - specify an options dictionary to pass to processor
  • kwargs - specify options with keyword arguments instead of options.

adapter(cls, adapter_type)
Class Method

source code 

Returns the adapter specified by adapter_type

If the adapter has not been configured correctly ConfigurationError will be raised.

Parameters:
  • adapter_type - type of adapter ('read' or 'write')
Returns:
the adapter specified by adapter_type

define_attributes(cls, *attributes)
Class Method

source code 

Define available attributes for a model.

This method is automatically called when the attributes var is set on the class during definition. Each call will union any new attributes into the set of defined attributes.

aliased as attributes

Parameters:
  • attributes - list parameters as strings, or the first argument is a list of strings.

attributes(cls, *attributes)
Class Method

source code 

Define available attributes for a model.

This method is automatically called when the attributes var is set on the class during definition. Each call will union any new attributes into the set of defined attributes.

aliased as attributes

Parameters:
  • attributes - list parameters as strings, or the first argument is a list of strings.

set_primary_key(cls, attr_name)
Class Method

source code 

Set the name of the primary key attribute for the model. The new primary key attribute must be one of the definted attributes otherwise set_primary_key will raise an AttributeError.

fetch_records(cls, relation)
Class Method

source code 

Execute query using relation on the read adapter stack

Parameters:
  • relation - An instance of Relation describing the query
Returns:
list of records from adapter query data each with new_record set to false. None items are removed.

relation(cls)
Class Method

source code 

A base instance of Relation for this model.

All query scopes originate from this instance, and should not change this instance.

Returns:
Relation instance for this model

current_scope(cls)
Class Method

source code 

Base instance of Relation after default scopes are applied.

Returns an instance of Relation after applying the latest scope in the class variable _scoped_methods.

Returns:
Relation instance with default scopes applied if default scopes are present. Otherwise returns None.

scoped(cls)
Class Method

source code 

Unique instance of Relation to build queries on.

If you want an instance of relation on this model you most likely want this method.

Returns:
Cloned return value from current_scope or relation

default_scope(cls, *args, **kwargs)
Class Method

source code 

Add a default scoping for this model.

All queries will be built based on the default scope of this model. Only specify a default scope if you always want the scope applied. Calls to default_scope aggregate. So each call will append to options from previous calls.

Note: You can bypass default scopings using the unscoped method.

Similar to arguments accepted by scope. The only thing not supported is lambdas/functions accepting additional arguments. Here are some examples:

   Model.default_scope(where={'type': 'Foo'})
   Model.default_scope({ 'order': 'name DESC' })

unscoped(cls, function)
Class Method

source code 

Execute function without default scopes

All default scoping is temporarily removed and the given function is then executed. After the function is executed all previous default scopes are applied.

Parameters:
  • function - function to execute

scope(cls, name_or_func, *args, **kwargs)
Class Method

source code 

Defines a scope on the given model.

A scope can be defined in one of several ways:

Dictionary or Keyword Arguments

If your scope is simply setting a few static query arguments than this is the easiest option. Here are a few examples:

   # With a dictionary
   Model.scope('ordered', { 'order': "name" })

   # With keyword arguments
   Model.scope('awesome', where={'awesome': 1})
   Model.scope('latest', order="created_at DESC", limit=1)

With a Lambda or Function

When your scope involves chaining other scopes, delayed values (such as a relative time), or if it takes arguments then this is the preferred method. Here are a few examples:

   Model.scope('awesome_ordered', lambda(cls): cls.ordered().awesome())

   # Returns a scope dynamically generating condition using fictional
   # minutes_ago function.  Without the lambda this wouldn't update
   # each time the scope is used, but only when the code was reloaded.
   Model.scope('recent', lambda(cls): cls.where(
           'created_at > %s' % minutes_ago(5))

   # You can also use the method as a decorator!  Whatever you call
   # your method will be the name of the scope.  Make sure it's unique.
   @Model.scope
   def name_like(cls, word):
       return cls.where(["name LIKE '%?%", word])

These scopes can be chained. Like so:

   # Returns a max of 5 records that have a name containing 'bob'
   # ordered
   Model.name_like('bob').ordered().limit(5)

belongs_to(cls, id, **kwargs)
Class Method

source code 

Create a belongs association

Defines a belongs association by the name specified by id, and you can access the association through a method by this name will be created. A call to this method will run the query for this association and return the result, or, if this query has been run previously (or if it was eager loaded), it will return the cached result.

In addition to keywords listed below this method also accepts all of the query finder options specified on Relation

Parameters:
  • id - name of the association
  • class_name - Unambiguous name (string) of source class (required).
  • klass - Can be used in place of class_name -- the source class.
  • primary_key - Primary key of source model (default: primary key of source model)
  • foreign_key - Foreign key of the target model (default: id + '_id')
  • polymorphic - Set to True if this is a polymorphic association. Class name will be looked for in the (id + '_type') field. (default: False)
  • namespace - For polymorphic associations set the full or partial namespace to prepend to the '_type' field. (default: None)
Returns:
None

has_many(cls, id, **kwargs)
Class Method

source code 

Create has collection association

Defines a has association by the name specified by id. After adding this association you will be able to access it through a method named the same as the association. This method will return an instance of Relation representing the query to be run. You can treat the resulting object as a list of results, and the query will be executed whenever necessary. This allows you to chain additional scopes on the query before executing (e.g. person.addresses().primary()).

In addition to keywords listed below this method also accepts all of the query finder options specified on Relation

Parameters:
  • id - name of the association
  • class_name - Unambiguous name (string) of source class (required).
  • klass - Can be used in place of class_name -- the source class.
  • primary_key - Primary key of target model (default: primary key of target model)
  • foreign_key - Foreign key on the source model (default: id + '_id')
  • as_ - When source is polymorphic this will specify the class name to use (required when source is polymorphic).
Returns:
None

has_one(cls, id, **kwargs)
Class Method

source code 

Create singular has association

Defines a has association by the name specified by id, and allows access to the association by a method of the same name. A call to that method will run the query for this association and return the resulting object, or, if the query has been run previously (or it was eager loaded), it will return the cached result.

In addition to keywords listed below this method also accepts all of the query finder options specified on Relation

Parameters:
  • id - name of the association
  • class_name - Unambiguous name (string) of source class (required).
  • klass - Can be used in place of class_name -- the source class.
  • primary_key - Primary key of target model (default: primary key of target model)
  • foreign_key - Foreign key on the source model (default: id + '_id')
  • as_ - When source is polymorphic this will specify the class name to use (required when source is polymorphic).
Returns:
None

__repr__(self)
(Representation operator)

source code 

Return a string representation of the object

Overrides: object.__repr__