Skip to content

Commit fbcf5a4

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 09a7a69 + 2e59e42 commit fbcf5a4

File tree

7 files changed

+72
-20
lines changed

7 files changed

+72
-20
lines changed

doc/source/whatsnew/v0.15.2.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ Bug Fixes
9797
- ``sql_schema`` now generates dialect appropriate ``CREATE TABLE`` statements (:issue:`8697`)
9898
- ``slice`` string method now takes step into account (:issue:`8754`)
9999
- Bug in ``BlockManager`` where setting values with different type would break block integrity (:issue:`8850`)
100+
- Bug in ``DatetimeIndex`` when using ``time`` object as key (:issue:`8667`)
100101
- Fix negative step support for label-based slices (:issue:`8753`)
101102

102103
Old behavior:
@@ -142,7 +143,7 @@ Bug Fixes
142143

143144

144145

145-
146+
- BUG: Option context applies on __enter__ (:issue:`8514`)
146147

147148

148149

pandas/core/common.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,13 @@ def array_equivalent(left, right, strict_nan=False):
404404
405405
Examples
406406
--------
407-
>>> array_equivalent(np.array([1, 2, nan]), np.array([1, 2, nan]))
407+
>>> array_equivalent(
408+
... np.array([1, 2, np.nan]),
409+
... np.array([1, 2, np.nan]))
408410
True
409-
>>> array_equivalent(np.array([1, nan, 2]), np.array([1, 2, nan]))
411+
>>> array_equivalent(
412+
... np.array([1, np.nan, 2]),
413+
... np.array([1, 2, np.nan]))
410414
False
411415
"""
412416

@@ -2171,8 +2175,8 @@ def iterpairs(seq):
21712175
21722176
Examples
21732177
--------
2174-
>>> iterpairs([1, 2, 3, 4])
2175-
[(1, 2), (2, 3), (3, 4)
2178+
>>> list(iterpairs([1, 2, 3, 4]))
2179+
[(1, 2), (2, 3), (3, 4)]
21762180
"""
21772181
# input may not be sliceable
21782182
seq_it = iter(seq)

pandas/core/config.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -385,19 +385,18 @@ def __init__(self, *args):
385385
'option_context(pat, val, [(pat, val), ...)).'
386386
)
387387

388-
ops = list(zip(args[::2], args[1::2]))
388+
self.ops = list(zip(args[::2], args[1::2]))
389+
390+
def __enter__(self):
389391
undo = []
390-
for pat, val in ops:
392+
for pat, val in self.ops:
391393
undo.append((pat, _get_option(pat, silent=True)))
392394

393395
self.undo = undo
394396

395-
for pat, val in ops:
397+
for pat, val in self.ops:
396398
_set_option(pat, val, silent=True)
397399

398-
def __enter__(self):
399-
pass
400-
401400
def __exit__(self, *args):
402401
if self.undo:
403402
for pat, val in self.undo:

pandas/index.pyx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,14 @@ cdef class DatetimeEngine(Int64Engine):
545545
val = _to_i8(val)
546546
return self._get_loc_duplicates(val)
547547
values = self._get_index_values()
548-
conv = _to_i8(val)
549-
loc = values.searchsorted(conv, side='left')
548+
549+
try:
550+
conv = _to_i8(val)
551+
loc = values.searchsorted(conv, side='left')
552+
except TypeError:
553+
self._date_check_type(val)
554+
raise KeyError(val)
555+
550556
if loc == len(values) or util.get_value_at(values, loc) != conv:
551557
raise KeyError(val)
552558
return loc

pandas/tests/test_config.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,3 +425,24 @@ def f3(key):
425425
options.c = 1
426426
self.assertEqual(len(holder), 1)
427427

428+
def test_option_context_scope(self):
429+
# Ensure that creating a context does not affect the existing
430+
# environment as it is supposed to be used with the `with` statement.
431+
# See https://github.com/pydata/pandas/issues/8514
432+
433+
original_value = 60
434+
context_value = 10
435+
option_name = 'a'
436+
437+
self.cf.register_option(option_name, original_value)
438+
439+
# Ensure creating contexts didn't affect the current context.
440+
ctx = self.cf.option_context(option_name, context_value)
441+
self.assertEqual(self.cf.get_option(option_name), original_value)
442+
443+
# Ensure the correct value is available inside the context.
444+
with ctx:
445+
self.assertEqual(self.cf.get_option(option_name), context_value)
446+
447+
# Ensure the current context is reset
448+
self.assertEqual(self.cf.get_option(option_name), original_value)

pandas/tests/test_index.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,6 +1887,27 @@ def test_reindex_preserves_tz_if_target_is_empty_list_or_array(self):
18871887
self.assertEqual(str(index.reindex([])[0].tz), 'US/Eastern')
18881888
self.assertEqual(str(index.reindex(np.array([]))[0].tz), 'US/Eastern')
18891889

1890+
def test_time_loc(self): # GH8667
1891+
from datetime import time
1892+
from pandas.index import _SIZE_CUTOFF
1893+
1894+
ns = _SIZE_CUTOFF + np.array([-100, 100])
1895+
key = time(15, 11, 30)
1896+
start = key.hour * 3600 + key.minute * 60 + key.second
1897+
step = 24 * 3600
1898+
1899+
for n in ns:
1900+
idx = pd.date_range('2014-11-26', periods=n, freq='S')
1901+
ts = pd.Series(np.random.randn(n), index=idx)
1902+
i = np.arange(start, n, step)
1903+
1904+
tm.assert_array_equal(ts.index.get_loc(key), i)
1905+
tm.assert_series_equal(ts[key], ts.iloc[i])
1906+
1907+
left, right = ts.copy(), ts.copy()
1908+
left[key] *= -10
1909+
right.iloc[i] *= -10
1910+
tm.assert_series_equal(left, right)
18901911

18911912
class TestPeriodIndex(Base, tm.TestCase):
18921913
_holder = PeriodIndex

pandas/tseries/index.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,10 @@ def get_value(self, series, key):
12101210

12111211
return self.get_value_maybe_box(series, key)
12121212

1213+
if isinstance(key, time):
1214+
locs = self.indexer_at_time(key)
1215+
return series.take(locs)
1216+
12131217
try:
12141218
return _maybe_box(self, Index.get_value(self, series, key), series, key)
12151219
except KeyError:
@@ -1219,10 +1223,6 @@ def get_value(self, series, key):
12191223
except (TypeError, ValueError, KeyError):
12201224
pass
12211225

1222-
if isinstance(key, time):
1223-
locs = self.indexer_at_time(key)
1224-
return series.take(locs)
1225-
12261226
try:
12271227
return self.get_value_maybe_box(series, key)
12281228
except (TypeError, ValueError, KeyError):
@@ -1250,6 +1250,9 @@ def get_loc(self, key):
12501250
stamp = Timestamp(key, tz=self.tz)
12511251
return self._engine.get_loc(stamp)
12521252

1253+
if isinstance(key, time):
1254+
return self.indexer_at_time(key)
1255+
12531256
try:
12541257
return Index.get_loc(self, key)
12551258
except (KeyError, ValueError):
@@ -1258,9 +1261,6 @@ def get_loc(self, key):
12581261
except (TypeError, KeyError, ValueError):
12591262
pass
12601263

1261-
if isinstance(key, time):
1262-
return self.indexer_at_time(key)
1263-
12641264
try:
12651265
stamp = Timestamp(key, tz=self.tz)
12661266
return self._engine.get_loc(stamp)

0 commit comments

Comments
 (0)