8000 minor improvements, more tests · matplotlib/matplotlib@601f8e8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 601f8e8

Browse files
committed
minor improvements, more tests
1 parent 9b0f34b commit 601f8e8

File tree

2 files changed

+265
-37
lines changed

2 files changed

+265
-37
lines changed

lib/matplotlib/dates.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -308,16 +308,16 @@ def get_epoch():
308308
return _epoch
309309

310310

311-
def _dt64_to_ordinalf(d, *, is_timedelta=False):
311+
def _to_ordinalf(d, *, is_timedelta=False):
312312
"""
313313
Convert `numpy.datetime64` or an `numpy.ndarray` of those types to
314314
Gregorian date as UTC float relative to the epoch (see `.get_epoch`).
315315
Roundoff is float64 precision. Practically: microseconds for dates
316316
between 290301 BC, 294241 AD, milliseconds for larger dates
317317
(see `numpy.datetime64`).
318-
`is_timedelta` indicates that the converted values are timedelta instead
319-
of datetime. The converted floating point timedelta values are relative
320-
to `timedelta(0)`.
318+
If `is_timedelta=True`, converts `numpy.timedelta64` or an `numpy.ndarray`
319+
of those types to float. The converted floating point timedelta values are
320+
relative to `timedelta(0)`.
321321
"""
322322

323323
# the "extra" ensures that we at least allow the dynamic range out to
@@ -336,11 +336,7 @@ def _dt64_to_ordinalf(d, *, is_timedelta=False):
336336

337337
NaT_int = np.datetime64('NaT').astype(np.int64)
338338
t_int = d.astype(np.int64)
339-
try:
340-
dt[t_int == NaT_int] = np.nan
341-
except TypeError:
342-
if t_int == NaT_int:
343-
dt = np.nan
339+
dt[t_int == NaT_int] = np.nan
344340

345341
return dt
346342

@@ -486,7 +482,7 @@ def _timevalue2num(v, *, is_timedelta=False):
486482
elif not is_timedelta and not np.issubdtype(v.dtype, np.datetime64):
487483
# datetime arrays
488484
if not v.size:
489-
# deals with an empty array...
485+
# deals with an empty array; only required for datetime
490486
return v
491487
tzi = getattr(v[0], 'tzinfo', None)
492488
if tzi is not None:
@@ -496,7 +492,7 @@ def _timevalue2num(v, *, is_timedelta=False):
496492
v = v.astype('datetime64[us]')
497493

498494
v = np.ma.masked_array(v, mask=mask) if masked else v
499-
v = _dt64_to_ordinalf(v, is_timedelta=is_timedelta)
495+
v = _to_ordinalf(v, is_timedelta=is_timedelta)
500496

501497
return v if iterable else v[0]
502498

@@ -704,8 +700,10 @@ def strftimedelta(td, fmt_str):
704700

705701
try:
706702
result = _TimedeltaFormatTemplate(fmt_str).substitute(**values)
707-
except KeyError:
708-
raise ValueError(f"Invalid format string '{fmt_str}' for timedelta")
703+
except ValueError as exc:
704+
# show a more understandable error message
705+
exc.args = (f"Invalid format string '{fmt_str}' for timedelta", )
706+
raise exc
709707
return sign + result
710708

711709

@@ -785,6 +783,7 @@ def __init__(self, locator, show_offset=True, *, usetex=None):
785783
self.offset_string = ''
786784
self.show_offset = show_offset
787785
self._usetex = mpl._val_or_rc(usetex, 'text.usetex')
786+
self._zerovals = [None, None, None, None, None, None, None]
788787

789788
self.formats = list()
790789
self.zero_formats = list()
@@ -826,11 +825,10 @@ def _format_ticks(self, tickvalue, ticktuple):
826825

