def hacking_import_rules(logical_line, filename, noqa): r"""Check for imports. OpenStack HACKING guide recommends one import per line: Do not import more than one module per line Examples: Okay: from nova.compute import api H301: from nova.compute import api, utils Do not use wildcard import Do not make relative imports Examples: Okay: from os import path Okay: from os import path as p Okay: from os import (path as p) Okay: import os.path Okay: from nova.compute import rpcapi Okay: from six.moves.urllib import parse H303: from os.path import * H304: from .compute import rpcapi """ # TODO(jogo): make the following doctests pass: # H301: import os, sys # TODO(mordred: We need to split this into different checks so that they # can be disabled by command line switches properly if noqa: return split_line = logical_line.split() split_line_len = len(split_line) if (split_line_len > 1 and split_line[0] in ('import', 'from') and not core.is_import_exception(split_line[1])): pos = logical_line.find(',') if pos != -1: if split_line[0] == 'from': yield pos, "H301: one import per line" pos = logical_line.find('*') if pos != -1: yield pos, "H303: No wildcard (*) import." return if split_line_len in (2, 4, 6) and split_line[1] != "__future__": if 'from' == split_line[0] and split_line_len > 3: mod = '.'.join((split_line[1], split_line[3])) if core.is_import_exception(mod): return if RE_RELATIVE_IMPORT.search(logical_line): yield logical_line.find('.'), ( "H304: No relative imports. '%s' is a relative import" % logical_line) return
def hacking_import_rules(logical_line, physical_line, filename, noqa): r"""Check for imports. OpenStack HACKING guide recommends one import per line: Do not import more than one module per line Examples: Okay: from nova.compute import api H301: from nova.compute import api, utils Do not use wildcard import Do not make relative imports Examples: Okay: from os import path Okay: from os import path as p Okay: from os import (path as p) Okay: import os.path Okay: from nova.compute import rpcapi Okay: from six.moves.urllib import parse H303: from os.path import * H304: from .compute import rpcapi """ # TODO(jogo): make the following doctests pass: # H301: import os, sys # TODO(mordred: We need to split this into different checks so that they # can be disabled by command line switches properly if noqa: return split_line = logical_line.split() split_line_len = len(split_line) if (split_line_len > 1 and split_line[0] in ('import', 'from') and not core.is_import_exception(split_line[1])): pos = logical_line.find(',') if pos != -1: if split_line[0] == 'from': yield pos, "H301: one import per line" pos = logical_line.find('*') if pos != -1: yield pos, "H303: No wildcard (*) import." return if split_line_len in (2, 4, 6) and split_line[1] != "__future__": if 'from' == split_line[0] and split_line_len > 3: mod = '.'.join((split_line[1], split_line[3])) if core.is_import_exception(mod): return if RE_RELATIVE_IMPORT.search(logical_line): yield logical_line.find('.'), ( "H304: No relative imports. '%s' is a relative import" % logical_line) return
def get_alias(logical_line): parts = logical_line.split() if (len(parts) > 3 and parts[0] == 'from' and parts[1] != '__future__' and not core.is_import_exception(parts[1])): # from path.to.module import module if len(parts) == 4: return '.'.join([parts[1], parts[3]]), None # from path.to.module import module as alias if len(parts) > 5 and parts[4] == 'as': return '.'.join([parts[1], parts[3]]), parts[5] return None
def check_module_only(logical_line, physical_line, filename, noqa): """Check imports. Imports should be modules only. Examples: Okay: from orquesta import conducting Okay: from orquesta import states Okay: from orquesta.utils import date O101: from orquesta.conducting import WorkflowConductor O101: from orquesta.states import REQUESTED O101: from orquesta.utils.date import parse """ if noqa: return def check_is_module(mod, search_path=sys.path): mod = mod.replace('(', '') # Ignore parentheses for finder in sys.meta_path: if finder.find_module(mod) is not None: return True try: mod_name = mod while '.' in mod_name: pack_name, _sep, mod_name = mod_name.partition('.') f, p, d = imp.find_module(pack_name, search_path) search_path = [p] imp.find_module(mod_name, search_path) except ImportError: try: # Handle namespace modules if '.' in mod: pack_name, mod_name = mod.rsplit('.', 1) __import__(pack_name, fromlist=[mod_name]) else: __import__(mod) except ImportError: # Import error here means the thing is not importable in # current environment, either because of missing dependency, # typo in code being checked, or any other reason. Anyway, we # have no means to know if it is module or not, so we return # True to avoid false positives. return True except Exception: # Skip stack trace on unexpected import error, # log and continue. traceback.print_exc() return False else: # The line was imported. If it is a module, it must be there. # If it is not there under its own name, look to see if it is # a module redirection import.. if mod in sys.modules: return True else: pack_name, _sep, mod_name = mod.rpartition('.') if pack_name in sys.modules: _mod = getattr(sys.modules[pack_name], mod_name, None) return inspect.ismodule(_mod) return False return True def is_module(mod): if mod not in MODULES_CACHE: MODULES_CACHE[mod] = check_is_module(mod) return MODULES_CACHE[mod] parts = logical_line.split() if (len(parts) > 3 and parts[0] == 'from' and parts[1] != '__future__' and not core.is_import_exception(parts[1]) and not is_module('.'.join([parts[1], parts[3]]))): yield 0, 'O101 import must be module only'
def hacking_import_rules(logical_line, physical_line, filename, noqa): r"""Check for imports. OpenStack HACKING guide recommends one import per line: Do not import more than one module per line Examples: Okay: from nova.compute import api H301: from nova.compute import api, utils Imports should usually be on separate lines. OpenStack HACKING guide recommends importing only modules: Do not import objects, only modules Examples: Okay: from os import path Okay: from os import path as p Okay: from os import (path as p) Okay: import os.path Okay: from nova.compute import rpcapi Okay: from os.path import dirname as dirname2 # noqa H302: from os.path import dirname as dirname2 H302: from os.path import (dirname as dirname2) H303: from os.path import * H304: from .compute import rpcapi """ # TODO(jogo): make the following doctests pass: # H301: import os, sys # NOTE(afazekas): An old style relative import example will not be able to # pass the doctest, since the relativity depends on the file's locality # TODO(mordred: We need to split this into 4 different checks so that they # can be disabled by command line switches properly if noqa: return def is_module_for_sure(mod, search_path=sys.path): mod = mod.replace('(', '') # Ignore parentheses try: mod_name = mod while '.' in mod_name: pack_name, _sep, mod_name = mod.partition('.') f, p, d = imp.find_module(pack_name, search_path) search_path = [p] imp.find_module(mod_name, search_path) except ImportError: try: # NOTE(vish): handle namespace modules if '.' in mod: pack_name, mod_name = mod.rsplit('.', 1) __import__(pack_name, fromlist=[mod_name]) else: __import__(mod) except ImportError: # NOTE(imelnikov): import error here means the thing is # not importable in current environment, either because # of missing dependency, typo in code being checked, or # any other reason. Anyway, we have no means to know if # it is module or not, so we return True to avoid # false positives. return True except Exception: # NOTE(jogo) don't stack trace if unexpected import error, # log and continue. traceback.print_exc() return False else: # NOTE(imelnikov): we imported the thing; if it was module, # it must be there: return mod in sys.modules return True def is_module(mod): """Checks for non module imports.""" if mod in modules_cache: return modules_cache[mod] res = is_module_for_sure(mod) modules_cache[mod] = res return res current_path = os.path.dirname(filename) current_mod = os.path.basename(filename) if current_mod[-3:] == ".py": current_mod = current_mod[:-3] split_line = logical_line.split() split_line_len = len(split_line) if (split_line_len > 1 and split_line[0] in ('import', 'from') and not core.is_import_exception(split_line[1])): pos = logical_line.find(',') if pos != -1: if split_line[0] == 'from': yield pos, "H301: one import per line" return # ',' is not supported by the H302 checker yet pos = logical_line.find('*') if pos != -1: yield pos, "H303: No wildcard (*) import." return if split_line_len in (2, 4, 6) and split_line[1] != "__future__": if 'from' == split_line[0] and split_line_len > 3: mod = '.'.join((split_line[1], split_line[3])) if core.is_import_exception(mod): return if RE_RELATIVE_IMPORT.search(logical_line): yield logical_line.find('.'), ( "H304: No relative imports. '%s' is a relative import" % logical_line) return if not is_module(mod): yield 0, ("H302: import only modules." "'%s' does not import a module" % logical_line) return # NOTE(afazekas): import searches first in the package # The import keyword just imports modules # The guestfs module now imports guestfs mod = split_line[1] if (current_mod != mod and not is_module(mod) and is_module_for_sure(mod, [current_path])): yield 0, ("H304: No relative imports." " '%s' is a relative import" % logical_line)
def hacking_import_rules(logical_line, physical_line, filename, noqa): r"""Check for imports. OpenStack HACKING guide recommends one import per line: Do not import more than one module per line Examples: Okay: from nova.compute import api H301: from nova.compute import api, utils Imports should usually be on separate lines. OpenStack HACKING guide recommends importing only modules: Do not import objects, only modules Examples: Okay: from os import path Okay: from os import path as p Okay: from os import (path as p) Okay: import os.path Okay: from nova.compute import rpcapi Okay: from os.path import dirname as dirname2 # noqa Okay: from six.moves.urllib import parse H302: from os.path import dirname as dirname2 H302: from os.path import (dirname as dirname2) H303: from os.path import * H304: from .compute import rpcapi """ # TODO(jogo): make the following doctests pass: # H301: import os, sys # NOTE(afazekas): An old style relative import example will not be able to # pass the doctest, since the relativity depends on the file's locality # TODO(mordred: We need to split this into 4 different checks so that they # can be disabled by command line switches properly if noqa: return def is_module_for_sure(mod, search_path=sys.path): mod = mod.replace('(', '') # Ignore parentheses for finder in sys.meta_path: if finder.find_module(mod) is not None: return True try: mod_name = mod while '.' in mod_name: pack_name, _sep, mod_name = mod.partition('.') f, p, d = imp.find_module(pack_name, search_path) search_path = [p] imp.find_module(mod_name, search_path) except ImportError: try: # NOTE(vish): handle namespace modules if '.' in mod: pack_name, mod_name = mod.rsplit('.', 1) __import__(pack_name, fromlist=[mod_name]) else: __import__(mod) except ImportError: # NOTE(imelnikov): import error here means the thing is # not importable in current environment, either because # of missing dependency, typo in code being checked, or # any other reason. Anyway, we have no means to know if # it is module or not, so we return True to avoid # false positives. return True except Exception: # NOTE(jogo) don't stack trace if unexpected import error, # log and continue. traceback.print_exc() return False else: # NOTE(imelnikov): we imported the thing; if it was module, # it must be there: return mod in sys.modules return True def is_module(mod): """Checks for non module imports.""" if mod in modules_cache: return modules_cache[mod] res = is_module_for_sure(mod) modules_cache[mod] = res return res current_path = os.path.dirname(filename) current_mod = os.path.basename(filename) if current_mod[-3:] == ".py": current_mod = current_mod[:-3] split_line = logical_line.split() split_line_len = len(split_line) if (split_line_len > 1 and split_line[0] in ('import', 'from') and not core.is_import_exception(split_line[1])): pos = logical_line.find(',') if pos != -1: if split_line[0] == 'from': yield pos, "H301: one import per line" return # ',' is not supported by the H302 checker yet pos = logical_line.find('*') if pos != -1: yield pos, "H303: No wildcard (*) import." return if split_line_len in (2, 4, 6) and split_line[1] != "__future__": if 'from' == split_line[0] and split_line_len > 3: mod = '.'.join((split_line[1], split_line[3])) if core.is_import_exception(mod): return if RE_RELATIVE_IMPORT.search(logical_line): yield logical_line.find('.'), ( "H304: No relative imports. '%s' is a relative import" % logical_line) return if not is_module(mod): yield 0, ("H302: import only modules." "'%s' does not import a module" % logical_line) return # NOTE(afazekas): import searches first in the package # The import keyword just imports modules # The guestfs module now imports guestfs mod = split_line[1] if (current_mod != mod and not is_module(mod) and is_module_for_sure(mod, [current_path])): yield 0, ("H304: No relative imports." " '%s' is a relative import" % logical_line)