Exemple #1
0
 class X(BlackBox):
     def get_a(self): return 1
     get_b = lambda self: 2
     c = attr(int)
     d = attr(int)
     e = attr(int, default=5)
     def set_c(self, value): self.d = 4
     def set_e(self, value): pass
Exemple #2
0
class User(Strongbox):

    ID = attr(long, default=None)
    uid = attr(str)
    username = attr(str)
    email = attr(str)
    password = attr(str)

    def __init__(self, **init):
        super(User, self).__init__(**init)
        if not self.uid: self.uid = handy.uid()
Exemple #3
0
class Item(Strongbox):
    """
    A line item inside a Transaction.
    """
    account = attr(str)
    amount = attr(Decimal)
    implied = attr(bool, default=False)
    state = attr(str, okay=[CLEARED, PENDING, DEFAULT])
    charPos = attr(int, default=0)

    def clone(self):
        return Item(account=self.account, amount=Decimal(self.amount))
Exemple #4
0
class Cyclic(Strongbox):
    """
    Mixin class for cyclic behavior.
    By default, this uses a monthly cycle.

    Classes that use this should assign nextDue
    in their constructors.
    """
    __ver__ = "$Id: Cyclic.py,v 1.15 2007/03/30 00:29:18 sabren Exp $"

    nextDue = attr(Date)
    cycLen = attr(str, okay=["month", "year"], default="month")

    def get_cycle(self):
        if self.cycLen == "year":
            return YearlyCycle(self)
        else:
            return MonthlyCycle(self)

    def calcNextDue(self):
        """
        Returns one month after current due date.
        """
        return self.get_cycle().nextDue()

    def isDue(self):
        # note that we use duckbill.TODAY rather than TODAY
        # so we can test more easily.
        # @TODO: this really ought to call a function,
        # even for testing... (???)
        return (self.nextDue is not None) \
               and (self.nextDue <= duckbill.TODAY)

    def catchup(self):
        wasDue = 0
        while self.isDue():
            wasDue = 1
            self.onDue()
            self.nextDue = self.calcNextDue()
        self.onCatchup(wasDue)

    ## events #################################################

    def onDue(self):
        pass

    def onCatchup(self, wasDue):
        pass
Exemple #5
0
class Node(Strongbox):
    ID = attr(long)
    name = attr(str)
    path = attr(str)
    data = attr(str)
    parent = link(lambda: Node)
    children = linkset((lambda: sixthday.Node), "parent")

    def __init__(self, **kwargs):
        super(Node, self).__init__()
        self.private.named = False
        self.update(**kwargs)

##     def set_path(self, value):
##         # only allow setting once
##         if self.private.path:
##             raise AttributeError, "Node.path is read only"

    def get_crumbs(self):
        res = []
        node = self
        while node.parent:
            node = node.parent
            res.append(node)
        res.reverse()  # crumbs go top-down, but we went bottom-up :)
        return res


##     def set_parent(self, value):
##         assert value is not self, \
##                "A node can't be its own parent!"

    def set_name(self, value):
        self.private.name = str(value)
        # this .private.named thing prevents a max
        # bug of some kind. It probably needs a
        # closer look.
        if self.private.named:
            self._updatePath(self.crumbs)
        self.private.named = True

    def _updatePath(self, crumbs):
        path = crumbs + [self]
        self.path = "/".join([n.name for n in path])
        for kid in self.children:
            kid._updatePath(path)
Exemple #6
0
class Card(Strongbox):
    expMonth = attr(int)
    expYear = attr(int)
    number = attr(str)

    def getEditableAttrs(self):
        return super(Card, self).getEditableAttrs() + ["masked", "issuer"]

    def _new(self):
        super(Card, self)._new()
        nowYear, nowMonth = time.localtime(time.time())[0:2]
        self.expYear = nowYear
        self.expMonth = nowMonth
        self.customerID = 0

    def get_issuer(self):
        return issuer(self.number)

    def get_masked(self):
        return ("x" * (len(self.number) - 4)) + self.number[-4:]

    def checkdigits(self, digits):
        return validate(digits)

    def isExpired(self):
        import time
        # @TODO: does a card expire on the first or last of expiration month?
        nowYear, nowMonth = time.localtime(time.time())[0:2]
        return (nowYear, nowMonth) > (self.expYear, self.expMonth)

    def set_number(self, value):
        # Strip dashes and spaces..
        # I'm leaving letters and other characters in
        # so that they generate an error.
        num = ""
        for ch in str(value):
            if ch not in "- ":
                num = num + ch

        # validate the card:
        if (issuer(num) != "unknown") and checkLength(issuer(num), len(num)) \
           and self.checkdigits(num):
            self.__values__['number'] = num
        else:
            raise ValueError, "Invalid credit card number."
