def apply(self, items, evaluation): '%(name)s[items__]' items_sequence = items.get_sequence() all_numeric = all(item.is_numeric() and item.get_precision() is None for item in items_sequence) if all_numeric and any(not isinstance(item, Number) for item in items_sequence): # All expressions are numeric but exact and they are not all numbers, # so apply N and compare them. items = items_sequence n_items = [] for item in items: if not isinstance(item, Number): # TODO: use $MaxExtraPrecision insterad of hard-coded 50 n_expr = Expression('N', item, Integer(50)) item = n_expr.evaluate(evaluation) n_items.append(item) items = n_items else: items = items.numerify(evaluation).get_sequence() wanted = operators[self.get_name()] prev = None for item in items: if item.get_real_value() is None and not item.has_form( 'DirectedInfinity', None): return if prev is not None and do_cmp(prev, item) not in wanted: return Symbol('False') prev = item return Symbol('True')
def apply_makeboxes(self, rules, f, evaluation): """MakeBoxes[<|rules___|>, f:StandardForm|TraditionalForm|OutputForm|InputForm]""" def validate(exprs): for expr in exprs: if expr.has_form(("Rule", "RuleDelayed"), 2): pass elif expr.has_form("List", None) or expr.has_form( "Association", None): if validate(expr.leaves) is not True: return False else: return False return True rules = rules.get_sequence() if self.error_idx == 0 and validate(rules) is True: expr = Expression( "RowBox", Expression(SymbolList, *list_boxes(rules, f, "<|", "|>"))) else: self.error_idx += 1 symbol = Expression(SymbolMakeBoxes, SymbolAssociation, f) expr = Expression( "RowBox", Expression(SymbolList, symbol, *list_boxes(rules, f, "[", "]")), ) expr = expr.evaluate(evaluation) if self.error_idx > 0: self.error_idx -= 1 return expr
def apply(self, items, evaluation): '%(name)s[items__]' items_sequence = items.get_sequence() all_numeric = all(item.is_numeric() and item.get_precision() is None for item in items_sequence) if all_numeric and any(not isinstance(item, Number) for item in items_sequence): # All expressions are numeric but exact and they are not all numbers, # so apply N and compare them. items = items_sequence n_items = [] for item in items: if not isinstance(item, Number): # TODO: use $MaxExtraPrecision insterad of hard-coded 50 n_expr = Expression('N', item, Real(50)) item = n_expr.evaluate(evaluation) n_items.append(item) items = n_items else: items = items.numerify(evaluation).get_sequence() wanted = operators[self.get_name()] prev = None for item in items: if item.get_real_value() is None and not item.has_form('DirectedInfinity', None): return if prev is not None and do_cmp(prev, item) not in wanted: return Symbol('False') prev = item return Symbol('True')
def apply(self, f, x, x0, evaluation, options): "FindRoot[f_, {x_, x0_}, OptionsPattern[]]" # First, determine x0 and x x0 = apply_N(x0, evaluation) if not isinstance(x0, Number): evaluation.message("FindRoot", "snum", x0) return x_name = x.get_name() if not x_name: evaluation.message("FindRoot", "sym", x, 2) return # Now, get the explicit form of f, depending of x # keeping x without evaluation (Like inside a "Block[{x},f]) f = dynamic_scoping(lambda ev: f.evaluate(ev), {x_name: None}, evaluation) # If after evaluation, we get an "Equal" expression, # convert it in a function by substracting both # members. Again, ensure the scope in the evaluation if f.get_head_name() == "System`Equal": f = Expression("Plus", f.leaves[0], Expression("Times", Integer(-1), f.leaves[1])) f = dynamic_scoping(lambda ev: f.evaluate(ev), {x_name: None}, evaluation) # Determine the method method = options["System`Method"] if isinstance(method, Symbol): method = method.get_name().split("`")[-1] if method == "Automatic": method = "Newton" elif not isinstance(method, String): method = None evaluation.message("FindRoot", "bdmthd", method, [String(m) for m in self.methods.keys()]) return else: method = method.value # Determine the "jacobian" if method in ("Newton", ) and options["System`Jacobian"].sameQ( Symbol("Automatic")): def diff(evaluation): return Expression("D", f, x).evaluate(evaluation) d = dynamic_scoping(diff, {x_name: None}, evaluation) options["System`Jacobian"] = d method = self.methods.get(method, None) if method is None: evaluation.message("FindRoot", "bdmthd", method, [String(m) for m in self.methods.keys()]) return x0, success = method(f, x0, x, options, evaluation) if not success: return return Expression(SymbolList, Expression(SymbolRule, x, x0))
def apply(self, f, expr, test, m, evaluation): 'NestWhile[f_, expr_, test_, Pattern[m,_Integer|All]]' results = [expr] while True: if m.get_name() == 'All': test_leaves = results else: test_leaves = results[-m.value:] test_expr = Expression(test, *test_leaves) test_result = test_expr.evaluate(evaluation) if test_result.is_true(): next = Expression(f, results[-1]) results.append(next.evaluate(evaluation)) else: break return results[-1]
def apply_elements(self, filename, expr, elems, evaluation, options={}): "Export[filename_, expr_, elems_List?(AllTrue[#, NotOptionQ]&), OptionsPattern[]]" # Check filename if not self._check_filename(filename, evaluation): return Symbol('$Failed') # Process elems {comp* format?, elem1*} leaves = elems.get_leaves() format_spec, elems_spec = [], [] found_form = False for leaf in leaves[::-1]: leaf_str = leaf.get_string_value() if not found_form and leaf_str in EXPORTERS: found_form = True if found_form: format_spec.append(leaf_str) else: elems_spec.append(leaf) # Infer format if not present if not found_form: assert format_spec == [] format_spec = self._infer_form(filename, evaluation) if format_spec is None: evaluation.message('Export', 'infer', filename) return Symbol('$Failed') format_spec = [format_spec] else: assert format_spec != [] # First item in format_spec is the explicit format. # The other elements (if present) are compression formats if elems_spec != []: # FIXME: support elems evaluation.message('Export', 'noelem', elems, String(format_spec[0])) return Symbol('$Failed') # Load the exporter exporter_symbol, exporter_options = EXPORTERS[format_spec[0]] stream_options, custom_options = _importer_exporter_options( exporter_options.get("System`Options"), options, evaluation) exporter_function = Expression( exporter_symbol, filename, expr, *list(chain(stream_options, custom_options))) if exporter_function.evaluate(evaluation) == Symbol('Null'): return filename return Symbol('$Failed')
def apply_normal(self, dims, default, data, evaluation): """System`Normal[System`SparseArray[System`Automatic, dims_List, default_, data_List]]""" its = [Expression("List", n) for n in dims.leaves] table = Expression("Table", default, *its) table = table.evaluate(evaluation) # Now, apply the rules... for item in data.leaves: pos, val = item.leaves if pos.has_form("List", None): table = walk_parts([table], pos.leaves, evaluation, val) return table
def apply_elements(self, filename, expr, elems, evaluation, options={}): "Export[filename_, expr_, elems_List?(AllTrue[#, NotOptionQ]&), OptionsPattern[]]" # Check filename if not self._check_filename(filename, evaluation): return Symbol('$Failed') # Process elems {comp* format?, elem1*} leaves = elems.get_leaves() format_spec, elems_spec = [], [] found_form = False for leaf in leaves[::-1]: leaf_str = leaf.get_string_value() if not found_form and leaf_str in EXPORTERS: found_form = True if found_form: format_spec.append(leaf_str) else: elems_spec.append(leaf) # Infer format if not present if not found_form: assert format_spec == [] format_spec = self._infer_form(filename, evaluation) if format_spec is None: evaluation.message('Export', 'infer', filename) return Symbol('$Failed') format_spec = [format_spec] else: assert format_spec != [] # First item in format_spec is the explicit format. # The other elements (if present) are compression formats if elems_spec != []: # FIXME: support elems evaluation.message( 'Export', 'noelem', elems, String(format_spec[0])) return Symbol('$Failed') # Load the exporter exporter_symbol, exporter_options = EXPORTERS[format_spec[0]] stream_options, custom_options = _importer_exporter_options( exporter_options.get("System`Options"), options, evaluation) exporter_function = Expression( exporter_symbol, filename, expr, *list(chain(stream_options, custom_options))) if exporter_function.evaluate(evaluation) == Symbol('Null'): return filename return Symbol('$Failed')
def apply(self, list, expr, evaluation): 'Select[list_, expr_]' if list.is_atom(): evaluation.message('Select', 'normal') return new_leaves = [] for leaf in list.leaves: test = Expression(expr, leaf) if test.evaluate(evaluation) == Symbol('True'): new_leaves.append(leaf) return Expression(list.head, *new_leaves)
def _norm_calc(head, u, v, evaluation): expr = Expression(head, u, v) old_quiet_all = evaluation.quiet_all try: evaluation.quiet_all = True expr_eval = expr.evaluate(evaluation) finally: evaluation.quiet_all = old_quiet_all if expr_eval.same(expr): evaluation.message('Norm', 'nvm') return None else: return expr_eval
def apply(self, s, item, evaluation): "AppendTo[s_, item_]" resolved_s = s.evaluate(evaluation) if s == resolved_s: return evaluation.message("AppendTo", "rvalue", s) if not resolved_s.is_atom(): result = Expression("Set", s, Expression("Append", resolved_s, item)) return result.evaluate(evaluation) return evaluation.message("AppendTo", "normal", Expression("AppendTo", s, item))
def eval_color(x, y, v): v_scaled = (v - v_min) / v_range if color_function_scaling and color_function_min is not None and color_function_max is not None: v_color_scaled = color_function_min + v_scaled * color_function_range else: v_color_scaled = v v_lookup = int(v_scaled * 100 + 0.5) # calculate and store 100 different shades max. value = colors.get(v_lookup) if value is None: value = Expression(color_func, Real(v_color_scaled)) value = value.evaluate(evaluation) colors[v_lookup] = value return value
def apply(self, filename, expr, elems, evaluation): "Export[filename_, expr_, elems_List]" # Check filename if not self._check_filename(filename, evaluation): return Symbol('$Failed') ## Process elems {comp* format?, elem1*} leaves = elems.get_leaves() format_spec, elems_spec = [], [] found_form = False for leaf in leaves[::-1]: leaf_str = leaf.get_string_value() if not found_form and leaf_str in EXPORTERS: found_form = True if found_form: format_spec.append(leaf_str) else: elems_spec.append(leaf) # Infer format if not present if not found_form: assert format_spec == [] format_spec = self._infer_form(filename, evaluation) if format_spec is None: evaluation.message('Export', 'infer', filename) return Symbol('$Failed') format_spec = [format_spec] else: assert format_spec != [] # First item in format_spec is the explicit format. # The other elements (if present) are compression formats if elems_spec != []: # FIXME: support elems evaluation.message('Export', 'noelem', elems, String(format_spec[0])) return Symbol('$Failed') # Load the exporter exporter_symbol = EXPORTERS[format_spec[0]] exporter_function = Expression(exporter_symbol, filename, expr) if exporter_function.evaluate(evaluation) == Symbol('Null'): return filename return Symbol('$Failed')
def apply(self, filename, expr, elems, evaluation): "Export[filename_, expr_, elems_List]" # Check filename if not self._check_filename(filename, evaluation): return Symbol('$Failed') ## Process elems {comp* format?, elem1*} leaves = elems.get_leaves() format_spec, elems_spec = [], [] found_form = False for leaf in leaves[::-1]: leaf_str = leaf.get_string_value() if not found_form and leaf_str in EXPORTERS: found_form = True if found_form: format_spec.append(leaf_str) else: elems_spec.append(leaf) # Infer format if not present if not found_form: assert format_spec == [] format_spec = self._infer_form(filename, evaluation) if format_spec is None: evaluation.message('Export', 'infer', filename) return Symbol('$Failed') format_spec = [format_spec] else: assert format_spec != [] # First item in format_spec is the explicit format. # The other elements (if present) are compression formats if elems_spec != []: # FIXME: support elems evaluation.message( 'Export', 'noelem', elems, String(format_spec[0])) return Symbol('$Failed') # Load the exporter exporter_symbol = EXPORTERS[format_spec[0]] exporter_function = Expression(exporter_symbol, filename, expr) if exporter_function.evaluate(evaluation) == Symbol('Null'): return filename return Symbol('$Failed')
def yield_match(vars_2, rest): items = expression.get_sequence() for item in items: quick_test = self.quick_pattern_test(item, self.test_name) if quick_test is not None: if not quick_test: break #raise StopGenerator else: test_expr = Expression(self.test, item) test_value = test_expr.evaluate(evaluation) if not test_value.is_true(): break #raise StopGenerator else: yield_func(vars_2, None)
def apply_asy(self, filename, expr, evaluation, **options): '%(name)s[filename_String, expr_, OptionsPattern[%(name)s]]' if expr.get_head_name() == "System`Image": res = Expression("System`ImageExport", filename, expr) return res.evaluate(evaluation) filename = filename.value if expr.get_head_name() not in ("System`Graphics", "System`Graphics3D"): expr = Expression("Text", expr) expr = Expression("Graphics", Expression("List", expr)) asy_code = Expression("MakeBoxes", expr).evaluate(evaluation) try: asy_code = asy_code.boxes_to_tex(evaluation=evaluation) except BoxError as e: evaluation.message(self.get_name(), "boxerr", e.box) return SymbolFailed asy_code = asy_code[13:-10] asy_code = replace_wl_with_plain_text(asy_code, False) # TODO: Handle properly WL characters to latex commands asy_code = asy_code.replace("\\[DifferentialD]", "d ") fin = os.path.join(tempfile._get_default_tempdir(), next(tempfile._get_candidate_names())) from pymathics.asy import asy_path try: with open(fin, 'w+') as borrador: borrador.write(asy_code) except: evaluation.message(self.get_name(), "nowrtacs") return SymbolFailed if self.extension == "svg": cmdline = [ asy_path, '-f', self.extension, '--svgemulation', '-o', filename, fin ] else: cmdline = [asy_path, '-f', self.extension, '-o', filename, fin] try: check_call(cmdline, stdout=DEVNULL, stderr=DEVNULL) except: evaluation.message(self.get_name(), "asyfld") return SymbolFailed return SymbolNull
def apply(self, mlist, test, evaluation): 'Split[mlist_, test_]' expr = Expression('Split', mlist, test) if mlist.is_atom(): evaluation.message('Select', 'normal', 1, expr) return result = [[mlist.leaves[0]]] for leaf in mlist.leaves[1:]: applytest = Expression(test, result[-1][-1], leaf) if applytest.evaluate(evaluation) == Symbol('True'): result[-1].append(leaf) else: result.append([leaf]) return Expression(mlist.head, *[Expression('List', *l) for l in result])
def apply(self, f, x, x0, evaluation): 'FindRoot[f_, {x_, x0_}]' x0 = Expression('N', x0).evaluate(evaluation) if not isinstance(x0, Number): evaluation.message('FindRoot', 'snum', x0) return x_name = x.get_name() if not x_name: evaluation.message('FindRoot', 'sym', x, 2) return count = 0 def diff(evaluation): return Expression('D', f, x).evaluate(evaluation) d = dynamic_scoping(diff, {x_name: None}, evaluation) def sub(evaluation): d_value = d.evaluate(evaluation) if d_value == Integer(0): return None return Expression('Times', f, Expression('Power', d_value, Integer(-1))).evaluate(evaluation) while count < 100: minus = dynamic_scoping(sub, {x_name: x0}, evaluation) if minus is None: evaluation.message('FindRoot', 'dsing', x_name, x0) return x1 = Expression('Plus', x0, Expression('Times', Integer(-1), minus)).evaluate(evaluation) if not isinstance(x1, Number): evaluation.message('FindRoot', 'nnum', x_name, x0) return if x1 == x0: break x0 = x1.evaluate(evaluation) count += 1 else: evaluation.message('FindRoot', 'maxiter') return Expression('List', Expression('Rule', x, x0))
def check(level, expr): if not expr.has_form('List', None): test_expr = Expression(test, expr) if test_expr.evaluate(evaluation) != Symbol('True'): return False level_dim = None else: level_dim = len(expr.leaves) if len(dims) > level: if dims[level] != level_dim: return False else: dims.append(level_dim) if level_dim is not None: for leaf in expr.leaves: if not check(level + 1, leaf): return False return True
def numerify_args(items, evaluation): items_sequence = items.get_sequence() all_numeric = all(item.is_numeric() and item.get_precision() is None for item in items_sequence) # All expressions are numeric but exact and they are not all numbers, if all_numeric and any(not isinstance(item, Number) for item in items_sequence): # so apply N and compare them. items = items_sequence n_items = [] for item in items: if not isinstance(item, Number): # TODO: use $MaxExtraPrecision insterad of hard-coded 50 n_expr = Expression('N', item, Integer(50)) item = n_expr.evaluate(evaluation) n_items.append(item) items = n_items else: items = items.numerify(evaluation).get_sequence() return items
def eval_color(x, y, v): #v_lookup = int(v * 100) #if color_function_scaling: v_scaled = (v - v_min) / v_range if color_function_scaling and color_function_min is not None and color_function_max is not None: v_color_scaled = color_function_min + v_scaled * color_function_range else: v_color_scaled = v v_lookup = int(v_scaled * 100 + 0.5) # calculate and store 100 different shades max. value = colors.get(v_lookup) if value is None: #print "Calc" #print "Scale" #print "Expression" #print "Calc color for %f" % v_scaled value = Expression(color_func, Real(v_color_scaled)) #print "Evaluate %s" % value value = value.evaluate(evaluation) #value = Expression('RGBColor', Real(0.5), Real(0.5), Real(0.5)) #print "Set" colors[v_lookup] = value return value
def eval_color(x, y, v): #v_lookup = int(v * 100) #if color_function_scaling: v_scaled = (v - v_min) / v_range if color_function_scaling and color_function_min is not None and color_function_max is not None: v_color_scaled = color_function_min + v_scaled * color_function_range else: v_color_scaled = v v_lookup = int( v_scaled * 100 + 0.5) # calculate and store 100 different shades max. value = colors.get(v_lookup) if value is None: #print "Calc" #print "Scale" #print "Expression" #print "Calc color for %f" % v_scaled value = Expression(color_func, Real(v_color_scaled)) #print "Evaluate %s" % value value = value.evaluate(evaluation) #value = Expression('RGBColor', Real(0.5), Real(0.5), Real(0.5)) #print "Set" colors[v_lookup] = value return value
def find_root_secant(f, x0, x, opts, evaluation) -> (Number, bool): region = opts.get("$$Region", None) if not type(region) is list: if x0.is_zero: region = (Real(-1), Real(1)) else: xmax = 2 * x0.to_python() xmin = -2 * x0.to_python() if xmin > xmax: region = (Real(xmax), Real(xmin)) else: region = (Real(xmin), Real(xmax)) maxit = opts["System`MaxIterations"] x_name = x.get_name() if maxit.sameQ(Symbol("Automatic")): maxit = 100 else: maxit = maxit.evaluate(evaluation).get_int_value() x0 = from_python(region[0]) x1 = from_python(region[1]) f0 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x0}, evaluation) f1 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x1}, evaluation) if not isinstance(f0, Number): return x0, False if not isinstance(f1, Number): return x0, False f0 = f0.to_python(n_evaluation=True) f1 = f1.to_python(n_evaluation=True) count = 0 while count < maxit: if f0 == f1: x1 = Expression( "Plus", x0, Expression( "Times", Real(0.75), Expression("Plus", x1, Expression("Times", Integer(-1), x0)), ), ) x1 = x1.evaluate(evaluation) f1 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x1}, evaluation) if not isinstance(f1, Number): return x0, False f1 = f1.to_python(n_evaluation=True) continue inv_deltaf = from_python(1.0 / (f1 - f0)) num = Expression( "Plus", Expression("Times", x0, f1), Expression("Times", x1, f0, Integer(-1)), ) x2 = Expression("Times", num, inv_deltaf) x2 = x2.evaluate(evaluation) f2 = dynamic_scoping(lambda ev: f.evaluate(evaluation), {x_name: x2}, evaluation) if not isinstance(f2, Number): return x0, False f2 = f2.to_python(n_evaluation=True) f1, f0 = f2, f1 x1, x0 = x2, x1 if x1 == x0 or abs(f2) == 0: break count = count + 1 else: evaluation.message("FindRoot", "maxiter") return x0, False return x0, True
def get_assumption_rules_dispatch(evaluation): # TODO: cache the generated rules... assumptions_list = get_assumptions_list(evaluation) if assumptions_list is None: return None # check for consistency: consistent_assumptions = Expression("And", *assumptions_list) val_consistent_assumptions = consistent_assumptions.evaluate(evaluation) if val_consistent_assumptions == SymbolFalse: evaluation.message("Inconsistent assumptions") if assumptions_list is None: return remove_nots_when_unnecesary(pred, evaluation).evaluate(evaluation) # Expands Logically assumptions_list, cont = logical_expand_assumptions(assumptions_list, evaluation) while cont: assumptions_list, cont = logical_expand_assumptions( assumptions_list, evaluation ) # Expands algebraically assumptions_list, cont = algebraic_expand_assumptions(assumptions_list, evaluation) while cont: assumptions_list, cont = algebraic_expand_assumptions( assumptions_list, evaluation ) assumption_rules = [] for pat in assumptions_list: value = True while pat.has_form("Not", 1): value = not value pat = pat._leaves[0] if value: symbol_value = SymbolTrue symbol_negate_value = SymbolFalse else: symbol_value = SymbolFalse symbol_negate_value = SymbolTrue if pat.has_form("Equal", 2): if value: lhs, rhs = pat._leaves if lhs.is_numeric(evaluation): assumption_rules.append(Rule(rhs, lhs)) else: assumption_rules.append(Rule(lhs, rhs)) else: assumption_rules.append(Rule(pat, SymbolFalse)) symm_pat = Expression(pat._head, pat._leaves[1], pat._leaves[0]) assumption_rules.append(Rule(symm_pat, SymbolFalse)) elif pat.has_form("Equivalent", 2): assumption_rules.append(Rule(pat, symbol_value)) symm_pat = Expression(pat._head, pat._leaves[1], pat._leaves[0]) assumption_rules.append(Rule(symm_pat, symbol_value)) elif pat.has_form("Less", 2): if value: assumption_rules.append(Rule(pat, SymbolTrue)) assumption_rules.append( Rule( Expression(pat._head, pat._leaves[1], pat._leaves[0]), SymbolFalse, ) ) for head in ("Equal", "Equivalent"): assumption_rules.append( Rule( Expression(head, pat._leaves[0], pat._leaves[1]), SymbolFalse, ) ) assumption_rules.append( Rule( Expression(head, pat._leaves[1], pat._leaves[0]), SymbolFalse, ) ) else: assumption_rules.append(Rule(pat, SymbolFalse)) else: assumption_rules.append(Rule(pat, symbol_value)) # TODO: expand the pred and assumptions into an standard, # atomized form, and then apply the rules... if len(assumption_rules) == 0: return None return assumption_rules
def cond(leaf): test = Expression(expr, leaf) return test.evaluate(evaluation).is_true()
def apply_elements(self, filename, expr, elems, evaluation, options={}): "Export[filename_, expr_, elems_List?(AllTrue[#, NotOptionQ]&), OptionsPattern[]]" # Check filename if not self._check_filename(filename, evaluation): return Symbol('$Failed') # Process elems {comp* format?, elem1*} leaves = elems.get_leaves() format_spec, elems_spec = [], [] found_form = False for leaf in leaves[::-1]: leaf_str = leaf.get_string_value() if not found_form and leaf_str in EXPORTERS: found_form = True if found_form: format_spec.append(leaf_str) else: elems_spec.append(leaf) # Just to be sure that the following calls do not change the state of this property current_predetermined_out = evaluation.predetermined_out # Infer format if not present if not found_form: assert format_spec == [] format_spec = self._infer_form(filename, evaluation) if format_spec is None: evaluation.message('Export', 'infer', filename) evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') format_spec = [format_spec] else: assert format_spec != [] # First item in format_spec is the explicit format. # The other elements (if present) are compression formats if elems_spec != []: # FIXME: support elems evaluation.message('Export', 'noelem', elems, String(format_spec[0])) evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') # Load the exporter exporter_symbol, exporter_options = EXPORTERS[format_spec[0]] function_channels = exporter_options.get("System`FunctionChannels") stream_options, custom_options = _importer_exporter_options( exporter_options.get("System`Options"), options, evaluation) if function_channels is None: evaluation.message('Export', 'emptyfch') evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') elif function_channels == Expression('List', String('FileNames')): exporter_function = Expression( exporter_symbol, filename, expr, *list(chain(stream_options, custom_options))) res = exporter_function.evaluate(evaluation) elif function_channels == Expression('List', String('Streams')): stream = Expression('OpenWrite', filename, *stream_options).evaluate(evaluation) if stream.get_head_name() != 'System`OutputStream': evaluation.message('Export', 'nffil') evaluation.predetermined_out = current_predetermined_out return Symbol("$Failed") exporter_function = Expression( exporter_symbol, stream, expr, *list(chain(stream_options, custom_options))) res = exporter_function.evaluate(evaluation) Expression('Close', stream).evaluate(evaluation) if res == Symbol('Null'): evaluation.predetermined_out = current_predetermined_out return filename evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed')
def apply_elements(self, expr, elems, evaluation, options={}): "ExportString[expr_, elems_List?(AllTrue[#, NotOptionQ]&), OptionsPattern[]]" # Process elems {comp* format?, elem1*} leaves = elems.get_leaves() format_spec, elems_spec = [], [] found_form = False for leaf in leaves[::-1]: leaf_str = leaf.get_string_value() if not found_form and leaf_str in EXPORTERS: found_form = True if found_form: format_spec.append(leaf_str) else: elems_spec.append(leaf) # Just to be sure that the following evaluations do not change the value of this property current_predetermined_out = evaluation.predetermined_out # Infer format if not present if format_spec is None: evaluation.message('ExportString', 'infer', filename) evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') # First item in format_spec is the explicit format. # The other elements (if present) are compression formats if elems_spec != []: # FIXME: support elems if format_spec != []: evaluation.message('ExportString', 'noelem', elems, String(format_spec[0])) else: evaluation.message('ExportString', 'noelem', elems, String("Unknown")) evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') # Load the exporter exporter_symbol, exporter_options = EXPORTERS[format_spec[0]] function_channels = exporter_options.get("System`FunctionChannels") stream_options, custom_options = _importer_exporter_options( exporter_options.get("System`Options"), options, evaluation) if function_channels is None: evaluation.message('ExportString', 'emptyfch') evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') elif function_channels == Expression('List', String('FileNames')): # Generates a temporary file import tempfile tmpfile = tempfile.NamedTemporaryFile(dir=tempfile.gettempdir()) filename = String(tmpfile.name) tmpfile.close() exporter_function = Expression( exporter_symbol, filename, expr, *list(chain(stream_options, custom_options))) if exporter_function.evaluate(evaluation) != Symbol('Null'): evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') else: try: tmpstream = open(filename.value, 'rb') res = tmpstream.read().decode('utf-8') tmpstream.close() except Exception as e: print("something went wrong") print(e) evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') res = String(str(res)) elif function_channels == Expression('List', String('Streams')): from io import StringIO from mathics.builtin.files import STREAMS, NSTREAMS pystream = StringIO() n = next(NSTREAMS) STREAMS.append(pystream) stream = Expression('OutputStream', String('String'), Integer(n)) exporter_function = Expression( exporter_symbol, stream, expr, *list(chain(stream_options, custom_options))) res = exporter_function.evaluate(evaluation) if res == Symbol('Null'): res = String(str(pystream.getvalue())) else: res = Symbol("$Failed") Expression('Close', stream).evaluate(evaluation) else: evaluation.message('ExportString', 'emptyfch') evaluation.predetermined_out = current_predetermined_out return Symbol('$Failed') evaluation.predetermined_out = current_predetermined_out return res