Skip to content

Commit cfb55fb

Browse files
committed
Merge pull request pandas-dev#89 from manahl/python3
Python3 support
2 parents bb74aab + aead1e9 commit cfb55fb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+326
-206
lines changed

.travis.yml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
sudo: false
2+
language: python
3+
python:
4+
- "2.7"
5+
- "3.3"
6+
install:
7+
- pip install --upgrade pip
8+
- pip install python-dateutil --upgrade
9+
- pip install pytz --upgrade
10+
- pip install tzlocal --upgrade
11+
- pip install cython --upgrade
12+
- pip install pymongo --upgrade
13+
- pip install numpy --upgrade
14+
- pip install pandas --upgrade
15+
- pip install decorator --upgrade
16+
- pip install enum34 --upgrade
17+
- pip install lz4 --upgrade
18+
- pip install mock --upgrade
19+
- pip install mockextras
20+
- pip install pytest --upgrade
21+
- pip install pytest-cov --upgrade
22+
- pip install pytest-dbfixtures --upgrade
23+
- pip install pytest-timeout --upgrade
24+
- pip install pytest-xdist --upgrade
25+
- pip install setuptools-git --upgrade
26+
script: python setup.py test

CHANGES.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## Changelog
22

3+
### 1.19
4+
5+
* Feature: Add python 3.3 support
6+
37
### 1.18 (2016-01-05)
48

59
* Bugfix: #81 Fix broken read of multi-index DataFrame written by old version of Arctic

README.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ shows how.](howtos/how_to_custom_arctic_library.py)
7171

7272
Arctic provides namespaced *libraries* of data. These libraries allow
7373
bucketing data by *source*, *user* or some other metric (for example frequency:
74-
End-Of-Day; Minute Bars; etc.).
74+
End-Of-Day; Minute Bars; etc.).
7575

7676
Arctic supports multiple data libraries per user. A user (or namespace)
7777
maps to a MongoDB database (the granularity of mongo authentication). The library
@@ -105,7 +105,7 @@ Arctic storage implementations are **pluggable**. VersionStore is the default.
105105

106106
Arctic currently works with:
107107

108-
* Python 2.7
108+
* Python 2.7 or 3.3
109109
* pymongo >= 3.0
110110
* Pandas
111111
* MongoDB >= 2.4.x
@@ -133,4 +133,3 @@ Contributions welcome!
133133
## License
134134

135135
Arctic is licensed under the GNU LGPL v2.1. A copy of which is included in [LICENSE](LICENSE)
136-

arctic/_compression.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
try:
88
from . import _compress as clz4
99
except ImportError:
10-
logger.warn("Couldn't import cython lz4")
10+
logger.warning("Couldn't import cython lz4")
1111
import lz4 as clz4
1212

1313

arctic/_util.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
from pandas import DataFrame
22
from pandas.util.testing import assert_frame_equal
33
from pymongo.errors import OperationFailure
4-
import string
54
import logging
65

76
logger = logging.getLogger(__name__)
87

98

109
def indent(s, num_spaces):
11-
s = string.split(s, '\n')
10+
s = s.split('\n')
1211
s = [(num_spaces * ' ') + line for line in s]
13-
s = string.join(s, '\n')
12+
s = '\n'.join(s)
1413
return s
1514

1615

@@ -31,7 +30,7 @@ def enable_sharding(arctic, library_name, hashed=False):
3130
library_name = lib.get_top_level_collection().name
3231
try:
3332
c.admin.command('enablesharding', dbname)
34-
except OperationFailure, e:
33+
except OperationFailure as e:
3534
if not 'failed: already enabled' in str(e):
3635
raise
3736
if not hashed:

arctic/arctic.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from .hooks import get_mongodb_uri
1212
from .store import version_store
1313
from .tickstore import tickstore, toplevel
14+
from six import string_types
1415

1516

