1 ###################################################################### 2 # This file should be kept compatible with Python 2.3, see PEP 291. # 3 ###################################################################### 4 """ 5 Generic dylib path manipulation 6 """ 7 8 import re 9 10 __all__ = ['dylib_info'] 11 12 DYLIB_RE = re.compile(r"""(?x) 13 (?P<location>^.*)(?:^|/) 14 (?P<name> 15 (?P<shortname>\w+?) 16 (?:\.(?P<version>[^._]+))? 17 (?:_(?P<suffix>[^._]+))? 18 \.dylib$ 19 ) 20 """) 21 22 def dylib_info(filename): 23 """ 24 A dylib name can take one of the following four forms: 25 Location/Name.SomeVersion_Suffix.dylib 26 Location/Name.SomeVersion.dylib 27 Location/Name_Suffix.dylib 28 Location/Name.dylib 29 30 returns None if not found or a mapping equivalent to: 31 dict( 32 location='Location', 33 name='Name.SomeVersion_Suffix.dylib', 34 shortname='Name', 35 version='SomeVersion', 36 suffix='Suffix', 37 ) 38 39 Note that SomeVersion and Suffix are optional and may be None 40 if not present. 41 """ 42 is_dylib = DYLIB_RE.match(filename) 43 if not is_dylib: 44 return None 45 return is_dylib.groupdict() 46 47 48 def test_dylib_info(): 49 def d(location=None, name=None, shortname=None, version=None, suffix=None): 50 return dict( 51 location=location, 52 name=name, 53 shortname=shortname, 54 version=version, 55 suffix=suffix 56 ) 57 assert dylib_info('completely/invalid') is None 58 assert dylib_info('completely/invalide_debug') is None 59 assert dylib_info('P/Foo.dylib') == d('P', 'Foo.dylib', 'Foo') 60 assert dylib_info('P/Foo_debug.dylib') == d('P', 'Foo_debug.dylib', 'Foo', suffix='debug') 61 assert dylib_info('P/Foo.A.dylib') == d('P', 'Foo.A.dylib', 'Foo', 'A') 62 assert dylib_info('P/Foo_debug.A.dylib') == d('P', 'Foo_debug.A.dylib', 'Foo_debug', 'A') 63 assert dylib_info('P/Foo.A_debug.dylib') == d('P', 'Foo.A_debug.dylib', 'Foo', 'A', 'debug') 64 65 if __name__ == '__main__': 66 test_dylib_info() 67