Skip to content

Commit 4d14bca

Browse files
jbrockmendelphofl
authored andcommitted
API: make some Timestamp args keyword-only (pandas-dev#49416)
* API: make some Timestamp args keyword-only * mypy fixup * docstring arg order
1 parent 1da1ac6 commit 4d14bca

File tree

5 files changed

+31
-46
lines changed

5 files changed

+31
-46
lines changed

doc/source/whatsnew/v2.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ See :ref:`install.dependencies` and :ref:`install.optional_dependencies` for mor
133133

134134
Other API changes
135135
^^^^^^^^^^^^^^^^^
136+
- The ``freq``, ``tz``, ``nanosecond``, and ``unit`` keywords in the :class:`Timestamp` constructor are now keyword-only (:issue:`45307`)
136137
- Passing ``nanoseconds`` greater than 999 or less than 0 in :class:`Timestamp` now raises a ``ValueError`` (:issue:`48538`, :issue:`48255`)
137138
- :func:`read_csv`: specifying an incorrect number of columns with ``index_col`` of now raises ``ParserError`` instead of ``IndexError`` when using the c parser.
138139
- Default value of ``dtype`` in :func:`get_dummies` is changed to ``bool`` from ``uint8`` (:issue:`45848`)

pandas/_libs/tslibs/timestamps.pyi

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,19 @@ class Timestamp(datetime):
3737
def __new__( # type: ignore[misc]
3838
cls: type[_DatetimeT],
3939
ts_input: np.integer | float | str | _date | datetime | np.datetime64 = ...,
40-
freq: int | None | str | BaseOffset = ...,
41-
tz: str | _tzinfo | None | int = ...,
42-
unit: str | int | None = ...,
4340
year: int | None = ...,
4441
month: int | None = ...,
4542
day: int | None = ...,
4643
hour: int | None = ...,
4744
minute: int | None = ...,
4845
second: int | None = ...,
4946
microsecond: int | None = ...,
50-
nanosecond: int | None = ...,
5147
tzinfo: _tzinfo | None = ...,
5248
*,
49+
nanosecond: int | None = ...,
50+
freq: int | None | str | BaseOffset = ...,
51+
tz: str | _tzinfo | None | int = ...,
52+
unit: str | int | None = ...,
5353
fold: int | None = ...,
5454
) -> _DatetimeT | NaTType: ...
5555
def _set_freq(self, freq: BaseOffset | None) -> None: ...

pandas/_libs/tslibs/timestamps.pyx

+17-35
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,10 @@ class Timestamp(_Timestamp):
12421242
----------
12431243
ts_input : datetime-like, str, int, float
12441244
Value to be converted to Timestamp.
1245+
year, month, day : int
1246+
hour, minute, second, microsecond : int, optional, default 0
1247+
tzinfo : datetime.tzinfo, optional, default None
1248+
nanosecond : int, optional, default 0
12451249
freq : str, DateOffset
12461250
Offset which Timestamp will have.
12471251
tz : str, pytz.timezone, dateutil.tz.tzfile or None
@@ -1250,10 +1254,6 @@ class Timestamp(_Timestamp):
12501254
Unit used for conversion if ts_input is of type int or float. The
12511255
valid values are 'D', 'h', 'm', 's', 'ms', 'us', and 'ns'. For
12521256
example, 's' means seconds and 'ms' means milliseconds.
1253-
year, month, day : int
1254-
hour, minute, second, microsecond : int, optional, default 0
1255-
nanosecond : int, optional, default 0
1256-
tzinfo : datetime.tzinfo, optional, default None
12571257
fold : {0, 1}, default None, keyword-only
12581258
Due to daylight saving time, one wall clock time can occur twice
12591259
when shifting from summer to winter time; fold describes whether the
@@ -1480,19 +1480,19 @@ class Timestamp(_Timestamp):
14801480
def __new__(
14811481
cls,
14821482
object ts_input=_no_input,
1483-
object freq=None,
1484-
tz=None,
1485-
unit=None,
14861483
year=None,
14871484
month=None,
14881485
day=None,
14891486
hour=None,
14901487
minute=None,
14911488
second=None,
14921489
microsecond=None,
1493-
nanosecond=None,
14941490
tzinfo_type tzinfo=None,
14951491
*,
1492+
nanosecond=None,
1493+
object freq=None,
1494+
tz=None,
1495+
unit=None,
14961496
fold=None,
14971497
):
14981498
# The parameter list folds together legacy parameter names (the first
@@ -1527,27 +1527,6 @@ class Timestamp(_Timestamp):
15271527
# GH#17690 tzinfo must be a datetime.tzinfo object, ensured
15281528
# by the cython annotation.
15291529
if tz is not None:
1530-
if (is_integer_object(tz)
1531-
and is_integer_object(ts_input)
1532-
and is_integer_object(freq)
1533-
):
1534-
# GH#31929 e.g. Timestamp(2019, 3, 4, 5, 6, tzinfo=foo)
1535-
# TODO(GH#45307): this will still be fragile to
1536-
# mixed-and-matched positional/keyword arguments
1537-
ts_input = datetime(
1538-
ts_input,
1539-
freq,
1540-
tz,
1541-
unit or 0,
1542-
year or 0,
1543-
month or 0,
1544-
day or 0,
1545-
fold=fold or 0,
1546-
)
1547-
nanosecond = hour
1548-
tz = tzinfo
1549-
return cls(ts_input, nanosecond=nanosecond, tz=tz)
1550-
15511530
raise ValueError('Can provide at most one of tz, tzinfo')
15521531

15531532
# User passed tzinfo instead of tz; avoid silently ignoring
@@ -1596,7 +1575,7 @@ class Timestamp(_Timestamp):
15961575
if any(arg is not None for arg in _date_attributes):
15971576
raise ValueError(
15981577
"Cannot pass a date attribute keyword "
1599-
"argument when passing a date string"
1578+
"argument when passing a date string; 'tz' is keyword-only"
16001579
)
16011580

16021581
elif ts_input is _no_input:
@@ -1620,17 +1599,20 @@ class Timestamp(_Timestamp):
16201599

16211600
ts_input = datetime(**datetime_kwargs)
16221601

1623-
elif is_integer_object(freq):
1602+
elif is_integer_object(year):
16241603
# User passed positional arguments:
16251604
# Timestamp(year, month, day[, hour[, minute[, second[,
16261605
# microsecond[, nanosecond[, tzinfo]]]]]])
1627-
ts_input = datetime(ts_input, freq, tz, unit or 0,
1628-
year or 0, month or 0, day or 0, fold=fold or 0)
1629-
nanosecond = hour
1630-
tz = minute
1606+
ts_input = datetime(ts_input, year, month, day or 0,
1607+
hour or 0, minute or 0, second or 0, fold=fold or 0)
16311608
freq = None
16321609
unit = None
16331610

1611+
if nanosecond is None:
1612+
# nanosecond was not passed as a keyword, but may have been
1613+
# passed positionally see test_constructor_nanosecond
1614+
nanosecond = microsecond
1615+
16341616
if getattr(ts_input, 'tzinfo', None) is not None and tz is not None:
16351617
raise ValueError("Cannot pass a datetime or Timestamp with tzinfo with "
16361618
"the tz parameter. Use tz_convert instead.")

pandas/tests/indexes/datetimes/test_scalar_compat.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def test_dti_timestamp_freq_fields(self):
8181

8282
msg = "The 'freq' argument in Timestamp is deprecated"
8383
with tm.assert_produces_warning(FutureWarning, match=msg):
84-
ts = Timestamp(idx[-1], idx.freq)
84+
ts = Timestamp(idx[-1], freq=idx.freq)
8585

8686
msg2 = "Timestamp.freq is deprecated"
8787
with tm.assert_produces_warning(FutureWarning, match=msg2):

pandas/tests/scalar/timestamp/test_constructors.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ def test_constructor_invalid_tz(self):
232232
with pytest.raises(ValueError, match=msg):
233233
Timestamp("2017-10-22", tzinfo=pytz.utc, tz="UTC")
234234

235-
msg = "Invalid frequency:"
235+
msg = "Cannot pass a date attribute keyword argument when passing a date string"
236236
msg2 = "The 'freq' argument"
237237
with pytest.raises(ValueError, match=msg):
238238
# GH#5168
@@ -268,11 +268,15 @@ def test_constructor_positional_with_tzinfo(self):
268268
expected = Timestamp("2020-12-31", tzinfo=timezone.utc)
269269
assert ts == expected
270270

271-
@pytest.mark.xfail(reason="GH#45307")
272271
@pytest.mark.parametrize("kwd", ["nanosecond", "microsecond", "second", "minute"])
273-
def test_constructor_positional_keyword_mixed_with_tzinfo(self, kwd):
272+
def test_constructor_positional_keyword_mixed_with_tzinfo(self, kwd, request):
274273
# TODO: if we passed microsecond with a keyword we would mess up
275274
# xref GH#45307
275+
if kwd != "nanosecond":
276+
# nanosecond is keyword-only as of 2.0, others are not
277+
mark = pytest.mark.xfail(reason="GH#45307")
278+
request.node.add_marker(mark)
279+
276280
kwargs = {kwd: 4}
277281
ts = Timestamp(2020, 12, 31, tzinfo=timezone.utc, **kwargs)
278282

@@ -394,9 +398,7 @@ def test_constructor_fromordinal(self):
394398
tz="UTC",
395399
),
396400
Timestamp(2000, 1, 2, 3, 4, 5, 6, 1, None),
397-
# error: Argument 9 to "Timestamp" has incompatible type "_UTCclass";
398-
# expected "Optional[int]"
399-
Timestamp(2000, 1, 2, 3, 4, 5, 6, 1, pytz.UTC), # type: ignore[arg-type]
401+
Timestamp(2000, 1, 2, 3, 4, 5, 6, 1, pytz.UTC),
400402
],
401403
)
402404
def test_constructor_nanosecond(self, result):

0 commit comments

Comments
 (0)