-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pypyr.steps.pyimport. includes all plumbing to make it work per conte…
…xt instance. pypyr.steps.contextclearall also wipes pyimports. closes #110.
- Loading branch information
Showing
23 changed files
with
822 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
"""Global cache for namespace imports. | ||
Attributes: | ||
pystring_namespace_cache: global instance of the namespace cache for | ||
PyString expressions. Use this attribute to access the cache from | ||
elsewhere. | ||
""" | ||
import logging | ||
from sys import intern | ||
from pypyr.cache.cache import Cache | ||
from pypyr.moduleloader import ImportVisitor | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class NamespaceCache(Cache): | ||
"""Cache of namespace dictionaries. | ||
Parse source string for python import statements using AST Visitor. | ||
""" | ||
|
||
def get_namespace(self, source): | ||
"""Get cached namespace. Adds to cache if not exist. | ||
Args: | ||
source (str): String with python 'import x.y'/'from x import y' | ||
statements. | ||
Returns: | ||
Namespace dictionary of imported references. | ||
""" | ||
logger.debug("starting") | ||
|
||
# source can be relatively long. | ||
# interning means cache dict compare obj id rather than full str parse | ||
interned_source = intern(source) | ||
namespace = self.get( | ||
interned_source, | ||
lambda: ImportVisitor().get_namespace(interned_source)) | ||
|
||
logger.debug("done") | ||
return namespace | ||
|
||
|
||
# global instance of the cache. use this to access the cache from elsewhere. | ||
pystring_namespace_cache = NamespaceCache() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
"""pypyr step that imports to the namespace for PyString. | ||
Make Python stdlib or your own code available to any PyString in the pipeline. | ||
Only supports absolute imports, not relative. | ||
Supports python import syntax like: | ||
import x | ||
import x as y | ||
import x.y | ||
import x.y as z | ||
from x import y | ||
from x import y as z | ||
from x import y, z | ||
from a.b import c as d, e as f | ||
""" | ||
import logging | ||
from pypyr.cache.namespacecache import pystring_namespace_cache | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def run_step(context): | ||
"""Import modules, classes or functions for PyString expressions. | ||
Args: | ||
context (pypyr.context.Context): | ||
Context is a dictionary or dictionary-like. | ||
Context must contain key 'pyimport' | ||
The value of pyimport is a string containing python import | ||
statements. | ||
""" | ||
logger.debug("started") | ||
context.assert_key_has_value(key='pyImport', caller=__name__) | ||
|
||
# block yaml style could be LiteralScalarString, which is not hashable for | ||
# cache key. Explicitly make a string. | ||
source = str(context['pyImport']) | ||
|
||
namespace = pystring_namespace_cache.get_namespace(source) | ||
# len safe coz get_namespace returns {}, not None. | ||
logger.debug("imported %s objects to merge into PyString namespace", | ||
len(namespace)) | ||
|
||
context.pystring_globals.update(namespace) | ||
|
||
# pystring_globals initialized to {} on Context init, so len() is safe. | ||
logger.debug("PyString namespace now contains %s objects.", | ||
len(context.pystring_globals)) | ||
|
||
logger.debug("done") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
"""Arbitrary module with a test attribute.""" | ||
|
||
|
||
def arb_func_in_arbmod2(arg): | ||
"""Arbitrary function just returns input.""" | ||
return arg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
"""Arbitrary module with a test attribute.""" | ||
|
||
|
||
def arb_func_in_arbmod3(arg): | ||
"""Arbitrary function just returns input.""" | ||
return arg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
"""Arbitrary module with a test attribute. | ||
DON'T use me anywhere except moduleloader_test.py > test_import_visitor. | ||
Because otherwise coverage will drop <100% since Python import machinery will | ||
cache the module lookup and test_import_visitor explicitly tests a code-path | ||
where a module is not found in cache. | ||
Believe it or not, this is the least painful way of achieving it. | ||
""" | ||
|
||
|
||
def arb_func_in_arbmod4(arg): | ||
"""Arbitrary function just returns input.""" | ||
return arg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
"""Arbitrary module with multiple attributes.""" | ||
|
||
arb_attr = 123.456 | ||
|
||
|
||
def arb_func(arg): | ||
"""Arbitrary function just returns input.""" | ||
return arg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.