Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: third_party/logilab/common/modutils.py

Issue 719313003: Revert "pylint: upgrade to 1.3.1" (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/logilab/common/logging_ext.py ('k') | third_party/logilab/common/optik_ext.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 # copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 2 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
3 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr 3 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
4 # 4 #
5 # This file is part of logilab-common. 5 # This file is part of logilab-common.
6 # 6 #
7 # logilab-common is free software: you can redistribute it and/or modify it unde r 7 # logilab-common is free software: you can redistribute it and/or modify it unde r
8 # the terms of the GNU Lesser General Public License as published by the Free 8 # the terms of the GNU Lesser General Public License as published by the Free
9 # Software Foundation, either version 2.1 of the License, or (at your option) an y 9 # Software Foundation, either version 2.1 of the License, or (at your option) an y
10 # later version. 10 # later version.
11 # 11 #
12 # logilab-common is distributed in the hope that it will be useful, but WITHOUT 12 # logilab-common is distributed in the hope that it will be useful, but WITHOUT
13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15 # details. 15 # details.
16 # 16 #
17 # You should have received a copy of the GNU Lesser General Public License along 17 # You should have received a copy of the GNU Lesser General Public License along
18 # with logilab-common. If not, see <http://www.gnu.org/licenses/>. 18 # with logilab-common. If not, see <http://www.gnu.org/licenses/>.
19 """Python modules manipulation utility functions. 19 """Python modules manipulation utility functions.
20 20
21 :type PY_SOURCE_EXTS: tuple(str) 21 :type PY_SOURCE_EXTS: tuple(str)
22 :var PY_SOURCE_EXTS: list of possible python source file extension 22 :var PY_SOURCE_EXTS: list of possible python source file extension
23 23
24 :type STD_LIB_DIR: str 24 :type STD_LIB_DIR: str
25 :var STD_LIB_DIR: directory where standard modules are located 25 :var STD_LIB_DIR: directory where standard modules are located
26 26
27 :type BUILTIN_MODULES: dict 27 :type BUILTIN_MODULES: dict
28 :var BUILTIN_MODULES: dictionary with builtin module names has key 28 :var BUILTIN_MODULES: dictionary with builtin module names has key
29 """ 29 """
30
31 __docformat__ = "restructuredtext en" 30 __docformat__ = "restructuredtext en"
32 31
33 import sys 32 import sys
34 import os 33 import os
35 from os.path import splitext, join, abspath, isdir, dirname, exists, basename 34 from os.path import splitext, join, abspath, isdir, dirname, exists, basename
36 from imp import find_module, load_module, C_BUILTIN, PY_COMPILED, PKG_DIRECTORY 35 from imp import find_module, load_module, C_BUILTIN, PY_COMPILED, PKG_DIRECTORY
37 from distutils.sysconfig import get_config_var, get_python_lib, get_python_versi on 36 from distutils.sysconfig import get_config_var, get_python_lib, get_python_versi on
38 from distutils.errors import DistutilsPlatformError
39
40 from six.moves import range
41 37
42 try: 38 try:
43 import zipimport 39 import zipimport
44 except ImportError: 40 except ImportError:
45 zipimport = None 41 zipimport = None
46 42
47 ZIPFILE = object() 43 ZIPFILE = object()
48 44
49 from logilab.common import STD_BLACKLIST, _handle_blacklist 45 from logilab.common import STD_BLACKLIST, _handle_blacklist
50 46
51 # Notes about STD_LIB_DIR 47 # Notes about STD_LIB_DIR
52 # Consider arch-specific installation for STD_LIB_DIR definition 48 # Consider arch-specific installation for STD_LIB_DIR definition
53 # :mod:`distutils.sysconfig` contains to much hardcoded values to rely on 49 # :mod:`distutils.sysconfig` contains to much hardcoded values to rely on
54 # 50 #
55 # :see: `Problems with /usr/lib64 builds <http://bugs.python.org/issue1294959>`_ 51 # :see: `Problems with /usr/lib64 builds <http://bugs.python.org/issue1294959>`_
56 # :see: `FHS <http://www.pathname.com/fhs/pub/fhs-2.3.html#LIBLTQUALGTALTERNATEF ORMATESSENTIAL>`_ 52 # :see: `FHS <http://www.pathname.com/fhs/pub/fhs-2.3.html#LIBLTQUALGTALTERNATEF ORMATESSENTIAL>`_
57 if sys.platform.startswith('win'): 53 if sys.platform.startswith('win'):
58 PY_SOURCE_EXTS = ('py', 'pyw') 54 PY_SOURCE_EXTS = ('py', 'pyw')
59 PY_COMPILED_EXTS = ('dll', 'pyd') 55 PY_COMPILED_EXTS = ('dll', 'pyd')
56 STD_LIB_DIR = get_python_lib(standard_lib=1)
60 else: 57 else:
61 PY_SOURCE_EXTS = ('py',) 58 PY_SOURCE_EXTS = ('py',)
62 PY_COMPILED_EXTS = ('so',) 59 PY_COMPILED_EXTS = ('so',)
63 60 # extend lib dir with some arch-dependant paths
64 try: 61 STD_LIB_DIR = join(get_config_var("LIBDIR"), "python%s" % get_python_version ())
65 STD_LIB_DIR = get_python_lib(standard_lib=1)
66 # get_python_lib(standard_lib=1) is not available on pypy, set STD_LIB_DIR to
67 # non-valid path, see https://bugs.pypy.org/issue1164
68 except DistutilsPlatformError:
69 STD_LIB_DIR = '//'
70
71 EXT_LIB_DIR = get_python_lib()
72 62
73 BUILTIN_MODULES = dict(zip(sys.builtin_module_names, 63 BUILTIN_MODULES = dict(zip(sys.builtin_module_names,
74 [1]*len(sys.builtin_module_names))) 64 [1]*len(sys.builtin_module_names)))
75 65
76 66
77 class NoSourceFile(Exception): 67 class NoSourceFile(Exception):
78 """exception raised when we are not able to get a python 68 """exception raised when we are not able to get a python
79 source file for a precompiled file 69 source file for a precompiled file
80 """ 70 """
81 71
82 class LazyObject(object): 72 class LazyObject(object):
83 def __init__(self, module, obj): 73 def __init__(self, module, obj):
84 self.module = module 74 self.module = module
85 self.obj = obj 75 self.obj = obj
86 self._imported = None 76 self._imported = None
87 77
88 def _getobj(self): 78 def _getobj(self):
89 if self._imported is None: 79 if self._imported is None:
90 self._imported = getattr(load_module_from_name(self.module), 80 self._imported = getattr(load_module_from_name(self.module),
91 self.obj) 81 self.obj)
92 return self._imported 82 return self._imported
93 83
94 def __getattribute__(self, attr): 84 def __getattribute__(self, attr):
95 try: 85 try:
96 return super(LazyObject, self).__getattribute__(attr) 86 return super(LazyObject, self).__getattribute__(attr)
97 except AttributeError as ex: 87 except AttributeError, ex:
98 return getattr(self._getobj(), attr) 88 return getattr(self._getobj(), attr)
99 89
100 def __call__(self, *args, **kwargs): 90 def __call__(self, *args, **kwargs):
101 return self._getobj()(*args, **kwargs) 91 return self._getobj()(*args, **kwargs)
102 92
103 93
104 def load_module_from_name(dotted_name, path=None, use_sys=1): 94 def load_module_from_name(dotted_name, path=None, use_sys=1):
105 """Load a Python module from its name. 95 """Load a Python module from it's name.
106 96
107 :type dotted_name: str 97 :type dotted_name: str
108 :param dotted_name: python name of a module or package 98 :param dotted_name: python name of a module or package
109 99
110 :type path: list or None 100 :type path: list or None
111 :param path: 101 :param path:
112 optional list of path where the module or package should be 102 optional list of path where the module or package should be
113 searched (use sys.path if nothing or None is given) 103 searched (use sys.path if nothing or None is given)
114 104
115 :type use_sys: bool 105 :type use_sys: bool
116 :param use_sys: 106 :param use_sys:
117 boolean indicating whether the sys.modules dictionary should be 107 boolean indicating whether the sys.modules dictionary should be
118 used or not 108 used or not
119 109
120 110
121 :raise ImportError: if the module or package is not found 111 :raise ImportError: if the module or package is not found
122 112
123 :rtype: module 113 :rtype: module
124 :return: the loaded module 114 :return: the loaded module
125 """ 115 """
126 return load_module_from_modpath(dotted_name.split('.'), path, use_sys) 116 return load_module_from_modpath(dotted_name.split('.'), path, use_sys)
127 117
128 118
129 def load_module_from_modpath(parts, path=None, use_sys=1): 119 def load_module_from_modpath(parts, path=None, use_sys=1):
130 """Load a python module from its splitted name. 120 """Load a python module from it's splitted name.
131 121
132 :type parts: list(str) or tuple(str) 122 :type parts: list(str) or tuple(str)
133 :param parts: 123 :param parts:
134 python name of a module or package splitted on '.' 124 python name of a module or package splitted on '.'
135 125
136 :type path: list or None 126 :type path: list or None
137 :param path: 127 :param path:
138 optional list of path where the module or package should be 128 optional list of path where the module or package should be
139 searched (use sys.path if nothing or None is given) 129 searched (use sys.path if nothing or None is given)
140 130
(...skipping 13 matching lines...) Expand all
154 pass 144 pass
155 modpath = [] 145 modpath = []
156 prevmodule = None 146 prevmodule = None
157 for part in parts: 147 for part in parts:
158 modpath.append(part) 148 modpath.append(part)
159 curname = '.'.join(modpath) 149 curname = '.'.join(modpath)
160 module = None 150 module = None
161 if len(modpath) != len(parts): 151 if len(modpath) != len(parts):
162 # even with use_sys=False, should try to get outer packages from sys .modules 152 # even with use_sys=False, should try to get outer packages from sys .modules
163 module = sys.modules.get(curname) 153 module = sys.modules.get(curname)
164 elif use_sys:
165 # because it may have been indirectly loaded through a parent
166 module = sys.modules.get(curname)
167 if module is None: 154 if module is None:
168 mp_file, mp_filename, mp_desc = find_module(part, path) 155 mp_file, mp_filename, mp_desc = find_module(part, path)
169 module = load_module(curname, mp_file, mp_filename, mp_desc) 156 module = load_module(curname, mp_file, mp_filename, mp_desc)
170 if prevmodule: 157 if prevmodule:
171 setattr(prevmodule, part, module) 158 setattr(prevmodule, part, module)
172 _file = getattr(module, '__file__', '') 159 _file = getattr(module, '__file__', '')
173 if not _file and len(modpath) != len(parts): 160 if not _file and len(modpath) != len(parts):
174 raise ImportError('no module in %s' % '.'.join(parts[len(modpath):]) ) 161 raise ImportError('no module in %s' % '.'.join(parts[len(modpath):]) )
175 path = [dirname( _file )] 162 path = [dirname( _file )]
176 prevmodule = module 163 prevmodule = module
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 if extrapath is not None: 223 if extrapath is not None:
237 for path_ in extrapath: 224 for path_ in extrapath:
238 path = abspath(path_) 225 path = abspath(path_)
239 if path and base[:len(path)] == path: 226 if path and base[:len(path)] == path:
240 submodpath = [pkg for pkg in base[len(path):].split(os.sep) 227 submodpath = [pkg for pkg in base[len(path):].split(os.sep)
241 if pkg] 228 if pkg]
242 if _check_init(path, submodpath[:-1]): 229 if _check_init(path, submodpath[:-1]):
243 return extrapath[path_].split('.') + submodpath 230 return extrapath[path_].split('.') + submodpath
244 for path in sys.path: 231 for path in sys.path:
245 path = abspath(path) 232 path = abspath(path)
246 if path and base.startswith(path): 233 if path and base[:len(path)] == path:
234 if filename.find('site-packages') != -1 and \
235 path.find('site-packages') == -1:
236 continue
247 modpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg] 237 modpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg]
248 if _check_init(path, modpath[:-1]): 238 if _check_init(path, modpath[:-1]):
249 return modpath 239 return modpath
250 raise ImportError('Unable to find module for %s in %s' % ( 240 raise ImportError('Unable to find module for %s in %s' % (
251 filename, ', \n'.join(sys.path))) 241 filename, ', \n'.join(sys.path)))
252 242
253 243
254 244
255 def file_from_modpath(modpath, path=None, context_file=None): 245 def file_from_modpath(modpath, path=None, context_file=None):
256 """given a mod path (i.e. splitted module / package name), return the 246 """given a mod path (i.e. splitted module / package name), return the
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 source_path = '%s.%s' % (base, ext) 439 source_path = '%s.%s' % (base, ext)
450 if exists(source_path): 440 if exists(source_path):
451 return source_path 441 return source_path
452 if include_no_ext and not orig_ext and exists(base): 442 if include_no_ext and not orig_ext and exists(base):
453 return base 443 return base
454 raise NoSourceFile(filename) 444 raise NoSourceFile(filename)
455 445
456 446
457 def cleanup_sys_modules(directories): 447 def cleanup_sys_modules(directories):
458 """remove submodules of `directories` from `sys.modules`""" 448 """remove submodules of `directories` from `sys.modules`"""
459 cleaned = [] 449 for modname, module in sys.modules.items():
460 for modname, module in list(sys.modules.items()):
461 modfile = getattr(module, '__file__', None) 450 modfile = getattr(module, '__file__', None)
462 if modfile: 451 if modfile:
463 for directory in directories: 452 for directory in directories:
464 if modfile.startswith(directory): 453 if modfile.startswith(directory):
465 cleaned.append(modname)
466 del sys.modules[modname] 454 del sys.modules[modname]
467 break 455 break
468 return cleaned
469 456
470 457
471 def is_python_source(filename): 458 def is_python_source(filename):
472 """ 459 """
473 rtype: bool 460 rtype: bool
474 return: True if the filename is a python source file 461 return: True if the filename is a python source file
475 """ 462 """
476 return splitext(filename)[1][1:] in PY_SOURCE_EXTS 463 return splitext(filename)[1][1:] in PY_SOURCE_EXTS
477 464
478 465
(...skipping 11 matching lines...) Expand all
490 477
491 :rtype: bool 478 :rtype: bool
492 :return: 479 :return:
493 true if the module: 480 true if the module:
494 - is located on the path listed in one of the directory in `std_path` 481 - is located on the path listed in one of the directory in `std_path`
495 - is a built-in module 482 - is a built-in module
496 """ 483 """
497 modname = modname.split('.')[0] 484 modname = modname.split('.')[0]
498 try: 485 try:
499 filename = file_from_modpath([modname]) 486 filename = file_from_modpath([modname])
500 except ImportError as ex: 487 except ImportError, ex:
501 # import failed, i'm probably not so wrong by supposing it's 488 # import failed, i'm probably not so wrong by supposing it's
502 # not standard... 489 # not standard...
503 return 0 490 return 0
504 # modules which are not living in a file are considered standard 491 # modules which are not living in a file are considered standard
505 # (sys and __builtin__ for instance) 492 # (sys and __builtin__ for instance)
506 if filename is None: 493 if filename is None:
507 return 1 494 return 1
508 filename = abspath(filename) 495 filename = abspath(filename)
509 if filename.startswith(EXT_LIB_DIR):
510 return 0
511 for path in std_path: 496 for path in std_path:
512 if filename.startswith(abspath(path)): 497 path = abspath(path)
513 return 1 498 if filename.startswith(path):
499 pfx_len = len(path)
500 if filename[pfx_len+1:pfx_len+14] != 'site-packages':
501 return 1
502 return 0
514 return False 503 return False
515 504
516 505
517 506
518 def is_relative(modname, from_file): 507 def is_relative(modname, from_file):
519 """return true if the given module name is relative to the given 508 """return true if the given module name is relative to the given
520 file name 509 file name
521 510
522 :type modname: str 511 :type modname: str
523 :param modname: name of the module we are interested in 512 :param modname: name of the module we are interested in
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 elif mtype == PKG_DIRECTORY: 558 elif mtype == PKG_DIRECTORY:
570 mp_filename = _has_init(mp_filename) 559 mp_filename = _has_init(mp_filename)
571 return mp_filename 560 return mp_filename
572 561
573 def _search_zip(modpath, pic): 562 def _search_zip(modpath, pic):
574 for filepath, importer in pic.items(): 563 for filepath, importer in pic.items():
575 if importer is not None: 564 if importer is not None:
576 if importer.find_module(modpath[0]): 565 if importer.find_module(modpath[0]):
577 if not importer.find_module('/'.join(modpath)): 566 if not importer.find_module('/'.join(modpath)):
578 raise ImportError('No module named %s in %s/%s' % ( 567 raise ImportError('No module named %s in %s/%s' % (
579 '.'.join(modpath[1:]), filepath, modpath)) 568 '.'.join(modpath[1:]), file, modpath))
580 return ZIPFILE, abspath(filepath) + '/' + '/'.join(modpath), fil epath 569 return ZIPFILE, abspath(filepath) + '/' + '/'.join(modpath), fil epath
581 raise ImportError('No module named %s' % '.'.join(modpath)) 570 raise ImportError('No module named %s' % '.'.join(modpath))
582 571
583 try:
584 import pkg_resources
585 except ImportError:
586 pkg_resources = None
587
588 def _module_file(modpath, path=None): 572 def _module_file(modpath, path=None):
589 """get a module type / file path 573 """get a module type / file path
590 574
591 :type modpath: list or tuple 575 :type modpath: list or tuple
592 :param modpath: 576 :param modpath:
593 splitted module's name (i.e name of a module or package splitted 577 splitted module's name (i.e name of a module or package splitted
594 on '.'), with leading empty strings for explicit relative import 578 on '.'), with leading empty strings for explicit relative import
595 579
596 :type path: list or None 580 :type path: list or None
597 :param path: 581 :param path:
(...skipping 10 matching lines...) Expand all
608 _path = (path is None and sys.path or path) 592 _path = (path is None and sys.path or path)
609 for __path in _path: 593 for __path in _path:
610 if not __path in pic: 594 if not __path in pic:
611 try: 595 try:
612 pic[__path] = zipimport.zipimporter(__path) 596 pic[__path] = zipimport.zipimporter(__path)
613 except zipimport.ZipImportError: 597 except zipimport.ZipImportError:
614 pic[__path] = None 598 pic[__path] = None
615 checkeggs = True 599 checkeggs = True
616 except AttributeError: 600 except AttributeError:
617 checkeggs = False 601 checkeggs = False
618 # pkg_resources support (aka setuptools namespace packages)
619 if (pkg_resources is not None
620 and modpath[0] in pkg_resources._namespace_packages
621 and modpath[0] in sys.modules
622 and len(modpath) > 1):
623 # setuptools has added into sys.modules a module object with proper
624 # __path__, get back information from there
625 module = sys.modules[modpath.pop(0)]
626 path = module.__path__
627 imported = [] 602 imported = []
628 while modpath: 603 while modpath:
629 modname = modpath[0]
630 # take care to changes in find_module implementation wrt builtin modules
631 #
632 # Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23)
633 # >>> imp.find_module('posix')
634 # (None, 'posix', ('', '', 6))
635 #
636 # Python 3.3.1 (default, Apr 26 2013, 12:08:46)
637 # >>> imp.find_module('posix')
638 # (None, None, ('', '', 6))
639 try: 604 try:
640 _, mp_filename, mp_desc = find_module(modname, path) 605 _, mp_filename, mp_desc = find_module(modpath[0], path)
641 except ImportError: 606 except ImportError:
642 if checkeggs: 607 if checkeggs:
643 return _search_zip(modpath, pic)[:2] 608 return _search_zip(modpath, pic)[:2]
644 raise 609 raise
645 else: 610 else:
646 if checkeggs and mp_filename: 611 if checkeggs:
647 fullabspath = [abspath(x) for x in _path] 612 fullabspath = [abspath(x) for x in _path]
648 try: 613 try:
649 pathindex = fullabspath.index(dirname(abspath(mp_filename))) 614 pathindex = fullabspath.index(dirname(abspath(mp_filename)))
650 emtype, emp_filename, zippath = _search_zip(modpath, pic) 615 emtype, emp_filename, zippath = _search_zip(modpath, pic)
651 if pathindex > _path.index(zippath): 616 if pathindex > _path.index(zippath):
652 # an egg takes priority 617 # an egg takes priority
653 return emtype, emp_filename 618 return emtype, emp_filename
654 except ValueError: 619 except ValueError:
655 # XXX not in _path 620 # XXX not in _path
656 pass 621 pass
657 except ImportError: 622 except ImportError:
658 pass 623 pass
659 checkeggs = False 624 checkeggs = False
660 imported.append(modpath.pop(0)) 625 imported.append(modpath.pop(0))
661 mtype = mp_desc[2] 626 mtype = mp_desc[2]
662 if modpath: 627 if modpath:
663 if mtype != PKG_DIRECTORY: 628 if mtype != PKG_DIRECTORY:
664 raise ImportError('No module %s in %s' % ('.'.join(modpath), 629 raise ImportError('No module %s in %s' % ('.'.join(modpath),
665 '.'.join(imported))) 630 '.'.join(imported)))
666 # XXX guess if package is using pkgutil.extend_path by looking for 631 path = [mp_filename]
667 # those keywords in the first four Kbytes
668 try:
669 with open(join(mp_filename, '__init__.py')) as stream:
670 data = stream.read(4096)
671 except IOError:
672 path = [mp_filename]
673 else:
674 if 'pkgutil' in data and 'extend_path' in data:
675 # extend_path is called, search sys.path for module/packages
676 # of this name see pkgutil.extend_path documentation
677 path = [join(p, *imported) for p in sys.path
678 if isdir(join(p, *imported))]
679 else:
680 path = [mp_filename]
681 return mtype, mp_filename 632 return mtype, mp_filename
682 633
683 def _is_python_file(filename): 634 def _is_python_file(filename):
684 """return true if the given filename should be considered as a python file 635 """return true if the given filename should be considered as a python file
685 636
686 .pyc and .pyo are ignored 637 .pyc and .pyo are ignored
687 """ 638 """
688 for ext in ('.py', '.so', '.pyd', '.pyw'): 639 for ext in ('.py', '.so', '.pyd', '.pyw'):
689 if filename.endswith(ext): 640 if filename.endswith(ext):
690 return True 641 return True
691 return False 642 return False
692 643
693 644
694 def _has_init(directory): 645 def _has_init(directory):
695 """if the given directory has a valid __init__ file, return its path, 646 """if the given directory has a valid __init__ file, return its path,
696 else return None 647 else return None
697 """ 648 """
698 mod_or_pack = join(directory, '__init__') 649 mod_or_pack = join(directory, '__init__')
699 for ext in PY_SOURCE_EXTS + ('pyc', 'pyo'): 650 for ext in PY_SOURCE_EXTS + ('pyc', 'pyo'):
700 if exists(mod_or_pack + '.' + ext): 651 if exists(mod_or_pack + '.' + ext):
701 return mod_or_pack + '.' + ext 652 return mod_or_pack + '.' + ext
702 return None 653 return None
OLDNEW
« no previous file with comments | « third_party/logilab/common/logging_ext.py ('k') | third_party/logilab/common/optik_ext.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698