Skip to content

Commit

Permalink
Merge pull request #33 from mCallesen/5-add-list-imports-function
Browse files Browse the repository at this point in the history
Added python_package_imports functioN
  • Loading branch information
fhightower authored Jul 14, 2021
2 parents 4e5e817 + ba6ae00 commit 2ea5a0a
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
46 changes: 45 additions & 1 deletion d8s_python/python_data.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import argparse
import re
import sys
from typing import Any, Iterator, List, Union
from ast import Import, ImportFrom
from typing import Any, Dict, Iterator, List, Union

from .ast_data import python_ast_objects_of_type


# @decorators.map_firstp_arg
Expand Down Expand Up @@ -359,3 +362,44 @@ def python_type_name(python_type: type) -> str:
def python_object_type_to_word(python_object: Any) -> str:
"""Convert the given python type to a string."""
return python_type_name(type(python_object))


def _get_importfrom_module_name(node: ImportFrom) -> str:
"""Extract the module name from an ast.ImportFrom node.
The module name on the ast.ImportFrom node can be None for relative imports
In this case, this function will return the name as the dots from the import statement.
A few examples:
"from requests import get" -> "requests"
"from . import *" -> "."
"from .. import *" -> ".."
"from .foo import bar" -> "foo"
"""
if node.module is None:
module_name = "." * node.level
else:
module_name = node.module

return module_name


def python_package_imports(code: str) -> Dict[str, List[str]]:
"""Return a dictionary containing the names of all imported modules."""
# Start with the Import nodes.
# These will always have an empty list of submodules
# so we can just overwrite them without losing any data
modules = dict()
nodes = python_ast_objects_of_type(code, Import)
for node in nodes:
for alias in node.names:
modules[alias.name] = []

# Now for the ImportFrom nodes
importfrom_nodes = python_ast_objects_of_type(code, ImportFrom)
for node in importfrom_nodes:
module_name = _get_importfrom_module_name(node)

for alias in node.names:
modules.setdefault(module_name, []).append(alias.name)

return modules
32 changes: 32 additions & 0 deletions tests/test_python_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
python_object_source_code,
python_object_source_file,
python_object_type_to_word,
python_package_imports,
python_sort_type_list_by_name,
python_stack_local_data,
python_todos,
Expand Down Expand Up @@ -482,3 +483,34 @@ def test_python_function_blocks__async_functions():
'def foo(n):\n """Foo."""\n return n',
'async def bar(n):\n """Some async func."""\n return n',
]


def test_python_package_imports():
s = ''
assert python_package_imports(s) == {}

s = '''import requests'''
assert python_package_imports(s) == {'requests': []}

s = '''from math import sqrt'''
assert python_package_imports(s) == {'math': ['sqrt']}

s = '''
import os as _
import sys,random'''
assert python_package_imports(s) == {'os': [], 'sys': [], 'random': []}

s = '''
from democritus_dates import date_parse, date_now
import requests
print(date_parse('2 days from now'))
'''
assert python_package_imports(s) == {'democritus_dates': ['date_parse', 'date_now'], 'requests': []}

s = '''
from . import everything
from ..foo.bar import *
'''

assert python_package_imports(s) == {'.': ['everything'], 'foo.bar': ['*']}

0 comments on commit 2ea5a0a

Please sign in to comment.