예제 #1
0
파일: reader.py 프로젝트: dingens/settle
def store_payment(payment, filename=None):
    """
    Store the Payment to disk as a new file.

    If no filename is given, generate a random one.

    N.B: This is not race condition safe for python < 3.3.
    """
    if filename is not None:
        path = payment.group.path('payments', filename)
        if os.path.exists(path):
            raise ValueError('File already exists: %r' % path)

    while filename is None:
        filename = generate_random_filename(
            format_datetime(payment.date, date_only=True),
            payment.giver)
        debug(filename)
        path = payment.group.path('payments', filename)

        if os.path.exists(path):
            filename = None

    mode = 'w' if sys.version_info < (3,3) else 'x'

    with open(path, mode, encoding=FILE_CHARSET) as f:
        write(f, payment.serialize())
예제 #2
0
    def run(self, args):
        args = args[:]
        if len(args) == 0:
            print('Error: No command given\nAvailable commands:',
                  file=sys.stderr)
            for c in self.funcdict:
                print('  %s' % c, file=sys.stderr)
            return

        if args[0] == 'init':
            # special case because we don't pass a group here
            self.do_init(args[1:])
            return

        if args[0] in self.funcdict:
            args.insert(0, 'DEFAULTREPO')  #TODO

        if len(args) <= 1:
            print('Error: No command given\nAvailable commands:',
                  file=sys.stderr)
            for c in self.funcdict:
                print('  %s' % c, file=sys.stderr)
            return

        group = Group.load(args[0])
        cmd = args[1]
        rest = args[2:]

        try:
            f = self.funcdict[cmd]
        except KeyError:
            print('no such command: %s' % cmd, file=sys.stderr)
        else:
            debug('running %s(%s) with %r' % (cmd, rest, group))
            f(group, rest)
예제 #3
0
    def _calculate_balances(self):
        from settle import MAX_LIST_RESOLVER_RECURSION_DEPTH

        self.balances = []
        raw_balances, self.amount = self.receivers.apply(
            self.amount, self.currency)

        i = MAX_LIST_RESOLVER_RECURSION_DEPTH
        while raw_balances:
            new_raw_balances = []

            debug('raw: %r' % raw_balances)
            for name, val in raw_balances:
                if is_list(name):
                    bal, _amount = self.group.lists[name[1:]].apply(-val)
                    new_raw_balances.extend(bal)
                else:
                    self.balances.append((name, val))
            raw_balances = new_raw_balances
            i -= 1

            if i <= 0:
                raise RuntimeError(
                    'Maximum list resolver recursion depth reached. Maybe there is a loop?'
                )

        self.balances.append((self.giver, Money(+self.amount, self.currency)))
예제 #4
0
def store_payment(payment, filename=None):
    """
    Store the Payment to disk as a new file.

    If no filename is given, generate a random one.

    N.B: This is not race condition safe for python < 3.3.
    """
    if filename is not None:
        path = payment.group.path('payments', filename)
        if os.path.exists(path):
            raise ValueError('File already exists: %r' % path)

    while filename is None:
        filename = generate_random_filename(
            format_datetime(payment.date, date_only=True), payment.giver)
        debug(filename)
        path = payment.group.path('payments', filename)

        if os.path.exists(path):
            filename = None

    mode = 'w' if sys.version_info < (3, 3) else 'x'

    with open(path, mode, encoding=FILE_CHARSET) as f:
        write(f, payment.serialize())
예제 #5
0
파일: commands.py 프로젝트: dingens/settle
    def run(self, args):
        args = args[:]
        if len(args) == 0:
            print('Error: No command given\nAvailable commands:', file=sys.stderr)
            for c in self.funcdict:
                print('  %s' % c, file=sys.stderr)
            return

        if args[0] == 'init':
            # special case because we don't pass a group here
            self.do_init(args[1:])
            return

        if args[0] in self.funcdict:
            args.insert(0, 'DEFAULTREPO') #TODO

        if len(args) <= 1:
            print('Error: No command given\nAvailable commands:', file=sys.stderr)
            for c in self.funcdict:
                print('  %s' % c, file=sys.stderr)
            return

        group = Group.load(args[0])
        cmd = args[1]
        rest = args[2:]

        try:
            f = self.funcdict[cmd]
        except KeyError:
            print('no such command: %s' % cmd, file=sys.stderr)
        else:
            debug('running %s(%s) with %r' % (cmd, rest, group))
            f(group, rest)
예제 #6
0
파일: reader.py 프로젝트: dingens/settle
def find_payment_files(group):
    dir = group.path('payments')
    debug('searching for payments in %s' % dir)
    for f_ in os.listdir(dir):
        f = os.path.join(dir, f_)
        if f_[0] != '.' and os.path.isfile(f):
            yield f
        else:
            debug('skip %s' % f)
예제 #7
0
def find_payment_files(group):
    dir = group.path('payments')
    debug('searching for payments in %s' % dir)
    for f_ in os.listdir(dir):
        f = os.path.join(dir, f_)
        if f_[0] != '.' and os.path.isfile(f):
            yield f
        else:
            debug('skip %s' % f)
