Skip to content

Commit

Permalink
Merge pull request #151 from bcaller/imports
Browse files Browse the repository at this point in the history
Import woes
  • Loading branch information
KevinHock authored Jul 24, 2018
2 parents 6d81d91 + 11bb85b commit fbca4d2
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 28 deletions.
1 change: 0 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
show_missing = True

exclude_lines =
def valid_date
def __repr__
def __str__
if __name__ == .__main__.:
Expand Down
Empty file.
5 changes: 3 additions & 2 deletions pyt/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,16 @@ def main(command_line_args=sys.argv[1:]): # noqa: C901
directory = os.path.normpath(args.project_root)
else:
directory = os.path.dirname(path)
project_modules = get_modules(directory)
project_modules = get_modules(directory, prepend_module_root=args.prepend_module_root)
local_modules = get_directory_modules(directory)
tree = generate_ast(path)

cfg = make_cfg(
tree,
project_modules,
local_modules,
path
path,
allow_local_directory_imports=args.allow_local_imports
)
cfg_list = [cfg]

Expand Down
6 changes: 4 additions & 2 deletions pyt/cfg/expr_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ def __init__(
project_modules,
local_modules,
filename,
module_definitions=None
module_definitions=None,
allow_local_directory_imports=True
):
"""Create an empty CFG."""
super().__init__(allow_local_directory_imports=allow_local_directory_imports)
self.project_modules = project_modules
self.local_modules = local_modules
self.local_modules = local_modules if self._allow_local_modules else []
self.filenames = [filename]
self.blackbox_assignments = set()
self.nodes = list()
Expand Down
6 changes: 4 additions & 2 deletions pyt/cfg/make_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@ def make_cfg(
project_modules,
local_modules,
filename,
module_definitions=None
module_definitions=None,
allow_local_directory_imports=True
):
visitor = ExprVisitor(
tree,
project_modules,
local_modules,
filename,
module_definitions
module_definitions,
allow_local_directory_imports
)
return CFG(
visitor.nodes,
Expand Down
5 changes: 4 additions & 1 deletion pyt/cfg/stmt_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@


class StmtVisitor(ast.NodeVisitor):
def __init__(self, allow_local_directory_imports=True):
self._allow_local_modules = allow_local_directory_imports
super().__init__()

def visit_Module(self, node):
return self.stmt_star_handler(node.body)
Expand Down Expand Up @@ -784,7 +787,7 @@ def add_module( # noqa: C901

# Analyse the file
self.filenames.append(module_path)
self.local_modules = get_directory_modules(module_path)
self.local_modules = get_directory_modules(module_path) if self._allow_local_modules else []
tree = generate_ast(module_path)

# module[0] is None during e.g. "from . import foo", so we must str()
Expand Down
20 changes: 13 additions & 7 deletions pyt/core/project_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def get_directory_modules(directory):
return _local_modules


def get_modules(path):
def get_modules(path, prepend_module_root=True):
"""Return a list containing tuples of
e.g. ('test_project.utils', 'example/test_project/utils.py')
"""
Expand All @@ -52,14 +52,20 @@ def get_modules(path):
'.'
)
directory = directory.replace('.', '', 1)

module_name_parts = []
if prepend_module_root:
module_name_parts.append(module_root)
if directory:
modules.append(
('.'.join((module_root, directory, filename.replace('.py', ''))), os.path.join(root, filename))
)
module_name_parts.append(directory)

if filename == '__init__.py':
path = root
else:
modules.append(
('.'.join((module_root, filename.replace('.py', ''))), os.path.join(root, filename))
)
module_name_parts.append(os.path.splitext(filename)[0])
path = os.path.join(root, filename)

modules.append(('.'.join(module_name_parts), path))

return modules

Expand Down
24 changes: 15 additions & 9 deletions pyt/usage.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@
)


def valid_date(s):
date_format = "%Y-%m-%d"
try:
return datetime.strptime(s, date_format).date()
except ValueError:
msg = "Not a valid date: '{0}'. Format: {1}".format(s, date_format)
raise argparse.ArgumentTypeError(msg)


def _add_required_group(parser):
required_group = parser.add_argument_group('required arguments')
required_group.add_argument(
Expand Down Expand Up @@ -101,6 +92,21 @@ def _add_optional_group(parser):
default='',
help='Separate files with commas'
)
optional_group.add_argument(
'--dont-prepend-root',
help="In project root e.g. /app, imports are not prepended with app.*",
action='store_false',
default=True,
dest='prepend_module_root'
)
optional_group.add_argument(
'--no-local-imports',
help='If set, absolute imports must be relative to the project root. '
'If not set, modules in the same directory can be imported just by their names.',
action='store_false',
default=True,
dest='allow_local_imports'
)


