Пример #1
0
# test with floats
print "\nSelection by float",
for i in range(10):
    x = random.uniform(-10**random.randint(-307,307),
            10**random.randint(-307,307))
    r1 = [ r for r in db if r.afloat > x ]
    r2 = db.select(['name'],'afloat > v',v=x)
    print len(r1)==len(r2)

houses = Base('houses')

try:
    houses.create(('address',str),('resident',db))
except IOError:
    houses.destroy()
    houses.create(('address',str),('resident',db))

addresses = ['Giono','Proust','Mauriac','Gide','Bernanos','Racine',
    'La Fontaine']
ks = db.keys()
for i in range(50):
    x = random.choice(ks)
    print x,
    houses.insert(address=random.choice(addresses),resident=db[x])
print
print houses[0]
print houses[0].resident.name

print '\nhouses with jean'
for h in houses:
Пример #2
0
class TransactionsDB(object):

    BASE = 'banan/transactions'

    def __init__(self, conf):
        self.config = conf
        self._sessions = {}
        self.open()

    # Management
    def open(self):
        self.db = Base(TransactionsDB.BASE)
        try:
            self.db.open()
        except IOError:
            self.db.create(('amount'      , float), 
                           ('amount_local', float),
                           ('date'        , date),
                           ('account'     , str),
                           ('label'       , str),
                           ('currency'    , str))

    def close(self):
        self.db.close()
            
    def clearall(self):
        self.db.destroy()
        self.open()
        
    def insert(self, entry):
        self.db.insert(amount       = entry['amount'],
                       amount_local = entry['amount_local'],
                       date         = entry['date'],
                       account      = entry['account'],
                       label        = entry['label'],
                       currency     = entry['currency'])

    def feed(self, fpath, parser, skip_duplicates=True, overwrite=False, delete=False, dry_run=False):

        deleted = added = 0
        for entry in parser.parse(fpath):
            if dry_run:
                print('%s %-40s\t%12.2f %s' % (entry['date'].isoformat(),
                                               entry['account'][:40],
                                               entry['amount'], 
                                               entry['currency'])); continue

            if skip_duplicates or overwrite or delete:
                _dup = self.db(date=entry['date'], account=entry['account'], amount=entry['amount'])
                if _dup:
                    if overwrite or delete:
                        deleted += len(_dup)
                        self.db.delete(_dup)
                    else:
                        continue
                if delete:
                    continue

            entry['label'] = self.config.assign_label(entry)
            self.insert(entry)
            added += 1
        
        if not dry_run:
            INFO('  added %i transactions' % added)
            INFO('  deleted %i transactions' % deleted)
            parser.post_process(self.db, added)

    def update_labels(self):
        
        # Load all records into memory. File will get corrupt if using the iterator.
        records = [rec for rec in self.db]
        for record in records:
            as_dict = dict((field, getattr(record, field)) for field in record.fields)
            label = self.config.assign_label(as_dict)
            if label != record.label:
                self.db.update(record, label=label)

        self.db.cleanup()


    # Queries
    get_amount = lambda rec: rec.amount_local    

    def results_as_text(self, results):

        results.sort_by('date')
        idx = 0
        record = results[idx]
        text_list = []
        while True:
            text_list.append('%s   %-40s\t%12.2f %s' %
                             (record.date.isoformat(), 
                              unicode(record.account[:40], 'utf-8'),
                              record.amount,
                              record.currency)); 
            try:
                idx += 1
                record = results[idx]
            except IndexError:
                return text_list

    
    def assemble_data(self, sid, datatype, foreach, show, select):

        try:

            session = self._sessions.get(sid, {})
            if session:
                if session['raw_query'] == (foreach, show, select):
                    # Same query, return cached result
                    return True, \
                        self._sessions[sid]['flot_' + show] if datatype == 'plot' else \
                        self._sessions[sid]['text']

            # Helpers
            get_amount = lambda rec: rec.amount_local
            M = range(1,13)
            total = strlen = 0

            data = {}
            text = {}
            query = 'date1 <= date < date2 and label == l'

            if foreach == 'label':
                
                if session:
                    if session['raw_query'][0] == 'label' and session['raw_query'][2] == select:
                        # Same query, but different presentation (sum or average)
                        return True, \
                            self._sessions[sid]['flot_' + show] if datatype == 'plot' else \
                            self._sessions[sid]['text']

                # New query
                dates = re.findall('[0-9]{6}', unquote_plus(select))
                date1 = date2 = date(int(dates[0][2:]), int(dates[0][:2]), 1)
                if len(dates) == 2:
                    date2 = date(int(dates[1][2:]), int(dates[1][:2]), 1)
                date2 = date(date2.year + (date2.month == 12), M[date2.month - 12], 1)

                for label in self.config.labels.iterkeys():

                    results = self.db.select(None, query, l = label, date1 = date1, date2 = date2)
                    value = sum(map(get_amount, results))

                    if abs(value) > 1:
                        data[label] = value

                        if label not in self.config.cash_flow_ignore:
                            total += value
                        else:
                            label += '*'

                        text[label] = self.results_as_text(results)
                        strlen = len(text[label][-1])
                        sumstr = '%12.2f %s' % (value, self.config.local_currency)
                        text[label].append('-' * strlen)
                        text[label].append(' ' * (strlen - len(sumstr)) + sumstr)

                ydelta = date2.year - date1.year
                mdelta = date2.month - date1.month
                delta = 12 * ydelta + mdelta

                session['flot_average'] = {}
                for key, val in data.iteritems():
                    session['flot_average'][key] = val/delta


            elif foreach in ('month', 'year'):
                
                # New query
                date1 = date2 = first = datetime.now()
                if foreach == 'month':
                    first = date(date1.year - 1, date1.month, 1)
                    date1 = date(date1.year - (date1.month == 1), M[date1.month - 2], 1)
                    date2 = date(date2.year, date2.month, 1)
                else:
                    first = date(date1.year - 9, 1, 1)
                    date1 = date(date1.year, 1, 1)
                    date2 = date(date2.year + 1, 1, 1)

                select = unquote_plus(select)

                while date1 >= first:

                    results = self.db.select(None, query, l = select, date1 = date1, date2 = date2)
                    value = sum(map(get_amount, results))

                    date2 = date1 
                    if foreach == 'month':
                        key = date1.strftime('%Y.%m') 
                        date1 = date(date2.year - (date2.month == 1), M[date2.month - 2], 1)
                    else:
                        key = str(date1.year)
                        date1 = date(date2.year - 1, 1, 1)

                    data[key] = value
                    total += value
                    if results:
                        text[key] = self.results_as_text(results)
                        strlen = len(text[key][-1])
                        sumstr = '%12.2f %s' % (value, self.config.local_currency)
                        text[key].append('-' * strlen)
                        text[key].append(' ' * (strlen - len(sumstr)) + sumstr)


            # All good, set new session attributes
            session['raw_query'] = (foreach, show, select)
            session['flot_sum'] = data
            session['text'] = text

            if session['text']:
                session['text']['***'] = ['-' * strlen,
                                          'SUM: %12.2f %s' % (total, self.config.local_currency),
                                          '-' * strlen]

            self._sessions[sid] = session
            return True, session['flot_' + show] if datatype == 'plot' else session['text']

        except Exception as e:
            return False, str(e)
Пример #3
0
# test with floats
print "\nSelection by float",
for i in range(10):
    x = random.uniform(-10**random.randint(-307, 307),
                       10**random.randint(-307, 307))
    r1 = [r for r in db if r.afloat > x]
    r2 = db.select(['name'], 'afloat > v', v=x)
    print len(r1) == len(r2)

houses = Base('houses')

try:
    houses.create(('address', str), ('resident', db))
except IOError:
    houses.destroy()
    houses.create(('address', str), ('resident', db))

addresses = [
    'Giono', 'Proust', 'Mauriac', 'Gide', 'Bernanos', 'Racine', 'La Fontaine'
]
ks = db.keys()
for i in range(50):
    x = random.choice(ks)
    print x,
    houses.insert(address=random.choice(addresses), resident=db[x])
print
print houses[0]
print houses[0].resident.name

print '\nhouses with jean'