Commit ab407fad authored by Nicolas Dandrimont's avatar Nicolas Dandrimont

New upstream version 2.0.0

parents
repo: 26cf45c5599ff39ae649d05d52e820039256157e
node: 8af008648277cd9bf2a6699d6db550ad12d88453
branch: default
tag: 2.0.0
syntax: glob
*.pyc
*.swp
*~
TAGS
build
dist
*.a
*.so
.noseids
examples/generated/*
beancount/parser/grammar.output
*.picklecache
*.DS_Store
.idea
beancount.egg-info
.cache
12b7f102ffbb8ae6d18fd6edf40f5cf2d354a4d6 v1
1f60a2293b600c4bc22926fb1cc0d4300145eba2 old-posting
da62959c106a3f06ffc4a1fcdb5e6ae97e77152d master
6d69f09be1d4ac9365432b2a8a4bc130b521ccda github/master
a85679977ede1586585ae0b92cd121e1b8835481 github/master
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
Martin Blais (blais at furius dot ca)
Original author of Beancount v1 and v2.
Daniel Clemente (n142857 at gmail dot com)
Was an early and patient user of an incomplete Beancount v2, reported a large
numbers of bugs and discussed many of the design ideas from the perspective of
a user. This helped motivate the completion and polishing of this new version,
as well as understand what aspects needed more explanations and documentation.
#!/usr/bin/env make
# Just my big old fat ledger file.
INPUT = $(HOME)/q/office/accounting/blais.beancount
DOWNLOADS = $(HOME)/u/Downloads
GREP="grep --include="*.py" -srnE"
TOOLS=./etc
PYTHON=python3
all: build
# Clean everything up.
clean:
rm -f core
rm -rf build
rm -f $(CROOT)/grammar.h $(CROOT)/grammar.c
rm -f $(CROOT)/lexer.h $(CROOT)/lexer.c
rm -f $(CROOT)/*.so
find . -name __pycache__ -exec rm -r "{}" \; -prune
# Targets to generate and compile the C parser.
CROOT = beancount/parser
LEX = flex
YACC = bison --report=itemset --verbose
FILTERYACC = sed -e 's@/\*[ \t]yacc\.c:.*\*/@@'
TMP=/tmp
$(CROOT)/grammar.c $(CROOT)/grammar.h: $(CROOT)/grammar.y
$(YACC) -o $(CROOT)/grammar.c $<
(cat $(CROOT)/grammar.c | $(FILTERYACC) > $(TMP)/grammar.c ; mv $(TMP)/grammar.c $(CROOT)/grammar.c )
(cat $(CROOT)/grammar.h | $(FILTERYACC) > $(TMP)/grammar.h ; mv $(TMP)/grammar.h $(CROOT)/grammar.h )
$(CROOT)/lexer.c $(CROOT)/lexer.h: $(CROOT)/lexer.l $(CROOT)/grammar.h
$(LEX) --outfile=$(CROOT)/lexer.c --header-file=$(CROOT)/lexer.h $<
SOURCES = \
$(CROOT)/lexer.c \
$(CROOT)/lexer.h \
$(CROOT)/grammar.c \
$(CROOT)/grammar.h
.PHONY: build
build: $(SOURCES)
$(PYTHON) setup.py build_ext -i
build35: $(SOURCES)
python3.5 setup.py build_ext -i
# Dump the lexer parsed output. This can be used to check across languages.
dump_lexer:
bean-dump-lexer $(INPUT)
# Check for memory leaks.
grind:
valgrind --leak-check=full $(PYTHON) bean-sandbox $(INPUT)
# Regenerate the website.
html docs:
projects docs beancount
# Compute and plot inter-module dependencies.
# We want to insure a really strict set of relationships between the modules,
# and this is the high-level picture.
build/beancount.deps:
sfood -i bin beancount > $@
CLUSTERS_REGEXPS = \
beancount/core/.*_test\.py core/tests \
beancount/core core \
beancount/ops/.*_test\.py ops/tests \
beancount/ops ops \
beancount/parser/printer_test\.py printer/tests \
beancount/parser/printer.py printer \
beancount/parser/options_test\.py options/tests \
beancount/parser/options.py options \
beancount/parser/.*_test\.py parser/tests \
beancount/parser parser \
beancount/plugins/.*_test\.py plugins/tests \
beancount/plugins plugins \
beancount/reports/.*_test\.py reports/tests \
beancount/reports reports \
beancount/scripts/bake.*_test\.py scripts/bake/tests \
beancount/scripts/bake.* scripts/bake \
beancount/scripts/.*_test\.py scripts/tests \
beancount/scripts scripts \
beancount/utils/.*_test\.py utils/tests \
beancount/utils utils \
beancount/web/.*_test\.py web/tests \
beancount/web web \
beancount/query/.*_test\.py query/tests \
beancount/query query \
beancount/load.*_test\.py load/tests \
beancount/load.*\.py load \
beancount load
GRAPHER = dot
build/beancount.pdf: build/beancount.deps
cat $< | sfood-cluster-regexp $(CLUSTERS_REGEXPS) | grep -v /tests | sfood-graph | $(GRAPHER) -Tps | ps2pdf - $@
evince $@
build/beancount_tests.pdf: build/beancount.deps
cat $< | sfood-cluster-regexp $(CLUSTERS_REGEXPS) | sfood-graph | $(GRAPHER) -Tps | ps2pdf - $@
evince $@
# Compute ahd plot the dependencies within the core.
# We are considering a separation of the basic data structure and the basic operations.
# This provides the detail of the relationships between these sets of fils.
build/beancount-core.pdf: build/beancount-core.deps
sfood -ii beancount/core/*.py | sfood-graph | $(GRAPHER) -Tps | ps2pdf - $@
showdeps-core: build/beancount-core.pdf
evince $<
# Run in the debugger.
debug:
gdb --args $(PYTHON) /home/blais/p/beancount/bin/bean-sandbox $(INPUT)
# Push to github.
github:
hg bookmark -r default master
hg push github
# Bake a release.
release:
$(PYTHON) setup.py register sdist upload
# Run the unittests.
NOSE = nosetests3
vtest vtests verbose-test verbose-tests:
$(NOSE) -v -s beancount
qtest qtests quiet-test quiet-tests test tests:
$(NOSE) beancount
test-failed:
$(NOSE) --failed beancount
nakedtests:
PATH=/bin:/usr/bin PYTHONPATH= /usr/local/bin/$(NOSE) -x beancount
# Run the parser and measure its performance.
.PHONY: check
check:
bean-check $(INPUT)
# Run the demo program.
demo:
bin/bean-web --debug examples/demo.beancount
# Generate the tutorial files from the example file.
EXAMPLE=examples/example.beancount
example $(EXAMPLE):
./bin/bean-example --seed=0 -o $(EXAMPLE)
TUTORIAL=examples/tutorial
tutorial: $(EXAMPLE)
$(PYTHON) beancount/scripts/tutorial.py $(EXAMPLE) $(TUTORIAL)
# Run the web server.
.PHONY: web
web:
bean-web --debug $(INPUT)
.PHONY: web-incognito
web-incognito:
bean-web --incognito --debug $(INPUT)
# Run the importer.
.PHONY: import
import:
bean-import $(INPUT) $(DOWNLOADS)
# My development sandbox script. This is messy and it's okay.
.PHONY: sandbox
sandbox:
bean-sandbox $(INPUT)
missing-tests:
$(TOOLS)/find_missing_tests.py beancount
fixmes:
egrep -srn '\b(FIXME|TODO\()' beancount || true
filter-terms:
egrep --exclude-dir='.hg' --exclude-dir='__pycache__' -srn 'GOOGL?\b' $(PWD) | grep -v GOOGLE_APIS || true
multi-imports:
(egrep -srn '^(from.*)?import.*,' beancount | grep -v 'from typing') || true
# Check for unused imports.
sfood-checker:
sfood-checker bin beancount
# Check dependency constraints.
constraints dep-constraints: build/beancount.deps
$(TOOLS)/dependency_constraints.py $<
# Run the linter on all source code.
# To list all messages, call: "pylint --list-msgs"
LINT_SRCS = \
beancount \
examples/ingest/office/importers \
bin/* \
tools/*.py
# Note: Keeping to 3.5 because 3.6 pylint raises an exception (as of 2017-01-15).
#PYLINT = pylint
PYLINT = python3.5 $(shell which pylint)
pylint lint:
$(PYLINT) --rcfile=$(PWD)/etc/pylintrc $(LINT_SRCS)
pyflakes:
pyflakes $(LINT_SRCS)
# Check everything.
status check: pylint pyflakes filter-terms missing-tests dep-constraints multi-imports test
# Experimental docs conversion.
download-pdf:
./tools/download_docs.py pdf $(HOME)/p/beancount-downloads/pdf
download-odt:
./tools/download_docs.py odt $(HOME)/p/beancount-downloads/odt
sphinx sphinx_odt2rst:
./tools/sphinx_odt2rst.py $(HOME)/p/beancount-downloads/odt $(HOME)/p/beancount-docs
convert_test:
./tools/convert_doc.py --cache=/tmp/convert_test.cache '1WjARst_cSxNE-Lq6JnJ5CC41T3WndEsiMw4d46r2694' /tmp/trading.md
Description: Command-line Double-Entry Accounting
Official-Homepage: http://furius.ca/beancount
Author: Martin Blais
Author-Email: blais@furius.ca
ChangeLog: http://furius.ca/beancount/CHANGES
Bugs-Reporting: mailto:blais@furius.ca
Download-Snapshots: http://bitbucket.org/blais/beancount
License: GNU GPLv2 only
========================================================
beancount: Double-Entry Accounting from Text Files
========================================================
.. contents::
..
1 Description
2 Documentation
3 Download & Installation
4 Filing Bugs
5 Copyright and License
6 Author
Description
===========
A double-entry bookkeeping computer language that lets you define financial
transaction records in a text file, read them in memory, generate a variety of
reports from them, and provides a web interface.
Documentation
=============
Documentation lives on Google Docs. You can find an index to all the available
documents here:
http://furius.ca/beancount/doc/index
There's a `mailing-list dedicated to Beancount
<https://groups.google.com/forum/#!forum/beancount>`_, please post questions
there, so others can share in the responses. More general discussions about
command-line accounting also occur on the `Ledger mailing-list
<https://groups.google.com/forum/#!forum/ledger-cli>`_ so you might be
interested in that group as well.
Download & Installation
=======================
You can obtain the source code from the official Mercurial repository on
BitBucket:
| http://bitbucket.org/blais/beancount/
See the `Installing Beancount`__ document for more details.
__ http://furius.ca/beancount/doc/install
Filing Bugs
===========
Tickets can be filed at on the BitBucket project page:
http://bitbucket.org/blais/beancount/issues
Copyright and License
=====================
Copyright (C) 2007-2016 Martin Blais. All Rights Reserved.
This code is distributed under the terms of the "GNU GPLv2 only".
See COPYING file for details.
Author
======
Martin Blais <blais@furius.ca>
This diff is collapsed.
environment:
matrix:
# For Python versions available on Appveyor, see
# http://www.appveyor.com/docs/installed-software#python
# The list here is complete (excluding Python 2.6, which
# isn't covered by this document) at the time of writing.
- PYTHON: "C:\\Python36-x64"
install:
# We need wheel installed to build wheels
- "%PYTHON%\\python.exe -m pip install wheel"
build: off
# test_script:
# Put your test command here.
# If you don't need to build C extensions on 64-bit Python 3.3 or 3.4,
# you can remove "build.cmd" from the front of the command, as it's
# only needed to support those cases.
# Note that you must use the environment variable %PYTHON% to refer to
# the interpreter you're using - Appveyor does not do anything special
# to put the Python evrsion you want to use on PATH.
# - "%PYTHON%\\python.exe setup.py test"
after_test:
# This step builds your wheels.
# Again, you only need build.cmd if you're building C extensions for
# 64-bit Python 3.3/3.4. And you need to use %PYTHON% to get the correct
# interpreter
- "%PYTHON%\\python.exe setup.py build_ext --compiler=msvc --define YY_NO_UNISTD_H"
- "%PYTHON%\\python.exe setup.py bdist_wheel"
artifacts:
# bdist_wheel puts your built wheel in the dist directory
- path: dist\*.whl
#on_success:
# You can use this step to upload your artifacts to a public website.
# See Appveyor's documentation for more details. Or you can simply
# access your wheels from the Appveyor "artifacts" tab for your build.
"""Beancount, a double-entry bookkeeping software.
This is v2, a complete rewrite of Beancount v1, simplified and improved
drastically.
"""
__copyright__ = "Copyright (C) 2013-2014, 2016 Martin Blais"
__license__ = "GNU GPLv2"
# Check the version requirements.
import sys
if (sys.version_info.major, sys.version_info.minor) < (3, 3):
raise ImportError("Python 3.3 or above is required")
"""Core basic objects and data structures to represent a list of entries.
"""
__copyright__ = "Copyright (C) 2013-2014, 2016 Martin Blais"
__license__ = "GNU GPLv2"
"""Functions that operate on account strings.
These account objects are rather simple and dumb; they do not contain the list
of their associated postings. This is achieved by building a realization; see
realization.py for details.
"""
__copyright__ = "Copyright (C) 2013-2016 Martin Blais"
__license__ = "GNU GPLv2"
import re
import os
from os import path
# Component separator for account names.
# pylint: disable=invalid-name
sep = ':'
# Regular expression string that matchs a valid account.
# (Also see valid_account_regexp() which is coupled to this value.)
ACCOUNT_RE = '(?:[A-Z][A-Za-z0-9\-]*)(?:{}[A-Z0-9][A-Za-z0-9\-]*)+'.format(sep)
# A dummy object which stands for the account type. Values in custom directives
# use this to disambiguate between string objects and account names.
TYPE = '<AccountDummy>'
def is_valid(string):
"""Return true if the given string is a valid account name.
This does not check for the root account types, just the general syntax.
Args:
string: A string, to be checked for account name pattern.
Returns:
A boolean, true if the string has the form of an account's name.
"""
return (isinstance(string, str) and
bool(re.match('{}$'.format(ACCOUNT_RE), string)))
def join(*components):
"""Join the names with the account separator.
Args:
*components: Strings, the components of an account name.
Returns:
A string, joined in a single account name.
"""
return sep.join(components)
def split(account_name):
"""Split an account's name into its components.
Args:
account_name: A string, an account name.
Returns:
A list of strings, the components of the account name (without the separators).
"""
return account_name.split(sep)
def parent(account_name):
<