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

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

77 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 TypeGuard, 

12) 

13 

14import numpy as np 

15 

16from pandas._libs import lib 

17from pandas.util._decorators import set_module 

18 

19if TYPE_CHECKING: 

20 from collections.abc import Hashable 

21 

22is_bool = lib.is_bool 

23 

24is_integer = lib.is_integer 

25 

26is_float = lib.is_float 

27 

28is_complex = lib.is_complex 

29 

30is_scalar = lib.is_scalar 

31 

32is_decimal = lib.is_decimal 

33 

34is_list_like = lib.is_list_like 

35 

36is_iterator = lib.is_iterator 

37 

38 

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

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

41 """ 

42 Check if the object is a number. 

43 

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

45 

46 Parameters 

47 ---------- 

48 obj : any type 

49 The object to check if is a number. 

50 

51 Returns 

52 ------- 

53 bool 

54 Whether `obj` is a number or not. 

55 

56 See Also 

57 -------- 

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

59 

60 Examples 

61 -------- 

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

63 >>> is_number(1) 

64 True 

65 >>> is_number(7.15) 

66 True 

67 

68 Booleans are valid because they are int subclass. 

69 

70 >>> is_number(False) 

71 True 

72 

73 >>> is_number("foo") 

74 False 

75 >>> is_number("5") 

76 False 

77 """ 

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

79 

80 

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

82 """ 

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

84 

85 Parameters 

86 ---------- 

87 obj : The object to check. 

88 

89 Returns 

90 ------- 

91 is_iter_not_string : bool 

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

93 

94 Examples 

95 -------- 

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

97 True 

98 >>> iterable_not_string("foo") 

99 False 

100 >>> iterable_not_string(1) 

101 False 

102 """ 

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

104 

105 

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

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

108 """ 

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

110 

111 For objects to be considered file-like, they must 

112 be an iterator AND have either a `read` and/or `write` 

113 method as an attribute. 

114 

115 Note: file-like objects must be iterable, but 

116 iterable objects need not be file-like. 

117 

118 Parameters 

119 ---------- 

120 obj : object 

121 The object to check for file-like properties. 

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

123 check if it has attributes typically associated with 

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

125 

126 Returns 

127 ------- 

128 bool 

129 Whether `obj` has file-like properties. 

130 

131 See Also 

132 -------- 

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

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

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

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

137 

138 Examples 

139 -------- 

140 >>> import io 

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

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

143 >>> is_file_like(buffer) 

144 True 

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

146 False 

147 """ 

148 if not (hasattr(obj, "read") or hasattr(obj, "write")): 

149 return False 

150 

151 return bool(hasattr(obj, "__iter__")) 

152 

153 

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

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

156 """ 

157 Check if the object is a regex pattern instance. 

158 

159 Parameters 

160 ---------- 

161 obj : object 

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

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

164 pattern from the `re` module. 

165 

166 Returns 

167 ------- 

168 bool 

169 Whether `obj` is a regex pattern. 

170 

171 See Also 

172 -------- 

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

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

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

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

177 into a regex pattern instance. 

178 

179 Examples 

180 -------- 

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

182 >>> import re 

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

184 True 

185 >>> is_re("foo") 

186 False 

187 """ 

188 return isinstance(obj, Pattern) 

189 

190 

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

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

193 """ 

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

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 Parameters 

312 ---------- 

313 obj : object 

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

315 and the function will determine whether it 

316 behaves like a dictionary. 

317 

318 Returns 

319 ------- 

320 bool 

321 Whether `obj` has dict-like properties. 

322 

323 See Also 

324 -------- 

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

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

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

328 

329 Examples 

330 -------- 

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

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

333 True 

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

335 False 

336 >>> is_dict_like(dict) 

337 False 

338 >>> is_dict_like(dict()) 

339 True 

340 """ 

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

342 return ( 

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

344 # [GH 25196] exclude classes 

345 and not isinstance(obj, type) 

346 ) 

347 

348 

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

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

351 """ 

352 Check if the object is a named tuple. 

353 

354 Parameters 

355 ---------- 

356 obj : object 

357 The object that will be checked to determine 

358 whether it is a named tuple. 

359 

360 Returns 

361 ------- 

362 bool 

363 Whether `obj` is a named tuple. 

364 

365 See Also 

366 -------- 

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

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

369 will succeed, False otherwise. 

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

371 

372 Examples 

373 -------- 

374 >>> from collections import namedtuple 

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

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

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

378 >>> 

379 >>> is_named_tuple(p) 

380 True 

381 >>> is_named_tuple((1, 2)) 

382 False 

383 """ 

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

385 

386 

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

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

389 """ 

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

391 

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

393 they are actually hashed with hash(). 

394 

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

396 seeing if they raise TypeError. 

397 

398 Parameters 

399 ---------- 

400 obj : object 

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

402 allow_slice : bool 

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

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

405 

406 Returns 

407 ------- 

408 bool 

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

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

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

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

413 

414 See Also 

415 -------- 

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

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

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

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

420 

421 Examples 

422 -------- 

423 >>> import collections 

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

425 >>> a = ([],) 

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

427 True 

428 >>> is_hashable(a) 

429 False 

430 """ 

431 # Unfortunately, we can't use isinstance(obj, collections.abc.Hashable), 

432 # which can be faster than calling hash. That is because numpy scalars 

433 # fail this test. 

434 

435 # Reconsider this decision once this numpy bug is fixed: 

436 # https://github.com/numpy/numpy/issues/5562 

437 

438 if allow_slice is False: 

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

440 return False 

441 elif isinstance(obj, slice): 

442 return False 

443 

444 try: 

445 hash(obj) 

446 except TypeError: 

447 return False 

448 else: 

449 return True 

450 

451 

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

453 """ 

454 Check if the object is a sequence of objects. 

455 String types are not included as sequences here. 

456 

457 Parameters 

458 ---------- 

459 obj : The object to check 

460 

461 Returns 

462 ------- 

463 is_sequence : bool 

464 Whether `obj` is a sequence of objects. 

465 

466 Examples 

467 -------- 

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

469 >>> 

470 >>> is_sequence(l) 

471 True 

472 >>> is_sequence(iter(l)) 

473 False 

474 """ 

475 try: 

476 # Can iterate over it. 

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

478 # Has a length associated with it. 

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

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

481 except (TypeError, AttributeError): 

482 return False 

483 

484 

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

486 """ 

487 Checks if the object is a data-class instance 

488 

489 Parameters 

490 ---------- 

491 item : object 

492 

493 Returns 

494 -------- 

495 is_dataclass : bool 

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

497 will return false if you pass the data class itself 

498 

499 Examples 

500 -------- 

501 >>> from dataclasses import dataclass 

502 >>> @dataclass 

503 ... class Point: 

504 ... x: int 

505 ... y: int 

506 

507 >>> is_dataclass(Point) 

508 False 

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

510 True 

511 

512 """ 

513 try: 

514 import dataclasses 

515 

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

517 except ImportError: 

518 return False