Exemple #7
0
    def test_simple(self):

        Person = MetaBox("Person", (), {"name": attr(str, okay=["fred", "wanda"], default="fred")})

        assert type(Person) == MetaBox
        assert isinstance(Person.name, attr)
        assert Person.name.okay == ["fred", "wanda"]
        assert Person.name.__name__ == "name"
        assert Person.name.__owner__ == Person
Exemple #8
0
class Right(zdc.RecordObject):
    """
    Another test class for use with Junction.
    """
    __super = zdc.RecordObject
    _tablename = "test_right"
    ID = attr(long)

    def _new(self):
        self._super._new(self)
        self.name = ""
Exemple #9
0
    def test_simple(self):

        Person = MetaBox(
            "Person", (), {
                "name": attr(str, okay=['fred', 'wanda'], default="fred"),
            })

        assert type(Person) == MetaBox
        assert isinstance(Person.name, attr)
        assert Person.name.okay == ['fred', 'wanda']
        assert Person.name.__name__ == "name"
        assert Person.name.__owner__ == Person
Exemple #10
0
 class Foo(BlackBox):
     m_str = attr(str)
     m_int = attr(int)
     m_long = attr(float)
     m_float = attr(float)
     n_int = attr(int, default=None)
     n_str = attr(str, default=None)
Exemple #11
0
 class MockCyclic(duckbill.Cyclic):
     nextDue = attr(Date) # @TODO: strongbox should support inheritance!
     def __init__(self):
         super(MockCyclic, self).__init__()
         self.private.calls = {"onDue":0, "onCatchup":0}
         self.nextDue = YESTERDAY
     def calcNextDue(self):
         return self.nextDue + 1
     def onDue(self):
         self.private.calls["onDue"] += 1
     def onCatchup(self, wasDue):
         self.private.calls["onCatchup"] += 1
         self.private.wasDue = wasDue
Exemple #12
0
class Left(zdc.RecordObject):
    """
    A test class for a Junction.
    """
    __super = zdc.RecordObject
    _tablename = "test_left"
    ID = attr(long)

    def _new(self):
        self._super._new(self)
        self.name = ""

    #@TODO: is this really the best way to do this?
    def get_rights(self):
        if not self._data.has_key("rights"):
            self._data["rights"] = zdc.Junction(self, Left, "test_left_right",
                                                "leftID", "rightID")
            self._data["rights"].fetch()
        return self._data["rights"]
Exemple #13
0
 class Paint(BlackBox):
     color = attr(str, ["red", "green", "blue"])
Exemple #14
0
class Model(Strongbox):
    name = attr(str)
    age = attr(int, default=None)
    prefill = attr(str, default="example")
    limited = attr(str, okay=["a", "b", "c"], default="a")
Exemple #15
0
 class Subject(WhiteBox):
     name = attr(str)
Exemple #16
0
 class Dirt(WhiteBox):
     x = attr(str)
Exemple #17
0
 class SlotMachine(BlackBox):
     a = attr(int, default=1)
     b = attr(int, default=2)
     c = attr(int, default=3)
Exemple #18
0
 class Y(BlackBox):
     a = attr(int)
     b = attr(str)
     c = link(X)
     d = link(X)
Exemple #19
0
 class Foo(BlackBox):
     i = attr(int)
     s = attr(str)
     d = attr(Date)
Exemple #20
0
 class Dad(BlackBox):
     nose = attr(str, default="big")
Exemple #21
0
 class Foo(BlackBox):
     bar = attr(int, default=5)  
Exemple #22
0
class Node(Strongbox):
    ID = attr(long)
    data = attr(str)
    parent = link(forward)
    kids = linkset(forward, "parent")
Exemple #23
0
 class Foo(BlackBox):
     bar = attr(UpCase, default="xyz")
     abc = attr(str, default="xyz")
Exemple #24
0
class Child(Strongbox):
    mama = link(forward)
    name = attr(str)
Exemple #25
0
 class Foo(BlackBox):
     bar = attr(int, lambda x: 5 < x < 10)