1617
__all__ = ['Arctic', 'VERSION_STORE', 'TICK_STORE', 'register_library_type']
@@ -92,7 +93,7 @@ def __init__(self, mongo_host, app_name=APPLICATION_NAME, allow_secondary=False,
9293
self._server_selection_timeout = serverSelectionTimeoutMS
9394
self._lock = threading.Lock()
9495

95-
if isinstance(mongo_host, basestring):
96+
if isinstance(mongo_host, string_types):
9697
self.mongo_host = mongo_host
9798
else:
9899
self.__conn = mongo_host
@@ -230,7 +231,7 @@ def get_library(self, library):
230231
error = None
231232
l = ArcticLibraryBinding(self, library)
232233
lib_type = l.get_library_type()
233-
except (OperationFailure, AutoReconnect), e:
234+
except (OperationFailure, AutoReconnect) as e:
234235
error = e
235236

236237
if error:
@@ -249,7 +250,7 @@ def get_library(self, library):
249250
return self._library_cache[library]
250251

251252
def __getitem__(self, key):
252-
if isinstance(key, basestring):
253+
if isinstance(key, string_types):
253254
return self.get_library(key)
254255
else:
255256
raise ArcticException("Unrecognised library specification - use [libraryName]")
@@ -424,18 +425,18 @@ def to_gigabytes(bytes_):
424425
to_gigabytes(self.quota)))
425426

