コード例 #1
0
ファイル: basic.py プロジェクト: millejoh/pycells
class Rectangle(cells.Model):
    # Now let's add a cell to our model. This will be an Input cell,
    # which can be set from outside the Model:
    width = cells.makecell(value=1)
    # I didn't specify an InputCell (though I could have);
    # cells.makecell will create an InputCell if it gets a value
    # argument.

    # Similarly, we can make the aspect ratio cell:
    ratio = cells.makecell(value=GOLDEN)

    # Now, I make the cell which gives the calculated length. It's
    # called a Rule cell, and I can make it like this:
    @cells.fun2cell()
    def length(self, prev):
        # The signature of the rule which defines a RuleCell's value
        # must be f(self, prev); self will be passed an instance of
        # this Model (just like you'd expect), and prev will be passed
        # the cell's previous (aka out-of-date) value.

        # For this Rule I'm going to be ignoring the previous value,
        # and just using this instance's ratio and width to get the
        # new length:
        return float(self.width) * float(self.ratio)

    # There's another way to make RuleCells. We can pass anonymous
    # functions to the cells.makecell function:
    area = cells.makecell(
        rule=lambda self, p: float(self.length) * float(self.width))
コード例 #2
0
ファイル: family.py プロジェクト: millejoh/pycells
class AddressBooks(cells.Family):
    # Note that kid_slots is just a cell. It could be any type of cell
    # so long as the value it produced was a class.
    kid_slots = cells.makecell(value=NamedAddressBook)

    # I'd like to be able to get all of the names and emails from all
    # of the address books:
    @cells.fun2cell()
    def entries(self, prev):
        d = {}
        for model in self.kids:
            d.update(model.entries)

        return d

    # And also get all the names:
    names = cells.makecell(rule=lambda s,p: s.entries.keys())

    # Let's also get all the address book names & indexes
    @cells.fun2cell()
    def booknames(self, prev):
        d = {}
        for model in self.kids:
            # I'll use one of the Family convenience methods, position
            d[model.name] = model.position()

        return d
コード例 #3
0
class Real(Column):
    value = cells.makecell(value=0.0)
    translate_from_sql = cells.makecell(value=lambda v: float(v))

    @cells.fun2cell()
    def create_column_string(self, prev):
        return self.name + " REAL"

    @cells.fun2cell()
    def sql_value(self, prev):
        return str(self.value)
コード例 #4
0
class String(Column):
    value = cells.makecell(value="")
    translate_from_sql = cells.makecell(value=lambda v: v)

    @cells.fun2cell()
    def create_column_string(self, prev):
        return self.name + " TEXT"

    @cells.fun2cell()
    def sql_value(self, prev):
        return self.value
コード例 #5
0
class Integer(Column):
    value = cells.makecell(value=0)
    translate_from_sql = cells.makecell(value=lambda v: int(v))

    @cells.fun2cell()
    def create_column_string(self, prev):
        return self.name + " INTEGER"

    @cells.fun2cell()
    def sql_value(self, prev):
        return str(self.value)
コード例 #6
0
class Column(cells.Model):
    value = cells.makecell(value=None)
    name = cells.makecell(value="anonymous")
    table = cells.makecell(value=None)
    translate_from_sql = cells.makecell(value=lambda v: pickle.loads(str(v)))

    @cells.fun2cell()
    def create_column_string(self, prev):
        return self.name + " BLOB"

    @cells.fun2cell()
    def sql_value(self, prev):
        return pickle.dumps(self.value)
コード例 #7
0
ファイル: celltk.py プロジェクト: millejoh/pycells
class Label(BasicTkinterObject):
    def __init__(self, *args, **kwargs):
        BasicTkinterObject.__init__(self, *args, **kwargs)
        self.stringvar = Tkinter.StringVar(self.container)
        self.widget = Tkinter.Label(self.container,
                                    textvariable=self.stringvar)
        self.widget.pack()

    stringvar = cells.makecell(value=None)
    update_on = cells.makecell(value="none")

    @cells.fun2cell()
    def container(self, prev):
        print "Entry.container"
        return self.parent.widget
