@@ -1186,6 +1186,7 @@ cdef class Seen:
11861186 bint coerce_numeric # coerce data to numeric
11871187 bint timedelta_ # seen_timedelta
11881188 bint datetimetz_ # seen_datetimetz
1189+ bint period_ # seen_period
11891190
11901191 def __cinit__(self , bint coerce_numeric = False ):
11911192 """
@@ -1210,6 +1211,7 @@ cdef class Seen:
12101211 self .datetime_ = False
12111212 self .timedelta_ = False
12121213 self .datetimetz_ = False
1214+ self .period_ = False
12131215 self .coerce_numeric = coerce_numeric
12141216
12151217 cdef inline bint check_uint64_conflict(self ) except - 1 :
@@ -1996,18 +1998,35 @@ cpdef bint is_time_array(ndarray values, bint skipna=False):
19961998 return validator.validate(values)
19971999
19982000
1999- cdef class PeriodValidator(TemporalValidator):
2000- cdef inline bint is_value_typed(self , object value) except - 1 :
2001- return is_period_object(value)
2001+ cdef bint is_period_array(ndarray[object ] values):
2002+ """
2003+ Is this an ndarray of Period objects (or NaT) with a single `freq`?
2004+ """
2005+ cdef:
2006+ Py_ssize_t i, n = len (values)
2007+ int dtype_code = - 10000 # i.e. c_FreqGroup.FR_UND
2008+ object val
20022009
2003- cdef inline bint is_valid_null( self , object value) except - 1 :
2004- return checknull_with_nat(value)
2010+ if len (values) == 0 :
2011+ return False
20052012
2013+ for val in values:
2014+ if is_period_object(val):
2015+ if dtype_code == - 10000 :
2016+ dtype_code = val._dtype._dtype_code
2017+ elif dtype_code != val._dtype._dtype_code:
2018+ # mismatched freqs
2019+ return False
2020+ elif checknull_with_nat(val):
2021+ pass
2022+ else :
2023+ # Not a Period or NaT-like
2024+ return False
20062025
2007- cpdef bint is_period_array(ndarray values) :
2008- cdef:
2009- PeriodValidator validator = PeriodValidator( len (values), skipna = True )
2010- return validator.validate(values)
2026+ if dtype_code == - 10000 :
2027+ # we saw all-NaTs, no actual Periods
2028+ return False
2029+ return True
20112030
20122031
20132032cdef class IntervalValidator(Validator):
@@ -2249,9 +2268,13 @@ def maybe_convert_numeric(
22492268
22502269@ cython.boundscheck (False )
22512270@ cython.wraparound (False )
2252- def maybe_convert_objects (ndarray[object] objects , bint try_float = False ,
2253- bint safe = False , bint convert_datetime = False ,
2271+ def maybe_convert_objects (ndarray[object] objects ,
2272+ *,
2273+ bint try_float = False ,
2274+ bint safe = False ,
2275+ bint convert_datetime = False ,
22542276 bint convert_timedelta = False ,
2277+ bint convert_period = False ,
22552278 bint convert_to_nullable_integer = False ) -> "ArrayLike":
22562279 """
22572280 Type inference function-- convert object array to proper dtype
@@ -2272,6 +2295,9 @@ def maybe_convert_objects(ndarray[object] objects, bint try_float=False,
22722295 convert_timedelta : bool , default False
22732296 If an array-like object contains only timedelta values or NaT is
22742297 encountered , whether to convert and return an array of m8[ns] dtype.
2298+ convert_period : bool , default False
2299+ If an array-like object contains only (homogeneous-freq ) Period values
2300+ or NaT , whether to convert and return a PeriodArray.
22752301 convert_to_nullable_integer : bool , default False
22762302 If an array-like object contains only integer values (and NaN ) is
22772303 encountered , whether to convert and return an IntegerArray.
@@ -2292,7 +2318,7 @@ def maybe_convert_objects(ndarray[object] objects, bint try_float=False,
22922318 int64_t[:] itimedeltas
22932319 Seen seen = Seen()
22942320 object val
2295- float64_t fval , fnan
2321+ float64_t fval , fnan = np.nan
22962322
22972323 n = len (objects)
22982324
@@ -2311,8 +2337,6 @@ def maybe_convert_objects(ndarray[object] objects, bint try_float=False,
23112337 timedeltas = np.empty(n, dtype = ' m8[ns]' )
23122338 itimedeltas = timedeltas.view(np.int64)
23132339
2314- fnan = np.nan
2315-
23162340 for i in range(n ):
23172341 val = objects[i]
23182342 if itemsize_max != - 1 :
@@ -2330,7 +2354,7 @@ def maybe_convert_objects(ndarray[object] objects, bint try_float=False,
23302354 idatetimes[i] = NPY_NAT
23312355 if convert_timedelta:
23322356 itimedeltas[i] = NPY_NAT
2333- if not (convert_datetime or convert_timedelta):
2357+ if not (convert_datetime or convert_timedelta or convert_period ):
23342358 seen.object_ = True
23352359 break
23362360 elif val is np.nan:
@@ -2343,14 +2367,6 @@ def maybe_convert_objects(ndarray[object] objects, bint try_float=False,
23432367 elif util.is_float_object(val):
23442368 floats[i] = complexes[i] = val
23452369 seen.float_ = True
2346- elif util.is_datetime64_object(val):
2347- if convert_datetime:
2348- idatetimes[i] = convert_to_tsobject(
2349- val, None , None , 0 , 0 ).value
2350- seen.datetime_ = True
2351- else :
2352- seen.object_ = True
2353- break
23542370 elif is_timedelta(val):
23552371 if convert_timedelta:
23562372 itimedeltas[i] = convert_to_timedelta64(val, " ns" ).view(" i8" )
@@ -2396,6 +2412,13 @@ def maybe_convert_objects(ndarray[object] objects, bint try_float=False,
23962412 else :
23972413 seen.object_ = True
23982414 break
2415+ elif is_period_object(val):
2416+ if convert_period:
2417+ seen.period_ = True
2418+ break
2419+ else :
2420+ seen.object_ = True
2421+ break
23992422 elif try_float and not isinstance (val, str ):
24002423 # this will convert Decimal objects
24012424 try :
@@ -2419,6 +2442,14 @@ def maybe_convert_objects(ndarray[object] objects, bint try_float=False,
24192442 return dti._data
24202443 seen.object_ = True
24212444
2445+ if seen.period_:
2446+ if is_period_array(objects):
2447+ from pandas import PeriodIndex
2448+ pi = PeriodIndex(objects)
2449+
2450+ # unbox to PeriodArray
2451+ return pi._data
2452+
24222453 if not seen.object_:
24232454 result = None
24242455 if not safe:
0 commit comments