426427
# Quota not exceeded, print an informational message and return
427-
avg_size = size / count if count > 1 else 100 * 1024
428+
avg_size = size // count if count > 1 else 100 * 1024
428429
remaining = self.quota - size
429430
remaining_count = remaining / avg_size
430431
if remaining_count < 100:
431-
logger.warn("Mongo Quota: %.3f / %.0f GB used" % (to_gigabytes(size),
432+
logger.warning("Mongo Quota: %.3f / %.0f GB used" % (to_gigabytes(size),
432433
to_gigabytes(self.quota)))
433434
else:
434435
logger.info("Mongo Quota: %.3f / %.0f GB used" % (to_gigabytes(size),
435436
to_gigabytes(self.quota)))
436437

437438
# Set-up a timer to prevent us for checking for a few writes.
438-
self.quota_countdown = max(remaining_count / 2, 1)
439+
self.quota_countdown = int(max(remaining_count // 2, 1))
439440

440441
def get_library_type(self):
441442
return self.get_library_metadata(ArcticLibraryBinding.TYPE_FIELD)

arctic/auth.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ def get_auth(host, app_name, database_name):
2626
"""
2727
Authentication hook to allow plugging in custom authentication credential providers
2828
"""
29-
from hooks import _get_auth_hook
29+
from .hooks import _get_auth_hook
3030
return _get_auth_hook(host, app_name, database_name)

arctic/date/_daterange.py

+7
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ def __eq__(self, rhs):
170170
return False
171171
return self.end == rhs.end and self.start == rhs.start
172172

173+
def __lt__(self, other):
174+
if self.start is None:
175+
return True
176+
if other.start is None:
177+
return False
178+
return self.start < other.start
179+
173180
def __hash__(self):
174181
return hash((self.start, self.end, self.step, self.interval))
175182

arctic/date/_util.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
from ._generalslice import OPEN_OPEN, CLOSED_CLOSED, OPEN_CLOSED, CLOSED_OPEN
77
from ._parse import parse
88
from ._mktz import mktz
9+
import sys
10+
if sys.version_info > (3,):
11+
long = int
912

10-
13+
1114
# Support standard brackets syntax for open/closed ranges.
1215
Ranges = {'()': OPEN_OPEN,
1316
'(]': OPEN_CLOSED,

arctic/decorators.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def _handle_error(f, e, retry_count, **kwargs):
8181
logger.error('Too many retries %s [%s], raising' % (f.__name__, e))
8282
e.traceback = sys.exc_info()[2]
8383
raise
84-
log_fn = logger.warn if retry_count > 2 else logger.debug
84+
log_fn = logger.warning if retry_count > 2 else logger.debug
8585
log_fn('%s %s [%s], retrying %i' % (type(e), f.__name__, e, retry_count))
8686
# Log operation failure errors
8787
_log_exception(f.__name__, e, retry_count, **kwargs)

arctic/fixtures/mongo.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import os
2020
import pytest
2121

22-
from path import path
22+
from path import Path as path
2323
from tempfile import mkdtemp
2424

2525
from pytest_dbfixtures.executors import TCPExecutor

arctic/hosts.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import re
55
import logging
66
from weakref import WeakValueDictionary
7+
import six
78

89
__all__ = ['get_arctic_lib', 'get_arctic_for_library']
910

@@ -41,7 +42,7 @@ def get_arctic_lib(connection_string, **kwargs):
4142

4243
def _get_arctic(instance, **kwargs):
4344
# Consider any kwargs passed to the Arctic as discriminators for the cache
44-
key = instance, frozenset(kwargs.iteritems())
45+
key = instance, frozenset(six.iteritems(kwargs))
4546

4647
# Don't create lots of Arctic instances
4748
arctic = arctic_cache.get(key, None)

arctic/multi_index.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import numpy as np
1111
import pandas as pd
12+
import six
1213

1314

1415
logger = logging.getLogger(__name__)
@@ -42,7 +43,7 @@ def fancy_group_by(df, grouping_level=0, aggregate_level=1, method='last', max_=
4243
if method not in ('first', 'last'):
4344
raise ValueError('Invalid method')
4445

45-
if isinstance(aggregate_level, basestring):
46+
if isinstance(aggregate_level, six.string_types):
4647
aggregate_level = df.index.names.index(aggregate_level)
4748

4849
# Trim any rows outside the aggregate value bounds

arctic/scripts/arctic_create_user.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def main():
3737
write_access = args.write
3838
p = args.password
3939
if p is None:
40-
p = base64.b64encode(uuid.uuid4().bytes).replace('/', '')[:12]
40+
p = base64.b64encode(uuid.uuid4().bytes).replace(b'/', b'')[:12]
4141
db = args.db
4242
if not db:
4343
# Users always have write access to their database

arctic/scripts/arctic_delete_library.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from __future__ import print_function
12
import optparse
23
import pymongo
34
import logging
@@ -28,7 +29,7 @@ def main():
2829
if not opts.library:
2930
parser.error('Must specify the full path of the library e.g. arctic_jblackburn.lib!')
3031

31-
print "Deleting: %s on mongo %s" % (opts.library, opts.host)
32+
print("Deleting: %s on mongo %s" % (opts.library, opts.host))
3233
c = pymongo.MongoClient(get_mongodb_uri(opts.host))
3334

3435
db_name = opts.library[:opts.library.index('.')] if '.' in opts.library else None

arctic/scripts/arctic_enable_sharding.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from __future__ import print_function
12
import optparse
23
import pymongo
34

@@ -25,7 +26,7 @@ def main():
2526
if not opts.library or '.' not in opts.library:
2627
parser.error('must specify the full path of the library e.g. arctic_jblackburn.lib!')
2728

28-
print "Enabling-sharding: %s on mongo %s" % (opts.library, opts.host)
29+
print("Enabling-sharding: %s on mongo %s" % (opts.library, opts.host))
2930

3031
c = pymongo.MongoClient(get_mongodb_uri(opts.host))
3132
credentials = get_auth(opts.host, 'admin', 'admin')

arctic/scripts/arctic_init_library.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from __future__ import print_function
12
import argparse
23
import pymongo
34
import logging
@@ -36,7 +37,7 @@ def main():
3637
parser.error('Must specify the full path of the library e.g. user.library!')
3738
db_name, _ = ArcticLibraryBinding._parse_db_lib(opts.library)
3839

39-
print "Initializing: %s on mongo %s" % (opts.library, opts.host)
40+
print("Initializing: %s on mongo %s" % (opts.library, opts.host))
4041
c = pymongo.MongoClient(get_mongodb_uri(opts.host))
4142

4243
if not do_db_auth(opts.host, c, db_name):

arctic/scripts/arctic_prune_versions.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from __future__ import print_function
12
import optparse
23
import pymongo
34
import logging
@@ -36,8 +37,8 @@ def main():
3637
parser.error('Must specify the Arctic library e.g. arctic_jblackburn.library!')
3738
db_name, _ = ArcticLibraryBinding._parse_db_lib(opts.library)
3839

39-
print "Pruning (old) versions in : %s on mongo %s" % (opts.library, opts.host)
40-
print "Keeping all versions <= %s mins old" % (opts.keep_mins)
40+
print("Pruning (old) versions in : %s on mongo %s" % (opts.library, opts.host))
41+
print("Keeping all versions <= %s mins old" % (opts.keep_mins))
4142
c = pymongo.MongoClient(get_mongodb_uri(opts.host))
4243

4344
if not do_db_auth(opts.host, c, db_name):

arctic/store/_ndarray_store.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import logging
22
import hashlib
3-
import pprint
43

54
from bson.binary import Binary
65
import numpy as np
@@ -13,6 +12,8 @@
1312

1413
from .._compression import compress_array, decompress
1514
from ..exceptions import ConcurrentModificationException
15+
from six.moves import xrange
16+
1617

1718
logger = logging.getLogger(__name__)
1819

@@ -116,7 +117,7 @@ def _ensure_index(collection):
116117
collection.create_index([('symbol', pymongo.ASCENDING),
117118
('parent', pymongo.ASCENDING),
118119
('segment', pymongo.ASCENDING)], unique=True, background=True)
119-
except OperationFailure, e:
120+
except OperationFailure as e:
120121
if "can't use unique indexes" in str(e):
121122
return
122123
raise
@@ -199,7 +200,7 @@ def _do_read(self, collection, version, symbol, index_range=None):
199200
collection.find_one({'_id': x['_id']}),
200201
collection.find_one({'_id': x['_id']}))
201202
raise
202-
data = ''.join(segments)
203+
data = b''.join(segments)
203204

204205
# Check that the correct number of segments has been returned
205206
if segment_count is not None and i + 1 != segment_count:
@@ -401,7 +402,7 @@ def _do_write(self, collection, version, symbol, item, previous_version, segment
401402
sze = int(item.dtype.itemsize * np.prod(item.shape[1:]))
402403

403404
# chunk and store the data by (uncompressed) size
404-
chunk_size = _CHUNK_SIZE / sze
405+
chunk_size = int(_CHUNK_SIZE / sze)
405406

406407
previous_shas = []
407408
if previous_version:

arctic/store/_pandas_ndarray_store.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def _index_to_records(self, df):
3939
if isinstance(index, MultiIndex):
4040
# array of tuples to numpy cols. copy copy copy
4141
if len(df) > 0:
42-
ix_vals = map(np.array, [index.get_level_values(i) for i in range(index.nlevels)])
42+
ix_vals = list(map(np.array, [index.get_level_values(i) for i in range(index.nlevels)]))
4343
else:
4444
# empty multi index has no size, create empty arrays for recarry..
4545
ix_vals = [np.array([]) for n in index.names]
@@ -93,7 +93,7 @@ def to_records(self, df):
9393
metadata['columns'] = columns
9494
names = index_names + columns
9595
arrays = ix_vals + column_vals
96-
arrays = map(_to_primitive, arrays)
96+
arrays = list(map(_to_primitive, arrays))
9797
dtype = np.dtype([(str(x), v.dtype) if len(v.shape) == 1 else (str(x), v.dtype, v.shape[1]) for x, v in zip(names, arrays)],
9898
metadata=metadata)
9999

@@ -186,7 +186,7 @@ def _index_range(self, version, symbol, date_range=None, **kwargs):
186186
return -1, -1
187187
idxstart = min(np.searchsorted(dts, start), len(dts) - 1)
188188
idxend = min(np.searchsorted(dts, end), len(dts) - 1)
189-
return index['index'][idxstart], index['index'][idxend] + 1
189+
return int(index['index'][idxstart]), int(index['index'][idxend] + 1)
190190
return super(PandasStore, self)._index_range(version, symbol, **kwargs)
191191

192192
def _daterange(self, recarr, date_range):

0 commit comments

Comments
 (0)