def register(self, func, name=None, nArgs=None, moduleName=None): name = name or func.__name__ if name in self._functions: self.debug('Registering new functionality for already known ' 'function named %r.' % name) moduleName = moduleName or 'calculator-registered-method' nArgs = countArgs(func, 1) if nArgs is None else nArgs self._functions[name] = Function(moduleName, name, func, nArgs)
def importCallables(self, module): moduleName = module.__name__ exec('import ' + moduleName, globals(), self._variables) callables = inspect.getmembers(module, callable) for name, func in callables: if name.startswith('_'): continue try: if issubclass(func, BaseException): continue except TypeError: pass nArgs = countArgs(func) if nArgs is None: continue path = '%s.%s' % (moduleName, name) if path in self.OVERRIDES: self.debug('Not importing %r' % path) continue if path in self._functions: if path not in ('decimal.Decimal', 'builtins.float'): self.err('Function %r already exists' % path) else: # Add the function to our functions dict along with a # default number of positional parameters it expects. This # allows the user to call it and have the arguments taken # from the stack (the number of arguments used can always # be specified on the command line (e.g., :3) exec('self._functions["%s"] = Function("%s", "%s", %s, %d)' % (path, moduleName, name, path, nArgs)) # Import the function by name to allow the user to use it in a # command with an explicit argument, instead of applying it to # whatever is on the stack. if name in self._variables: self.debug('name %s already defined! Ignoring %s' % (name, path)) else: exec('from %s import %s' % (moduleName, name), globals(), self._variables) if name not in self._variables: self.err('name %s not now defined!!!' % name) assert name not in self._functions self._functions[name] = self._functions[path]
def _tryVariable(self, command, modifiers, count): if modifiers.forceCommand: return False, self.NO_VALUE if command in self._variables: self.debug('%r is a variable (value %r)' % (command, self._variables[command])) value = self._variables[command] if callable(value): if not modifiers.push: return self._runFunction( command, modifiers, count, Function('<stdin>', value.__name__, value, countArgs(value, 1))) else: if modifiers.push: value = Variable(command, self._variables) if count is None: count = 1 self._finalize([value] * count, modifiers, extend=True) return True, value else: self.debug('%r is not a variable' % command) return False, self.NO_VALUE
def testZero(self): "A function that takes zero arguments must be processed correctly" self.assertEqual(0, countArgs(lambda: 3))
def testLogWithDefault(self): """The signature of math.log can't be inspected (at least in Python 3.7). Pass a default value.""" self.assertEqual(3, countArgs(log, 3))
def testLog(self): "The signature of math.log can't be inspected (at least in Python 3.7)" self.assertEqual(None, countArgs(log))
def testTwo(self): "A function that takes two arguments must be processed correctly" self.assertEqual(2, countArgs(lambda x, y: 3))
def testOne(self): "A function that takes one argument must be processed correctly" self.assertEqual(1, countArgs(lambda x: 3))
def defaultArgCount(func): return countArgs(func, 1)