Skip to content

Instantly share code, notes, and snippets.

@runsun
Last active January 20, 2018 04:47
Show Gist options
  • Save runsun/f777262e04b993a1ff2a0c03515dca6c to your computer and use it in GitHub Desktop.
Save runsun/f777262e04b993a1ff2a0c03515dca6c to your computer and use it in GitHub Desktop.
Print function names in the given .scad file and prepare them for doctest
__description__ = "Print function names in the given .scad file and prepare them for doctest."
__author__= "Runsun Pan"
__version__= "180119-1"
'''
When an openSCAD file gets larger, it may contain too many functions and trying
to list them for doctest(https://bitbucket.org/runsun/doctest.scad), like:
[ //index_test( mode, opt ) // to-be-coded
, getdeci_test( mode, opt )
, int_test( mode, opt )
, num_test( mode, opt )
, numstr_test( mode, opt )
...
]
might be too tedious and error-prone.
This script prints out an openSCAD function code (for a XXX.scad, creates
a function get_XXX_test_results(...) ) that handles doctests of all functions
residing in target file. See the EXAMPLE below.
'''
''' === ARGUMENTS ===
>>> py get_openscad_funcs_for_doctest.py -h
usage: get_openscad_funcs_for_doctest.py [-h] [--version] [-fn filename]
[-fo folder]
Print function names in the given .scad file and prepare them for doctest.
optional arguments:
-h, --help show this help message and exit
--version Shows version and exits.
-fn filename Target file
-fo folder Target folder
'''
''' === EXAMPLE ===
>>> py get_openscad_funcs_for_doctest.py -fo scadx -fn scadx_num.scad
Copy and paste the following to scadx_num.scad:
---------------------------------------------------------------------------
/////////////////////////////////////////////////////////
//
// TESTING
//
/////////////////////////////////////////////////////////
function get_scadx_num_test_results( mode=MODE, opt=["showmode",true] )=
(
// Generated automatically using:
// >>> py get_openscad_funcs_for_doctest.py -fo scadx -fn scadx_num.scad
// Ref: https://gist.github.com/runsun/f777262e04b993a1ff2a0c03515dca6c
// Usages:
//
// results = get_scadx_num_test_results(...);
//
// (1) for(r = results) echo( r[1] )
// (2) scadx_file_test( "scadx_num", results, showEach = false );
[
fracstr_test( mode, opt )
, fullnumstr_test( mode, opt )
//, fullnumstr_old_test( mode, opt ) // to-be-coded
, getPowerOrder_test( mode, opt )
, getdeci_test( mode, opt )
//, index_test( mode, opt ) // to-be-coded
, int_test( mode, opt )
, intstr_test( mode, opt )
, num_test( mode, opt )
, numstr_test( mode, opt )
//, showPts_test( mode, opt ) // to-be-coded
, uconv_test( mode, opt )
]
);
---------------------------------------------------------------------------
'''
import os, sys, re, argparse, traceback
# argument setup and parse
argp = argparse.ArgumentParser(
prog= __file__ # Needed in --version below
,description= __description__ )
argp.add_argument('--version', action='version'
, version='%(prog)s '+__version__
, help='Shows version and exits.')
argp.add_argument("-fn", metavar="filename", type=str, help="Target file" )
argp.add_argument("-fo", metavar="folder", type=str, default=".", help="Target folder")
argp.add_argument("-sc", metavar="showContent", type=str, default=False
, help="Show the target file content.")
args= argp.parse_args()
error = ""
#print("args=", args)
fullpath = os.path.join( args.fo, args.fn )
#print("Opening "+fullpath)
try:
lines = open(fullpath, "r").read().split("\n")
funcs = []
func_tests = []
results=[]
for i,line in enumerate(lines):
line= line.strip()
if line.startswith("function"):
#print("line #"+str(i)+ " " + line)
funcname = line.split(" ")[1].split("(")[0]
if ( not funcname.endswith("_test") and
not funcname=="get_{file_label}_test_results".format(file_label=args.fn.split(".")[0])
):
funcs.append( funcname )
#print( " "+funcname)
#print( "\n\nfuncs = "+str(funcs) )
#print( "\n\nfuncs sorted = "+str(funcs.sort() or funcs) )
for i,line in enumerate(lines):
line= line.strip()
if line.startswith("function"):
#print("line #"+str(i)+ " " + line)
funcname = line.split(" ")[1].split("(")[0]
if funcname.endswith("_test"):
func_tests.append( funcname[:-len("_test")] )
#print( "\n\nfuncs = "+str(funcs) )
#print( "\func_tests = "+str(func_tests) )
#print()
#for fn in funcs: print(fn)
#print("\nAdding func test names \n")
for fn in (funcs.sort() or funcs):
#print(" fn= "+fn)
results.append(
fn in func_tests
and "{fn}_test( mode, opt )".format( fn= fn )
or "//{fn}_test( mode, opt ) // to-be-coded".format( fn= fn )
)
#print("\nresults = "+ str(results))
#print("funcs= ", funcs)
#print("\nfunc_tests= ", func_tests)
except:
error= str(traceback.format_exc().split("\n")[-2])
if args.sc: ## show target file content (mainly for debug purpose)
print( "\n".join(lines) )
else:
template= '''
Copy and paste the following to {file_label}.scad:
---------------------------------------------------------------------------
/////////////////////////////////////////////////////////
//
// TESTING
//
/////////////////////////////////////////////////////////
function get_{file_label}_test_results( mode=MODE, opt=["showmode",true] )=
(
// Generated automatically using:
// >>> py {this_file} -fo scadx -fn {file_label}.scad
// Ref: https://gist.github.com/runsun/f777262e04b993a1ff2a0c03515dca6c
// Usages:
//
// results = get_{file_label}_test_results(...);
//
// (1) for(r = results) echo( r[1] )
// (2) scadx_file_test( "{file_label}", results, showEach = false );
//
{func_list}
);
---------------------------------------------------------------------------
'''
results = [ (i==0 and r) or (r.startswith("//") and ("//, "+r[2:])) or (", "+r)
for i,r in enumerate(results) ]
print( template.format( file_label = args.fn.split(".")[0]
, func_list= "[\n "+ "\n ".join(results) + "\n ]"
, this_file= __file__
)
)
if error:
print( "Error: ", "\n", error )
#print("results = ", results)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment