62 self.__repeat = repeat |
62 self.__repeat = repeat |
63 self.__filename = filename |
63 self.__filename = filename |
64 self.__source = source[:] |
64 self.__source = source[:] |
65 self.__tree = copy.deepcopy(tree) |
65 self.__tree = copy.deepcopy(tree) |
66 self.__args = args |
66 self.__args = args |
|
67 |
|
68 # parameters for import sorting |
|
69 if args["SortOrder"] == "native": |
|
70 self.__sortingFunction = sorted |
|
71 else: |
|
72 # naturally is the default sort order |
|
73 self.__sortingFunction = self.__naturally |
|
74 self.__sortCaseSensitive = args["SortCaseSensitive"] |
67 |
75 |
68 # statistics counters |
76 # statistics counters |
69 self.counters = {} |
77 self.counters = {} |
70 |
78 |
71 # collection of detected errors |
79 # collection of detected errors |
391 self.__error(node.lineno - 1, node.col_offset, reason) |
399 self.__error(node.lineno - 1, node.col_offset, reason) |
392 |
400 |
393 ####################################################################### |
401 ####################################################################### |
394 ## Import order |
402 ## Import order |
395 ## |
403 ## |
396 ## adapted from: flake8-alphabetize v0.0.17 |
404 ## adapted from: flake8-alphabetize v0.0.18 |
397 ####################################################################### |
405 ####################################################################### |
398 |
406 |
399 # TODO: upgrade to v0.0.18 |
|
400 # TODO: introduce sort type iaw. isort |
|
401 def __checkImportOrder(self): |
407 def __checkImportOrder(self): |
402 """ |
408 """ |
403 Private method to check the order of import statements. |
409 Private method to check the order of import statements. |
404 """ |
410 """ |
405 from .ImportNode import ImportNode |
411 from .ImportNode import ImportNode |
497 actualList.append(el.s) |
503 actualList.append(el.s) |
498 else: |
504 else: |
499 # Can't handle anything that isn't a string literal |
505 # Can't handle anything that isn't a string literal |
500 return None |
506 return None |
501 |
507 |
502 expectedList = sorted(actualList) |
508 expectedList = self.sorted(actualList, key=self.moduleKey) |
503 if expectedList != actualList: |
509 if expectedList != actualList: |
504 return (node, "I204", ", ".join(expectedList)) |
510 return (node, "I204", ", ".join(expectedList)) |
505 |
511 |
506 return None |
512 return None |
|
513 |
|
514 def sorted(self, toSort, key=None, reverse=False): |
|
515 """ |
|
516 Public method to sort the given list of names. |
|
517 |
|
518 @param toSort list of names to be sorted |
|
519 @type list of str |
|
520 @param key function to generate keys (defaults to None) |
|
521 @type function (optional) |
|
522 @param reverse flag indicating a reverse sort (defaults to False) |
|
523 @type bool (optional) |
|
524 @return sorted list of names |
|
525 @rtype list of str |
|
526 """ |
|
527 return self.__sortingFunction(toSort, key=key, reverse=reverse) |
|
528 |
|
529 def __naturally(self, toSort, key=None, reverse=False): |
|
530 """ |
|
531 Private method to sort the given list of names naturally. |
|
532 |
|
533 Note: Natural sorting maintains the sort order of numbers (i.e. |
|
534 [Q1, Q10, Q2] is sorted as [Q1, Q2, Q10] while the Python |
|
535 standard sort would yield [Q1, Q10, Q2]. |
|
536 |
|
537 @param toSort list of names to be sorted |
|
538 @type list of str |
|
539 @param key function to generate keys (defaults to None) |
|
540 @type function (optional) |
|
541 @param reverse flag indicating a reverse sort (defaults to False) |
|
542 @type bool (optional) |
|
543 @return sorted list of names |
|
544 @rtype list of str |
|
545 """ |
|
546 if key is None: |
|
547 keyCallback = self.__naturalKeys |
|
548 else: |
|
549 def keyCallback(text): |
|
550 return self.__naturalKeys(key(text)) |
|
551 |
|
552 return sorted(toSort, key=keyCallback, reverse=reverse) |
|
553 |
|
554 def __atoi(self, text): |
|
555 """ |
|
556 Private method to convert the given text to an integer number. |
|
557 |
|
558 @param text text to be converted |
|
559 @type str |
|
560 @return integer number |
|
561 @rtype int |
|
562 """ |
|
563 return int(text) if text.isdigit() else text |
|
564 |
|
565 def __naturalKeys(self, text): |
|
566 """ |
|
567 Private method to generate keys for natural sorting. |
|
568 |
|
569 @param text text to generate a key for |
|
570 @type str |
|
571 @return key for natural sorting |
|
572 @rtype list of str or int |
|
573 """ |
|
574 return [self.__atoi(c) for c in re.split(r"(\d+)", text)] |
|
575 |
|
576 def moduleKey(self, moduleName): |
|
577 """ |
|
578 Public method to generate a key for the given module name. |
|
579 |
|
580 @param moduleName module name |
|
581 @type str |
|
582 @return generated key |
|
583 @rtype str |
|
584 """ |
|
585 prefix = "" |
|
586 |
|
587 if moduleName.isupper() and len(moduleName) > 1: |
|
588 prefix = "A" |
|
589 elif moduleName[0:1].isupper(): |
|
590 prefix = "B" |
|
591 else: |
|
592 prefix = "C" |
|
593 if not self.__sortCaseSensitive: |
|
594 moduleName = moduleName.lower() |
|
595 |
|
596 return f"{prefix}{moduleName}" |
507 |
597 |
508 ####################################################################### |
598 ####################################################################### |
509 ## Tidy imports |
599 ## Tidy imports |
510 ## |
600 ## |
511 ## adapted from: flake8-tidy-imports v4.8.0 |
601 ## adapted from: flake8-tidy-imports v4.8.0 |