Skip to content

Commit 79c024e

Browse files
s-cellesdavidastephens
authored andcommitted
CLN: Split into subpackages
1 parent df405e2 commit 79c024e

File tree

14 files changed

+1284
-1234
lines changed

14 files changed

+1284
-1234
lines changed

pandas_datareader/common.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import time
2+
import warnings
3+
import numpy as np
4+
import datetime as dt
5+
6+
from pandas import to_datetime
7+
import pandas.compat as compat
8+
from pandas.core.common import PandasError
9+
from pandas import Panel, DataFrame
10+
from pandas.io.common import urlopen
11+
from pandas import read_csv
12+
from pandas.compat import StringIO, bytes_to_str
13+
from pandas.util.testing import _network_error_classes
14+
15+
16+
class SymbolWarning(UserWarning):
17+
pass
18+
19+
class RemoteDataError(PandasError, IOError):
20+
pass
21+
22+
def _get_data_from(symbols, start, end, interval, retry_count, pause,
23+
chunksize, src_fn):
24+
25+
# If a single symbol, (e.g., 'GOOG')
26+
if isinstance(symbols, (compat.string_types, int)):
27+
hist_data = src_fn(symbols, start, end, interval, retry_count, pause)
28+
# Or multiple symbols, (e.g., ['GOOG', 'AAPL', 'MSFT'])
29+
elif isinstance(symbols, DataFrame):
30+
hist_data = _dl_mult_symbols(symbols.index, start, end, interval, chunksize,
31+
retry_count, pause, src_fn)
32+
else:
33+
hist_data = _dl_mult_symbols(symbols, start, end, interval, chunksize,
34+
retry_count, pause, src_fn)
35+
return hist_data
36+
37+
def _dl_mult_symbols(symbols, start, end, interval, chunksize, retry_count, pause,
38+
method):
39+
stocks = {}
40+
failed = []
41+
passed = []
42+
for sym_group in _in_chunks(symbols, chunksize):
43+
for sym in sym_group:
44+
try:
45+
stocks[sym] = method(sym, start, end, interval, retry_count, pause)
46+
passed.append(sym)
47+
except IOError:
48+
warnings.warn('Failed to read symbol: {0!r}, replacing with '
49+
'NaN.'.format(sym), SymbolWarning)
50+
failed.append(sym)
51+
52+
if len(passed) == 0:
53+
raise RemoteDataError("No data fetched using "
54+
"{0!r}".format(method.__name__))
55+
try:
56+
if len(stocks) > 0 and len(failed) > 0 and len(passed) > 0:
57+
df_na = stocks[passed[0]].copy()
58+
df_na[:] = np.nan
59+
for sym in failed:
60+
stocks[sym] = df_na
61+
return Panel(stocks).swapaxes('items', 'minor')
62+
except AttributeError:
63+
# cannot construct a panel with just 1D nans indicating no data
64+
raise RemoteDataError("No data fetched using "
65+
"{0!r}".format(method.__name__))
66+
67+
68+
def _sanitize_dates(start, end):
69+
"""
70+
Return (datetime_start, datetime_end) tuple
71+
if start is None - default is 2010/01/01
72+
if end is None - default is today
73+
"""
74+
start = to_datetime(start)
75+
end = to_datetime(end)
76+
if start is None:
77+
start = dt.datetime(2010, 1, 1)
78+
if end is None:
79+
end = dt.datetime.today()
80+
return start, end
81+
82+
def _in_chunks(seq, size):
83+
"""
84+
Return sequence in 'chunks' of size defined by size
85+
"""
86+
return (seq[pos:pos + size] for pos in range(0, len(seq), size))
87+
88+
def _retry_read_url(url, retry_count, pause, name):
89+
"""
90+
Open url (and retry)
91+
"""
92+
for _ in range(retry_count):
93+
time.sleep(pause)
94+
95+
# kludge to close the socket ASAP
96+
try:
97+
with urlopen(url) as resp:
98+
lines = resp.read()
99+
except _network_error_classes:
100+
pass
101+
else:
102+
rs = read_csv(StringIO(bytes_to_str(lines)), index_col=0,
103+
parse_dates=True, na_values='-')[::-1]
104+
# Yahoo! Finance sometimes does this awesome thing where they
105+
# return 2 rows for the most recent business day
106+
if len(rs) > 2 and rs.index[-1] == rs.index[-2]: # pragma: no cover
107+
rs = rs[:-1]
108+
109+
#Get rid of unicode characters in index name.
110+
try:
111+
rs.index.name = rs.index.name.decode('unicode_escape').encode('ascii', 'ignore')
112+
except AttributeError:
113+
#Python 3 string has no decode method.
114+
rs.index.name = rs.index.name.encode('ascii', 'ignore').decode()
115+
116+
return rs
117+
118+
raise IOError("after %d tries, %s did not "
119+
"return a 200 for url %r" % (retry_count, name, url))

0 commit comments

Comments
 (0)