{ "packages": [ "whl/tomli-2.0.1-py3-none-any.whl", "whl/click-8.1.7-py3-none-any.whl", "whl/glom-23.5.0-py3-none-any.whl", "whl/face-20.1.1-py3-none-any.whl", "whl/packaging-23.2-py3-none-any.whl", "whl/boltons-23.1.1-py2.py3-none-any.whl", "whl/platformdirs-4.1.0-py3-none-any.whl", "whl/mypy_extensions-1.0.0-py3-none-any.whl", "whl/black-24.1.0-py3-none-any.whl", "whl/pathspec-0.12.1-py3-none-any.whl", "whl/attrs-23.2.0-py3-none-any.whl", "whl/typing_extensions-4.9.0-py3-none-any.whl" ], "paths": [] } import ast import json import time import pprint import datetime import traceback import js # type: ignore from pyodide.ffi import create_proxy # type: ignore import glom import black # TODO: try dataclasses here again. # First time it seemed to introduce a delay, possibly due to eval/compilation. class InputStatus: def __init__(self, kind, run_id=0, subtitle='', detail='', timing=-0.0, start_time=None): self.subtitle = subtitle self.detail = detail self.timing = timing self.kind = kind self.run_id = run_id self.created_at = datetime.datetime.now().isoformat() if not self.timing and start_time is not None: self.timing = time.time() - start_time @classmethod def success(cls, **kw): return cls(kind='success', **kw) @classmethod def pending(cls, *a, **kw): return cls(kind='pending', *a, **kw) @classmethod def error(cls, *a, **kw): return cls(kind='error', *a, **kw) def to_dict(self): return dict(self.__dict__) def store(self, svelte_store): proxy = create_proxy(self.to_dict()); svelte_store.setProxy(proxy) return def get_store_value(store): "Get the current value of a Svelte store." ret = None def set_ret(val): nonlocal ret ret = val unsub = store.subscribe(set_ret) unsub() return ret def load_target(target_input, run_id=0): target = None length = len(target_input) try: start_time = time.time() target = json.loads(target_input) except json.JSONDecodeError as jde: # js.window.console.log(repr(jde)) try: start_time = time.time() target = ast.literal_eval(target_input) except Exception as se: tb = ''.join(traceback.format_exception(se)) load_error = f"Target must be a JSON or Python literal.\n\n{tb}" status = InputStatus.error(detail=load_error, start_time=start_time, run_id=run_id) else: status = InputStatus.success(subtitle=f"Python ({length:,} chars)", start_time=start_time, run_id=run_id) else: status = InputStatus.success(subtitle=f"JSON ({length:,} chars)", start_time=start_time, run_id=run_id) return target, status def run(): js.createObject(create_proxy(globals()), "pyg") glom_kwargs = {} padStore = js.window.SvelteApp.padStore stateStack = get_store_value(padStore.stateStack) spec_val = glom.glom(stateStack, glom.T[0].specValue, default='').strip() scope_val = glom.glom(stateStack, glom.T[0].scopeValue, default='').strip() target_input = glom.glom(stateStack, glom.T[0].targetValue, default='').strip() run_id = get_store_value(padStore.curRunID) if not spec_val and not run_id: InputStatus.pending().store(padStore.specStatus) return run_id += 1 padStore.curRunID.set(run_id) enable_autoformat = bool(get_store_value(padStore.enableAutoformat)) enable_scope = bool(get_store_value(padStore.enableScope)) load_error = None try: start_time = time.time() spec = build_spec(spec_val) if enable_autoformat: fmtd_spec_val = autoformat(spec_val) padStore.specValue.set(fmtd_spec_val) except Exception as e: load_error = InputStatus.error(detail=str(e), start_time=start_time, run_id=run_id) load_error.store(padStore.specStatus) else: InputStatus.success(start_time=start_time, run_id=run_id).store(padStore.specStatus) if enable_scope: try: start_time = time.time() scope = build_spec(scope_val) if scope_val.strip() else None if scope: glom_kwargs['scope'] = scope if enable_autoformat: fmtd_scope_val = autoformat(scope_val) padStore.scopeValue.set(fmtd_scope_val) except Exception as e: load_error = InputStatus.error(detail=str(e), start_time=start_time, run_id=run_id) load_error.store(padStore.scopeStatus) else: InputStatus.success(start_time=start_time, run_id=run_id).store(padStore.scopeStatus) if not load_error: target, load_status = load_target(target_input, run_id=run_id) load_status.store(padStore.targetStatus) if load_status.kind == 'error': load_error = load_status if load_status.kind == 'success' and enable_autoformat: if load_status.subtitle.startswith('JSON'): fmtd_target_val = json.dumps(target, indent=2) else: fmtd_target_val = autoformat(target_input) padStore.targetValue.set(fmtd_target_val) if load_error: error_detail = load_error.detail if spec_val else '' padStore.resultValue.set(error_detail) else: try: start_time = time.time() result = glom.glom(target, spec, **glom_kwargs) if 'json' in load_status.subtitle.lower(): # kind of hacky, but we'd like to do JSON in, JSON out try: result = json.dumps(result, indent=4) except Exception: result = pprint.pformat(result) else: result = pprint.pformat(result) if enable_autoformat: try: result = autoformat(result) except Exception as e: print(e) print(result) except glom.GlomError as ge: err = str(ge) result = err InputStatus.error(subtitle=type(ge).__name__, detail=err, start_time=start_time, run_id=run_id).store(padStore.resultStatus) padStore.resultValue.set(err) else: InputStatus.success(start_time=start_time, run_id=run_id).store(padStore.resultStatus) padStore.resultValue.set(result) return def build_spec(spec_str): try: res = eval(spec_str, dict(glom.__dict__)) except NameError: res = spec_str.partition('#')[0] # probably? may need a better heuristic except SyntaxError: raise return res def autoformat(code): return black.format_str(code, mode=black.Mode()) py_ready_div = js.document.getElementById("python-ready") py_ready_div.innerHTML = datetime.datetime.now().isoformat() run() js.createObject(create_proxy(globals()), "pyg")