コード例 #8
0
        class MyModel(cells.Model):
            x = cells.makecell(value=5)

            @cells.fun2cell()
            def a(modelself, prev):
                self.a_ran = True
                return modelself.x + modelself.offset

            def __init__(self, *args, **kwargs):
                self.offset = 1
                cells.Model.__init__(self, *args, **kwargs)
コード例 #9
0
ファイル: celltk.py プロジェクト: millejoh/pycells
class Entry(BasicTkinterObject):
    def __init__(self, *args, **kwargs):
        BasicTkinterObject.__init__(self, *args, **kwargs)
        self.stringvar = Tkinter.StringVar(self.container)
        self.stringvar.trace("u", self.text_copier)
        self.widget = Tkinter.Entry(self.container,
                                    textvariable=self.stringvar)
        self.widget.pack()

    text = cells.makecell(value=None)
    stringvar = cells.makecell(value=None)
    update_on = cells.makecell(value="none")

    def text_copier(self, *args):
        print "updating text", repr(args), "field is", self.stringvar.get()
        self.text = self.stringvar.get()

    @cells.fun2cell()
    def container(self, prev):
        print "Entry.container"
        return self.parent.widget
コード例 #10
0
class AlternateInputAddressBook(WorkingAddressBook):
    # I'll add an ephemeral input cell to take the tuple
    entry = cells.makecell(value=None, ephemeral=True)

    # and a RuleCell to build a dictionary with the entries
    @cells.fun2cell()
    def entries(self, prev):
        d = copy.copy(prev)  # prevent the old == new dict issue
        if not d:
            d = {}

        if self.entry:
            d[self.entry[0]] = self.entry[1]
        return d
コード例 #11
0
class StorableAddressBook(WorkingAddressBook):
    entry_file = cells.makecell(value="./addresses.pickle")

    # We'll build this autoloading entry db with a RuleThenInputCell:
    @cells.fun2cell(celltype=cells.RuleThenInputCell)
    def entries(self, prev):
        # These are written like RuleCells. First we'll look for an
        # extant entry file:
        if not os.path.isfile(self.entry_file):
            # And if it doesn't exist, we'll just return an empty dictionary.
            return {}
        else:
            # If there is a file there, we'll load it into memory
            # using the pickle module.
            return pickle.load(open(self.entry_file, 'r'))
コード例 #12
0
ファイル: family.py プロジェクト: millejoh/pycells
 class C(cells.Model):
     model_value = cells.makecell(rule=lambda s, p: s.x * 10)
コード例 #13
0
	class TestDB(cellql.Database):
	    connection = cells.makecell(value="sqlite://" + TESTDB)
コード例 #14
0
ファイル: family.py プロジェクト: millejoh/pycells
 class A(cells.Model):
     model_name = cells.makecell(value=word)
コード例 #15
0
ファイル: family.py プロジェクト: millejoh/pycells
 class B(cells.Model):
     model_name = cells.makecell(value="Bee")
コード例 #16
0
ファイル: family.py プロジェクト: millejoh/pycells
class NamedAddressBook(cells.Family):
    name = cells.makecell(value="Anonymous")
    entries = cells.makecell(value={}, celltype=cells.DictCell)
    names = cells.makecell(rule=lambda s,p: s.entries.keys())
コード例 #17
0
ファイル: family.py プロジェクト: millejoh/pycells
 class F(cells.Family):
     kid_slots = cells.makecell(value=K)
コード例 #18
0
class WorkingAddressBook(AddressBook):
    entries = cells.makecell(value={}, celltype=cells.DictCell)
