/usr/lib/python2.7/dist-packages/ofxclient/institution.py is in python-ofxclient 1.3.8-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | import StringIO
import hashlib
from ofxclient.client import Client
from ofxparse import OfxParser
from BeautifulSoup import BeautifulStoneSoup
class Institution(object):
"""Represents an institution or bank
:param id: FI Id
:type id: string
:param org: FI Org
:type org: string
:param url: FI Url
:type url: string
:param username: Customer username or member id
:type username: string
:param password: Customer password or PIN
:type password: string
:param broker_id: FI Broker ID (optional)
:type broker_id: string
:param description: Description of the bank (optional)
:type description: string or None
:param client_args: :py:class:`ofxclient.Client` kwargs (optional)
:type client_args: dict
Values for many of the parameters need to come from some sort of
OFX registry which knows about each banks particular setup.
For help obtaining this sort of information; please see the
:py:mod:`ofxhome` python module and/or the `OFX Home <http://ofxhome.com>`_
website.
Example::
from ofxclient import Institution
inst = Institution(
id = '3101',
org = 'AMEX',
url = 'https://online.americanexpress.com/myca\
/ofxdl/desktop/desktop Download.do?\
request_type=nl_ofxdownload',
username = 'gene',
password = 'wilder'
)
for a in inst.accounts():
print a.statement(days=5).balance
"""
def __init__(self, id, org, url, username, password,
broker_id='', description=None, client_args={}):
self.id = id
self.org = org
self.url = url
self.broker_id = broker_id
self.username = username
self.password = password
self.description = description or self._default_description()
self.client_args = client_args
def client(self):
"""Build a :py:class:`ofxclient.Client` for talking with the bank
It implicitly passes in the ``client_args`` that were passed
when instantiating this ``Institution``.
:rtype: :py:class:`ofxclient.Client`
"""
return Client(institution=self, **self.client_args)
def local_id(self):
"""Locally generated unique account identifier.
:rtype: string
"""
return hashlib.sha256("%s%s" % (
self.id,
self.username)).hexdigest()
def _default_description(self):
return self.org
def authenticate(self, username=None, password=None):
"""Test the authentication credentials
Raises a ``ValueError`` if there is a problem authenticating
with the human readable reason given by the institution.
:param username: optional username (use self.username by default)
:type username: string or None
:param password: optional password (use self.password by default)
:type password: string or None
"""
u = self.username
p = self.password
if username and password:
u = username
p = password
client = self.client()
query = client.authenticated_query(username=u, password=p)
res = client.post(query)
ofx = BeautifulStoneSoup(res)
sonrs = ofx.find('sonrs')
code = int(sonrs.find('code').contents[0].strip())
try:
status = sonrs.find('message').contents[0].strip()
except Exception:
status = ''
if code == 0:
return 1
raise ValueError(status)
def accounts(self):
"""Ask the bank for the known :py:class:`ofxclient.Account` list.
:rtype: list of :py:class:`ofxclient.Account` objects
"""
from ofxclient.account import Account
client = self.client()
query = client.account_list_query()
resp = client.post(query)
resp_handle = StringIO.StringIO(resp)
parsed = OfxParser.parse(resp_handle)
return [Account.from_ofxparse(a, institution=self)
for a in parsed.accounts]
def serialize(self):
"""Serialize predictably for use in configuration storage.
Output looks like this::
{
'local_id': 'unique local identifier',
'id': 'FI Id',
'org': 'FI Org',
'url': 'FI OFX Endpoint Url',
'broker_id': 'FI Broker Id',
'username': 'Customer username',
'password': 'Customer password',
'description': 'descr',
'client_args': {
'id': 'random client id - see Client() for default',
'app_id': 'app name - see Client() for default',
'app_version': 'app version - see Client() for default',
'ofx_version': 'ofx version - see Client() for default',
}
}
:rtype: nested dictionary
"""
client = self.client()
client_args = {
'id': client.id,
'app_id': client.app_id,
'app_version': client.app_version,
'ofx_version': client.ofx_version,
}
return {
'id': self.id,
'org': self.org,
'url': self.url,
'broker_id': self.broker_id,
'username': self.username,
'password': self.password,
'description': self.description,
'client_args': client_args,
'local_id': self.local_id()
}
@staticmethod
def deserialize(raw):
"""Instantiate :py:class:`ofxclient.Institution` from dictionary
:param raw: serialized ``Institution``
:param type: dict per :py:method:`~Institution.serialize`
:rtype: subclass of :py:class:`ofxclient.Institution`
"""
return Institution(
id=raw['id'],
org=raw['org'],
url=raw['url'],
broker_id=raw.get('broker_id', ''),
username=raw['username'],
password=raw['password'],
description=raw.get('description', None),
client_args=raw.get('client_args', {})
)
|