def _add_print_group(parser):
Expand Down
34 changes: 32 additions & 2 deletions tests/core/project_handler_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,58 @@ def test_get_modules(self):
utils_path = os.path.join(project_folder, 'utils.py')
exceptions_path = os.path.join(project_folder, 'exceptions.py')
some_path = os.path.join(project_folder, folder, 'some.py')
__init__path = os.path.join(project_folder, folder)
indhold_path = os.path.join(project_folder, folder, directory, 'indhold.py')

# relative_folder_name = '.' + folder
app_name = project_namespace + '.' + 'app'
utils_name = project_namespace + '.' + 'utils'
exceptions_name = project_namespace + '.' + 'exceptions'
some_name = project_namespace + '.' + folder + '.some'
__init__name = project_namespace + '.' + folder
indhold_name = project_namespace + '.' + folder + '.' + directory + '.indhold'

app_tuple = (app_name, app_path)
utils_tuple = (utils_name, utils_path)
exceptions_tuple = (exceptions_name, exceptions_path)
some_tuple = (some_name, some_path)
__init__tuple = (__init__name, __init__path)
indhold_tuple = (indhold_name, indhold_path)

self.assertIn(app_tuple, modules)
self.assertIn(utils_tuple, modules)
self.assertIn(exceptions_tuple, modules)
self.assertIn(some_tuple, modules)
self.assertIn(__init__tuple, modules)
self.assertIn(indhold_tuple, modules)

self.assertEqual(len(modules), 5)
self.assertEqual(len(modules), 6)

def test_get_modules_no_prepend_root(self):
project_folder = os.path.normpath(os.path.join('examples', 'test_project'))

folder = 'folder'
directory = 'directory'

modules = get_modules(project_folder, prepend_module_root=False)

app_path = os.path.join(project_folder, 'app.py')
__init__path = os.path.join(project_folder, folder)
indhold_path = os.path.join(project_folder, folder, directory, 'indhold.py')

app_name = 'app'
__init__name = folder
indhold_name = folder + '.' + directory + '.indhold'

app_tuple = (app_name, app_path)
__init__tuple = (__init__name, __init__path)
indhold_tuple = (indhold_name, indhold_path)

self.assertIn(app_tuple, modules)
self.assertIn(__init__tuple, modules)
self.assertIn(indhold_tuple, modules)

self.assertEqual(len(modules), 6)

def test_get_modules_and_packages(self):
project_folder = os.path.normpath(os.path.join('examples', 'test_project'))
Expand Down Expand Up @@ -104,4 +134,4 @@ def test_get_modules_and_packages(self):
self.assertIn(some_tuple, modules)
self.assertIn(indhold_tuple, modules)

self.assertEqual(len(modules), 7)
self.assertEqual(len(modules), 8)
11 changes: 9 additions & 2 deletions tests/usage_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ def test_no_args(self):
EXPECTED = """usage: python -m pyt [-h] [-a ADAPTOR] [-pr PROJECT_ROOT]
[-b BASELINE_JSON_FILE] [-j] [-m BLACKBOX_MAPPING_FILE]
[-t TRIGGER_WORD_FILE] [-o OUTPUT_FILE] [--ignore-nosec]
[-r] [-x EXCLUDED_PATHS] [-trim] [-i]
[-r] [-x EXCLUDED_PATHS] [--dont-prepend-root]
[--no-local-imports] [-trim] [-i]
targets [targets ...]
required arguments:
Expand All @@ -55,6 +56,11 @@ def test_no_args(self):
-r, --recursive find and process files in subdirectories
-x EXCLUDED_PATHS, --exclude EXCLUDED_PATHS
Separate files with commas
--dont-prepend-root In project root e.g. /app, imports are not prepended
with app.*
--no-local-imports If set, absolute imports must be relative to the
project root. If not set, modules in the same
directory can be imported just by their names.
print arguments:
-trim, --trim-reassigned-in
Expand All @@ -73,7 +79,8 @@ def test_valid_args_but_no_targets(self):
EXPECTED = """usage: python -m pyt [-h] [-a ADAPTOR] [-pr PROJECT_ROOT]
[-b BASELINE_JSON_FILE] [-j] [-m BLACKBOX_MAPPING_FILE]
[-t TRIGGER_WORD_FILE] [-o OUTPUT_FILE] [--ignore-nosec]
[-r] [-x EXCLUDED_PATHS] [-trim] [-i]
[-r] [-x EXCLUDED_PATHS] [--dont-prepend-root]
[--no-local-imports] [-trim] [-i]
targets [targets ...]
python -m pyt: error: the following arguments are required: targets\n"""

Expand Down

0 comments on commit fbca4d2

Please sign in to comment.