예제 #8
0
    def do_new(self, group, raw_args):
        p = argparse.ArgumentParser('create new payment')
        p.add_argument('amount', nargs='?')
        p.add_argument('receivers', nargs='*')
        args = p.parse_args(raw_args)

        if args.amount is None:
            amount = ask('Amount? ', require=r'^[0-9]*(\.[0-9]*)?$')
        else:
            amount = args.amount
            print('Amount: %s' % amount)

        if not args.receivers:
            receivers = ask('Receivers? ', 'Enter the names of the person(s) '
                            'the payment was done for. Separate multiple '
                            'persons by spaces. Use %name for a payment to a '
                            'list of people. ',
                            require=_identifiers_re)
            #TODO: verify if the names are valid receivers
        else:
            receivers = args.receivers
            print('Receivers:', ' '.join(receivers))

        giver = ask('Who payed? ', default=group.default_giver)

        def _verify_date(d):
            try:
                parse_date(d)
            except ValueError:
                return 'Invalid date.'

        date = ask('Date? (- for none) ',
                   default='now',
                   forbidden=_verify_date)
        if date == 'now':
            date = datetime.now()
        elif date == '-':
            date = None
        else:
            date = parse_date(date)

        comment = ask('Comment? ', blank=True)

        p = Payment(group,
                    giver,
                    receivers,
                    amount,
                    date=date,
                    comment=comment)
        debug('%r\n  %r' % (p, p.receivers.to_string()))
        store_payment(p)
예제 #9
0
파일: commands.py 프로젝트: dingens/settle
    def do_new(self, group, raw_args):
        p = argparse.ArgumentParser('create new payment')
        p.add_argument('amount', nargs='?')
        p.add_argument('receivers', nargs='*')
        args = p.parse_args(raw_args)

        if args.amount is None:
            amount = ask('Amount? ', require=r'^[0-9]*(\.[0-9]*)?$')
        else:
            amount = args.amount
            print('Amount: %s' % amount)

        if not args.receivers:
            receivers = ask('Receivers? ', 'Enter the names of the person(s) '
                            'the payment was done for. Separate multiple '
                            'persons by spaces. Use %name for a payment to a '
                            'list of people. ', require=_identifiers_re)
            #TODO: verify if the names are valid receivers
        else:
            receivers = args.receivers
            print('Receivers:', ' '.join(receivers))

        giver = ask('Who payed? ', default=group.default_giver)

        def _verify_date(d):
            try:
                parse_date(d)
            except ValueError:
                return 'Invalid date.'

        date = ask('Date? (- for none) ', default='now', forbidden=_verify_date)
        if date == 'now':
            date = datetime.now()
        elif date == '-':
            date = None
        else:
            date = parse_date(date)

        comment = ask('Comment? ', blank=True)

        p = Payment(group, giver, receivers, amount, date=date, comment=comment)
        debug('%r\n  %r' % (p, p.receivers.to_string()))
        store_payment(p)
예제 #10
0
파일: group.py 프로젝트: dingens/settle
    def load(cls, name):
        from settle import DEFAULT_CURRENCY
        args = {}

        if not os.path.isdir(Group._path(name)):
            raise NoSuchGroupError(name)

        config = read_file(cls._path(name, 'config'), {})
        config.update(read_file(cls._path(name, 'localconfig'), {}))
        args['default_currency'] = config.get('default_currency', DEFAULT_CURRENCY)
        args['default_giver'] = config.get('default_giver', None)
        g = cls(name, **args)

        lists_ = read_file(cls._path(name, 'lists'), {})
        for name, s in lists_.items():
            debug('parse receivers: %s' % s)
            g.lists[name] = Receivers.from_string(g, s, is_list=True)

        return g
예제 #11
0
    def load(cls, name):
        from settle import DEFAULT_CURRENCY
        args = {}

        if not os.path.isdir(Group._path(name)):
            raise NoSuchGroupError(name)

        config = read_file(cls._path(name, 'config'), {})
        config.update(read_file(cls._path(name, 'localconfig'), {}))
        args['default_currency'] = config.get('default_currency',
                                              DEFAULT_CURRENCY)
        args['default_giver'] = config.get('default_giver', None)
        g = cls(name, **args)

        lists_ = read_file(cls._path(name, 'lists'), {})
        for name, s in lists_.items():
            debug('parse receivers: %s' % s)
            g.lists[name] = Receivers.from_string(g, s, is_list=True)

        return g
예제 #12
0
파일: payment.py 프로젝트: dingens/settle
    def _calculate_balances(self):
        from settle import MAX_LIST_RESOLVER_RECURSION_DEPTH

        self.balances = []
        raw_balances, self.amount = self.receivers.apply(self.amount, self.currency)

        i = MAX_LIST_RESOLVER_RECURSION_DEPTH
        while raw_balances:
            new_raw_balances = []

            debug('raw: %r' % raw_balances)
            for name, val in raw_balances:
                if is_list(name):
                    bal, _amount = self.group.lists[name[1:]].apply(-val)
                    new_raw_balances.extend(bal)
                else:
                    self.balances.append((name, val))
            raw_balances = new_raw_balances
            i -= 1

            if i <= 0:
                raise RuntimeError('Maximum list resolver recursion depth reached. Maybe there is a loop?')

        self.balances.append((self.giver, Money(+self.amount, self.currency)))
예제 #13
0
파일: reader.py 프로젝트: dingens/settle
def read_all_payments(group):
    for f in find_payment_files(group):
        debug('payment found: %s' % f)
        yield read_payment(f, group)
예제 #14
0
def read_all_payments(group):
    for f in find_payment_files(group):
        debug('payment found: %s' % f)
        yield read_payment(f, group)