Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/core/dtypes/inference.py: 57%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

75 statements  

1"""basic inference routines""" 

2 

3from __future__ import annotations 

4 

5from collections import abc 

6from numbers import Number 

7import re 

8from re import Pattern 

9from typing import ( 

10 TYPE_CHECKING, 

11 Any, 

12 TypeGuard, 

13) 

14 

15import numpy as np 

16 

17from pandas._libs import lib 

18from pandas.util._decorators import set_module 

19 

20if TYPE_CHECKING: 

21 from collections.abc import Hashable 

22 

23is_bool = lib.is_bool 

24 

25is_integer = lib.is_integer 

26 

27is_float = lib.is_float 

28 

29is_complex = lib.is_complex 

30 

31is_scalar = lib.is_scalar 

32 

33is_decimal = lib.is_decimal 

34 

35is_list_like = lib.is_list_like 

36 

37is_iterator = lib.is_iterator 

38 

39 

40@set_module("pandas.api.types") 

41def is_number(obj: object) -> TypeGuard[Number | np.number]: 

42 """ 

43 Check if the object is a number. 

44 

45 Returns True when the object is a number, and False if is not. 

46 

47 Parameters 

48 ---------- 

49 obj : any type 

50 The object to check if is a number. 

51 

52 Returns 

53 ------- 

54 bool 

55 Whether `obj` is a number or not. 

56 

57 See Also 

58 -------- 

59 api.types.is_integer: Checks a subgroup of numbers. 

60 

61 Examples 

62 -------- 

63 >>> from pandas.api.types import is_number 

64 >>> is_number(1) 

65 True 

66 >>> is_number(7.15) 

67 True 

68 

69 Booleans are valid because they are int subclass. 

70 

71 >>> is_number(False) 

72 True 

73 

74 >>> is_number("foo") 

75 False 

76 >>> is_number("5") 

77 False 

78 """ 

79 return isinstance(obj, (Number, np.number)) 

80 

81 

82def iterable_not_string(obj: object) -> bool: 

83 """ 

84 Check if the object is an iterable but not a string. 

85 

86 Parameters 

87 ---------- 

88 obj : The object to check. 

89 

90 Returns 

91 ------- 

92 is_iter_not_string : bool 

93 Whether `obj` is a non-string iterable. 

94 

95 Examples 

96 -------- 

97 >>> iterable_not_string([1, 2, 3]) 

98 True 

99 >>> iterable_not_string("foo") 

100 False 

101 >>> iterable_not_string(1) 

102 False 

103 """ 

104 return isinstance(obj, abc.Iterable) and not isinstance(obj, str) 

105 

106 

107@set_module("pandas.api.types") 

108def is_file_like(obj: object) -> bool: 

109 """ 

110 Check if the object is a file-like object. 

111 

112 For objects to be considered file-like, they must have 

113 a `read` and/or `write` method as an attribute. 

114 

115 Parameters 

116 ---------- 

117 obj : object 

118 The object to check for file-like properties. 

119 This can be any Python object, and the function will 

120 check if it has attributes typically associated with 

121 file-like objects (e.g., `read`, `write`). 

122 

123 Returns 

124 ------- 

125 bool 

126 Whether `obj` has file-like properties. 

127 

128 See Also 

129 -------- 

130 api.types.is_dict_like : Check if the object is dict-like. 

131 api.types.is_hashable : Return True if hash(obj) will succeed, False otherwise. 

132 api.types.is_named_tuple : Check if the object is a named tuple. 

133 api.types.is_iterator : Check if the object is an iterator. 

134 

135 Examples 

136 -------- 

137 >>> import io 

138 >>> from pandas.api.types import is_file_like 

139 >>> buffer = io.StringIO("data") 

140 >>> is_file_like(buffer) 

141 True 

142 >>> is_file_like([1, 2, 3]) 

143 False 

144 """ 

145 return bool(hasattr(obj, "read") or hasattr(obj, "write")) 

146 

147 

148@set_module("pandas.api.types") 

149def is_re(obj: object) -> TypeGuard[Pattern[Any]]: 

150 """ 

151 Check if the object is a regex pattern instance. 

152 

153 This function tests whether ``obj`` is an instance of a compiled 

154 regular expression pattern, as created by :func:`re.compile`. 

155 

156 Parameters 

157 ---------- 

158 obj : object 

159 The object to check for being a regex pattern. Typically, 

160 this would be an object that you expect to be a compiled 

161 pattern from the `re` module. 

162 

163 Returns 

164 ------- 

165 bool 

166 Whether `obj` is a regex pattern. 

167 

168 See Also 

169 -------- 

170 api.types.is_float : Return True if given object is float. 

171 api.types.is_iterator : Check if the object is an iterator. 

172 api.types.is_integer : Return True if given object is integer. 

173 api.types.is_re_compilable : Check if the object can be compiled 

174 into a regex pattern instance. 

175 

176 Examples 

177 -------- 

178 >>> from pandas.api.types import is_re 

179 >>> import re 

180 >>> is_re(re.compile(".*")) 

181 True 

182 >>> is_re("foo") 

183 False 

184 """ 

