def test_loads_dumps(self): U = self.U['Pa*mm2'] for s in '123456789Pa*mm2', '12.34Pa*mm2', '0Pa*mm2', '0.000012345Pa*mm2': v = stringly.loads(U, s) self.assertEqual(s, stringly.dumps(U, v)) with self.assertRaises(ValueError): stringly.dumps(U, 'foo')
def check(self, *args, **powers): s, v = args u = self.U(s) U = type(u) self.assertEqual(u, v) self.assertEqual(self.U._parse(s)[1], powers) self.assertEqual(stringly.dumps(U, u), s) self.assertEqual(stringly.loads(U, s), u)
def run(func, *, args=None, loaduserconfig=True): '''parse command line arguments and call function''' if args is None: args = sys.argv.copy() scriptname = os.path.basename(args.pop(0)) sig = inspect.signature(func) doc = stringly.util.DocString(func) argdocs = doc.argdocs for param in sig.parameters.values(): if isinstance(param.annotation, str): argdocs[param.name] = param.annotation types = { param.name: param.annotation for param in inspect.signature(setup).parameters.values() if param.default is not param.empty } for param in sig.parameters.values(): if param.annotation is not param.empty and not isinstance( param.annotation, str): types[param.name] = param.annotation elif param.default is not param.empty: types[param.name] = type(param.default) else: sys.exit('cannot infer type of argument {!r}'.format(param.name)) if '-h' in args or '--help' in args: usage = [] if doc.text: usage.append(doc.text) usage.append('\n\n') usage.append('USAGE: {}'.format(scriptname)) if doc.presets: usage.append(' [{}]'.format('|'.join(doc.presets))) if sig.parameters: usage.append(' [arg=value] [...]\n') defaults = doc.defaults for param in sig.parameters.values(): usage.append('\n {}'.format(param.name)) if param.name in defaults: usage.append(' [{}]'.format(defaults[param.name])) elif param.default is not param.empty: usage.append(' [{}]'.format( stringly.dumps(types[param.name], param.default))) if param.name in argdocs: usage.extend( textwrap.wrap(argdocs[param.name], initial_indent='\n ', subsequent_indent='\n ')) print(''.join(usage)) sys.exit(1) strargs = doc.defaults if args and args[0] in doc.presets: strargs.update(doc.presets[args.pop(0)]) for arg in args: name, sep, value = arg.lstrip('-').partition('=') if not sep: if name in types: value = 'yes' elif name.startswith('no') and name[2:] in types: name = name[2:] value = 'no' else: print('argument {!r} requires a value'.format(name)) sys.exit(2) strargs[name] = value funcargs = {} setupargs = {} if loaduserconfig: home = os.path.expanduser('~') for path in os.path.join(home, '.config', 'nutils', 'config'), os.path.join(home, '.nutilsrc'): if os.path.isfile(path): setupargs.update(_load_rcfile(path)) for name, s in strargs.items(): if name not in types: sys.exit('unexpected argument: {}'.format(name)) try: value = stringly.loads(types[name], s) except stringly.error.StringlyError as e: print(e) sys.exit(2) (funcargs if name in sig.parameters else setupargs)[name] = value kwargs = [(param.name, stringly.dumps(types[param.name], funcargs.get(param.name, param.default)), argdocs.get(param.name)) for param in sig.parameters.values()] with setup(scriptname=scriptname, kwargs=kwargs, **setupargs): func(**funcargs)