def test_happy_path(self): with tempdir_context() as tempdir: zip_path = tempdir / "importmodule.1.zip" with zipfile.ZipFile(zip_path, mode="w") as zf: zf.writestr( "importmodule.yaml", json.dumps( dict( id_name="importmodule", name="Importable module", category="Clean", parameters=[], )).encode("utf-8"), ) zf.writestr("importmodule.py", b"def render(table, params): return table") clientside_module = import_zipfile(zip_path) self.assertEqual( clientside_module, clientside.Module( spec=ModuleSpec( id_name="importmodule", name="Importable module", category="Clean", parameters=[], ), js_module="", ), )
def import_zipfile(path: Path) -> clientside.Module: """ Save a zipfile to database and minio and build a `clientside.Module`. Raise `WorkbenchModuleImportError` if `path` points to an invalid module. Otherwise, do not raise any errors one can sensibly recover from. """ temp_zipfile = ModuleZipfile(path) validate_zipfile(temp_zipfile) # raise WorkbenchModuleImportError module_id = temp_zipfile.module_id version = temp_zipfile.version module_spec = temp_zipfile.get_spec() js_module = temp_zipfile.get_optional_js_module() or "" minio.fput_file(minio.ExternalModulesBucket, "%s/%s" % (module_id, path.name), path) ModuleVersion.objects.update_or_create( id_name=module_id, source_version_hash=version, spec=asdict(temp_zipfile.get_spec()), js_module=js_module, ) return clientside.Module(module_spec, js_module)
def make_init_state(request, workflow: Workflow, modules: Dict[str, ModuleZipfile]) -> Dict[str, Any]: """Build a dict to embed as JSON in `window.initState` in HTML. Raise Http404 if the workflow disappeared. Side-effect: update workflow.last_viewed_at. """ try: with workflow.cooperative_lock(): # raise DoesNotExist on race if request.user.is_anonymous: user = None else: lock_user_by_id(request.user.id, for_write=False) user = query_clientside_user(request.user.id) workflow.last_viewed_at = datetime.datetime.now() workflow.save(update_fields=["last_viewed_at"]) state = clientside.Init( user=user, workflow=workflow.to_clientside(), tabs={ tab.slug: tab.to_clientside() for tab in workflow.live_tabs }, steps={ step.id: step.to_clientside( force_module_zipfile=modules.get(step.module_id_name)) for step in Step.live_in_workflow( workflow).prefetch_related("tab") }, modules={ module_id: clientside.Module( spec=module.get_spec(), js_module=module.get_optional_js_module(), ) for module_id, module in modules.items() }, blocks={ block.slug: block.to_clientside() for block in workflow.blocks.all() }, settings={ "bigTableRowsPerTile": settings.BIG_TABLE_ROWS_PER_TILE, "bigTableColumnsPerTile": settings.BIG_TABLE_COLUMNS_PER_TILE, }, ) except Workflow.DoesNotExist: raise Http404("Workflow was recently deleted") ctx = JsonizeContext(request.locale_id, modules) return jsonize_clientside_init(state, ctx)
def make_init_state(request, workflow: Workflow, modules: Dict[str, ModuleZipfile]) -> Dict[str, Any]: """ Build a dict to embed as JSON in `window.initState` in HTML. Raise Http404 if the workflow disappeared. Side-effect: update workflow.last_viewed_at. """ try: with workflow.cooperative_lock(): # raise DoesNotExist on race workflow.last_viewed_at = timezone.now() workflow.save(update_fields=["last_viewed_at"]) state = clientside.Init( workflow=workflow.to_clientside(), tabs={ tab.slug: tab.to_clientside() for tab in workflow.live_tabs }, steps={ step.id: step.to_clientside() for step in WfModule.live_in_workflow(workflow) }, modules={ module_id: clientside.Module( spec=module.get_spec(), js_module=module.get_optional_js_module(), ) for module_id, module in modules.items() }, ) except Workflow.DoesNotExist: raise Http404("Workflow was recently deleted") ctx = JsonizeContext(request.user, request.session, request.locale_id, modules) return jsonize_clientside_init(state, ctx)
def to_clientside(self) -> clientside.Module: return clientside.Module(spec=self.spec, js_module=self.js_module)