コード例 #19
0
ファイル: family.py プロジェクト: millejoh/pycells
class Family(Model):
    """
    Family
    
    A specialized C{L{Model}} which has C{kids}, C{kid_slots}, and a
    number of convenience functions for traversing the parent/child
    graph.

    @ivar kids: A list of Models which are guaranteed to have the
        attribute overrides defined in C{L{kid_slots}}

    @ivar kid_slots: An override definition for the Cells inserted
        into the C{L{kids}} list. The attributes overridden are every
        attribute defined in the class in C{kid_slots} minus the
        attributes defined in every Model.
    """
    kids = cells.makecell(celltype=ListCell, kid_overrides=False)
    kid_slots = cells.makecell(value=Model, kid_overrides=False)

    def __init__(self, *args, **kwargs):
        Model.__init__(self, *args, **kwargs)

    def _kid_instance(self, klass=None):
        """
        _kid_instance(self, klass) -> Cell
        
        Creates a new instance of a Cell based on the passed class (in
        C{klass}) and the overrides defined in C{kid_slots}.

        @param klass: The base type for the new kid instance
        """
        if not klass:
            klass = self.kid_slots
        _debug("making an instance of", str(klass))
        # first, find the attributes the kid_slots attrib actual wants to
        # define:
        override_attrnames = []
        for attrname in dir(self.kid_slots):
            cvar = getattr(self.kid_slots, attrname)
            # if it's a cell attribute, check to see if it's one of
            # the "special", non-overriding slots (eg kids)
            if isinstance(cvar, CellAttr):
                if cvar.kid_overrides:
                    # and if it isn't, add it to the list of overrides
                    override_attrnames.append(attrname)
            # if it's a normal attribute, override only if it doesn't
            # exist in the base class
            else:
                if attrname not in dir(cells.Family):
                    override_attrnames.append(attrname)

        # now, do the overrides, bypassing normal getattrs
        for attrib_name in override_attrnames:
            _debug("overriding", attrib_name, "in", str(klass))
            setattr(klass, attrib_name, self.kid_slots.__dict__[attrib_name])

        # add any observers the kid_slots class defines:
        klass._observernames.update(self.kid_slots._observernames)

        # XXX: should we memoize all that work here?

        # finally, return an instance of that munged class with this obj set
        # as its parent:
        i = klass(parent=self)
        return i

    def make_kid(self, klass):
        """
        make_kid(self, klass) -> None

        Adds a new instance of a Cell based on the passed class (in
        C{klass}) and the overrides defined in C{kid_slots} into the
        C{kids} list

        @param klass: the base type for the new kid instance
        """
        _debug("make_kid called with", str(klass))
        self._add_kid(self._kid_instance(klass))

    def _add_kid(self, kid):
        """
        _add_kid(self, kid) -> None

        Inserts the kid into this Family's C{kids} list

        @param kid: the Model instance to insert
        """
        kid.parent = self
        self.kids.append(kid)

    def position(self):
        """
        position(self) -> int

        Returns this instance's position in the enclosing Family's
        C{kids} list. Returns -1 if there is no enclosing Family.

        @raise FamilyTraversalError: Raises if there is no enclosing Family
        """
        if self.parent:
            return self.parent.kids.index(self)
        raise FamilyTraversalError("No enclosing Family")

    def previous_sib(self):
        """
        previous_sib(self) -> Model

        Returns the Model previous to this Model in the enclosing
        Family's C{kids} list

        @raise FamilyTraversalError: Raises if there is no enclosing Family
        """
        if self.parent and self.position() > 0:
            return self.parent.kids[self.position() - 1]
        raise FamilyTraversalError("No enclosing Family")

    def next_sib(self):
        """
        previous_sib(self) -> Model

        Returns the Model subsequent to this Model in the enclosing
        Family's C{kids} list

        @raise FamilyTraversalError: Raises if there is no enclosing Family
        """
        if self.parent and self.position() < len(self.parent.kids) - 1:
            return self.parent.kids[self.position() + 1]
        raise FamilyTraversalError("No enclosing Family")

    def grandparent(self):
        """
        grandparent(self) -> Model

        Returns enclosing Family instance's enclosing Family instance,
        or None if no such object exists.
        """
        # raise or just return None?
        if self.parent:
            if self.parent.parent:
                return self.parent.parent
        return None
コード例 #20
0
 class M(cells.Model):
     x = cells.makecell(value=3)
     a = cells.makecell(rule=a_rule, celltype=cells.AlwaysLazyCell)
コード例 #21
0
 class MyModel(cells.Model):
     x = cells.makecell(value=5)
     a = cells.makecell(rule=lambda s, p: int(s.x) + s.offset)
     offset = 2
