def test_cell_new(self): cell_obj = types.CellType(1) self.assertEqual(cell_obj.cell_contents, 1) cell_obj = types.CellType() msg = "shouldn't be able to read an empty cell" with self.assertRaises(ValueError, msg=msg): cell_obj.cell_contents
def _function_getnewargs(self, func): code = func.__code__ # base_globals represents the future global namespace of func at # unpickling time. Looking it up and storing it in # CloudpiPickler.globals_ref allow functions sharing the same globals # at pickling time to also share them once unpickled, at one condition: # since globals_ref is an attribute of a CloudPickler instance, and # that a new CloudPickler is created each time pickle.dump or # pickle.dumps is called, functions also need to be saved within the # same invocation of cloudpickle.dump/cloudpickle.dumps (for example: # cloudpickle.dumps([f1, f2])). There is no such limitation when using # CloudPickler.dump, as long as the multiple invocations are bound to # the same CloudPickler. base_globals = self.globals_ref.setdefault(id(func.__globals__), {}) if base_globals == {}: # Add module attributes used to resolve relative imports # instructions inside func. for k in ["__package__", "__name__", "__path__", "__file__"]: if k in func.__globals__: base_globals[k] = func.__globals__[k] # Do not bind the free variables before the function is created to # avoid infinite recursion. if func.__closure__ is None: closure = None else: closure = tuple( types.CellType() for _ in range(len(code.co_freevars))) return code, base_globals, None, None, closure
def _populate_empty_object(cls, obj, dct): if cls is list: return obj.extend(_load_object(obj) for obj in dct["__value__"]) if cls is tuple: return tuple(_load_object(obj) for obj in dct["__value__"]) if cls is memoryview: return memoryview(_load_object(dct["__value__"])) if cls is set: return obj.update(_load_object(obj) for obj in dct["__value__"]) if cls is frozenset: return frozenset(_load_object(obj) for obj in dct["__value__"]) if cls is dict: return _load_dict(obj, dct) if cls is types.MappingProxyType: return _load_mapping(dct) if cls is types.MethodType: return types.MethodType( _load_object(dct["__func__"]), _load_object(dct["__self__"]), ) if cls is types.FunctionType: return _load_func(dct) if cls is types.CellType: return types.CellType(_load_object(dct["__value__"])) if cls is types.ModuleType: return import_module(dct["__name__"]) return None
def __deepcopy__(self, clone_from_id): cls = self.__class__ result = cls.__new__(cls) clone_from_id[id(self)] = result for k, v in self.__dict__.items(): if k in ["renderer", "time_progression"]: continue if k == "camera_class": setattr(result, k, v) setattr(result, k, copy.deepcopy(v, clone_from_id)) result.mobject_updater_lists = [] # Update updaters for mobject in self.mobjects: cloned_updaters = [] for updater in mobject.updaters: # Make the cloned updater use the cloned Mobjects as free variables # rather than the original ones. Analyzing function bytecode with the # dis module will help in understanding this. # https://docs.python.org/3/library/dis.html # TODO: Do the same for function calls recursively. free_variable_map = inspect.getclosurevars(updater).nonlocals cloned_co_freevars = [] cloned_closure = [] for i, free_variable_name in enumerate( updater.__code__.co_freevars): free_variable_value = free_variable_map[free_variable_name] # If the referenced variable has not been cloned, raise. if id(free_variable_value) not in clone_from_id: raise Exception( f"{free_variable_name} is referenced from an updater " "but is not an attribute of the Scene, which isn't " "allowed.") # Add the cloned object's name to the free variable list. cloned_co_freevars.append(free_variable_name) # Add a cell containing the cloned object's reference to the # closure list. cloned_closure.append( types.CellType(clone_from_id[id(free_variable_value)])) cloned_updater = types.FunctionType( updater.__code__.replace( co_freevars=tuple(cloned_co_freevars)), updater.__globals__, updater.__name__, updater.__defaults__, tuple(cloned_closure), ) cloned_updaters.append(cloned_updater) mobject_clone = clone_from_id[id(mobject)] mobject_clone.updaters = cloned_updaters if len(cloned_updaters) > 0: result.mobject_updater_lists.append( (mobject_clone, cloned_updaters)) return result
def get_global_references_from_nested_code(code, global_scope, global_refs): for constant in code.co_consts: if inspect.iscode(constant): closure = tuple( types.CellType(None) for _ in range(len(constant.co_freevars))) dummy_function = types.FunctionType(constant, global_scope, 'dummy_function', closure=closure) global_refs.update(inspect.getclosurevars(dummy_function).globals) get_global_references_from_nested_code(constant, global_scope, global_refs)
def __deepcopy__(self, memo): cls = self.__class__ result = cls.__new__(cls) memo[id(self)] = result for k, v in self.__dict__.items(): if type(v) in [FrameServer, Event, Camera]: continue setattr(result, k, copy.deepcopy(v, memo)) # Update updaters for mobject in self.mobjects: cloned_updaters = [] for updater in mobject.updaters: # Make the cloned updater use the cloned Mobjects as free variables # rather than the original ones. # TODO: The the same for function calls recursively. free_variable_map = inspect.getclosurevars(updater).nonlocals cloned_co_freevars = [] cloned_closure = [] for i, free_variable_name in enumerate( updater.__code__.co_freevars): free_variable_value = free_variable_map[free_variable_name] if isinstance(free_variable_value, Mobject): random_name = get_random_name(free_variable_map) # Put the cloned Mobject in the function's scope. free_variable_map[random_name] = memo[id( free_variable_value)] # Add the cloned Mobject's name to the free variable list. cloned_co_freevars.append(random_name) # Add a cell containing the cloned Mobject's reference to the # closure list. cloned_closure.append( types.CellType(memo[id(free_variable_value)])) else: cloned_co_freevars.append(free_variable_name) cloned_closure.append(updater.__closure__[i]) cloned_updater = types.FunctionType( updater.__code__.replace( co_freevars=tuple(cloned_co_freevars)), updater.__globals__, updater.__name__, updater.__defaults__, tuple(cloned_closure), ) cloned_updaters.append(cloned_updater) memo[id(mobject)].updaters = cloned_updaters return result
def cell_unpickle(): return types.CellType(None)
def dict_to_cell(obj): return types.CellType(obj)
lambda dct: memoryview(load_obj(dct["__value__"])), set: lambda dct: set(dct["__value__"]), frozenset: lambda dct: frozenset(dct["__value__"]), dict: load_dict, types.MappingProxyType: lambda dct: types.MappingProxyType(load_dict(dct)), types.FunctionType: load_func, types.CodeType: lambda dct: types.CodeType(*(load_obj(dct[key]) for key in code_attributes)), types.CellType: lambda dct: types.CellType(load_obj(dct["__value__"])), types.ModuleType: lambda dct: import_module(dct["__name__"]), } def load_obj(obj2load): if type(obj2load) is list: return tuple(load_obj(element) for element in obj2load) if not type(obj2load) is dict: return obj2load tmp_obj, is_loaded = load_id_data(obj2load["__id__"]) if is_loaded: return tmp_obj
def build(*args: typing.Any, **kwargs: typing.Any) -> typing.Any: bound_arguments = signature.bind(*args, **kwargs) bound_arguments.apply_defaults() global_dict: typing.Dict[str, typing.Any] = { # supported queries: # with ... select ... # select ... # insert into ... select ... # create table ... engine = ... as select ... # create view ... as select ... # create materialized view ... as select ... 'with_': ast.Initial('with'), 'select': ast.Initial('select'), 'select_distinct': ast.Initial('select_distinct'), 'insert': ast.Initial('insert'), 'insert_into': ast.Initial('insert_into'), 'create': ast.Initial('create'), 'create_table': ast.Initial('create_table'), 'create_table_if_not_exists': ast.Initial('create_table_if_not_exists'), 'create_view': ast.Initial('create_view'), 'create_or_replace_view': ast.Initial('create_or_replace_view'), 'create_view_if_not_exists': ast.Initial('create_view_if_not_exists'), 'create_materialized_view': ast.Initial('create_materialized_view'), 'create_materialized_view_if_not_exists': ast.Initial('create_materialized_view_if_not_exists'), } local_dict: typing.Dict[str, typing.Any] = { **bound_arguments.arguments, } # TODO: use types.CellType in type annotation cells: typing.Tuple[typing.Any, ...] = ( *(function.__closure__ or ()), *( types.CellType() # type: ignore[attr-defined] for _ in function.__code__.co_cellvars or ()), ) stack: typing.List[typing.Any] = [] # notice: see dis.opmap for instruction in instructions: done = _run(global_dict, local_dict, cells, stack, instruction.opname, instruction.arg, instruction.argval) if done: assert len(stack) == 1 return stack.pop() return None
import re, copy, types, forbiddenfruit env = types.CellType({}) def copyswitch(prenv): env.cell_contents = prenv def dummy(*args, **kwargs): return args[kwargs["i"]] def rmap(fn, i, t=tuple): yield from [t(rmap(fn, x)) if type(x) == t else fn(x) for x in i] def define(i): env.cell_contents[i[0]] = i[1] def safe(fn, *args, **kwargs): try: return fn(*args) except: return kwargs["default"] def binit(self, bname): self.name, self.exists = bname, True def bcall(self, *args): return (self,) + tuple(args) bvar = type("bvar", (), {"__init__": binit, "__repr__": lambda self: f"<bound variable '{self.name}'>", "__call__": bcall}) fns = (lambda d: dict(map(lambda tup: (tup[0], lambda i: (ans if any(map(lambda x: hasattr(x, "exists"), (ans := (tup[0],) + i))) else tup[1](i))), d.items())))({'+': sum, '-': lambda i: i[0] - sum(i[1:]), "if": lambda i: i[1] if i[0] else i[2], "define": define, "string": lambda i: " ".join(i), "display": lambda i: print(i[0], end=""), "run": lambda c: [k for x in c if (k := (lambda i: tuple(map(lambda x: dummy((prenv := env.cell_contents), copyswitch(copy.copy(prenv)), runln(x), copyswitch(prenv), i=2), i[1:])).sc(runln(i[0])) if type(i) == tuple else (env.cell_contents[i] if i in env.cell_contents else safe(lambda: eval(i, {}, {}), default=i)))(x)) != None], "lambda": lambda i: lambda reals: fns["run"](tuple(rmap(lambda a: dict(zip(i[0], reals)).get(a, a), i[1:])))}) parse = lambda t: t.regex(r'".*"', lambda x: f"(string {x.group(0)[1:-1]})").regex(r"\s", lambda x: " ").regex(r"[^\(\) ]+", lambda x: f"'{x.group(0)}',").regex(r"\)+", lambda x: x.group(0) + ",")[:-1].run() runln = lambda i: tuple(map(lambda x: dummy((prenv := env.cell_contents), copyswitch(copy.copy(prenv)), runln(x), copyswitch(prenv), i=2), i[1:])).sc(runln(i[0])) if type(i) == tuple else (env.cell_contents[i] if i in env.cell_contents else (fns[i] if i in fns else safe(lambda: eval(i, {}, {}), default=i))) run = lambda c: [k for x in c if (k := runln(x)) != None] def expose(): globals().update(env.cell_contents) forbiddenfruit.curse(str, "regex", lambda x, y, z: re.sub(y, z, x)) forbiddenfruit.curse(str, "run", lambda self: eval("(" + self + ",)")) forbiddenfruit.curse(tuple, "sc", lambda self, i: safe(lambda: (ans if (ans := env.cell_contents.get(i)) else (ans if (ans := fns.get(i)) else bvar(i))(self)), default=(i,) + self)) # code = '(display ((lambda (x) (+ x 1)) 1))\n(newline)\n(display "That was it!")' code = '(define inc (lambda (x) (+ x 1)))' print(run(parse(code))) expose() print(run(inc((5,))))