Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port jishaku.inline_import #20

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ importlib.import_module('urllib.parse').quote('hello there')
Counter({'e': 4, 'd': 3, 'c': 2, 'b': 1})
```

The other public functions are `exec`, `compile`, `parse`, `find_imports`, and `update_globals`.
The other public functions are `exec`, `compile`, and `parse`.
See their docstrings for details.

By default, the filename for `SyntaxError`s is `<string>`.
Expand All @@ -47,15 +47,6 @@ for line in sys.stdin:
print(import_expression.eval(code, dict(l=line)))
```

### Custom encoding

```py
# encoding: import_expression
print(typing!.TYPE_CHECKING)
```

This file, when run, will print True/False. For maximum laziness you can also do `#coding:ie`.

### REPL usage

Run `import-expression` for an import expression enabled REPL. \
Expand All @@ -67,11 +58,6 @@ See `import-expression --help` for more details.

Run `import-expression <filename.py>`.

### File rewriter

Run `import-expression-rewrite <file.py>` to rewrite a file containing import expressions to standard Python. \
Add the `-i` flag to rewrite in-place.

## Limitations / Known Issues

* Due to the hell that is f-string parsing, and because `!` is already an operator inside f-strings,
Expand Down
31 changes: 4 additions & 27 deletions import_expression/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,13 @@

from . import constants
from ._syntax import fix_syntax as _fix_syntax
from ._parser import parse_ast as _parse_ast
from ._parser import find_imports as _find_imports
from ._parser import transform_ast as _transform_ast
from .version import __version__

with _contextlib.suppress(NameError):
del version

__all__ = ('compile', 'parse', 'eval', 'exec', 'constants', 'find_imports', 'update_globals')
__all__ = ('compile', 'parse', 'eval', 'exec', 'constants')

_source = _typing.Union[_ast.AST, _typing.AnyStr]

Expand All @@ -57,14 +56,14 @@ def parse(source: _source, filename=constants.DEFAULT_FILENAME, mode='exec', *,
"""
# for some API compatibility with ast, allow parse(parse('foo')) to work
if isinstance(source, _ast.AST):
return _parse_ast(source, filename=filename)
return _transform_ast(source, filename=filename)

fixed = _fix_syntax(source, filename=filename)
if flags & PyCF_DONT_IMPLY_DEDENT:
# just run it for the syntax errors, which codeop picks up on
_builtins.compile(fixed, filename, mode, flags)
tree = _ast.parse(fixed, filename, mode, **kwargs)
return _parse_ast(tree, source=source, filename=filename)
return _transform_ast(tree, source=source, filename=filename)

def compile(
source: _source,
Expand Down Expand Up @@ -101,32 +100,10 @@ def exec(source: _code, globals=None, locals=None):
return _builtins.eval(source, globals, locals)
_builtins.eval(compile(source, constants.DEFAULT_FILENAME, 'exec'), globals, locals)

def find_imports(source: str, filename=constants.DEFAULT_FILENAME, mode='exec'):
"""return a list of all module names required by the given source code."""
# passing an AST is not supported because it doesn't make sense to.
# either the AST is one that we made, in which case the imports have already been made and calling parse_ast again
# would find no imports, or it's an AST made by parsing the output of fix_syntax, which is internal.
fixed = _fix_syntax(source, filename=filename)
tree = _ast.parse(fixed, filename, mode)
return _find_imports(tree, filename=filename)

def update_globals(globals: dict) -> dict:
"""Ensure that the variables required for eval/exec are present in the given dict.
Note that import_expression.eval and import_expression.exec do this for you automatically.
Calling this function yourself is only necessary if you want to call builtins.eval or builtins.exec
with the return value of import_expression.compile.

This function always returns the passed dictionary to make expression chaining easier.
"""
globals.update({constants.IMPORTER: _importlib.import_module})
return globals

def _parse_eval_exec_args(globals, locals):
if globals is None:
globals = {}

update_globals(globals)

if locals is None:
locals = globals

Expand Down
1 change: 0 additions & 1 deletion import_expression/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ def __call__(self, source, filename, symbol, **kwargs):
class ImportExpressionInteractiveConsole(code.InteractiveConsole):
def __init__(self, locals=None, filename='<console>'):
super().__init__(locals, filename)
self.locals.update({constants.IMPORTER: importlib.import_module})
self.compile = ImportExpressionCommandCompiler()

# we must vendor this class because it creates global variables that the main code depends on
Expand Down
63 changes: 0 additions & 63 deletions import_expression/_codec/__init__.py

This file was deleted.

27 changes: 0 additions & 27 deletions import_expression/_codec/compat.py

This file was deleted.

36 changes: 0 additions & 36 deletions import_expression/_main2.py

This file was deleted.

Loading