185 return isinstance(obj, Pattern) 

186 

187 

188@set_module("pandas.api.types") 

189def is_re_compilable(obj: object) -> bool: 

190 """ 

191 Check if the object can be compiled into a regex pattern instance. 

192 

193 This function attempts to compile ``obj`` as a regular expression 

194 using :func:`re.compile` and returns whether the compilation succeeds. 

195 

196 Parameters 

197 ---------- 

198 obj : The object to check 

199 The object to check if the object can be compiled into a regex pattern instance. 

200 

201 Returns 

202 ------- 

203 bool 

204 Whether `obj` can be compiled as a regex pattern. 

205 

206 See Also 

207 -------- 

208 api.types.is_re : Check if the object is a regex pattern instance. 

209 

210 Examples 

211 -------- 

212 >>> from pandas.api.types import is_re_compilable 

213 >>> is_re_compilable(".*") 

214 True 

215 >>> is_re_compilable(1) 

216 False 

217 """ 

218 try: 

219 re.compile(obj) # type: ignore[call-overload] 

220 except TypeError: 

221 return False 

222 else: 

223 return True 

224 

225 

226@set_module("pandas.api.types") 

227def is_array_like(obj: object) -> bool: 

228 """ 

229 Check if the object is array-like. 

230 

231 For an object to be considered array-like, it must be list-like and 

232 have a `dtype` attribute. 

233 

234 Parameters 

235 ---------- 

236 obj : The object to check 

237 

238 Returns 

239 ------- 

240 is_array_like : bool 

241 Whether `obj` has array-like properties. 

242 

243 Examples 

244 -------- 

245 >>> is_array_like(np.array([1, 2, 3])) 

246 True 

247 >>> is_array_like(pd.Series(["a", "b"])) 

248 True 

249 >>> is_array_like(pd.Index(["2016-01-01"])) 

250 True 

251 >>> is_array_like([1, 2, 3]) 

252 False 

253 >>> is_array_like(("a", "b")) 

254 False 

255 """ 

256 return is_list_like(obj) and hasattr(obj, "dtype") 

257 

258 

259def is_nested_list_like(obj: object) -> bool: 

260 """ 

261 Check if the object is list-like, and that all of its elements 

262 are also list-like. 

263 

264 Parameters 

265 ---------- 

266 obj : The object to check 

267 

268 Returns 

269 ------- 

270 is_list_like : bool 

271 Whether `obj` has list-like properties. 

272 

273 Examples 

274 -------- 

275 >>> is_nested_list_like([[1, 2, 3]]) 

276 True 

277 >>> is_nested_list_like([{1, 2, 3}, {1, 2, 3}]) 

278 True 

279 >>> is_nested_list_like(["foo"]) 

280 False 

281 >>> is_nested_list_like([]) 

282 False 

283 >>> is_nested_list_like([[1, 2, 3], 1]) 

284 False 

285 

286 Notes 

287 ----- 

288 This won't reliably detect whether a consumable iterator (e. g. 

289 a generator) is a nested-list-like without consuming the iterator. 

290 To avoid consuming it, we always return False if the outer container 

291 doesn't define `__len__`. 

292 

293 See Also 

294 -------- 

295 is_list_like 

296 """ 

297 return ( 

298 is_list_like(obj) 

299 and hasattr(obj, "__len__") 

300 # need PEP 724 to handle these typing errors 

301 and len(obj) > 0 # pyright: ignore[reportArgumentType] 

302 and all(is_list_like(item) for item in obj) # type: ignore[attr-defined] 

303 ) 

304 

305 

306@set_module("pandas.api.types") 

307def is_dict_like(obj: object) -> bool: 

308 """ 

309 Check if the object is dict-like. 

310 

311 An object is considered dict-like if it has the ``__getitem__``, 

312 ``keys``, and ``__contains__`` attributes but is not a type itself. 

313 

314 Parameters 

315 ---------- 

316 obj : object 

317 The object to check. This can be any Python object, 

318 and the function will determine whether it 

319 behaves like a dictionary. 

320 

321 Returns 

322 ------- 

323 bool 

324 Whether `obj` has dict-like properties. 

325 

326 See Also 

327 -------- 

328 api.types.is_list_like : Check if the object is list-like. 

329 api.types.is_file_like : Check if the object is a file-like. 

330 api.types.is_named_tuple : Check if the object is a named tuple. 

331 

332 Examples 

333 -------- 

334 >>> from pandas.api.types import is_dict_like 

335 >>> is_dict_like({1: 2}) 

336 True 

337 >>> is_dict_like([1, 2, 3]) 

338 False 

339 >>> is_dict_like(dict) 

340 False 

341 >>> is_dict_like(dict()) 

342 True 

343 """ 

344 dict_like_attrs = ("__getitem__", "keys", "__contains__") 

345 return ( 

346 all(hasattr(obj, attr) for attr in dict_like_attrs) 

347 # [GH 25196] exclude classes 

348 and not isinstance(obj, type) 

349 ) 

350 

351 

352@set_module("pandas.api.types") 

353def is_named_tuple(obj: object) -> bool: 

