def _manipulate_label(x): # gets the label that is displayed for a symbol or name if isinstance(x, String): return x.get_string_value() elif isinstance(x, Symbol): return strip_context(x.get_name()) else: return str(x)
def _load_spacy(self, evaluation, options): language_code = None language_name = self.get_option(options, 'Language', evaluation) if language_name is None: language_name = String('Undefined') if isinstance(language_name, String): language_code = _SpacyBuiltin._language_codes.get(language_name.get_string_value()) if not language_code: evaluation.message(self.get_name(), 'lang', language_name, strip_context(self.get_name())) return None instance = _SpacyBuiltin._spacy_instances.get(language_code) if instance: return instance try: if 'SPACY_DATA' in os.environ: instance = spacy.load(language_code, via=os.environ['SPACY_DATA']) else: instance = spacy.load(language_code) _SpacyBuiltin._spacy_instances[language_code] = instance return instance except RuntimeError as e: evaluation.message(self.get_name(), 'runtime', str(e)) return None
def clear_cache(self, name=None): # the definitions cache (self.definitions_cache) caches (incomplete and complete) names -> Definition(), # e.g. "xy" -> d and "MyContext`xy" -> d. we need to clear this cache if a Definition() changes (which # would happen if a Definition is combined from a builtin and a user definition and some content in the # user definition is updated) or if the lookup rules change and we could end up at a completely different # Definition. # the lookup cache (self.lookup_cache) caches what lookup_name() does. we only need to update this if some # change happens that might change the result lookup_name() calculates. we do not need to change it if a # Definition() changes. # self.proxy keeps track of all the names we cache. if we need to clear the caches for only one name, e.g. # 'MySymbol', then we need to be able to look up all the entries that might be related to it, e.g. 'MySymbol', # 'A`MySymbol', 'C`A`MySymbol', and so on. proxy identifies symbols using their stripped name and thus might # give us symbols in other contexts that are actually not affected. still, this is a safe solution. if name is None: self.definitions_cache = {} self.lookup_cache = {} self.proxy = defaultdict(set) else: definitions_cache = self.definitions_cache lookup_cache = self.lookup_cache tail = strip_context(name) for k in self.proxy.pop(tail, []): definitions_cache.pop(k, None) lookup_cache.pop(k, None)
def get_definition(self, name, only_if_exists=False): definition = self.definitions_cache.get(name, None) if definition is not None: return definition original_name = name name = self.lookup_name(name) user = self.user.get(name, None) builtin = self.builtin.get(name, None) if user is None and builtin is None: definition = None elif builtin is None: definition = user elif user is None: definition = builtin else: if user: attributes = user.attributes elif builtin: attributes = builtin.attributes else: attributes = set() if not user: user = Definition(name=name) if not builtin: builtin = Definition(name=name) options = builtin.options.copy() options.update(user.options) formatvalues = builtin.formatvalues.copy() for form, rules in six.iteritems(user.formatvalues): if form in formatvalues: formatvalues[form].extend(rules) else: formatvalues[form] = rules definition = Definition(name=name, ownvalues=user.ownvalues + builtin.ownvalues, downvalues=user.downvalues + builtin.downvalues, subvalues=user.subvalues + builtin.subvalues, upvalues=user.upvalues + builtin.upvalues, formatvalues=formatvalues, messages=user.messages + builtin.messages, attributes=attributes, options=options, nvalues=user.nvalues + builtin.nvalues, defaultvalues=user.defaultvalues + builtin.defaultvalues, ) if definition is not None: self.proxy[strip_context(original_name)].add(original_name) self.definitions_cache[original_name] = definition self.lookup_cache[original_name] = name elif not only_if_exists: definition = Definition(name=name) return definition
def do_replace(self, vars, options, evaluation): # The Python function implementing this builtin expects # argument names corresponding to the symbol names without # context marks. vars_noctx = dict(((strip_context(s), vars[s]) for s in vars)) if options: return self.function( evaluation=evaluation, options=options, **vars_noctx) else: return self.function(evaluation=evaluation, **vars_noctx)
def apply_int(self, n, prop, evaluation): "ElementData[n_?IntegerQ, prop_]" from mathics.core.parser import parse py_n = n.to_python() py_prop = prop.to_python() # Check element specifier n or "name" if isinstance(py_n, int): if not 1 <= py_n <= 118: evaluation.message("ElementData", "noent", n) return elif isinstance(py_n, six.string_types): pass else: evaluation.message("ElementData", "noent", n) return # Check property specifier if isinstance(py_prop, six.string_types): py_prop = str(py_prop) if py_prop == '"Properties"': result = [] for i, p in enumerate(_ELEMENT_DATA[py_n]): if p not in ["NOT_AVAILABLE", "NOT_APPLICABLE", "NOT_KNOWN"]: result.append(_ELEMENT_DATA[0][i]) return from_python(sorted(result)) if not (isinstance(py_prop, six.string_types) and py_prop[0] == py_prop[-1] == '"' and py_prop.strip('"') in _ELEMENT_DATA[0]): evaluation.message("ElementData", "noprop", prop) return iprop = _ELEMENT_DATA[0].index(py_prop.strip('"')) result = _ELEMENT_DATA[py_n][iprop] if result == "NOT_AVAILABLE": return Expression("Missing", "NotAvailable") if result == "NOT_APPLICABLE": return Expression("Missing", "NotApplicable") if result == "NOT_KNOWN": return Expression("Missing", "Unknown") result = parse(result, evaluation.definitions) if isinstance(result, Symbol): result = String(strip_context(result.get_name())) return result
def apply(self, pattern, evaluation): "Names[pattern_]" pattern = pattern.get_string_value() if pattern is None: return names = set([]) for full_name in evaluation.definitions.get_matching_names(pattern): short_name = strip_context(full_name) names.add(short_name if short_name not in names else full_name) # TODO: Mathematica ignores contexts when it sorts the list of # names. return Expression("List", *[String(name) for name in sorted(names)])
def add(self, expression, evaluation): expr = Expression('System`Private`ManipulateParameter', expression).evaluate(evaluation) if expr.get_head_name() != 'System`List': # if everything was parsed ok, we get a List return False # convert the rules given us by ManipulateParameter[] into a dict. note: duplicate keys # will be overwritten, the latest one wins. kwargs = {'evaluation': evaluation} for rule in expr.leaves: if rule.get_head_name() != 'System`Rule' or len(rule.leaves) != 2: return False kwargs[strip_context(rule.leaves[0].to_python()).lower()] = rule.leaves[1] widget = kwargs['type'].get_string_value() del kwargs['type'] getattr(self, '_add_%s_widget' % widget.lower())(**kwargs) # create the widget return True
def apply(self, expr, args, evaluation): 'Manipulate[expr_, args__]' if (not _jupyter) or (not Kernel.initialized()) or (Kernel.instance() is None): return evaluation.message('Manipulate', 'jupyter') instantiator = _WidgetInstantiator() # knows about the arguments and their widgets for arg in args.get_sequence(): try: if not instantiator.add(arg, evaluation): # not a valid argument pattern? return except IllegalWidgetArguments as e: return evaluation.message('Manipulate', 'widgetargs', strip_context(str(e.var))) except JupyterWidgetError as e: return evaluation.message('Manipulate', 'widgetmake', e.err) clear_output_callback = evaluation.output.clear display_data_callback = evaluation.output.display # for pushing updates try: clear_output_callback(wait=True) except NotImplementedError: return evaluation.message('Manipulate', 'imathics') def callback(**kwargs): clear_output_callback(wait=True) line_no = evaluation.definitions.get_line_no() vars = [Expression('Set', Symbol(name), value) for name, value in kwargs.items()] evaluatable = Expression('ReleaseHold', Expression('Module', Expression('List', *vars), expr)) result = evaluation.evaluate(evaluatable, timeout=settings.TIMEOUT) if result: display_data_callback(data=result.result, metadata={}) evaluation.definitions.set_line_no(line_no) # do not increment line_no for manipulate computations widgets = instantiator.get_widgets() if len(widgets) > 0: box = _interactive(instantiator.build_callback(callback), widgets) # create the widget formatter = IPythonDisplayFormatter() if not formatter(box): # make the widget appear on the Jupyter notebook return evaluation.message('Manipulate', 'widgetdisp') return Symbol('Null') # the interactive output is pushed via kernel.display_data_callback (see above)
def _load_wordnet(self, evaluation, language_name): language_code = None if isinstance(language_name, String): language_code = iso639_3.get(language_name.get_string_value()) if not language_code: evaluation.message(self.get_name(), 'lang', language_name, strip_context(self.get_name())) return None, None wordnet = _WordNetBuiltin._wordnet_instances.get(language_code) if not wordnet: try: wordnet = self._init_wordnet(evaluation, language_name, language_code) except LookupError as e: evaluation.message(self.get_name(), 'package', _parse_nltk_lookup_error(e)) return None, None _WordNetBuiltin._wordnet_instances[language_code] = wordnet return wordnet, language_code
def _init_wordnet(self, evaluation, language_name, language_code): try: wordnet_resource = nltk.data.find('corpora/wordnet') _init_nltk_maps() except LookupError: evaluation.message(self.get_name(), 'package', 'wordnet') return None try: omw = nltk.corpus.util.LazyCorpusLoader( 'omw', nltk.corpus.reader.CorpusReader, r'.*/wn-data-.*\.tab', encoding='utf8') except LookupError: evaluation.message(self.get_name(), 'package', 'omw') return None wordnet = nltk.corpus.reader.wordnet.WordNetCorpusReader(wordnet_resource, omw) if language_code not in wordnet.langs(): evaluation.message(self.get_name(), 'lang', language_name, strip_context(self.get_name())) return None return wordnet
def _importer_exporter_options(available_options, options, evaluation): stream_options = [] custom_options = [] if available_options and available_options.has_form('List', None): for name in available_options.leaves: if isinstance(name, String): py_name = name.get_string_value() elif isinstance(name, Symbol): py_name = strip_context(name.get_name()) else: py_name = None if py_name: value = Builtin.get_option(options, py_name, evaluation) if value is not None: expr = Expression('Rule', String(py_name), value) if py_name == 'CharacterEncoding': stream_options.append(expr) else: custom_options.append(expr) return stream_options, custom_options
def clear_definitions_cache(self, name): definitions_cache = self.definitions_cache tail = strip_context(name) for k in self.proxy.pop(tail, []): definitions_cache.pop(k, None)
def options_to_rules(options, filter=None): items = sorted(options.items()) if filter: items = [(name, value) for name, value in items if strip_context(name) in filter.keys()] return [Expression("Rule", Symbol(name), value) for name, value in items]
def get_completion_candidates(self, text): matches = self.definitions.get_matching_names(text + "*") if "`" not in text: matches = [strip_context(m) for m in matches] return matches
def apply(self, symbol, evaluation): "SymbolName[symbol_Symbol]" # MMA docs say "SymbolName always gives the short name, # without any context" return String(strip_context(symbol.get_name()))
def __init__(self, *args, **kwargs): super(SympyObject, self).__init__(*args, **kwargs) if self.sympy_name is None: self.sympy_name = strip_context(self.get_name()).lower()
def apply(**kwargs): # will override apply method kwargs['evaluation'].message( 'General', 'pyimport', # see inout.py strip_context(self.get_name()), package)
def apply(self, expr, args, evaluation): "Manipulate[expr_, args__]" if (not _jupyter) or (not Kernel.initialized()) or (Kernel.instance() is None): return evaluation.message("Manipulate", "jupyter") instantiator = (_WidgetInstantiator() ) # knows about the arguments and their widgets for arg in args.get_sequence(): try: if not instantiator.add( arg, evaluation): # not a valid argument pattern? return except IllegalWidgetArguments as e: return evaluation.message("Manipulate", "widgetargs", strip_context(str(e.var))) except JupyterWidgetError as e: return evaluation.message("Manipulate", "widgetmake", e.err) clear_output_callback = evaluation.output.clear display_data_callback = evaluation.output.display # for pushing updates try: clear_output_callback(wait=True) except NotImplementedError: return evaluation.message("Manipulate", "imathics") def callback(**kwargs): clear_output_callback(wait=True) line_no = evaluation.definitions.get_line_no() vars = [ Expression("Set", Symbol(name), value) for name, value in kwargs.items() ] evaluatable = Expression( "ReleaseHold", Expression("Module", Expression("List", *vars), expr)) result = evaluation.evaluate(evaluatable, timeout=settings.TIMEOUT) if result: display_data_callback(data=result.result, metadata={}) evaluation.definitions.set_line_no( line_no ) # do not increment line_no for manipulate computations widgets = instantiator.get_widgets() if len(widgets) > 0: box = _interactive(instantiator.build_callback(callback), widgets) # create the widget formatter = IPythonDisplayFormatter() if not formatter( box): # make the widget appear on the Jupyter notebook return evaluation.message("Manipulate", "widgetdisp") return Symbol( "Null" ) # the interactive output is pushed via kernel.display_data_callback (see above)
def apply_name(self, expr, prop, evaluation): "ElementData[expr_, prop_]" if isinstance(expr, String): py_name = expr.to_python(string_quotes=False) names = ["StandardName", "Name", "Abbreviation"] iprops = [_ELEMENT_DATA[0].index(s) for s in names] indx = None for iprop in iprops: try: indx = [element[iprop] for element in _ELEMENT_DATA[1:] ].index(py_name) + 1 except ValueError: pass if indx is None: evaluation.message("ElementData", "noent", expr) return # Enter in the next if, but with expr being the index expr = from_python(indx) if isinstance(expr, Integer): py_n = expr.value py_prop = prop.to_python() # Check element specifier n or "name" if isinstance(py_n, int): if not 1 <= py_n <= 118: evaluation.message("ElementData", "noent", expr) return else: evaluation.message("ElementData", "noent", expr) return # Check property specifier if isinstance(py_prop, str): py_prop = str(py_prop) if py_prop == '"Properties"': result = [] for i, p in enumerate(_ELEMENT_DATA[py_n]): if p not in [ "NOT_AVAILABLE", "NOT_APPLICABLE", "NOT_KNOWN" ]: result.append(_ELEMENT_DATA[0][i]) return from_python(sorted(result)) if not (isinstance(py_prop, str) and py_prop[0] == py_prop[-1] == '"' and py_prop.strip('"') in _ELEMENT_DATA[0]): evaluation.message("ElementData", "noprop", prop) return iprop = _ELEMENT_DATA[0].index(py_prop.strip('"')) result = _ELEMENT_DATA[py_n][iprop] if result == "NOT_AVAILABLE": return Expression("Missing", "NotAvailable") if result == "NOT_APPLICABLE": return Expression("Missing", "NotApplicable") if result == "NOT_KNOWN": return Expression("Missing", "Unknown") result = evaluation.parse(result) if isinstance(result, Symbol): result = String(strip_context(result.get_name())) return result
def get_completion_candidates(self, text): matches = self.definitions.get_matching_names(text + '*') if '`' not in text: matches = [strip_context(m) for m in matches] return matches
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self.numpy_name is None: self.numpy_name = strip_context(self.get_name()).lower() self.mathics_to_numpy[self.__class__.__name__] = self.numpy_name
def clear_definitions_cache(self, name) -> None: definitions_cache = self.definitions_cache tail = strip_context(name) for k in self.proxy.pop(tail, []): definitions_cache.pop(k, None)
def get_definition(self, name, only_if_exists=False) -> "Definition": definition = self.definitions_cache.get(name, None) if definition is not None: return definition original_name = name name = self.lookup_name(name) user = self.user.get(name, None) pymathics = self.pymathics.get(name, None) builtin = self.builtin.get(name, None) candidates = [user] if user else [] builtin_instance = None if pymathics: builtin_instance = pymathics candidates.append(pymathics) if builtin: candidates.append(builtin) if builtin_instance is None: builtin_instance = builtin definition = candidates[0] if len(candidates) == 1 else None if len(candidates) > 0 and not definition: attributes = (user.attributes if user else (pymathics.attributes if pymathics else (builtin.attributes if builtin else set()))) upvalues = ([], ) messages = ([], ) nvalues = ([], ) defaultvalues = ([], ) options = {} formatvalues = { "": [], } # Merge definitions its = [c for c in candidates] while its: curr = its.pop() options.update(curr.options) for form, rules in curr.formatvalues.items(): if form in formatvalues: formatvalues[form].extend(rules) else: formatvalues[form] = rules # Build the new definition definition = Definition( name=name, ownvalues=sum((c.ownvalues for c in candidates), []), downvalues=sum((c.downvalues for c in candidates), []), subvalues=sum((c.subvalues for c in candidates), []), upvalues=sum((c.upvalues for c in candidates), []), formatvalues=formatvalues, messages=sum((c.messages for c in candidates), []), attributes=attributes, options=options, nvalues=sum((c.nvalues for c in candidates), []), defaultvalues=sum((c.defaultvalues for c in candidates), []), builtin=builtin_instance, ) if definition is not None: self.proxy[strip_context(original_name)].add(original_name) self.definitions_cache[original_name] = definition self.lookup_cache[original_name] = name elif not only_if_exists: definition = Definition(name=name) if name[-1] != "`": self.user[name] = definition return definition
def apply(**kwargs): # will override apply method kwargs["evaluation"].message( "General", "pyimport", strip_context(self.get_name()), package # see inout.py )
def apply(self, symbol, evaluation): 'SymbolName[symbol_Symbol]' # MMA docs say "SymbolName always gives the short name, # without any context" return String(strip_context(symbol.get_name()))
def get_word_names(self: str): names = self.definitions.get_names() short_names = [strip_context(m) for m in names] return list(names) + short_names