Skip to content

Commit

Permalink
more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
rienafairefr committed Mar 12, 2018
1 parent 12e6e02 commit 49168ad
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 22 deletions.
17 changes: 12 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,33 @@ Or you can download the source, then call `python setup.py install`
Usage
-----

Either code your own script that uses the pynYNAB api, or use the provided scripts, ofximport, YNAB4 migrate, csvimport
For more in-depth info about the library, go to the documentation `DOCS`_

Either code your own script that uses the pynYNAB api, or use the provided scripts, `ynab ofximport`, or `ynab csvimport`

Scripts Documentation
---------------------

See appropriate `README`_
Using these scripts you can import a bunch of transactions in your budget, using either a CSV or an OFX file
This is especially useful if your bank is not supported by the automatic import feature of YNAB

See more documentation at `SCRIPTS_DOCS`_

API Documentation
-----------------

See the wiki `WIKI`_ for an extended explanation and usage examples
See some extended explanation in the `WIKI`_ or the `DOCS`_

Preventing harm to nYnab servers
Preventing harm to YNAB servers
--------------------------------

I've taken all precautionary steps so that this python Client can't affect YNAB even if used too widely.
I've taken all precautionary steps so that this python Client can't affect YNAB even if used too widely.

* It honors requests by the server to throttle its requests > Same mechanisme that the JS app uses
* It self-limits the requests to 5 request per second
* It clearly identifies itself by User-Agent > Easy to lock it out if it causes trouble

.. _README: https://github.com/rienafairefr/nYNABapi/blob/master/scripts/README.rst
.. _WIKI: https://github.com/rienafairefr/pynYNAB/wiki
.. _DOCS: http://rienafairefr.github.io/pynYNAB/
.. _SCRIPTS_DOCS: http://rienafairefr.github.io/pynYNAB/scripts.html
1 change: 0 additions & 1 deletion docs/readme.rst

This file was deleted.

5 changes: 0 additions & 5 deletions docs/reference/pynYNAB.rst

This file was deleted.

1 change: 1 addition & 0 deletions docs/scripts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ This library also include some scripts that you can use directly to import some
.. toctree::
:maxdepth: 1

cmd_main
cmd_csvimport
cmd_ofximport
88 changes: 86 additions & 2 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,91 @@
Usage
=====

To use pynYNAB in a project::
Canonical client creation
-------------------------

A way to create a client and fetch data::

from pynYNAB.Client import nYnabClient

client = nYnabClient(email="############", password="######", budgetname='TestBudget')
client.sync()

You can also decouple the connection and session management from the client object::

connection = nYnabConnection(email, password)
connection.init_session()
client = nYnabClient(nynabconnection=connection, budgetname='TestBudget')
client.sync()


Local database
--------------

Once data is downloaded from the servers, it is stored in a local database, accessed through sqlAlchemy.
All the relations between objects are in here through appropriate One-to-Many or Many-to-One relations, etc.


Client factory
--------------

A YNAB client (of type nYnabClient\_) is just another object that can be persisted in the database.
The nYnabClient( [...] ) --without the \_-- constructor is just a wrapper around calling
nYnabClientFactory().create_client( [...] )

The ClientFactory initializes the database, just pass it an engine URL, like::

from pynYNAB.ClientFactory import ClientFactory
factory = ClientFactoy('sqlite:////tmp/persist.db')
client1 = factory.create_client(email=***,password=***,budget_name=***)
[ do something with data in client1 ]
client2 = factory.create_client(email=***,password=***,budget_name=***)

These two clients will be strictly identical, referring to the same client in the database, so client2
will contain the modifications done in client1

Pushing entities
----------------

In order to sync data to the YNAB servers, we need to know how much data we want to push.
We don't need to construct the array of data to push, this is all done transparently
for you in the background through sqlAlchemy modification hooks.

Here we add two transactions and one payee, then push them::

client.sync()
client.budget.be_transactions.append(transaction1)
client.budget.be_transactions.append(transaction2)
client.budget.be_payees.append(payee)
client.budget.push(3)

With the first sync, the amount of currently modified data is reset to 0, and the additions of data are tracked

Previously, you could accidentally push a modification that erased all your YNAB data. Now the `push` method stops you
from doing that, by limiting the modifications to at most 1 entity if no paramaters are passed.


Database query
--------------

We can use the sqlAlchemy backend in order to get interesting views to the data::

from sqlalchemy.sql import func
from datetime import datetime
session = client.session

# sum of the amounts for all transactions younger than 10 weeks
session.query(func.sum(Transaction.amount)).filter(Transaction.date > datetime.datetime.now() - datetime.timedelta(weeks=10)).scalar()

# sum of the amounts for each month
session.query(func.strftime('%Y-%m',Transaction.date),func.sum(Transaction.amount)).group_by(extract('month',Transaction.date)).all()

# same for positive amounts only
session.query(func.strftime('%Y-%m',Transaction.date),func.sum(Transaction.amount)).filter(Transaction.amount>0).group_by(extract('month',Transaction.date)).all()

# see the total of the transactions, grouping per-payee
session.query(func.sum(Transaction.amount),Transaction.amount).group_by(Transaction.entities_payee).join(Payee).all()

Everything is possible, see sqlAlchemy docs :-)

import pynYNAB

22 changes: 13 additions & 9 deletions pynYNAB/scripts/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,21 @@ def ofximport_parser():
return OfxImport().parser


class MainCommands(object):
def __init__(self):
parser = argparse.ArgumentParser(
description='nYnab-CLI using the python library',
usage='''nynab <command> [<args>]
def main_parser():
parser = argparse.ArgumentParser(
description='nYnab-CLI using the python library',
usage='''nynab <command> [<args>]
''')

parser.add_argument('command', help='Subcommand to run', choices=COMMANDS.keys())
parser.usage += 'commands : ' + ','.join(COMMANDS.keys())
return parser

''')

parser.add_argument('command', help='Subcommand to run', choices=COMMANDS.keys())
parser.usage += 'commands : ' + ','.join(COMMANDS.keys())
class MainCommands(object):
def __init__(self):
parser = main_parser()
# parse_args defaults to [1:] for args, but you need to
# exclude the rest of the args too, or validation will fail
args = parser.parse_args(sys.argv[1:2])
Expand All @@ -146,7 +151,6 @@ def __init__(self):
if getattr(args, 'password', None):
args.password = getpass('YNAB password:')


sys.argv.pop(1)

COMMANDS[args.command]().command()
Expand Down

0 comments on commit 49168ad

Please sign in to comment.