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