827826
# level is the basic level we will label at.
828827
# now loop through and decide the actual ticklabels
829-
zerovals = [0, 1, 1, 0, 0, 0, 0]
830828
labels = [''] * len(ticktuple)
831829
for nn in range(len(ticktuple)):
832830
if level < 5:
833-
if ticktuple[nn][level] == zerovals[level]:
831+
if ticktuple[nn][level] == self._zerovals[level]:
834832
fmt = zerofmts[level]
835833
else:
836834
fmt = fmts[level]
@@ -964,6 +962,9 @@ def __init__(self, locator, tz=None, formats=None, offset_formats=None,
964962
"""
965963
super().__init__(locator, show_offset=show_offset, usetex=usetex)
966964
self._tz = tz
965+
# zerovals are values that are zeros for a given tick level, for dates,
966+
# months and days start at 1, while hours, minutes, ... start at 0
967+
self._zerovals = [0, 1, 1, 0, 0, 0, 0]
967968
self.defaultfmt = '%Y'
968969
# there are 6 levels with each level getting a specific format
969970
# 0: mostly years, 1: months, 2: days,
@@ -1038,7 +1039,10 @@ def __init__(self, locator, formats=None, offset_formats=None,
10381039
initial string, and then redundant elements are removed.
10391040
"""
10401041
super().__init__(locator, show_offset=show_offset, usetex=usetex)
1041-
self.defaultfmt = '%{d}D'
1042+
# zerovals are values that are zeros for a given tick level. For
1043+
# timedelta, this is always 0
1044+
self._zerovals = [0, 0, 0, 0, 0, 0, 0]
1045+
self.defaultfmt = '%d d'
10421046
# there are 6 levels with each level getting a specific format
10431047
# 0: mostly years, 1: months, 2: days,
10441048
# 3: hours, 4: minutes, 5: seconds
@@ -1049,7 +1053,7 @@ def __init__(self, locator, formats=None, offset_formats=None,
10491053
'4 format strings (or None)')
10501054
self.formats = formats
10511055
else:
1052-
self.formats = ['%{d} days', # days
1056+
self.formats = ['%d d', # days
10531057
'%-H:%M', # hours
10541058
'%-H:%M', # minutes
10551059
'%-S.%f', # secs
@@ -1064,7 +1068,7 @@ def __init__(self, locator, formats=None, offset_formats=None,
10641068
self.zero_formats = zero_formats
10651069
else:
10661070
# use the users formats for the zero tick formats
1067-
self.zero_formats = [''] + self.formats[:-1]
1071+
self.zero_formats = ['%d d'] + self.formats[:-1]
10681072

10691073
if offset_formats:
10701074
if len(offset_formats) != 4:
@@ -1074,8 +1078,8 @@ def __init__(self, locator, formats=None, offset_formats=None,
10741078
else:
10751079
self.offset_formats = ['',
10761080
'',
1077-
'%{d} days',
1078-
'%{d} days %-H:%M']
1081+
'%d days',
1082+
'%d days %-H:%M']
10791083

10801084
def __call__(self, x, pos=None):
10811085
formatter = TimedeltaFormatter(self.defaultfmt, usetex=self._usetex)
@@ -1107,7 +1111,7 @@ def format_ticks(self, values):
11071111
return super()._format_ticks(ticktimedelta, ticktuple)
11081112

11091113
def format_data_short(self, value):
1110-
return strftimedelta(num2timedelta(value), '%{d}D %H:%M:%S')
1114+
return strftimedelta(num2timedelta(value), '%d d %H:%M:%S')
11111115

11121116
def _format_string(self, value, fmt):
11131117
return strftimedelta(value, fmt)
@@ -2121,7 +2125,7 @@ class TimedeltaLocator(ticker.MultipleLocator):
21212125
locator = TimedeltaLocator(HOURLY, 4)
21222126
"""
21232127
default_range = (timedelta2num(datetime.timedelta(days=0)),
2124-
timedelta2num(datetime.timedelta(days=10)))
2128+
timedelta2num(datetime.timedelta(days=1)))
21252129
"""The default min and max limits of the axis."""
21262130

21272131
_FACTORS = {
@@ -2293,6 +2297,7 @@ def update_from_limits(self, dmin, dmax):
22932297
break
22942298
break
22952299
else:
2300+
# prevent interval from being undefined in case intervald was empty
22962301
interval = 1
22972302
super().set_params(freq=freq, interval=interval)
22982303

0 commit comments

Comments
 (0)
0