コード例 #22
0
class Database(cells.Family):
    """Class for interaction with a database.

    (Short example of init usage here)
    """
    # Public Non-Cells
    supported_rdbms = ("sqlite", )

    addtable = cells.Family.make_kid

    def __del__(self):
        self._rawcon.close()

    # Public Cells
    connection = cells.makecell(value="")

    @cells.fun2cell()
    def tables(self, prev):
        d = {}
        for kid in self.kids:
            d[kid.name] = kid

        return d

    @cells.fun2cell()
    def connected(self, prev):
        if self._rawcon:
            return True
        else:
            return False

    # Private Cells
    @cells.fun2cell()
    def _contuple(self, prev):
        """ The RDBMS and connection strings. """
        try:
            rdbms, constring = self.connection.split("://", 1)
            if rdbms not in self.supported_rdbms:
                raise UnsupportedRDBMSError(
                    "Only the following RDBMSs are supported:",
                    ",".join(self.supported_rdbms))
            return (rdbms, constring)
        except ValueError:
            return (None, None)

    @cells.fun2cell()
    def _rdbmsmodule(self, prev):
        """ The appropriate RDBMS module. """
        if not self._contuple[0]:
            return None
        if self._contuple[0] == "sqlite":
            from pysqlite2 import dbapi2 as sqlite
            return sqlite

    @cells.fun2cell()
    def _rawcon(self, prev):
        """ The "raw" connection to the database """
        if self._rdbmsmodule:
            return self._rdbmsmodule.connect(self._contuple[1])
        else:
            return None
コード例 #23
0
class Table(cells.Family):
    def __init__(self, *args, **kwargs):
        cells.Family.__init__(self, *args, **kwargs)

        self.rows.db = self.parent
        self.rows.table = self

        # build column list
        for attr in self.__dict__.keys():
            val = getattr(self, attr)
            if isinstance(val, (Column, PrimaryKey)):
                val.name = attr
                val.table = self
                self.columns.append(val)

        self.ready = True

        _debug(self.name, "has columns", list(self.columns))

    # TODO: Make the primary key not-hardcoded:
    pk = primary_key()
    columns = cells.makecell(celltype=cells.ListCell)
    ready = cells.makecell(value=False)
    rows = cells.makecell(celltype=RowList)
    inserted = cells.makecell(value=False)

    @cells.fun2cell(celltype=cells.RuleThenInputCell)
    def name(self, prev):
        return self.__class__.__name__

    # Sometimes a Table object acts like a Table, and so we need a
    # "create table" string to feed to the RDBMS
    @cells.fun2cell()
    def create_table_string(self, prev):
        colnames = [column.create_column_string for column in self.columns]
        if colnames:
            return "CREATE TABLE " + self.name + \
         "(" + ",\n".join(colnames) + ")"
        else:
            return ""

    # Other times the Table object acts like a row in a table, so we
    # need an "insert into" string to feed to the RDBMS when this row
    # is created
    @cells.fun2cell()
    def insert_string(self, prev):
        return " ".join(
            ("INSERT INTO", self.name, "(",
             ",".join([_.name for _ in self.columns]), ") VALUES (",
             ",".join(['?'] * len(self.columns)), ")"))

    # we'll also need a list of values for the rdbms to use with the
    # insert string
    @cells.fun2cell()
    def insert_values(self, prev):
        return [_.sql_value for _ in self.columns]

    # We'll also need an update string when objects change
    @cells.fun2cell()
    def update_string(self, prev):
        return " ".join(("UPDATE", self.name, "SET",
                         ", ".join([_.name + "=?" for _ in self.columns
                                    ]), "WHERE pk=" + str(self.pk.sql_value)))
コード例 #24
0
 class N(self.M):
     # modify an attribute the observers are looking for
     a = cells.makecell(rule=lambda s, p: int(s.x) * s.offset)
コード例 #25
0
class AddressBook(cells.Model):
    entries = cells.makecell(value={})
    names = cells.makecell(rule=lambda s, p: s.entries.keys())
コード例 #26
0
class PrimaryKey(Integer):
    name = cells.makecell(value="pk")

    @cells.fun2cell()
    def create_column_string(self, prev):
        return self.name + " INTEGER PRIMARY KEY"
