Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def biz():
"""
multiline 1-1-0 """
class Spam(object):
""" multiline 0-2-1
---
"""
def eggs():
""" multiline 0-2-0
---"""
pass
''')
self = static.TopLevelVisitor.parse(source)
calldefs = self.calldefs
sourcelines = source.split('\n')
for k, calldef in calldefs.items():
line = sourcelines[calldef.lineno - 1]
callname = calldef.callname
# Ensure linenumbers correspond with start of func/class def
assert callname.split('.')[-1] in line
docsrc_lines = sourcelines[calldef.doclineno - 1:calldef.doclineno_end]
# Ensure linenumbers correspond with start and end of doctest
assert docsrc_lines[0].strip().startswith('"""')
assert docsrc_lines[-1].strip().endswith('"""')
'Is it an old pyc file?'.format(modname))
continue
FORCE_DYNAMIC = '--xdoc-force-dynamic' in sys.argv
# if false just skip extension modules
# ALLOW_DYNAMIC = '--no-xdoc-dynamic' not in sys.argv
ALLOW_DYNAMIC = '--allow-xdoc-dynamic' in sys.argv
needs_dynamic = False
if FORCE_DYNAMIC:
# Force dynamic parsing for everything
do_dynamic = True
else:
# Some modules can only be parsed dynamically
needs_dynamic = modpath.endswith(static._platform_pylib_exts())
do_dynamic = needs_dynamic and ALLOW_DYNAMIC
if do_dynamic:
try:
calldefs = dynamic.parse_dynamic_calldefs(modpath)
except ImportError as ex:
# Some modules are just c modules
msg = 'Cannot dynamically parse module={} at path={}.\nCaused by: {!r} {}'
msg = msg.format(modname, modpath, type(ex), ex)
warnings.warn(msg)
except Exception as ex:
msg = 'Cannot dynamically parse module={} at path={}.\nCaused by: {!r} {}'
msg = msg.format(modname, modpath, type(ex), ex)
warnings.warn(msg)
raise
else:
>>> for key, calldef in sorted(calldefs.items()):
... print('key = {!r}'.format(key))
... print(' * calldef.callname = {}'.format(calldef.callname))
... if calldef.docstr is None:
... print(' * len(calldef.docstr) = {}'.format(calldef.docstr))
... else:
... print(' * len(calldef.docstr) = {}'.format(len(calldef.docstr)))
"""
from xdoctest import static_analysis as static
from xdoctest import utils # NOQA
# Possible option for dynamic parsing
module = utils.import_module_from_path(modpath)
calldefs = {}
if getattr(module, '__doc__'):
calldefs['__doc__'] = static.CallDefNode(
callname='__doc__',
docstr=module.__doc__,
lineno=0,
doclineno=1,
doclineno_end=1,
args=None
)
for key, val in iter_module_doctestables(module):
# if hasattr(val, '__doc__'):
if hasattr(val, '__doc__') and hasattr(val, '__name__'):
calldefs[key] = static.CallDefNode(
callname=val.__name__,
docstr=val.__doc__,
lineno=0,
doclineno=1,
"""
Args:
modpath (str): path to the module
References:
https://stackoverflow.com/questions/67631/import-module-given-path
Example:
>>> from xdoctest import utils
>>> modpath = utils.__file__
>>> module = import_module_from_path(modpath)
>>> assert module is utils
"""
# the importlib version doesnt work in pytest
import xdoctest.static_analysis as static
dpath, rel_modpath = static.split_modpath(modpath)
modname = static.modpath_to_modname(modpath)
with PythonPathContext(dpath):
try:
module = import_module_from_name(modname)
except Exception:
print('Failed to import modname={} with modpath={}'.format(
modname, modpath))
raise
# TODO: use this implementation once pytest fixes importlib
# if six.PY2: # nocover
# import imp
# module = imp.load_source(modname, modpath)
# elif sys.version_info[0:2] <= (3, 4): # nocover
# assert sys.version_info[0:2] <= (3, 2), '3.0 to 3.2 is not supported'
# from importlib.machinery import SourceFileLoader
# module = SourceFileLoader(modname, modpath).load_module()
def cmdline(self):
"""
A cli-instruction that can be used to execute *this* doctest.
Returns:
str:
"""
if self.mode == 'pytest':
return 'pytest ' + self.node
elif self.mode == 'native':
ALLOW_MODNAME_CMDLINE = False
if ALLOW_MODNAME_CMDLINE:
# not 100% reliable if any dynamic code has executed before
# or we are doing self-testing
in_path = static.is_modname_importable(self.modname)
if in_path:
# should be able to find the module by name
return 'python -m xdoctest ' + self.modname + ' ' + self.unique_callname
else:
# needs the full path to be able to run the module
return 'python -m xdoctest ' + self.modpath + ' ' + self.unique_callname
else:
# Probably safer to always use the path
return 'python -m xdoctest ' + self.modpath + ' ' + self.unique_callname
else:
raise KeyError(self.mode)
for rel_modname in imports:
sub_modpath = import_paths[rel_modname]
try:
if six.PY2:
with open(sub_modpath, 'r') as file:
source = file.read()
else:
with open(sub_modpath, 'r', encoding='utf8') as file:
source = file.read()
except Exception as ex: # nocover
raise IOError('Error reading {}, caused by {}'.format(
sub_modpath, repr(ex)))
valid_callnames = None
if use_all: # pragma: nobranch
try:
valid_callnames = static.parse_static_value('__all__', source)
except NameError:
pass
if valid_callnames is None:
# The __all__ variable is not specified or we dont care
top_level = static.TopLevelVisitor.parse(source)
attrnames = list(top_level.assignments) + list(top_level.calldefs.keys())
# list of names we wont export by default
invalid_callnames = dir(builtins)
valid_callnames = []
for attr in attrnames:
if '.' in attr or attr.startswith('_'):
continue
if attr in invalid_callnames: # nocover
continue
valid_callnames.append(attr)
from_imports.append((rel_modname, sorted(valid_callnames)))