diff --git a/docs/client.rst b/docs/client.rst
index b22d699..1b30d33 100644
--- a/docs/client.rst
+++ b/docs/client.rst
@@ -164,13 +164,6 @@ its nickname instead:
$ ofxget prof amex
-Or, if the server is known to OFX Home, then you can just use its database
-ID (the end part of its `institution page on OFX Home`_):
-
-.. code-block:: bash
-
- $ ofxget prof --ofxhome 424
-
Any of these work just fine, dumping a load of markup on the screen telling us
what OFX services are available and some parameters for accessing them.
@@ -192,12 +185,6 @@ provide a server nickname.
$ ofxget prof myfi --write --org AMEX --fid 3101 --url https://online.americanexpress.com/myca/ofxdl/desktop/desktopDownload.do\?request_type\=nl_ofxdownload
-If your server is up on OFX Home, this works as well:
-
-.. code-block:: bash
-
- ofxget prof myfi --ofxhome 424 --write
-
It's also easy to write a configuration file manually in a text editor - it's
just the command line options in simple INI format, with a server nicknames as
section headers. You can find a sample at
@@ -232,16 +219,6 @@ Our configuration file will look like this:
org: AMEX
fid: 3101
-Alternatively, since AmEx has working parameters listed on OFX Home, you could
-just use the OFX Home API to look them up for each request. Using the OFX Home
-database id (at the end of the webpage URL), the config looks like this:
-
-.. code-block:: ini
-
- # American Express
- [amex]
- ofxhome: 424
-
With either configuration, we can now use the provider nickname to make our
connection more conveniently:
@@ -608,8 +585,6 @@ Other methods available:
* ``OFXClient.request_accounts()``- ACCTINFORQ
* ``OFXClient.request_tax1099()``- TAX1099RQ (still a WIP)
-.. _OFX Home: http://www.ofxhome.com/
-.. _institution page on OFX Home: http://www.ofxhome.com/index.php/institution/view/424
.. _OFX Blog: https://ofxblog.wordpress.com/
.. _ABA routing number: http://routingnumber.aba.com/default1.aspx
.. _getfidata.sh: https://web.archive.org/web/20070120102800/http://www.jongsma.org/gc/bankinfo/getfidata.sh.gz
diff --git a/docs/resources.rst b/docs/resources.rst
index 2334aa1..89eecc2 100644
--- a/docs/resources.rst
+++ b/docs/resources.rst
@@ -18,7 +18,6 @@ More open-source OFX code
.. _OFX spec: https://financialdataexchange.org/ofx
.. _Quicken data mapping guide: https://web.archive.org/web/20110908185057if_/http://fi.intuit.com/ofximplementation/dl/OFXDataMappingGuide.pdfi
-.. _OFX Home: http://www.ofxhome.com/
.. _libofx: https://github.com/libofx/libofx
.. _ofxparse: https://github.com/jseutter/ofxparse
.. _csv2ofx: https://github.com/reubano/csv2ofx
diff --git a/ofxtools/config/ofxget_example.cfg b/ofxtools/config/ofxget_example.cfg
index 0021355..ab1f440 100644
--- a/ofxtools/config/ofxget_example.cfg
+++ b/ofxtools/config/ofxget_example.cfg
@@ -38,14 +38,6 @@ bankid = 056073502
checking = 1234567890
moneymrkt = 1234567890
-# Since credit card accts don't have a routing #, they can be placed in
-# any config section with proper url/org/fid
-[amex]
-# An example of referring to OFX Home for an API lookup, rather than manually
-# specifying URL/ORG/FID.
-ofxhome = 424
-creditcard = 111122233344556, 222333445561111
-
# Brokerage accounts are specified by brokerid/investment
[ameritrade]
url = https://ofxs.ameritrade.com/cgi-bin/apps/OFX
diff --git a/ofxtools/ofxhome.py b/ofxtools/ofxhome.py
deleted file mode 100644
index f968a58..0000000
--- a/ofxtools/ofxhome.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/env python
-"""
-Interface with http://ofxhome.com API
-"""
-
-
-__all__ = [
- "URL",
- "VALID_DAYS",
- "OFXServer",
- "list_institutions",
- "lookup",
- "ofx_invalid",
- "ssl_invalid",
-]
-
-
-# stdlib imports
-from collections import OrderedDict
-import datetime
-import xml.etree.ElementTree as ET
-from xml.sax import saxutils
-import urllib
-import urllib.error as urllib_error
-import urllib.parse as urllib_parse
-import re
-from typing import Dict, NamedTuple, Optional, Union, Mapping, Match
-
-
-URL = "http://www.ofxhome.com/api.php"
-VALID_DAYS = 90
-
-
-FID_REGEX = re.compile(r"([^<]*)")
-
-
-class OFXServer(NamedTuple):
- """Container for an OFX Home FI record"""
-
- id: Optional[str] = None
- name: Optional[str] = None
- fid: Optional[str] = None
- org: Optional[str] = None
- url: Optional[str] = None
- brokerid: Optional[str] = None
- ofxfail: Optional[bool] = True
- sslfail: Optional[bool] = True
- lastofxvalidation: Optional[datetime.datetime] = None
- lastsslvalidation: Optional[datetime.datetime] = None
- profile: Optional[Dict[str, Union[str, bool]]] = None
-
-
-def list_institutions() -> Mapping[str, str]:
- query = _make_query(all="yes")
- with urllib.request.urlopen(query) as f:
- response = f.read()
-
- return {
- fi.get("id").strip(): fi.get("name").strip() # type: ignore
- for fi in ET.fromstring(response)
- }
-
-
-def lookup(id: str) -> Optional[OFXServer]:
- etree = fetch_fi_xml(id)
- if etree is None:
- return None
-
- converters = {
- "ofxfail": _convert_bool,
- "sslfail": _convert_bool,
- "lastofxvalidation": _convert_dt,
- "lastsslvalidation": _convert_dt,
- "profile": _convert_profile,
- }
-
- # mypy doesn't accept NamedTuple(**kwargs); use OrderedDict as workaround
- attrs = [(e.tag, converters.get(e.tag, _convert_str)(e)) for e in etree]
- attrs.insert(0, ("id", etree.attrib["id"]))
- return OFXServer(**OrderedDict(attrs)) # type: ignore
-
-
-def fetch_fi_xml(id: str) -> Optional[ET.Element]:
- if not id:
- return None
-
- query = _make_query(lookup=id)
- try:
- with urllib.request.urlopen(query) as f:
- response = f.read()
- except urllib_error.URLError:
- return None
-
- try:
- etree = ET.fromstring(response)
- except ET.ParseError:
- # OFX Home fails to escape XML control characters for
- response_ = FID_REGEX.sub(_escape_fid, response.decode())
- etree = ET.fromstring(response_)
- return etree
-
-
-def ofx_invalid(srvr: OFXServer, valid_days: Optional[int] = None) -> bool:
- if srvr.ofxfail:
- return True
- if srvr.lastofxvalidation is None:
- return True
- if valid_days is None:
- valid_days = VALID_DAYS
- now = datetime.datetime.now()
- if (now - srvr.lastofxvalidation) > datetime.timedelta(days=valid_days):
- return True
-
- return False
-
-
-def ssl_invalid(srvr: OFXServer, valid_days: Optional[int] = None) -> bool:
- if srvr.sslfail:
- return True
- if srvr.lastsslvalidation is None:
- return True
- if valid_days is None:
- valid_days = VALID_DAYS
- now = datetime.datetime.now()
- if (now - srvr.lastsslvalidation) > datetime.timedelta(days=valid_days):
- return True
-
- return False
-
-
-def _make_query(**kwargs: str) -> str:
- params = urllib_parse.urlencode(kwargs)
- return "{}?{}".format(URL, params)
-
-
-def _convert_str(elem: ET.Element) -> Optional[str]:
- text = elem.text
- if text:
- return saxutils.unescape(text).strip()
- return None
-
-
-def _convert_dt(elem: ET.Element) -> Optional[datetime.datetime]:
- text = elem.text
- if text:
- return datetime.datetime.strptime(text, "%Y-%m-%d %H:%M:%S")
- return None
-
-
-def _convert_bool(elem: ET.Element) -> Optional[bool]:
- text = elem.text
- if text:
- return bool(int(text))
- return None
-
-
-def _convert_profile(elem: ET.Element) -> Dict[str, Union[str, bool]]:
- def convert_maybe_bool(key: str, val: str) -> Union[str, bool]:
- if key.endswith("msgset"):
- return {"true": True, "false": False}[val]
- return saxutils.unescape(val)
-
- return {k: convert_maybe_bool(k, v) for k, v in elem.attrib.items()}
-
-
-def _escape_fid(match: Match) -> str:
- fid = saxutils.escape(match.group(1))
- return "{}".format(fid)
diff --git a/ofxtools/scripts/ofxget.py b/ofxtools/scripts/ofxget.py
index 82adcce..919ddcd 100644
--- a/ofxtools/scripts/ofxget.py
+++ b/ofxtools/scripts/ofxget.py
@@ -49,7 +49,7 @@
# local imports
-from ofxtools import Client, header, Parser, utils, ofxhome, config, models
+from ofxtools import Client, header, Parser, utils, config, models
from ofxtools.Client import (
OFXClient,
StmtRq,
@@ -206,9 +206,6 @@ def add_subparser(
if server:
parser.add_argument("--url", help="OFX server URL")
- parser.add_argument(
- "--ofxhome", metavar="ID#", help="FI id# on http://www.ofxhome.com/"
- )
parser.add_argument(
"-w",
"--write",
@@ -849,7 +846,6 @@ def __init__(self, *args, **kwargs):
"verbose": 0,
"server": "",
"url": "",
- "ofxhome": "",
"version": 203,
"org": "",
"fid": "",
@@ -898,13 +894,11 @@ def __init__(self, *args, **kwargs):
# "Configurable" means "will be read from / written to config file".
# Subdivided into -
# "Configurable server", i.e. parameters used establish an OFX connection
-# (the kind of thing you'd pass to OFXClient.__init__(), which is
-# how they're used by update_fi_cfg.py); and
+# (the kind of thing you'd pass to OFXClient.__init__()); and
# "Configurable user", i.e. auth/account parameters that are completely
# user-specific and won't be shared by different users of the library.
configurable_srvr = (
"url",
- "ofxhome",
"version",
"pretty",
"unclosedelements",
@@ -1081,13 +1075,6 @@ def merge_config(
merged: ArgsType = ChainMap(_args, user_cfg, DEFAULTS) # type: ignore
# logger.debug(f"CLI args merged with user configs and defaults: {extrargs(merged)}")
- # Try to perform an OFX Home lookup if:
- # - it's configured from the CLI
- # - it's configured in ofxget.cfg
- # - we don't have a URL
- if "ofxhome" in _args or "ofxhome" in user_cfg or (not merged["url"]):
- merge_from_ofxhome(merged)
-
if not (
merged.get("url", None)
or merged.get("dryrun", False)
@@ -1099,7 +1086,7 @@ def merge_config(
logger.error(err)
msg = (
f"{err} - please provide a server nickname, "
- "or configure 'url' / 'ofxhome'\n"
+ "or configure 'url'\n"
)
print(msg)
command = merged["request"]
@@ -1113,33 +1100,13 @@ def merge_config(
merged["server"] = None
else:
logger.error(err)
- msg = f"{err} - please configure 'url' or 'ofxhome' for server '{server}'"
+ msg = f"{err} - please configure 'url' for server '{server}'"
raise ValueError(msg)
logger.info(f"Merged args: {extrargs(merged)}")
return merged
-def merge_from_ofxhome(args: ArgsType):
- ofxhome_id = args["ofxhome"]
- if ofxhome_id:
- logger.info(f"Looking up OFX Home API for id#{ofxhome_id}")
- lookup = ofxhome.lookup(ofxhome_id)
- if lookup:
- logger.debug(f"OFX Home lookup found {lookup}")
- # Insert OFX Home lookup ahead of DEFAULTS but after
- # CLI args and user configss
- args.maps.insert(
- -1,
- {
- "url": lookup.url,
- "org": lookup.org,
- "fid": lookup.fid,
- "brokerid": lookup.brokerid,
- },
- )
-
-
def extrargs(args: ArgsType) -> dict:
"""Extract non-null args"""
return {k: v for k, v in args.items() if v not in NULL_ARGS}
@@ -1484,6 +1451,7 @@ def list_fis(args: ArgsType) -> None:
msg = f"Unknown server '{server}'"
raise ValueError(msg)
else:
+ # Note: ofxhome.com doesn't exist anymore, but we still use its IDs for name lookups.
ofxhome = USERCFG[server].get("ofxhome", "")
name = USERCFG["NAMES"].get(ofxhome, "")
config = [" = ".join(pair) for pair in USERCFG[server].items()]
@@ -1499,7 +1467,8 @@ def fi_index() -> Sequence[Tuple[str, str, str]]:
names = {id_: name for id_, name in USERCFG["NAMES"].items()}
cfg_default_sect = USERCFG.default_section # type: ignore
servers = [
- (names.get(sct.get("ofxhome", None), ""), nick, sct.get("ofxhome", "--"))
+ # Note: ofxhome.com doesn't exist anymore, but we still use its IDs for name lookups.
+ (names.get(sct.get("ofxhome", ""), ""), nick, sct.get("ofxhome", "--"))
for nick, sct in USERCFG.items()
if nick not in (cfg_default_sect, "NAMES") and "url" in sct
]
diff --git a/ofxtools/scripts/update_fi_cfg.py b/ofxtools/scripts/update_fi_cfg.py
deleted file mode 100644
index 933efad..0000000
--- a/ofxtools/scripts/update_fi_cfg.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-"""
-Perform an OFX profile scan for the entire OFX Home list of FIs;
-update config/fi.cfg
-
-You probably don't want to run this script; it's for the library developers.
-
-It takes a long time to run and generates lots of HTTP requests, and the output
-is not at all stable so it needs to be checked.
-"""
-
-
-# stdlib imports
-import configparser
-from configparser import ConfigParser
-from xml.sax import saxutils
-from typing import Mapping, Optional, ChainMap
-import logging
-
-
-# local imports
-from ofxtools import ofxhome, config
-from ofxtools.scripts import ofxget
-
-
-LibraryConfig = ConfigParser()
-LibraryConfig.read(ofxget.CONFIGPATH)
-
-if not LibraryConfig.has_section("NAMES"):
- LibraryConfig["NAMES"] = {}
-
-# Map ofxhome_id: server_nick for all configs in library
-known_servers = {
- LibraryConfig[sct]["ofxhome"]: sct
- for sct in LibraryConfig
- if "ofxhome" in LibraryConfig[sct]
-}
-
-
-def mk_server_cfg(args: ofxget.ArgsType) -> configparser.SectionProxy:
- """
- Stripped-down version of ofxget.mk_server_cfg()
- """
- server = args["server"]
- assert server
-
- if not LibraryConfig.has_section(server):
- LibraryConfig[server] = {}
- cfg = LibraryConfig[server]
-
- for opt, opt_type in ofxget.CONFIGURABLE_SRVR.items():
- if opt in args:
- value = args[opt]
- default_value = ofxget.DEFAULTS[opt]
- if value != default_value and value not in ofxget.NULL_ARGS:
- cfg[opt] = ofxget.arg2config(opt, opt_type, value)
-
- return cfg
-
-
-def write_config(args: ofxget.ArgsType) -> None:
- """
- Modified version of ofxget.write_config()
- """
- mk_server_cfg(args)
-
- with open(ofxget.CONFIGPATH, "w") as f:
- LibraryConfig.write(f)
-
-
-def main():
- fis: Mapping[str, str] = ofxhome.list_institutions()
- for ofxhome_id in fis.keys():
- print("Scanning {}".format(ofxhome_id))
-
- lookup: Optional[ofxhome.OFXServer] = ofxhome.lookup(ofxhome_id)
- if lookup is None or lookup.url is None:
- continue
-
- url = lookup.url
- org = lookup.org
- fid = lookup.fid
-
- lookup_name = saxutils.unescape(lookup.name)
- srvr_nick = known_servers.get(ofxhome_id, lookup_name)
-
- ofxhome_id = lookup.id
- assert ofxhome_id
- names = LibraryConfig["NAMES"]
- if ofxhome_id not in names:
- names[ofxhome_id] = lookup_name
-
- if ofxhome.ofx_invalid(lookup) or ofxhome.ssl_invalid(lookup):
- blank_fmt = {"versions": [], "formats": {}}
- scan_results = (blank_fmt, blank_fmt, {})
- else:
- scan_results: ofxget.ScanResults = ofxget._scan_profile(
- url=url, org=org, fid=fid, timeout=10.0
- )
-
- v1, v2, _ = scan_results
- if (not v2["versions"]) and (not v1["versions"]):
- # If no OFX response, blank the server config
- LibraryConfig[srvr_nick] = {"ofxhome": ofxhome_id}
- continue
-
- format = ofxget._best_scan_format(scan_results)
-
- looked_up_data = {
- "ofxhome": ofxhome_id,
- "url": url,
- "org": org,
- "fid": fid,
- "brokerid": lookup.brokerid,
- }
-
- args = ChainMap({"server": srvr_nick}, looked_up_data, format)
- write_config(args)
-
-
-LOG_LEVELS = {0: logging.WARN, 1: logging.INFO, 2: logging.DEBUG}
-
-
-if __name__ == "__main__":
- from argparse import ArgumentParser
-
- argparser = ArgumentParser(description="Scan all FIs; update fi.cfg")
- argparser.add_argument(
- "--verbose",
- "-v",
- action="count",
- default=0,
- help="Give more output (option can be repeated)",
- )
- args = argparser.parse_args()
- log_level = LOG_LEVELS.get(args.verbose, logging.DEBUG)
- config.configure_logging(log_level)
- main()
diff --git a/tests/test_ofxget.py b/tests/test_ofxget.py
index 37d00cd..7275837 100644
--- a/tests/test_ofxget.py
+++ b/tests/test_ofxget.py
@@ -28,7 +28,6 @@
)
from ofxtools.utils import UTC
from ofxtools.scripts import ofxget
-from ofxtools.ofxhome import OFXServer
# test imports
import base
@@ -821,7 +820,6 @@ def testMkservercfg(self):
# args equal to defaults are omitted from the results
predicted = {
"url": "https://ofxget.test.com",
- "ofxhome": "123",
"org": "TEST",
"fid": "321",
"brokerid": "test.com",
@@ -893,177 +891,6 @@ def testString2config(self):
self.assertEqual(ofxget.arg2config(cfg, str, "Something"), "Something")
-class MergeConfigTestCase(unittest.TestCase):
- @property
- def args(self):
- return argparse.Namespace(
- server="2big2fail",
- dtstart="20070101000000",
- dtend="20071231000000",
- dtasof="20071231000000",
- checking=None,
- savings=["444"],
- moneymrkt=None,
- creditline=None,
- creditcard=["555"],
- investment=["666"],
- inctran=True,
- incoo=False,
- incpos=True,
- incbal=True,
- dryrun=True,
- user=None,
- clientuid=None,
- unclosedelements=False,
- )
-
- @classmethod
- def setUpClass(cls):
- # Monkey-patch ofxget.USERCFG
- default_cfg = """
- [2big2fail]
- ofxhome = 417
- version = 203
- pretty = true
- fid = 44
- org = 2big2fail
- """
-
- user_cfg = """
- [2big2fail]
- fid = 33
- user = porkypig
- savings = 111
- checking = 222, 333
- creditcard = 444, 555
- """
-
- cfg = ofxget.UserConfig()
- cfg.read_string(default_cfg)
- cfg.read_string(user_cfg)
-
- cls._USERCFG = ofxget.USERCFG
- ofxget.USERCFG = cfg
-
- @classmethod
- def tearDownClass(cls):
- # Undo monkey patches for ofxget.USERCFG
- # ofxget.UserConfig = cls._UserConfig
- ofxget.USERCFG = cls._USERCFG
-
- def testMergeConfig(self):
- args = argparse.Namespace(
- server="2big2fail", user="daffyduck", creditcard=["666"]
- )
-
- with patch("ofxtools.ofxhome.lookup") as ofxhome_lookup:
- ofxhome_lookup.return_value = OFXServer(
- id="1",
- name="Two Big Two Fail",
- fid="22",
- org="2BIG2FAIL",
- url="https://ofx.test.com",
- brokerid="2big2fail.com",
- )
-
- merged = ofxget.merge_config(args, ofxget.USERCFG)
-
- # None of args/usercfg/defaultcfg has the URL,
- # so there should have been an OFX Home lookup
- ofxhome_lookup.assert_called_once_with("417")
-
- # ChainMap(args, user_cfg, ofxhome_lookup, DEFAULTS)
- self.assertIsInstance(merged, collections.ChainMap)
- maps = merged.maps
- self.assertEqual(len(maps), 4)
- self.assertEqual(maps[0]["user"], "daffyduck")
- self.assertEqual(maps[1]["user"], "porkypig")
- self.assertEqual(maps[2]["org"], "2BIG2FAIL")
- self.assertEqual(maps[3], ofxget.DEFAULTS)
-
- # Any arg from the the CLI should be available in the merged map.
- self.assertEqual(merged["server"], "2big2fail")
-
- # Args passed from the CLI trump the same args from any other source.
- self.assertEqual(merged["user"], "daffyduck")
-
- # For list-type configs, higher-priority config overrides
- # lower-priority config (i.e. it's not appended).
- self.assertEqual(merged["creditcard"], ["666"])
-
- # Args missing from CLI fall back to user config...
- self.assertEqual(merged["savings"], ["111"])
-
- # ...or, failing that, fall back to library default config...
- self.assertEqual(merged["org"], "2big2fail")
-
- # ...or, failing that, fall back to ofxhome lookup
- self.assertEqual(merged["brokerid"], "2big2fail.com")
-
- # ...or, failing THAT, fall back to ofxget.DEFAULTS
- self.assertEqual(merged["unsafe"], False)
-
- # User config trumps library default config and ofxhome lookup
- self.assertEqual(merged["fid"], "33")
-
- # Library default config trumps ofxhome lookup
- self.assertEqual(merged["org"], "2big2fail")
-
- # Library default config drumps ofxget.DEFAULTS
- # Also, INI bool conversion works
- self.assertEqual(merged["pretty"], True)
-
- # INI list chunking works
- self.assertEqual(maps[1]["checking"], ["222", "333"])
-
- # INI int conversion works
- self.assertEqual(maps[1]["version"], 203)
-
- # We have proper types for all lists, even absent configuration
- for lst in (
- "checking",
- "savings",
- "moneymrkt",
- "creditline",
- "creditcard",
- "investment",
- "years",
- ):
- self.assertIsInstance(merged[lst], list)
-
- # We have proper types for all bools, even absent configuration
- for boole in (
- "dryrun",
- "unsafe",
- "unclosedelements",
- "pretty",
- "inctran",
- "incbal",
- "incpos",
- "incoo",
- "all",
- "write",
- ):
- self.assertIsInstance(merged[boole], bool)
-
- # We have default empty string for all unset string configs
- for string in (
- "appid",
- "appver",
- "bankid",
- "clientuid",
- "language",
- "acctnum",
- "recid",
- ):
- self.assertEqual(merged[string], "")
-
- def testMergeConfigUnknownFiArg(self):
- args = argparse.Namespace(server="3big4fail")
- with self.assertRaises(ValueError):
- ofxget.merge_config(args, ofxget.USERCFG)
-
-
###############################################################################
# PROFILE SCAN
###############################################################################
diff --git a/tests/test_ofxhome.py b/tests/test_ofxhome.py
deleted file mode 100644
index 34eda70..0000000
--- a/tests/test_ofxhome.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# coding: utf-8
-""" Unit tests for ofxtools.ofxhome """
-
-# stdlib imports
-import unittest
-from unittest.mock import patch
-from io import BytesIO
-from collections import OrderedDict
-from datetime import datetime
-
-# local imports
-from ofxtools import ofxhome
-
-
-class ListInstitutionsTestCase(unittest.TestCase):
- def test(self):
- mock_xml = BytesIO(
- b"""
-
-
-
-
- """
- )
-
- with patch("urllib.request.urlopen") as mock_urlopen:
- mock_urlopen.return_value = mock_xml
- lst = ofxhome.list_institutions()
-
- self.assertEqual(
- lst,
- OrderedDict([("1234", "American Express"), ("2222", "Bank of America")]),
- )
-
-
-class LookupTestCase(unittest.TestCase):
- def test(self):
- mock_xml = BytesIO(
- b"""
-
- American Express Card
- 3101
- AMEX
- https://online.americanexpress.com/myca/ofxdl/desktop/desktopDownload.do?request_type=nl_ofxdownload
- 0
- 0
- 2019-04-29 23:08:45
- 2019-04-29 23:08:44
-
-
- """
- )
-
- with patch("urllib.request.urlopen") as mock_urlopen:
- mock_urlopen.return_value = mock_xml
- lookup = ofxhome.lookup("424")
-
- self.assertIsInstance(lookup, ofxhome.OFXServer)
- self.assertEqual(lookup.id, "424")
- self.assertEqual(lookup.name, "American Express Card")
- self.assertEqual(lookup.fid, "3101")
- self.assertEqual(lookup.org, "AMEX")
- self.assertEqual(
- lookup.url,
- "https://online.americanexpress.com/myca/ofxdl/desktop/desktopDownload.do?request_type=nl_ofxdownload",
- )
- self.assertEqual(lookup.ofxfail, False)
- self.assertEqual(lookup.sslfail, False)
- self.assertEqual(lookup.lastofxvalidation, datetime(2019, 4, 29, 23, 8, 45))
- self.assertEqual(lookup.lastsslvalidation, datetime(2019, 4, 29, 23, 8, 44))
- self.assertEqual(
- lookup.profile,
- {
- "finame": "American Express",
- "addr1": "777 American Expressway",
- "city": "Fort Lauderdale",
- "state": "Fla.",
- "postalcode": "33337-0001",
- "country": "USA",
- "csphone": "1-800-AXP-7500 (1-800-297-7500)",
- "url": "https://online.americanexpress.com/myca/ofxdl/desktop/desktopDownload.do?request_type=nl_ofxdownload",
- "signonmsgset": True,
- "bankmsgset": True,
- "creditcardmsgset": True,
- },
- )
-
-
-class FetchFiXmlTestCase(unittest.TestCase):
- pass
-
-
-class OfxInvalidTestCase(unittest.TestCase):
- pass
-
-
-class SslInvalidTestCase(unittest.TestCase):
- pass
-
-
-if __name__ == "__main__":
- unittest.main()