Source code for utool.util_autogen

# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
import re
import os
import six
from collections import deque  # NOQA
from os.path import exists, dirname, join, expanduser, normpath
from utool import util_inject
print, rrr, profile = util_inject.inject2(__name__, '[autogen]')


[docs]class PythonStatement(object): """ Thin wrapper around a string representing executable python code """ def __init__(self, stmt): self.stmt = stmt def __repr__(self): return self.stmt def __str__(self): return self.stmt
[docs]def dump_autogen_code(fpath, autogen_text, codetype='python', fullprint=None): """ Helper that write a file if -w is given on command line, otherwise it just prints it out. It has the opption of comparing a diff to the file. """ import utool as ut dowrite = ut.get_argflag(('-w', '--write')) show_diff = ut.get_argflag('--diff') num_context_lines = ut.get_argval('--diff', type_=int, default=None) show_diff = show_diff or num_context_lines is not None num_context_lines = ut.get_argval('--diff', type_=int, default=None) if fullprint is None: fullprint = True if fullprint is False: fullprint = ut.get_argflag('--print') print('[autogen] Autogenerated %s...\n+---\n' % (fpath,)) if not dowrite: if fullprint: ut.print_code(autogen_text, lexer_name=codetype) print('\nL___') else: print('specify --print to write to stdout') pass print('specify -w to write, or --diff to compare') print('...would write to: %s' % fpath) if show_diff: if ut.checkpath(fpath, verbose=True): prev_text = ut.read_from(fpath) textdiff = ut.get_textdiff(prev_text, autogen_text, num_context_lines=num_context_lines) ut.print_difftext(textdiff) if dowrite: print('WARNING: Not writing. Remove --diff from command line') elif dowrite: ut.write_to(fpath, autogen_text)
[docs]def makeinit(mod_dpath, exclude_modnames=[], use_star=False): r""" Args: mod_dpath (str): exclude_modnames (list): (default = []) use_star (bool): (default = False) Returns: str: init_codeblock CommandLine: python -m utool.util_autogen --exec-makeinit --modname=ibeis.algo Example: >>> # SCRIPT >>> from utool.util_autogen import * # NOQA >>> import utool as ut >>> modname = ut.get_argval('--modname', str, default=None) >>> mod_dpath = (os.getcwd() if modname is None else >>> ut.get_modpath_from_modname(modname, prefer_pkg=True)) >>> mod_dpath = ut.unixpath(mod_dpath) >>> mod_fpath = join(mod_dpath, '__init__.py') >>> exclude_modnames = ut.get_argval(('--exclude', '-x'), list, default=[]) >>> use_star = ut.get_argflag('--star') >>> init_codeblock = makeinit(mod_dpath, exclude_modnames, use_star) >>> ut.dump_autogen_code(mod_fpath, init_codeblock) """ from utool._internal import util_importer import utool as ut module_name = ut.get_modname_from_modpath(mod_dpath) IMPORT_TUPLES = util_importer.make_import_tuples(mod_dpath, exclude_modnames=exclude_modnames) initstr = util_importer.make_initstr(module_name, IMPORT_TUPLES) regen_command = 'cd %s\n' % (mod_dpath) regen_command += ' makeinit.py' regen_command += ' --modname={modname}'.format(modname=module_name) if use_star: regen_command += ' --star' if len(exclude_modnames ) > 0: regen_command += ' -x ' + ' '.join(exclude_modnames) regen_block = (ut.codeblock(''' """ Regen Command: {regen_command} """ ''').format(regen_command=regen_command)) importstar_codeblock = ut.codeblock( ''' """ python -c "import {module_name}" --dump-{module_name}-init python -c "import {module_name}" --update-{module_name}-init """ __DYNAMIC__ = True if __DYNAMIC__: # TODO: import all utool external prereqs. Then the imports will not import # anything that has already in a toplevel namespace # COMMENTED OUT FOR FROZEN __INIT__ # Dynamically import listed util libraries and their members. from utool._internal import util_importer # FIXME: this might actually work with rrrr, but things arent being # reimported because they are already in the modules list import_execstr = util_importer.dynamic_import(__name__, IMPORT_TUPLES) exec(import_execstr) DOELSE = False else: # Do the nonexec import (can force it to happen no matter what if alwyas set # to True) DOELSE = True if DOELSE: # <AUTOGEN_INIT> pass # </AUTOGEN_INIT> '''.format(module_name=module_name) ) ts_line = '# Autogenerated on {ts}'.format(ts=ut.get_timestamp('printable')) init_codeblock_list = ['# -*- coding: utf-8 -*-', ts_line] init_codeblock_list.append(initstr) init_codeblock_list.append('\nIMPORT_TUPLES = ' + ut.list_str(IMPORT_TUPLES)) if use_star: init_codeblock_list.append(importstar_codeblock) init_codeblock_list.append(regen_block) init_codeblock = '\n'.join(init_codeblock_list) return init_codeblock
[docs]def write_modscript_alias(fpath, modname, args='', pyscript='python'): """ convinience function because $@ is annoying to paste into the terminal """ import utool as ut from os.path import splitext allargs_dict = { '.sh': ' $@', '.bat': ' %1', } _, script_ext = splitext(fpath) if script_ext not in ['.sh', '.bat']: script_ext = '.bat' if ut.WIN32 else 'sh' allargs = (args + allargs_dict[script_ext]).strip(' ') if not modname.endswith('.py'): fmtstr = '{pyscript} -m {modname} {allargs}' else: fmtstr = '{pyscript} {modname} {allargs}' cmdstr = fmtstr.format(pyscript=pyscript, modname=modname, allargs=allargs) ut.write_to(fpath, cmdstr) os.system('chmod +x ' + fpath)
[docs]def autofix_codeblock(codeblock, max_line_len=80, aggressive=False, very_aggressive=False, experimental=False): r""" Uses autopep8 to format a block of code Example: >>> import utool as ut >>> codeblock = ut.codeblock( ''' def func( with , some = 'Problems' ): syntax ='Ok' but = 'Its very messy' if None: # syntax might not be perfect due to being cut off ommiting_this_line_still_works= True ''') >>> fixed_codeblock = ut.autofix_codeblock(codeblock) >>> print(fixed_codeblock) """ # FIXME idk how to remove the blank line following the function with # autopep8. It seems to not be supported by them, but it looks bad. import autopep8 arglist = ['--max-line-length', '80'] if aggressive: arglist.extend(['-a']) if very_aggressive: arglist.extend(['-a', '-a']) if experimental: arglist.extend(['--experimental']) arglist.extend(['']) autopep8_options = autopep8.parse_args(arglist) fixed_codeblock = autopep8.fix_code(codeblock, options=autopep8_options) return fixed_codeblock
[docs]def load_func_from_module(modname, funcname, verbose=True, moddir=None): r""" Args: modname (str): module name funcname (str): function name verbose (bool): verbosity flag(default = True) moddir (None): (default = None) CommandLine: python -m utool.util_autogen --exec-load_func_from_module Example: >>> # UNSTABLE_DOCTEST >>> from utool.util_autogen import * # NOQA >>> import utool as ut >>> #modname = 'plottool.plots' >>> #funcname = 'multi_plot' >>> modname = 'utool.util_path' >>> funcname = 'checkpath' >>> verbose = True >>> moddir = None >>> func, module, error_str = load_func_from_module(modname, funcname, verbose, moddir) >>> source = ut.get_func_sourcecode(func, strip_docstr=True, strip_comments=True) >>> keyname = ut.named_field('keyname', ut.REGEX_VARNAME) >>> default = ut.named_field('default', '[\'\"A-Za-z_][A-Za-z0-9_\'\"]*') >>> pattern = re.escape('kwargs.get(\'') + keyname + re.escape('\',') >>> kwarg_keys = [match.groupdict()['keyname'] for match in re.finditer(pattern, source)] """ import utool as ut from os.path import join import imp func = None module = None error_str = None print('modname = %r' % (modname,)) print('funcname = %r' % (funcname,)) print('moddir = %r' % (moddir,)) if not isinstance(modname, six.string_types): error_str = 'modname=%r is not a string. bad input' % (modname,) else: if False: basemodname_ = modname basemodname = '' parts = modname.split('.') for index in range(len(parts)): #print('index = %r' % (index,)) basemodname = '.'.join(parts[0:index + 1]) #print('basemodname = %r' % (basemodname,)) basemodule = __import__(basemodname) #print('basemodule = %r' % (basemodule,)) #if hasattr(basemodule, 'rrrr'): # basemodule.rrrr() #imp.reload(basemodule) try: module = __import__(modname) except ImportError: if moddir is not None: #parts = # There can be a weird double import error thing happening here # Rectify the dots in the filename module = ut.import_module_from_fpath(join(moddir, modname.split('.')[-1] + '.py')) else: raise #import inspect try: imp.reload(module) except Exception as ex: pass if False: # Try removing pyc if it exists if module.__file__.endswith('.pyc'): ut.delete(module.__file__, verbose=False) try: module = __import__(modname) except ImportError: if moddir is not None: module = ut.import_module_from_fpath(join(moddir, modname.split('.')[-1] + '.py')) else: raise try: imp.reload(module) except Exception as ex: pass try: # FIXME: PYTHON 3 execstr = ut.codeblock( ''' try: import {modname} module = {modname} #print('Trying to reload module=%r' % (module,)) imp.reload(module) except Exception: # If it fails maybe the module is not in the path if moddir is not None: try: import imp import os orig_dir = os.getcwd() os.chdir(moddir) modname_str = '{modname}' modinfo = imp.find_module(modname_str, [moddir]) module = imp.load_module(modname_str, *modinfo) #print('loaded module=%r' % (module,)) except Exception as ex: ut.printex(ex, 'failed to imp.load_module') pass finally: os.chdir(orig_dir) import imp import utool as ut imp.reload(ut.util_autogen) imp.reload(ut.util_inspect) try: func = module.{funcname} except AttributeError: docstr = 'Could not find attribute funcname={funcname} in modname={modname} This might be a reloading issue' imp.reload(module) ''' ).format(**locals()) exec_locals = locals() exec_globals = globals() exec(execstr, exec_globals, exec_locals) func = exec_locals.get('func', None) module = exec_locals.get('module', None) except Exception as ex2: docstr = 'error ' + str(ex2) if verbose: import utool as ut #ut.printex(ex1, 'ex1') ut.printex(ex2, 'ex2', tb=True) testcmd = 'python -c "import utool; print(utool.auto_docstr(\'%s\', \'%s\'))"' % (modname, funcname) error_str = ut.formatex(ex2, 'ex2', tb=True, keys=['modname', 'funcname', 'testcmd']) error_str += '---' + execstr return func, module, error_str
[docs]def auto_docstr(modname, funcname, verbose=True, moddir=None, **kwargs): r""" called from vim. Uses strings of filename and modnames to build docstr Args: modname (str): name of a python module funcname (str): name of a function in the module Returns: str: docstr CommandLine: python -m utool.util_autogen --exec-auto_docstr python -m utool --tf auto_docstr Example: >>> import utool as ut >>> from utool.util_autogen import * # NOQA >>> ut.util_autogen.rrr(verbose=False) >>> #docstr = ut.auto_docstr('ibeis.algo.hots.smk.smk_index', 'compute_negentropy_names') >>> modname = ut.get_argval('--modname', default='utool.util_autogen') >>> funcname = ut.get_argval('--funcname', default='auto_docstr') >>> moddir = ut.get_argval('--moddir', type_=str, default=None) >>> docstr = ut.util_autogen.auto_docstr(modname, funcname) >>> print(docstr) """ #import utool as ut func, module, error_str = load_func_from_module( modname, funcname, verbose=verbose, moddir=moddir) if error_str is None: try: docstr = make_default_docstr(func, **kwargs) except Exception as ex: import utool as ut error_str = ut.formatex(ex, 'Caught Error in parsing docstr', tb=True) #ut.printex(ex) error_str += ( '\n\nReplicateCommand:\n ' 'python -m utool --tf auto_docstr ' '--modname={modname} --funcname={funcname} --moddir={moddir}').format( modname=modname, funcname=funcname, moddir=moddir) error_str += '\n kwargs=' + ut.dict_str(kwargs) return error_str else: docstr = error_str return docstr
[docs]def make_args_docstr(argname_list, argtype_list, argdesc_list, ismethod): r""" Builds the argument docstring Args: argname_list (list): names argtype_list (list): types argdesc_list (list): descriptions Returns: str: arg_docstr Example: >>> # ENABLE_DOCTEST >>> from utool.util_autogen import * # NOQA >>> argname_list = ['argname_list', 'argtype_list', 'argdesc_list'] >>> argtype_list = ['list', 'list', 'list'] >>> argdesc_list = ['names', 'types', 'descriptions'] >>> ismethod = False >>> arg_docstr = make_args_docstr(argname_list, argtype_list, argdesc_list, ismethod) >>> result = str(arg_docstr) >>> print(result) argname_list (list): names argtype_list (list): types argdesc_list (list): descriptions """ import utool as ut if ismethod: argname_list = argname_list[1:] argtype_list = argtype_list[1:] argdesc_list = argdesc_list[1:] argdoc_list = [arg + ' (%s): %s' % (_type, desc) for arg, _type, desc in zip(argname_list, argtype_list, argdesc_list)] # align? align_args = False if align_args: argdoc_aligned_list = ut.align_lines(argdoc_list, character='(') arg_docstr = '\n'.join(argdoc_aligned_list) else: arg_docstr = '\n'.join(argdoc_list) return arg_docstr
[docs]def make_returns_or_yeilds_docstr(return_type, return_name, return_desc): return_doctr = return_type + ': ' if return_name is not None: return_doctr += return_name if len(return_desc) > 0: return_doctr += ' - ' return_doctr += return_desc return return_doctr
[docs]def make_example_docstr(funcname=None, modname=None, argname_list=None, defaults=None, return_type=None, return_name=None, ismethod=False): """ Creates skeleton code to build an example doctest Args: funcname (str): function name modname (str): module name argname_list (str): list of argument names defaults (None): return_type (None): return_name (str): return variable name ismethod (bool): Returns: str: examplecode CommandLine: python -m utool.util_autogen --test-make_example_docstr Example: >>> # ENABLE_DOCTEST >>> from utool.util_autogen import * # NOQA >>> # build test data >>> funcname = 'make_example_docstr' >>> modname = 'utool.util_autogen' >>> argname_list = ['qaids', 'qreq_'] >>> defaults = None >>> return_type = tuple >>> return_name = 'foo' >>> ismethod = False >>> # execute function >>> examplecode = make_example_docstr(funcname, modname, argname_list, defaults, return_type, return_name, ismethod) >>> # verify results >>> result = str(examplecode) >>> print(result) # DISABLE_DOCTEST from utool.util_autogen import * # NOQA import utool as ut import ibeis species = ibeis.const.TEST_SPECIES.ZEB_PLAIN qaids = ibs.get_valid_aids(species=species) qreq_ = ibeis.testdata_qreq_() foo = make_example_docstr(qaids, qreq_) result = ('foo = %s' % (ut.repr2(foo),)) print(result) """ import utool as ut examplecode_lines = [] top_import_fmstr = 'from {modname} import * # NOQA' top_import = top_import_fmstr.format(modname=modname) import_lines = [top_import] if modname.startswith('utool'): import_lines += ['import utool as ut'] is_show_func = not modname.startswith('utool') and not modname.startswith('mtgmonte') # TODO: Externally register these default_argval_map = { 'ibs' : 'ibeis.opendb(defaultdb=\'testdb1\')', 'testres' : 'ibeis.testdata_expts(\'PZ_MTEST\')', #'qreq_' : 'ibs.new_query_request(qaids, daids)', 'qreq_' : 'ibeis.testdata_qreq_()', 'qres_list' : 'ibs.query_chips([1], [2, 3, 4, 5], cfgdict=dict())', 'qres' : 'ibs.query_chips([1], [2, 3, 4, 5], cfgdict=dict())[0]', 'aid_list' : 'ibs.get_valid_aids()', 'nid_list' : 'ibs._get_all_known_nids()', 'qaids' : 'ibs.get_valid_aids(species=species)', 'daids' : 'ibs.get_valid_aids(species=species)', 'species' : 'ibeis.const.TEST_SPECIES.ZEB_PLAIN', 'kpts' : 'vt.dummy.get_dummy_kpts()', 'dodraw' : 'ut.show_was_requested()', 'img_fpath' : 'ut.grab_test_imgpath(\'carl.jpg\')', 'gfpath' : 'ut.grab_test_imgpath(\'carl.jpg\')', 'img' : 'vt.imread(img_fpath)', 'img_in' : 'vt.imread(img_fpath)', 'bbox' : '(10, 10, 50, 50)', 'theta' : '0.0', 'rng' : 'np.random.RandomState(0)', } import_depends_map = { 'ibeis': 'import ibeis', 'vt': 'import vtool as vt', #'img': 'import vtool as vt', # TODO: remove. fix dependency #'species': 'import ibeis', } var_depends_map = { 'species': ['ibeis'], 'ibs': ['ibeis'], 'testres': ['ibeis'], 'kpts': ['vt'], #'qreq_': ['ibs', 'species', 'daids', 'qaids'], 'qreq_': ['ibeis'], 'qaids': ['ibs'], 'daids': ['ibs'], 'qaids': ['species'], 'daids': ['species'], 'img': ['img_fpath', 'vt'], } def find_arg_defaultrepr(argname, val): import types if val == '?': if argname in default_argval_map: val = ut.PythonStatement(default_argval_map[argname]) if argname in import_depends_map: import_lines.append(import_depends_map[argname]) elif isinstance(val, types.ModuleType): return val.__name__ return repr(val) # augment argname list with dependencies dependant_argnames = [] # deque() def append_dependant_argnames(argnames, dependant_argnames): """ use hints to add known dependencies for certain argument inputs """ for argname in argnames: # Check if argname just implies an import if argname in import_depends_map: import_lines.append(import_depends_map[argname]) # Check if argname was already added as dependency if (argname not in dependant_argnames and argname not in argname_list and argname not in import_depends_map): dependant_argnames.append(argname) # Check if argname has dependants if argname in var_depends_map: argdeps = var_depends_map[argname] # RECURSIVE CALL append_dependant_argnames(argdeps, dependant_argnames) append_dependant_argnames(argname_list, dependant_argnames) # Define argnames and dependencies in example code # argnames prefixed with dependeancies argname_list_ = list(dependant_argnames) + argname_list # Default example values defaults_ = [] if defaults is None else defaults num_unknown = (len(argname_list_) - len(defaults_)) default_vals = ['?'] * num_unknown + list(defaults_) arg_val_iter = zip(argname_list_, default_vals) infered_defaults = [find_arg_defaultrepr(argname, val) for argname, val in arg_val_iter] argdef_lines = ['%s = %s' % (argname, inferrepr) for argname, inferrepr in zip(argname_list_, infered_defaults)] import_lines = ut.unique_ordered(import_lines) if any([inferrepr == repr('?') for inferrepr in infered_defaults]): examplecode_lines.append('# DISABLE_DOCTEST') else: # Enable the test if it can be run immediately examplecode_lines.append('# DISABLE_DOCTEST') examplecode_lines.extend(import_lines) #examplecode_lines.append('# build test data') examplecode_lines.extend(argdef_lines) # Default example result assignment result_assign = '' result_print = None if 'return_name' in vars(): if return_type is not None: if return_name is None: return_name = 'result' result_assign = return_name + ' = ' result_print = 'print(result)' # + return_name + ')' # Default example call if ismethod: selfname = argname_list[0] methodargs = ', '.join(argname_list[1:]) tup = (selfname, '.', funcname, '(', methodargs, ')') example_call = ''.join(tup) else: funcargs = ', '.join(argname_list) tup = (funcname, '(', funcargs, ')') example_call = ''.join(tup) # Append call line #examplecode_lines.append('# execute function') examplecode_lines.append(result_assign + example_call) #examplecode_lines.append('# verify results') if result_print is not None: if return_name != 'result': #examplecode_lines.append('result = str(' + return_name + ')') result_line_fmt = 'result = (\'{return_name} = %s\' % (ut.repr2({return_name}),))' result_line = result_line_fmt.format(return_name=return_name) examplecode_lines.append(result_line) examplecode_lines.append(result_print) # TODO: infer this if is_show_func: examplecode_lines += [ 'ut.quit_if_noshow()', 'import plottool as pt', 'ut.show_if_requested()', ] examplecode = '\n'.join(examplecode_lines) return examplecode
[docs]def make_cmdline_docstr(funcname, modname): #cmdline_fmtstr = 'python -m {modname} --test-{funcname}' # --enableall' #cmdline_fmtstr = 'python -m {modname} --exec-{funcname}' # --enableall' if False and '.' in modname and '.' not in funcname: pkg = modname.split('.')[0] # TODO check if __main__ exists with the necessary utool stuffs # TODO check if --show should be given cmdline_fmtstr = 'python -m {pkg} --tf {funcname}' # --enableall' return cmdline_fmtstr.format(**locals()) else: # TODO: infer this is_show_func = True if is_show_func: cmdline_fmtstr = 'python -m {modname} --exec-{funcname} --show' else: cmdline_fmtstr = 'python -m {modname} --exec-{funcname}' # --enableall' return cmdline_fmtstr.format(**locals()) # </INVIDIAL DOCSTR COMPONENTS>
[docs]def make_docstr_block(header, block): import utool as ut indented_block = '\n' + ut.indent(block) docstr_block = ''.join([header, ':', indented_block]) return docstr_block
[docs]def make_default_docstr(func, with_args=True, with_ret=True, with_commandline=True, with_example=True, with_header=False, with_debug=False, ): r""" Tries to make a sensible default docstr so the user can fill things in without typing too much # TODO: Interleave old documentation with new documentation Args: func (function): live python function with_args (bool): with_ret (bool): (default = True) with_commandline (bool): (default = True) with_example (bool): (default = True) with_header (bool): (default = False) with_debug (bool): (default = False) Returns: tuple: (argname, val) Ignore: pass CommandLine: python -m utool.util_autogen --exec-make_default_docstr --show Example: >>> # ENABLE_DOCTEST >>> from utool.util_autogen import * # NOQA >>> import utool as ut >>> func = ut.make_default_docstr >>> #func = ut.make_args_docstr >>> func = PythonStatement >>> default_docstr = make_default_docstr(func) >>> result = str(default_docstr) >>> print(result) """ import utool as ut #from utool import util_inspect funcinfo = ut.util_inspect.infer_function_info(func) argname_list = funcinfo.argname_list argtype_list = funcinfo.argtype_list argdesc_list = funcinfo.argdesc_list return_header = funcinfo.return_header return_type = funcinfo.return_type return_name = funcinfo.return_name return_desc = funcinfo.return_desc funcname = funcinfo.funcname modname = funcinfo.modname defaults = funcinfo.defaults num_indent = funcinfo.num_indent needs_surround = funcinfo.needs_surround funcname = funcinfo.funcname ismethod = funcinfo.ismethod kwarg_keys = funcinfo.kwarg_keys docstr_parts = [] # Header part if with_header: header_block = funcname docstr_parts.append(header_block) # Args part if with_args and len(argname_list) > 0: argheader = 'Args' arg_docstr = make_args_docstr(argname_list, argtype_list, argdesc_list, ismethod) argsblock = make_docstr_block(argheader, arg_docstr) docstr_parts.append(argsblock) with_kw = with_args if with_kw and len(kwarg_keys) > 0: #ut.embed() import textwrap kwargs_docstr = ', '.join(kwarg_keys) kwargs_docstr = '\n'.join(textwrap.wrap(kwargs_docstr)) kwargsblock = make_docstr_block('Kwargs', kwargs_docstr) docstr_parts.append(kwargsblock) # Return / Yeild part if with_ret and return_header is not None: if return_header is not None: return_doctr = make_returns_or_yeilds_docstr(return_type, return_name, return_desc) returnblock = make_docstr_block(return_header, return_doctr) docstr_parts.append(returnblock) # Example part # try to generate a simple and unit testable example if with_commandline: cmdlineheader = 'CommandLine' cmdlinecode = make_cmdline_docstr(funcname, modname) cmdlineblock = make_docstr_block(cmdlineheader, cmdlinecode) docstr_parts.append(cmdlineblock) if with_example: exampleheader = 'Example' examplecode = make_example_docstr(funcname, modname, argname_list, defaults, return_type, return_name, ismethod) examplecode_ = ut.indent(examplecode, '>>> ') exampleblock = make_docstr_block(exampleheader, examplecode_) docstr_parts.append(exampleblock) # DEBUG part (in case something goes wrong) if with_debug: debugheader = 'Debug' debugblock = ut.codeblock( ''' num_indent = {num_indent} ''' ).format(num_indent=num_indent) debugblock = make_docstr_block(debugheader, debugblock) docstr_parts.append(debugblock) # Enclosure / Indentation Parts if needs_surround: docstr_parts = ['r"""'] + ['\n\n'.join(docstr_parts)] + ['"""'] default_docstr = '\n'.join(docstr_parts) else: default_docstr = '\n\n'.join(docstr_parts) docstr_indent = ' ' * (num_indent + 4) default_docstr = ut.indent(default_docstr, docstr_indent) return default_docstr
[docs]def remove_codeblock_syntax_sentinals(code_text): r""" Removes template comments and vim sentinals Args: code_text (str): Returns: str: code_text_ """ flags = re.MULTILINE | re.DOTALL code_text_ = code_text code_text_ = re.sub(r'^ *# *REM [^\n]*$\n?', '', code_text_, flags=flags) code_text_ = re.sub(r'^ *# STARTBLOCK *$\n', '', code_text_, flags=flags) code_text_ = re.sub(r'^ *# ENDBLOCK *$\n?', '', code_text_, flags=flags) code_text_ = code_text_.rstrip() return code_text_
[docs]def make_default_module_maintest(modname, modpath=None): """ make_default_module_maintest TODO: use path relative to home dir if the file is a script Args: modname (str): module name Returns: str: text source code CommandLine: python -m utool.util_autogen --test-make_default_module_maintest References: http://legacy.python.org/dev/peps/pep-0338/ Example: >>> # ENABLE_DOCTEST >>> from utool.util_autogen import * # NOQA >>> modname = 'utool.util_autogen' >>> text = make_default_module_maintest(modname) >>> result = str(text) >>> print(result) """ import utool as ut # Need to use python -m to run a module # otherwise their could be odd platform specific errors. #python -c "import utool, {modname}; # ut.doctest_funcs({modname}, allexamples=True)" #in_pythonpath, module_type, path = find_modname_in_pythonpath(modname) # only use the -m if it is part of a package directory if modpath is not None: moddir = dirname(modpath) pkginit_fpath = join(moddir, '__init__.py') use_modrun = exists(pkginit_fpath) else: use_modrun = True if use_modrun: pyargs = '-m ' + modname else: if ut.WIN32: modpath = normpath(modpath).replace(expanduser('~'), '%HOME%') pyargs = '-B ' + ut.ensure_unixslash(modpath) else: modpath = normpath(modpath).replace(expanduser('~'), '~') pyargs = modpath cmdline = ut.codeblock( ''' python {pyargs} python {pyargs} --allexamples # REM python {pyargs} --allexamples --noface --nosrc ''') if not use_modrun: if ut.WIN32: augpath = 'set PYTHONPATH=%PYTHONPATH%' + os.pathsep + moddir else: augpath = 'export PYTHONPATH=$PYTHONPATH' + os.pathsep + moddir cmdline = augpath + '\n' + cmdline cmdline = ut.indent(cmdline, ' ' * 8).lstrip(' ').format(pyargs=pyargs) text = ut.codeblock( r''' # STARTBLOCK if __name__ == '__main__': r""" CommandLine: {cmdline} """ import multiprocessing multiprocessing.freeze_support() # for win32 import utool as ut # NOQA ut.doctest_funcs() # ENDBLOCK ''' ).format(cmdline=cmdline) text = remove_codeblock_syntax_sentinals(text) return text
[docs]def is_modname_in_pythonpath(modname): in_pythonpath, module_type, path = find_modname_in_pythonpath(modname) print(module_type) return in_pythonpath
[docs]def find_modname_in_pythonpath(modname): import sys from os.path import exists, join rel_modpath = modname.replace('.', '/') in_pythonpath = False module_type = None path_list = sys.path path_list = os.environ['PATH'].split(os.pathsep) for path in path_list: full_modpath = join(path, rel_modpath) if exists(full_modpath + '.py'): in_pythonpath = True module_type = 'module' break if exists(join(full_modpath, '__init__.py')): in_pythonpath = True module_type = 'package' break return in_pythonpath, module_type, path #ut.get_modpath_from_modname(modname) #import imp #tup = imp.find_module(modname) #(file, filename, (suffix, mode, type))
if __name__ == '__main__': """ CommandLine: python ibeis/control/template_generator.py --tbls annotations --Tflags getters native python -c "import utool, utool.util_autogen; utool.doctest_funcs(utool.util_autogen, allexamples=True)" python -m utool.util_autogen python -m utool.util_autogen --allexamples python -m utool.util_autogen --allexamples --noface --nosrc """ import multiprocessing multiprocessing.freeze_support() # for win32 import utool as ut # NOQA ut.doctest_funcs()