Exemple #26
0
class Account(Cyclic):
    """
    An account contains Subscriptions and Events
    """
    __ver__ = "$Id: Account.py,v 1.37 2007/05/21 03:18:03 sabren Exp $"

    ID = attr(long)
    #@TODO: unhardcode the SEI-specific brand stuff (make Brand class instead)
    brand = attr(str,
                 default="cornerhost",
                 okay=["cornerhost", "versionhost", "dcd hosting"])
    fname = attr(unicode, default="")
    lname = attr(unicode, default="")
    email = attr(str, default="")
    email2 = attr(str, default="")
    phone = attr(str, default="")
    company = attr(unicode, default="")
    address1 = attr(unicode, default="")
    address2 = attr(unicode, default="")
    city = attr(unicode, default="")
    state = attr(unicode, default="")
    postal = attr(str, default="")
    countryCD = attr(str, default="")
    account = attr(str, default="")
    opened = attr(Date, default="today", allowNone=0)
    closed = attr(Date)
    cycLen = attr(str, okay=['month', 'year'], default='month')
    nextDue = attr(Date, default="today")
    autobill = attr(int, default=0, okay=[1, 0])
    cardinfo = attr(EncryptedCard, default="")
    lastfour = attr(str)
    statementStrategy = attr(str,
                             default="always",
                             okay=["always", "ifBalance"])
    status = attr(
        str,
        default='active',
        okay=['active', 'warned', 'locked', 'closed', 'comped', "lifer"])
    warned = attr(Date)

    subscriptions = linkset(Subscription, "account")
    events = linkset(Event, "account")

    # @TODO: making gracePeriod a link breaks FrontEndAppTest.test_closeAccount!!
    # For some reason, Clerk just doesn't handle 1-1 relations well. :(
    # perhaps because the column in the schema dict is "ID" and that causes
    # clerk to remove it from the data it sends to storage.store() ?
    # (it was triggering an insert instead of an update, but ONLY
    # after acc.close())
    gracePeriods = linkset(Grace, "account")

    def get_graced(self):
        return [g for g in self.gracePeriods if not g.hasExpired()]

    def grace(self, why, untilWhen):
        self.gracePeriods << Grace(reason=why, expires=untilWhen)

    def onCatchup(self, wasDue):
        """
        Send the statement via email and record the fact that we did so.
        """
        pass
        #if wasDue:
        #    self.sendCurrentStatement()
        #    #@TODO: "and record the fact that we did so"

    def sendCurrentStatement(self):
        sendmail(zebra.fetch("statement", self.currentStatement()))

    def currentStatement(self):
        return Statement(self, self.whenLastStatementPosted(), duckbill.NOW)

    def whenLastStatementPosted(self):
        """
        Return date of last statement, or date opened if no statement
        ever sent.
        """
        res = self.opened
        for e in self.events:
            if (e.event == "statement") and (e.posted > res):
                res = e.posted
        return res

    def balance(self, time=None):
        """
        Return account balance at given time, or now if no time given.
        """
        cutoff = time or duckbill.NOW
        bal = Decimal('0.0')
        for e in self.events:
            if e.posted < cutoff:
                bal += ((e.amount or 0) * e.sign)
        return bal

    def eventsBetween(self, start, end):
        """
        Uses the python style of inclusive start, exclusive end.
        """
        res = [e for e in self.events if start <= e.posted < end]
        res.sort()
        return tuple(res)

    def postCharges(self):
        """
        post charges for the account's subscriptions
        """
        for sub in self.subscriptions:
            sub.catchup()

    def aging(self):
        credit = 0
        charges = []

        def ischarge(x):
            return x > 0

        def iscredit(x):
            return x < 0

        for e in self.events:

            # whenever a new event is considered, we add
            # in any credit balance that might be there.
            amount = e.value + credit
            credit = 0

            # now apply this new merged value to the account:
            if ischarge(amount):
                charges.append(
                    Event(event="charge", amount=amount, posted=e.posted))
            else:
                cash = abs(amount)
                while cash > 0:
                    if charges:
                        # apply amount to latest charge
                        owed = abs(charges[-1].amount)

                        if cash >= owed:
                            charges.pop()
                            cash -= owed
                        else:
                            charges[-1].amount -= cash
                            cash = 0
                    else:
                        credit -= cash  # because credit is negative
                        cash = 0
        return charges

    def amountPastDue(self, dueDate="today"):
        """
        Given a dueDate, return the amount past due.
        This may be less than the total balance.
        """
        d = dueDate
        if not isinstance(d, Date):
            d = Date(dueDate)
        res = 0
        for e in self.aging():
            if e.posted < dueDate:
                res += e.value
        return res

    def unearnedIncome(self, cutoff):
        assert isinstance(cutoff, DateTime)
        sum = 0
        for e in self.events:
            if e.posted <= cutoff:
                sum += e.valueOn(cutoff)
        return -min(sum, 0)

    def close(self, why):
        self.status = "closed"
        self.closed = duckbill.TODAY
        for s in self.subscriptions:
            s.close()
        self.events << Event(event="close", note=why)
Exemple #27
0
 class UsCitizen(BlackBox):
     ssn = attr(str, r"\d{3}-?\d{2}-?\d{4}")
Exemple #28
0
class Fish(zdc.RecordObject):
    _tablename = "test_fish"
    ID = attr(long)
    fish = attr(str)
Exemple #29
0
 class Foo(BlackBox):
    bar = attr(int)
Exemple #30
0
class Record(Strongbox):
    ID = attr(long)
    val = attr(str)
    next = link(forward)
Exemple #31
0
 class Foo(BlackBox):
    bar = attr(int,allowNone=0)