354 """ 

355 Check if the object is a named tuple. 

356 

357 A named tuple is a subclass of :class:`tuple` that has named fields, 

358 as created by :func:`collections.namedtuple`. 

359 

360 Parameters 

361 ---------- 

362 obj : object 

363 The object that will be checked to determine 

364 whether it is a named tuple. 

365 

366 Returns 

367 ------- 

368 bool 

369 Whether `obj` is a named tuple. 

370 

371 See Also 

372 -------- 

373 api.types.is_dict_like: Check if the object is dict-like. 

374 api.types.is_hashable: Return True if hash(obj) 

375 will succeed, False otherwise. 

376 api.types.is_categorical_dtype : Check if the dtype is categorical. 

377 

378 Examples 

379 -------- 

380 >>> from collections import namedtuple 

381 >>> from pandas.api.types import is_named_tuple 

382 >>> Point = namedtuple("Point", ["x", "y"]) 

383 >>> p = Point(1, 2) 

384 >>> 

385 >>> is_named_tuple(p) 

386 True 

387 >>> is_named_tuple((1, 2)) 

388 False 

389 """ 

390 return isinstance(obj, abc.Sequence) and hasattr(obj, "_fields") 

391 

392 

393@set_module("pandas.api.types") 

394def is_hashable(obj: object, allow_slice: bool = True) -> TypeGuard[Hashable]: 

395 """ 

396 Return True if hash(obj) will succeed, False otherwise. 

397 

398 Some types will pass a test against collections.abc.Hashable but fail when 

399 they are actually hashed with hash(). 

400 

401 Distinguish between these and other types by trying the call to hash() and 

402 seeing if they raise TypeError. 

403 

404 Parameters 

405 ---------- 

406 obj : object 

407 The object to check for hashability. Any Python object can be passed here. 

408 allow_slice : bool 

409 If True, return True if the object is hashable (including slices). 

410 If False, return True if the object is hashable and not a slice. 

411 

412 Returns 

413 ------- 

414 bool 

415 True if object can be hashed (i.e., does not raise TypeError when 

416 passed to hash()) and passes the slice check according to 'allow_slice'. 

417 False otherwise (e.g., if object is mutable like a list or dictionary 

418 or if allow_slice is False and object is a slice or contains a slice). 

419 

420 See Also 

421 -------- 

422 api.types.is_float : Return True if given object is float. 

423 api.types.is_iterator : Check if the object is an iterator. 

424 api.types.is_list_like : Check if the object is list-like. 

425 api.types.is_dict_like : Check if the object is dict-like. 

426 

427 Examples 

428 -------- 

429 >>> import collections 

430 >>> from pandas.api.types import is_hashable 

431 >>> a = ([],) 

432 >>> isinstance(a, collections.abc.Hashable) 

433 True 

434 >>> is_hashable(a) 

435 False 

436 """ 

437 # We can't use isinstance(obj, collections.abc.Hashable) because it 

438 # returns True for tuples containing unhashable elements (e.g. ([],)). 

439 # Calling hash() is the only reliable check. 

440 if allow_slice is False: 

441 if isinstance(obj, tuple) and any(isinstance(v, slice) for v in obj): 

442 return False 

443 elif isinstance(obj, slice): 

444 return False 

445 

446 try: 

447 hash(obj) 

448 except TypeError: 

449 return False 

450 else: 

451 return True 

452 

453 

454def is_sequence(obj: object) -> bool: 

455 """ 

456 Check if the object is a sequence of objects. 

457 String types are not included as sequences here. 

458 

459 Parameters 

460 ---------- 

461 obj : The object to check 

462 

463 Returns 

464 ------- 

465 is_sequence : bool 

466 Whether `obj` is a sequence of objects. 

467 

468 Examples 

469 -------- 

470 >>> l = [1, 2, 3] 

471 >>> 

472 >>> is_sequence(l) 

473 True 

474 >>> is_sequence(iter(l)) 

475 False 

476 """ 

477 try: 

478 # Can iterate over it. 

479 iter(obj) # type: ignore[call-overload] 

480 # Has a length associated with it. 

481 len(obj) # type: ignore[arg-type] 

482 return not isinstance(obj, (str, bytes)) 

483 except (TypeError, AttributeError): 

484 return False 

485 

486 

487def is_dataclass(item: object) -> bool: 

488 """ 

489 Checks if the object is a data-class instance 

490 

491 Parameters 

492 ---------- 

493 item : object 

494 

495 Returns 

496 -------- 

497 is_dataclass : bool 

498 True if the item is an instance of a data-class, 

499 will return false if you pass the data class itself 

500 

501 Examples 

502 -------- 

503 >>> from dataclasses import dataclass 

504 >>> @dataclass 

505 ... class Point: 

506 ... x: int 

507 ... y: int 

508 

509 >>> is_dataclass(Point) 

510 False 

511 >>> is_dataclass(Point(0, 2)) 

512 True 

513 

514 """ 

515 try: 

516 import dataclasses 

517 

518 return dataclasses.is_dataclass(item) and not isinstance(item, type) 

519 except ImportError: 

520 return False