18
18
from glob import iglob
19
19
import itertools
20
20
import textwrap
21
- from typing import List , Optional , Set , TYPE_CHECKING
21
+ from typing import List , Optional , TYPE_CHECKING
22
22
23
23
from collections import defaultdict
24
24
from email import message_from_file
@@ -581,7 +581,6 @@ def _clean_req(self, req):
581
581
582
582
def _finalize_license_files (self ):
583
583
"""Compute names of all license files which should be included."""
584
- files : List [str ] = []
585
584
license_files : Optional [List [str ]] = self .metadata .license_files
586
585
patterns : List [str ] = license_files if license_files else []
587
586
@@ -595,16 +594,18 @@ def _finalize_license_files(self):
595
594
# -> 'Including license files in the generated wheel file'
596
595
patterns = ('LICEN[CS]E*' , 'COPYING*' , 'NOTICE*' , 'AUTHORS*' )
597
596
598
- for pattern in patterns :
599
- files_pattern : Set [str ] = set ()
600
- for path in iglob (pattern ):
601
- if path .endswith ('~' ):
602
- continue
603
- if path not in files and os .path .isfile (path ):
604
- files_pattern .add (path )
605
- files .extend (sorted (files_pattern ))
597
+ self .metadata .license_files = list (
598
+ unique_everseen (self ._expand_patterns (patterns )))
606
599
607
- self .metadata .license_files = files
600
+ @staticmethod
601
+ def _expand_patterns (patterns ):
602
+ return (
603
+ path
604
+ for pattern in patterns
605
+ for path in iglob (pattern )
606
+ if not path .endswith ('~' )
607
+ and os .path .isfile (path )
608
+ )
608
609
609
610
# FIXME: 'Distribution._parse_config_files' is too complex (14)
610
611
def _parse_config_files (self , filenames = None ): # noqa: C901
@@ -1111,3 +1112,21 @@ def handle_display_options(self, option_order):
1111
1112
class DistDeprecationWarning (SetuptoolsDeprecationWarning ):
1112
1113
"""Class for warning about deprecations in dist in
1113
1114
setuptools. Not ignored by default, unlike DeprecationWarning."""
1115
+
1116
+
1117
+ def unique_everseen (iterable , key = None ):
1118
+ "List unique elements, preserving order. Remember all elements ever seen."
1119
+ # unique_everseen('AAAABBBCCDAABBB') --> A B C D
1120
+ # unique_everseen('ABBCcAD', str.lower) --> A B C D
1121
+ seen = set ()
1122
+ seen_add = seen .add
1123
+ if key is None :
1124
+ for element in itertools .filterfalse (seen .__contains__ , iterable ):
1125
+ seen_add (element )
1126
+ yield element
1127
+ else :
1128
+ for element in iterable :
1129
+ k = key (element )
1130
+ if k not in seen :
1131
+ seen_add (k )
1132
+ yield element
0 commit comments