コード例 #27
0
ファイル: model.py プロジェクト: millejoh/pycells
class Model(object, metaclass=ModelMetatype):
    """
    A class in which CellAttrs may be used. Models automatically bring
    their cells up-to-date at C{L{__init__}}-time. Cells may be
    altered at runtime by passing C{attrname=value}, or
    C{attrname=hash} to the constructor.

    @ivar model_name: A cell holding The name of this Model. By
        default, None.

    @ivar model_value: A cell holding the value of this Model. By
        default, None.

    @ivar parent: A cell for C{L{Family}} graph traversal. By default,
        None.
    """

    _initialized = False

    model_name = cells.makecell(value=None, kid_overrides=False)
    model_value = cells.makecell(value=None, kid_overrides=False)
    parent = cells.makecell(value=None, kid_overrides=False)

    def __init__(self, *args, **kwargs):
        """
        __init__(self, [<attrname>=<value, rule or dict>], ...) -> None

        Initialize a Model with optional overrides. By passing a
        parameter with the same name as a cell attribute, you may
        override that cell attribute. For example:

            >>> class A(cells.Model):
            ...     x = cells.makecell(value=1)
            ... 
            >>> a1 = A()
            >>> a1.x
            1
            >>> a2 = A(x="blah")
            >>> a2.x
            'blah'

        This override can be arbitrarily complex; for instance, you
        can make a RuleCell into a ValueCell, change a attribute's
        celltype ... In short, anything you can do at Model defintion
        time you can alter at instantiation time:

            >>> class B(cells.Model):
            ...     x = cells.makecell(rule=lambda s,p: 3 * s.y)
            ...     y = cells.makecell(value=2)
            ... 
            >>> b = B()
            >>> b.x
            6
            >>> b.y = 1
            >>> b.x
            3
            >>> b = B(y=10)
            >>> b.x
            30
            >>> b.y
            10
            >>> b = B(x={'celltype': cells.RuleThenInputCell})
            >>> b.x
            6
            >>> b.y
            2
            >>> b.x = 5
            >>> b.x
            5
            >>> b.y = 1
            >>> b.x
            5

        @param attrname: The name of the attribute you wish to
            override. If this is set to a callable, it will override
            the rule for the cell. If it's set to a dictionary with
            one or more of 'rule', 'value', or 'celltype', those
            attributes will be overridden in the cell. Otherwise, it
            will override the value of the target cell.
        """
        self._initregistry = {}
        klass = self.__class__

        # do automagic overriding:
        for k, v in kwargs.items():  # for each keyword arg
            if k in dir(klass):  # if there's a match in my class
                # normalize the input
                if isinstance(v, collections.Callable):
                    cellinit = {'rule': v}
                elif 'keys' in dir(v):
                    # kinda ran out of synonyms/shortened versions of
                    # keys, here. I just want to see if any of 'rule',
                    # 'value', or 'celltype' are in the keys of the
                    # dict in v:
                    quays = list(v.keys())
                    for qui in ('rule', 'value', 'celltype'):
                        if qui in quays:
                            cellinit = v
                            break
                else:
                    cellinit = {'value': v}

                if not cellinit:
                    raise BadInitError(
                        "A cell initialization dictionary was not built. Try wrapping your value or rule assignment in a dictionary.")

                # set the new init in the registry for this cell name; to be
                # read at cell-build time
                self._initregistry[k] = cellinit

        # turn the observer name registry into a list of real Observers
        self._observers = []
        for name in self._observernames:
            self._observers.append(getattr(self, name))
        self._prioritize_observers()

        # do initial equalizations
        debug("INITIAL EQUALIZATIONS START")
        for name in dir(self):
            try:
                # if it's not been otherwise initialized
                debug("examining", name)
                if name not in self.__dict__:
                    debug(name, "is already in this object")
                    # grab the cell attr and figure out if it's an always-lazy
                    cellattr = getattr(self.__class__, name)
                    if isinstance(cellattr, cells.CellAttr):
                        kwargs = cellattr.getkwargs(self)
                        debug(name, "is a cellattr with kwargs", repr(kwargs))
                        # if it isn't an always-lazy
                        if issubclass(kwargs.get('celltype', object),
                                      cells.AlwaysLazyCell):
                            debug(name, "should be init'd")
                            # get it, initializing it
                            getattr(self, name)  # will run observers by itself
                        else:
                            debug(name, "is an always-lazy")
            except EphemeralCellUnboundError as e:
                debug(name, "was an unbound ephemeral")
        debug("INITIAL EQUALIZATIONS END")

        # run observers on non-cell attributes
        for key in self._noncells:
            self._run_observers(getattr(self, key))

        # and now we're initialized. lock the object down.
        self._initialized = True

    def __setattr__(self, key, value):
        """
	Per KT's spec, Models may not set non-cell attributes after
	__init__.

	@raise NonCellSetError: If you try to set a non-cell attribute
	"""
        # always set Cells
        if isinstance(self.__dict__.get(key), Cell):
            object.__setattr__(self, key, value)
        # we can set noncells before init
        elif not self._initialized:
            if key not in self._noncells:  # make sure it's registered, though
                self._noncells.add(key)
            object.__setattr__(self, key, value)  # and then set it
        # we can set anything we've not seen, too
        elif key not in list(self.__dict__.keys()):
            object.__setattr__(self, key, value)
        # but the only thing left is non-cells we've seen, which is verboten
        else:
            raise NonCellSetError("Setting non-cell attributes of models " + \
                                  "after init is disallowed")

    def _run_observers(self, attribute):
        """Runs each observer in turn. There's some optimization that
        could go on here, if it turns out to be neccessary.
        """
        debug("model running observers -- ", str(len(self._observers)),
              "to test")
        for observer in self._observers:
            observer.run_if_applicable(self, attribute)

    def _buildcell(self, name, *args, **kwargs):
        """
        
        """
        debug("Building cell: owner:", str(self))
        debug("                name:", name)
        debug("                args:", str(args))
        debug("              kwargs:", str(kwargs))
        # figure out what type the user wants:
        if 'celltype' in kwargs:
            celltype = kwargs["celltype"]
        elif 'rule' in kwargs:  # it's a rule-cell.
            celltype = cells.RuleCell
        elif 'value' in kwargs:  # it's a value-cell
            celltype = cells.InputCell
        else:
            raise Exception("Could not determine target type for cell " +
                            "given owner: " + str(self) +
                            ", name: " + name +
                            ", args:" + str(args) +
                            ", kwargs:" + str(kwargs))

        kwargs['name'] = name
        return celltype(self, *args, **kwargs)

    def _prioritize_observers(self):
        """
	_prioritize_observers(self) -> none

	(re)Sorts the observer list by priorities
	"""
        self._observers.sort(key=lambda x: x.priority,
                             reverse=True)

    @classmethod
    def observer(klass, attrib=None, oldvalue=None, newvalue=None,
                 priority=None):
        """
        observer(attrib=None, oldvalue=None, newvalue=None, priority=Non) -> decorator

        A classmethod to add an observer attribute to a Model. The
        observer may be set to fire on any change in the model, any
        change in an attribute, or when a function testing the new or
        old value of a cell returns true.

	    >>> import cells
	    >>> class A(cells.Model):
	    ...     x = cells.makecell(value=4)
	    ... 
	    >>> @A.observer(attrib="x", newvalue=lambda a: a % 2)
	    ... def odd_x_obs(model):
	    ...     print "New value of x is odd!"
	    ... 
	    >>> a = A()
	    >>> a.x
	    4
	    >>> a.x = 5
	    New value of x is odd!
	    >>> a.x = 42
	    >>> a.x = 11
	    New value of x is odd!

        @param attrib: An attribute name to attach the observer to

        @param oldvalue: A function to run on the now-out-of-date
            value of a cell which changed in this datapulse; if the
            function returns True, the observer will fire. The
            signature for the function must be C{f(val) -> bool}

        @param newvalue: A function to run on up-to-date value; if the
            function returns True, the observer will fire. The
            signature for the function must be C{f(val) -> bool}

        @param priority: When this observer should be run compared to
            the other observers on this model. Observers have a
            priority of None by default. Observers with larger
            priorities are run first, None last. Observers with the
            same priority are run in arbitrary order.

        """

        def observer_decorator(func):
            klass._observernames.add(func.__name__)
            setattr(klass, func.__name__, ObserverAttr(func.__name__, attrib,
                                                       oldvalue, newvalue,
                                                       func))

        return observer_decorator
