def parse_raw(cls, data: Union[bytes, str], *, encoding: str = None) -> "ProtoModel": # type: ignore """ Parses raw string or bytes into a Model object. Parameters ---------- data : Union[bytes, str] A serialized data blob to be deserialized into a Model. encoding : str, optional The type of the serialized array, available types are: {'json', 'json-ext', 'msgpack-ext', 'pickle'} Returns ------- Model The requested model from a serialized format. """ if encoding is None: if isinstance(data, str): encoding = "json" elif isinstance(data, bytes): encoding = "msgpack-ext" else: raise TypeError("Input is neither str nor bytes, please specify an encoding.") if encoding.endswith(("json", "javascript", "pickle")): return super().parse_raw(data, content_type=encoding) elif encoding in ["msgpack-ext", "json-ext"]: obj = deserialize(data, encoding) else: raise TypeError(f"Content type '{encoding}' not understood.") return cls.parse_obj(obj)
def prepare(self): if self._required_auth: self.authenticate(self._required_auth) try: self.data = deserialize(self.request.body, self.encoding) except: raise tornado.web.HTTPError(status_code=401, reason="Could not deserialize body.")
def prepare(self): if self._required_auth: self.authenticate(self._required_auth) try: if (self.encoding == "json") and isinstance( self.request.body, bytes): blob = self.request.body.decode() else: blob = self.request.body self.data = deserialize(blob, self.encoding) except: raise tornado.web.HTTPError(status_code=401, reason="Could not deserialize body.")
def compute(self, input_model: "AtomicInput", config: "TaskConfig") -> "AtomicResult": """ Runs Psi4 in API mode """ self.found(raise_error=True) pversion = parse_version(self.get_version()) if pversion < parse_version("1.2"): raise ResourceError("Psi4 version '{}' not understood.".format( self.get_version())) # Location resolution order config.scratch_dir, $PSI_SCRATCH, /tmp parent = config.scratch_directory if parent is None: parent = os.environ.get("PSI_SCRATCH", None) error_type = None error_message = None compute_success = False if isinstance(input_model.model.basis, BasisSet): raise InputError( "QCSchema BasisSet for model.basis not implemented. Use string basis name." ) # Basis must not be None for HF3c old_basis = input_model.model.basis input_model.model.__dict__["basis"] = old_basis or "" with temporary_directory(parent=parent, suffix="_psi_scratch") as tmpdir: caseless_keywords = { k.lower(): v for k, v in input_model.keywords.items() } if (input_model.molecule.molecular_multiplicity != 1) and ("reference" not in caseless_keywords): input_model.keywords["reference"] = "uhf" # Old-style JSON-based command line if pversion < parse_version("1.4a2.dev160"): # Setup the job input_data = input_model.dict(encoding="json") input_data["nthreads"] = config.ncores input_data["memory"] = int(config.memory * 1024 * 1024 * 1024 * 0.95) # Memory in bytes input_data["success"] = False input_data["return_output"] = True if input_data["schema_name"] == "qcschema_input": input_data["schema_name"] = "qc_schema_input" # Execute the program success, output = execute( [ which("psi4"), "--scratch", tmpdir, "--json", "data.json" ], {"data.json": json.dumps(input_data)}, ["data.json"], scratch_directory=tmpdir, ) output_data = input_data.copy() if success: output_data = json.loads(output["outfiles"]["data.json"]) if "extras" not in output_data: output_data["extras"] = {} # Check QCVars local_qcvars = output_data.pop("psi4:qcvars", None) if local_qcvars: # Edge case where we might already have qcvars, should not happen if "qcvars" in output_data["extras"]: output_data["extras"][ "local_qcvars"] = local_qcvars else: output_data["extras"]["qcvars"] = local_qcvars if output_data.get("success", False) is False: error_message, error_type = self._handle_errors( output_data) else: compute_success = True else: error_message = output.get("stderr", "No STDERR output") error_type = "execution_error" # Reset the schema if required output_data["schema_name"] = "qcschema_output" output_data.pop("memory", None) output_data.pop("nthreads", None) output_data["stdout"] = output_data.pop("raw_output", None) else: if input_model.extras.get("psiapi", False): import psi4 orig_scr = psi4.core.IOManager.shared_object( ).get_default_path() psi4.core.set_num_threads(config.ncores, quiet=True) psi4.set_memory(f"{config.memory}GB", quiet=True) # psi4.core.IOManager.shared_object().set_default_path(str(tmpdir)) if pversion < parse_version( "1.4"): # adjust to where DDD merged # slightly dangerous in that if `qcng.compute({..., psiapi=True}, "psi4")` called *from psi4 # session*, session could unexpectedly get its own files cleaned away. output_data = psi4.schema_wrapper.run_qcschema( input_model).dict() else: output_data = psi4.schema_wrapper.run_qcschema( input_model, postclean=False).dict() # success here means execution returned. output_data may yet be qcel.models.AtomicResult or qcel.models.FailedOperation success = True if output_data.get("success", False): output_data["extras"]["psiapi_evaluated"] = True psi4.core.IOManager.shared_object().set_default_path( orig_scr) else: run_cmd = [ which("psi4"), "--scratch", str(tmpdir), "--nthread", str(config.ncores), "--memory", f"{config.memory}GB", "--qcschema", "data.msgpack", ] input_files = { "data.msgpack": input_model.serialize("msgpack-ext") } success, output = execute(run_cmd, input_files, ["data.msgpack"], as_binary=["data.msgpack"], scratch_directory=tmpdir) if success: output_data = deserialize( output["outfiles"]["data.msgpack"], "msgpack-ext") else: output_data = input_model.dict() if success: if output_data.get("success", False) is False: error_message, error_type = self._handle_errors( output_data) else: compute_success = True else: error_message = output.get("stderr", "No STDERR output") error_type = "execution_error" # Dispatch errors, PSIO Errors are not recoverable for future runs if compute_success is False: if "PSIO Error" in error_message: if "scratch directory" in error_message: # Psi4 cannot access the folder or file raise ResourceError(error_message) else: # Likely a random error, worth retrying raise RandomError(error_message) elif ("SIGSEV" in error_message) or ( "SIGSEGV" in error_message) or ("segmentation fault" in error_message): raise RandomError(error_message) elif ("TypeError: set_global_option" in error_message) or (error_type == "ValidationError"): raise InputError(error_message) elif "RHF reference is only for singlets" in error_message: raise InputError(error_message) else: raise UnknownError(error_message) # Reset basis output_data["model"]["basis"] = old_basis # Move several pieces up a level output_data["provenance"]["memory"] = round(config.memory, 3) output_data["provenance"]["nthreads"] = config.ncores # Delete keys output_data.pop("return_output", None) return AtomicResult(**output_data)