Using Pyaella

Here we’ll create a demo application called Fusilli. Fusilli will do nothing, but show us how to create a new application from scratch and define a Pyaella logical domain, compile it, package it, and start it up.

Setup an environment

Install virtualenv

Install virtualenv using the easy_install for the Python 2.7 in /opt/:

sudo easy_install virtualenv

Create a new application virtualenv

After installing virtualenv package, create a new virtual environment for the new application:

virtualenv --no-site-packages --distribute FusilliEnv
cd FusilliEnv
source bin/activate

Installing Pyaella

Install Pyaella directly from Github (the prefered method), or download and copy the Pyaella egg to your new FusilliEnv project directory. Make sure you are still using the python executables in your new virtualenv (pip, easy_install, etc..)

Github

git clone http://github.com/migacollabs/Pyaella@master

Github into a virtualenv

pip install git+https://github.com/migacollabs/Pyaella@master

From an .egg

easy_install Pyaella[most current version].egg

Please refer to Installing Pyaella for more details

Make a new application

Using the python of the virtualenv, create a new demo application called Fusilli

python -m pyaella.scaffold.build Fusilli

Note

The directory structure of an app with a virtualenv can seem overly nested. However, each level has a purpose, and more details on this are included in the rest of the docs. But briefly:

VirtualEnvRoot
AppDevRoot(Git)
AppRoot
AppPackage (The App)

export the PYTHONPATH to the new Fusilli AppRoot

export PYTHONPATH=[/Users/..../FusilliEnv/Fusilli/fusilli

Warning

This PYTHONPATH export is very important. Nothing is expected to work if this is accidentally skipped

After running the scaffolding command, an application directory structure and initial files are created.

FusilliEnv/
  Fusilli/
    setup.py
    requirements.txt
    CHANGES.txt
    README.txt
    fusilli/
      development.ini
      production.ini
      fusilli/
        appcfg.yaml
        bgprocs.py
        composites.py
        contexts.py
        views.py
        assets/
        css/
        depot/
        player/
        sass/
        scripts/
        templates/
        uploads/

Included in this scaffold build are the standard javascript, coffeescript, sass, and Foundation libraries supported by Pyaella and available to Fusilli. The application is set up for immediate editing.

Create a new Domain file

Note

If you received an example domain file from Miga copy it into the AppPackage... or...

Create a new domain file, saving it in the AppPackage. Then compile the domain using pyaellac, and save a new models module in the AppPackage:

You can view the new models.py and see that it has generated some base classes. These can be edited, but usually during initial development the fast iterations of data or logical model changes are so rapid it is much easier to update the domain file and recompile the models.

Edit the application config

Now we can edit the appcfg.yaml file in the AppPackage, setting the correct Database values to point to your new localhost or remote test database.

Resources:
    Database:
        User: postgres
        Password:
        Host: localhost
        Port: 5432
        Schema: fusilli
        CreateTables: True

When starting up Pyaella or dashi will connect to this host and schema using the credentials you supply. If the machine is not accessible or you don’t have the proper credentials it will fail.

Testing the models and connection to the database

Once the entire environment is set up and the application has been built, you can use dashi to interact with your models and the database. The following command will start up an interactive that lets you play with your new models. If dashi throws an exception you know there is problem with the connection, the generated code, the PYTHONPATH is incorrect, or there is a conflict in your environment.

python -i -m pyaella.orm.dashi -c fusilli/appcfg.yaml
class pyaella.Configures

marking type

class pyaella.Configurable

marking type

class pyaella.Affector

class that supports context manager, planner

class pyaella.Affectable

marking type

class pyaella.Mix

marker interface to Mix in Mixables

class pyaella.Mixable
class pyaella.Container(klass, **kwds)

an object that dynamically collects and sets attribute from a class definition and keywords on __init__.

future: supporting exclusion of attributes passed based on name

class pyaella.SynchronisedContainer
pyaella.register_decorator(decorator)
pyaella.memoize(func)
pyaella.memoize_exp(expiration=None)

Memoize with an expiration time (in seconds)

pyaella.argument_bind_params(func)

@argument_bind_params

class pyaella.ExpFilter(*args, **kwds)
class Happy(ExpFilter):
pass
class Sad(ExpFilter):
def __init__(self, who, what, where, when, why):
ExpFilter.__init__(self, who, what, where, when, why)
class TestExpressible(object):

@accepts_expfilter def __mod__(self, other, **kwds):

def happy_func(*args):
print ‘Happy Func called’,
dir(args[0]), args[0]._kwds, args[0]._args
def sad_func(*args):
print ‘Sad Func called’, dir(args[0]),
args[0]._kwds, args[0]._args
dispatch = {
‘Happy’:happy_func, ‘Sad’:sad_func

} try:

dispatch[kwds.keys()[0]](kwds[kwds.keys()[0]])
except KeyError:
raise

TestExpressible() % Sad(1,2,3,4,5)

pyaella.recordtype(typename, field_names, verbose=False, **default_kwds)

Returns a new class with named fields.

@keyword field_defaults:
A mapping from (a subset of) field names to defaultvalues.
@keyword default: If provided, the default value for all fields without an
explicit default in field_defaults.
>>> Point = recordtype('Point', 'x y', default=0)
>>> Point.__doc__           # docstring for the new class
'Point(x, y)'
>>> Point()                 # instantiate with defaults
Point(x=0, y=0)
>>> p = Point(11, y=22)     # instantiate with positional args or keywords
>>> p[0] + p.y              # accessible by name and index
33
>>> p.x = 100; p[1] =200    # modifiable by name and index
>>> p
Point(x=100, y=200)
>>> x, y = p               # unpack
>>> x, y
(100, 200)
>>> d = p.todict()         # convert to a dictionary
>>> d['x']
100
>>> Point(**d) == p        # convert from a dictionary
True