コード例 #28
0
ファイル: family.py プロジェクト: millejoh/pycells
 class K(cells.Family):
     x = cells.makecell(value=1)
     model_value = cells.makecell(rule=lambda s, p: s.x * 3)
コード例 #29
0
class Page(cells.Model):
    """A number of representations of a given resource (eg, '/foo')"""
    def __init__(self, cache, *args, **kwargs):
        self.cache = cache
        self.config = CellCMSConfig
        cells.Model.__init__(self, *args, **kwargs)

    special = re.compile(r"/__.*__")
    cleanpath = re.compile(r"(/([A-Za-z0-9]+\.)*([A-Za-z0-9]*))*(\?.*)?")

    # INPUT CELLS
    request = cells.makecell(value=None)
    modified = cells.makecell(value=0)
    built = cells.makecell(value=0)

    # RULE CELLS
    @cells.fun2cell()
    def dirty_path(self, prev):
        """The not-cleaned path from self.request"""
        if not self.request:
            return "/"
        return self.request.path

    @cells.fun2cell()
    def cleaned_path(self, prev):
        """A safe path which may be used for reading/writing to"""
        if not self.cleanpath.match(self.dirty_path):
            print "Illegal path request:", self.dirty_path
            return "/"
        return self.dirty_path

    @cells.fun2cell()
    def dynamic_path(self, prev):
        """The location, on-disk, of the requested resource if it's dynamic"""
        return (self.config.get('directories', 'storage') + self.cleaned_path)

    @cells.fun2cell()
    def static_path(self, prev):
        """The location, on-disk, of the requested resource if it's static"""
        return (self.config.get('directories', 'static') + self.cleaned_path)

    # these just figure out if the request is for a dynamic or static
    # resource
    is_dynamic = cells.makecell(rule=lambda s, p: glob.glob(s.dynamic_path))
    is_static = cells.makecell(rule=lambda s, p: glob.glob(s.static_path))

    @cells.fun2cell()
    def is_directory(self, prev):
        """Is the request for a directory?"""
        return os.path.isdir(self.static_path)

    @cells.fun2cell()
    def is_special(self, prev):
        """Is the request for a 'special' resource (eg, '__foo__')"""
        return self.special.match(self.cleaned_path)

    @cells.fun2cell()
    def is_valid(self, prev):
        """Is the resource available on-disk?"""
        return self.is_dynamic or self.is_static

    @cells.fun2cell()
    def raw_source(self, prev):
        """Holds the unrendered source data for this Page"""
        if not self.is_valid:
            return "Resource not found. You can edit it below."

        # all we need to do is depend on self.modified and the source
        # will be updated whenever the modification-time is
        # changed. I'm pretty sure this test will always fail.
        if self.modified < self.built:
            return prev

        if self.is_directory:  # implies is_static
            currdir = os.getcwd()  # save old dir
            os.chdir(self.static_path)  # change to the requested dir
            out = ["Directory listing:", "------------------------------"]
            out += glob.glob("*")  # get the files here
            os.chdir(currdir)  # change back to the original dir
            return "\n".join(out)

        if self.is_static:  # because of above test, not a dir.
            return open(self.static_path).read()

        if self.is_dynamic:
            return (open(self.dynamic_path).read())

        else:
            return "Should not have got here!"

    @cells.fun2cell()
    def source(self, prev):
        """Holds the rendered, untemplatized version of this Page"""
        if self.is_dynamic:
            return markdown.markdown(self.raw_source)
        else:
            return self.raw_source

    @cells.fun2cell()
    def template_file(self, prev):
        """Determines which template to apply to this Page depending
        on request type"""
        if self.is_special:
            return "templates/just_edit.tmpl"
        if self.is_directory:
            return "templates/directory.tmpl"
        if self.is_static:
            return "templates/static.tmpl"
        else:
            return "templates/full.tmpl"

    @cells.fun2cell()
    def templatized(self, prev):
        """Holds the rendered, templatized version of this Page"""
        if self.is_dynamic or self.is_directory or not self.is_valid:
            return Template(cache=self.cache,
                            page=self,
                            template=self.template_file).render()
        else:
            return self.raw_source
コード例 #30
0
ファイル: family.py プロジェクト: millejoh/pycells
 class SomeContainer(cells.Family):
     entries = cells.makecell(value=[], celltype=cells.ListCell)
     size = cells.makecell(rule=lambda s,p: len(s.entries))