| Conditions | 51 |
| Total Lines | 232 |
| Code Lines | 130 |
| Lines | 0 |
| Ratio | 0 % |
| Tests | 111 |
| CRAP Score | 51 |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like abydos.fingerprint._synoname_toolcode.SynonameToolcode.fingerprint_tuple() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # Copyright 2018-2020 by Christopher C. Little. |
||
| 317 | def fingerprint_tuple( |
||
| 318 | self, lname: str, fname: str = '', qual: str = '', normalize: int = 0 |
||
| 319 | 1 | ) -> Tuple[str, str, str]: |
|
| 320 | 1 | """Build the Synoname toolcode. |
|
| 321 | 1 | ||
| 322 | Parameters |
||
| 323 | ---------- |
||
| 324 | 1 | lname : str |
|
| 325 | Last name |
||
| 326 | 1 | fname : str |
|
| 327 | First name (can be blank) |
||
| 328 | 1 | qual : str |
|
| 329 | 1 | Qualifier |
|
| 330 | 1 | normalize : int |
|
| 331 | 1 | Normalization mode (0, 1, or 2) |
|
| 332 | 1 | ||
| 333 | 1 | Returns |
|
| 334 | ------- |
||
| 335 | tuple |
||
| 336 | 1 | The transformed names and the synoname toolcode |
|
| 337 | 1 | ||
| 338 | Examples |
||
| 339 | 1 | -------- |
|
| 340 | 1 | >>> st = SynonameToolcode() |
|
| 341 | 1 | >>> st.fingerprint_tuple('hat') |
|
| 342 | 1 | ('hat', '', '0000000003$$h') |
|
| 343 | >>> st.fingerprint_tuple('niall') |
||
| 344 | 1 | ('niall', '', '0000000005$$n') |
|
| 345 | 1 | >>> st.fingerprint_tuple('colin') |
|
| 346 | 1 | ('colin', '', '0000000005$$c') |
|
| 347 | 1 | >>> st.fingerprint_tuple('atcg') |
|
| 348 | 1 | ('atcg', '', '0000000004$$a') |
|
| 349 | 1 | >>> st.fingerprint_tuple('entreatment') |
|
| 350 | ('entreatment', '', '0000000011$$e') |
||
| 351 | 1 | ||
| 352 | 1 | >>> st.fingerprint_tuple('Ste.-Marie', 'Count John II', normalize=2) |
|
| 353 | 1 | ('ste.-marie ii', 'count john', '0200491310$015b049a127c$smcji') |
|
| 354 | 1 | >>> st.fingerprint_tuple('Michelangelo IV', '', 'Workshop of') |
|
| 355 | 1 | ('michelangelo iv', '', '3000550015$055b$mi') |
|
| 356 | |||
| 357 | |||
| 358 | 1 | .. versionadded:: 0.6.0 |
|
| 359 | 1 | ||
| 360 | 1 | """ |
|
| 361 | 1 | lname = lname.lower() |
|
| 362 | 1 | fname = fname.lower() |
|
| 363 | 1 | qual = qual.lower() |
|
| 364 | 1 | ||
| 365 | 1 | # Start with the basic code |
|
| 366 | toolcode = ['0', '0', '0', '000', '00', '00', '$', '', '$', ''] |
||
| 367 | |||
| 368 | 1 | full_name = ' '.join((lname, fname)) |
|
| 369 | 1 | ||
| 370 | 1 | if qual in self._qual_3: |
|
| 371 | 1 | toolcode[0] = '3' |
|
| 372 | 1 | elif qual in self._qual_2: |
|
| 373 | toolcode[0] = '2' |
||
| 374 | elif qual in self._qual_1: |
||
| 375 | toolcode[0] = '1' |
||
| 376 | |||
| 377 | # Fill field 1 (punctuation) |
||
| 378 | if '.' in full_name: |
||
| 379 | 1 | toolcode[1] = '2' |
|
| 380 | 1 | else: |
|
| 381 | for punct in ',-/:;"&\'()!{|}?$%*+<=>[\\]^_`~': |
||
| 382 | if punct in full_name: |
||
| 383 | 1 | toolcode[1] = '1' |
|
| 384 | 1 | break |
|
| 385 | 1 | ||
| 386 | 1 | elderyounger = '' # save elder/younger for possible movement later |
|
| 387 | 1 | for gen in self._gen_1: |
|
| 388 | if gen in full_name: |
||
| 389 | toolcode[2] = '1' |
||
| 390 | 1 | elderyounger = gen |
|
| 391 | 1 | break |
|
| 392 | 1 | else: |
|
| 393 | 1 | for gen in self._gen_2: |
|
| 394 | 1 | if gen in full_name: |
|
| 395 | toolcode[2] = '2' |
||
| 396 | 1 | elderyounger = gen |
|
| 397 | break |
||
| 398 | |||
| 399 | # do comma flip |
||
| 400 | if normalize: |
||
| 401 | comma = lname.find(',') |
||
| 402 | if comma != -1: |
||
| 403 | lname_end = lname[comma + 1 :] |
||
| 404 | while lname_end[0] in {' ', ','}: |
||
| 405 | lname_end = lname_end[1:] |
||
| 406 | fname = lname_end + ' ' + fname |
||
| 407 | lname = lname[:comma].strip() |
||
| 408 | |||
| 409 | # do elder/younger move |
||
| 410 | if normalize == 2 and elderyounger: |
||
| 411 | elderyounger_loc = fname.find(elderyounger) |
||
| 412 | if elderyounger_loc != -1: |
||
| 413 | lname = ' '.join((lname, elderyounger.strip())) |
||
| 414 | fname = ' '.join( |
||
| 415 | ( |
||
| 416 | 1 | fname[:elderyounger_loc].strip(), |
|
| 417 | 1 | fname[elderyounger_loc + len(elderyounger) :], |
|
| 418 | ) |
||
| 419 | ).strip() |
||
| 420 | |||
| 421 | toolcode[4] = '{:02d}'.format(len(fname)) |
||
| 422 | 1 | toolcode[5] = '{:02d}'.format(len(lname)) |
|
| 423 | 1 | ||
| 424 | # strip punctuation |
||
| 425 | for char in ',/:;"&()!{|}?$%*+<=>[\\]^_`~': |
||
| 426 | full_name = full_name.replace(char, '') |
||
| 427 | for pos, char in enumerate(full_name): |
||
| 428 | if char == '-' and full_name[pos - 1 : pos + 2] != 'b-g': |
||
| 429 | 1 | full_name = full_name[:pos] + ' ' + full_name[pos + 1 :] |
|
| 430 | |||
| 431 | # Fill field 9 (search range) |
||
| 432 | 1 | for letter in [_[0] for _ in full_name.split()]: |
|
| 433 | 1 | if letter not in toolcode[9]: |
|
| 434 | 1 | toolcode[9] += letter |
|
| 435 | 1 | if len(toolcode[9]) == 15: |
|
| 436 | 1 | break |
|
| 437 | 1 | ||
| 438 | def roman_check( |
||
| 439 | numeral: str, fname: str, lname: str |
||
| 440 | 1 | ) -> Tuple[str, str]: |
|
| 441 | 1 | """Move Roman numerals from first name to last. |
|
| 442 | |||
| 443 | Parameters |
||
| 444 | 1 | ---------- |
|
| 445 | 1 | numeral : str |
|
| 446 | 1 | Roman numeral |
|
| 447 | 1 | fname : str |
|
| 448 | 1 | First name |
|
| 449 | 1 | lname : str |
|
| 450 | Last name |
||
| 451 | 1 | ||
| 452 | 1 | Returns |
|
| 453 | 1 | ------- |
|
| 454 | 1 | tuple |
|
| 455 | 1 | First and last names with Roman numeral moved |
|
| 456 | 1 | ||
| 457 | 1 | .. versionadded:: 0.3.0 |
|
| 458 | 1 | ||
| 459 | 1 | """ |
|
| 460 | 1 | loc = fname.find(numeral) |
|
| 461 | if fname and ( |
||
| 462 | loc != -1 |
||
| 463 | 1 | and (len(fname[loc:]) == len(numeral)) |
|
| 464 | or fname[loc + len(numeral)] in {' ', ','} |
||
| 465 | ): |
||
| 466 | lname = ' '.join((lname, numeral)) |
||
| 467 | 1 | fname = ' '.join( |
|
| 468 | 1 | ( |
|
| 469 | 1 | fname[:loc].strip(), |
|
| 470 | 1 | fname[loc + len(numeral) :].lstrip(' ,'), |
|
| 471 | 1 | ) |
|
| 472 | ) |
||
| 473 | return fname.strip(), lname.strip() |
||
| 474 | |||
| 475 | 1 | # Fill fields 7 (specials) and 3 (roman numerals) |
|
| 476 | for num, special in enumerate(self._synoname_special_table): |
||
| 477 | roman, match, extra, method = special |
||
| 478 | if method & self._method_dict['end']: |
||
| 479 | 1 | match_context = ' ' + match |
|
| 480 | 1 | loc = full_name.find(match_context) |
|
| 481 | 1 | if (len(full_name) > len(match_context)) and ( |
|
| 482 | 1 | loc == len(full_name) - len(match_context) |
|
| 483 | 1 | ): |
|
| 484 | 1 | if roman: |
|
| 485 | 1 | if not any( |
|
| 486 | 1 | abbr in fname for abbr in ('i.', 'v.', 'x.') |
|
| 487 | 1 | ): |
|
| 488 | 1 | full_name = full_name[:loc] |
|
| 489 | 1 | toolcode[7] += '{:03d}'.format(num) + 'a' |
|
| 490 | 1 | if toolcode[3] == '000': |
|
| 491 | 1 | toolcode[3] = '{:03d}'.format(num) |
|
| 492 | if normalize == 2: |
||
| 493 | 1 | fname, lname = roman_check(match, fname, lname) |
|
| 494 | 1 | else: |
|
| 495 | 1 | full_name = full_name[:loc] |
|
| 496 | 1 | toolcode[7] += '{:03d}'.format(num) + 'a' |
|
| 497 | if method & self._method_dict['middle']: |
||
| 498 | match_context = ' ' + match + ' ' |
||
| 499 | loc = 0 |
||
| 500 | while loc != -1: |
||
| 501 | loc = full_name.find(match_context, loc + 1) |
||
| 502 | 1 | if loc > 0: |
|
| 503 | if roman: |
||
| 504 | 1 | if not any( |
|
| 505 | abbr in fname for abbr in ('i.', 'v.', 'x.') |
||
| 506 | ): |
||
| 507 | 1 | full_name = ( |
|
| 508 | full_name[:loc] |
||
| 509 | + full_name[loc + len(match) + 1 :] |
||
| 510 | ) |
||
| 511 | toolcode[7] += '{:03d}'.format(num) + 'b' |
||
| 512 | if toolcode[3] == '000': |
||
| 513 | 1 | toolcode[3] = '{:03d}'.format(num) |
|
| 514 | if normalize == 2: |
||
| 515 | fname, lname = roman_check( |
||
| 516 | match, fname, lname |
||
| 517 | ) |
||
| 518 | else: |
||
| 519 | full_name = ( |
||
| 520 | full_name[:loc] |
||
| 521 | + full_name[loc + len(match) + 1 :] |
||
| 522 | ) |
||
| 523 | toolcode[7] += '{:03d}'.format(num) + 'b' |
||
| 524 | if method & self._method_dict['beginning']: |
||
| 525 | match_context = match + ' ' |
||
| 526 | loc = full_name.find(match_context) |
||
| 527 | if loc == 0: |
||
| 528 | full_name = full_name[len(match) + 1 :] |
||
| 529 | toolcode[7] += '{:03d}'.format(num) + 'c' |
||
| 530 | if method & self._method_dict['beginning_no_space']: |
||
| 531 | loc = full_name.find(match) |
||
| 532 | if loc == 0: |
||
| 533 | toolcode[7] += '{:03d}'.format(num) + 'd' |
||
| 534 | if full_name[: len(match)] not in toolcode[9]: |
||
| 535 | toolcode[9] += full_name[: len(match)] |
||
| 536 | |||
| 537 | if extra: |
||
| 538 | loc = full_name.find(extra) |
||
| 539 | if loc != -1: |
||
| 540 | toolcode[7] += '{:03d}'.format(num) + 'X' |
||
| 541 | # Since extras are unique, we only look for each of them |
||
| 542 | # once, and they include otherwise impossible characters |
||
| 543 | # for this field, it's not possible for the following line |
||
| 544 | # to have ever been false. |
||
| 545 | # if full_name[loc:loc+len(extra)] not in toolcode[9]: |
||
| 546 | toolcode[9] += full_name[loc : loc + len(match)] |
||
| 547 | |||
| 548 | return lname, fname, ''.join(toolcode) |
||
| 549 | |||
| 555 |