def run(self): self.log(f"Starting thread {self.id}.") self.__status__ = "running" response = None try: response = self.__run__() except AttributeError as e: if "has no attribute '" in str(e): missing = str(e).split("has no attribute '")[1].split("'")[0] if missing == "__run__": raise Exceptions.InvalidUsage( f"Thread [{self.id}] is missing the main [__run__] function." ) else: raise AttributeError(str(e)) else: raise AttributeError(str(e)) if isinstance(response, ResponseObject): if response.success: self.send_crash(response=response) else: self.send_stop(response=response) else: self.send_stop(response=response) return self.send_stop(f"Thread [{self.id}] has finished running.")
def __init__( self, # the path to the directory (str) (#1) path=None, # root permission required. sudo=False, ): # docs. DOCS = { "module": "dev0s.database.Database", "initialized": False, "description": [], "chapter": "Database", } # traceback. Traceback.__init__(self, traceback="Database") # checks. if path == None: raise Exceptions.InvalidUsage(self.__traceback__() + " Define parameter [path].") # args. self.path = gfp.clean(path) self.sudo = sudo # sys args. self.__cache__ = {} # attributes. self.dir = self.directory = Directory(self.path) # checks. if not self.dir.fp.exists(sudo=sudo): if self.sudo: _response_.log( f"&ORANGE&Root permission&END& required to create database [{self.path}]." ) Files.create( str(self.path), sudo=self.sudo, directory=True, permission=700, owner=defaults.vars.user, group=defaults.vars.group, ) # copy objects. self.fp = self.file_path = self.dir.fp self.ownership = self.fp.ownership self.permission = self.fp.permission # copy functions. self.join = self.dir.join self.subpath = self.dir.subpath self.fullpath = self.dir.fullpath
def assign(self, dictionary): if isinstance(dictionary, (dict, Dictionary)): for key, value in _response_.serialize(dictionary).items(): self[key] = value elif isinstance(dictionary, (tuple, list, Array)): for key, value in dictionary: self[key] = _response_.serialize(value) else: raise Exceptions.InvalidUsage( "The dictionary parameter must be a dict or tuple.") return self
def check( self, # the parameters (dict) (#1). parameters={"parameter": None}, # the recognizer value for when the parameters are supposed to be empty. default=None, # the traceback id. traceback=None, ): # single. if isinstance(parameters, tuple): name, parameter = parameters if parameter == default: if traceback != None: return _response_.error( f"{traceback}: Define parameter [{name}].") else: return _response_.error(f"Define parameter [{name}].") if ":" in name: name, formats = name.split(":") while True: if " " in formats: formats = formats.replace(" ", "") else: break formats = formats.split(",") param_format = Formats.get(parameter, serialize=True) if param_format not in formats: return _response_.error( f"Incorrect parameter [{name}:{param_format}] format, correct format(s): {Array(path=False, array=formats).string(joiner=', ')}." ) return _response_.success( f"Succesfully checked parameter [{name}].") # recursive. elif isinstance(parameters, (dict, Dictionary, ResponseObject)): for id, value in parameters.items(): response = self.check(parameters=(id, value), default=default, traceback=traceback) if response["error"] != None: return response return _response_.success( f"Succesfully checked {len(parameters)} parameter(s).") # invalid. else: raise Exceptions.InstanceError( f"Parameter [parameters] requires to be a [dict, Dictionary, tuple] not [{parameters.__class__.__name__}]." )
def __serialize_format__(self, format): format = str(format).lower() if format in ["bytes", "Bytes", bytes, Bytes]: format = "bytes" elif format in ["bool", "Boolean", bool, Boolean]: format = "bool" elif format in ["string", "str", "String", str, String]: format = "str" elif format in ["int", "integer", int]: format = "int" elif format in ["float", float, Integer]: format = "float" elif format in ["list", "array", "Array", list, Array]: format = "list" elif format in ["dict", "dictionary", "Dictionary", dict, Dictionary]: format = "dict" if format not in [ "bytes", "bool", "str", "int", "float", "dict", "list" ]: raise Exceptions.InvalidUsage( f"{self.__traceback__()}: Format [{format}] is not a valid option, options: [bool, str, int, float, dict, list]." ) return format
def unpack( self, # the key / keys / defaults parameter (#1). # str instance: # unpack the str key # list instance: # unpack all keys in the list. # dict instance: # unpack all keys from the dict & when not present return the key's value as default. keys, ): defaults_ = {} if isinstance(keys, (dict, Files.Dictionary)): if isinstance(keys, dict): defaults_ = dict(keys) keys = list(keys.keys()) else: defaults_ = keys.dict() keys = keys.keys() elif isinstance(keys, str): keys = [keys] unpacked = [] for key in keys: value, set = None, True try: value = self[key] except KeyError: try: value = defaults_[key] except KeyError: set = False if not set: raise Exceptions.UnpackError( f"Dictionary does not contain attribute [{key}].") unpacked.append(value) if len(unpacked) == 1: return unpacked[0] else: return unpacked
def __le__(self, response): if not isinstance(response, self.__class__): raise Exceptions.InstanceError( f"Can not compare object {self.__class__} & {response.__class__}." ) return len(self) <= len(response)
def __init__( self, # # Should be initialized with response.success or response.error. # # the response attributes (dict or dict in str format). attributes={ "success": False, "message": None, "error": None, }, ): # docs. DOCS = { "module": "ResponseObject", "initialized": False, "description": [], "chapter": "Response", } # serialize attributes to dict. serialized = _response_.serialize(attributes) if not isinstance(serialized, (dict, Dictionary)): raise Exceptions.InvalidUsage( f"<ResponseObject.attributes>: parameter [attributes] must be a [dict, dict in str format], not [{attributes.__class__.__name__}]." ) self.assign(serialized) # catch error so you can also init custom ResponseObjects. try: # clean message & error. if self.message != None: self.message = String(self.message).capitalized_word() if self.error != None: self.error = String(self.error).capitalized_word() while True: if self.message != None and len( self.message) >= 1 and self.message[len(self.message) - 1] in [ " ", ".", "," ]: self.message = self.message[:-1] elif self.error != None and len( self.error) >= 1 and self.error[len(self.error) - 1] in [" ", ".", ","]: self.error = self.error[:-1] elif self.error != None and len(self.error) >= len( "Error: ") and self.error[:len("Error: ")] in [ "Error: " ]: self.error = String( self.error[len("Error: "):]).capitalized_word() elif self.error != None and len( self.error) >= len("..") and String( self.error).last("..") in [".."]: self.error = str(String(self.error).remove_last(".")) else: break # add dot. if self.message != None and len( self.message) > 0 and self.message[len(self.message) - 1] not in ["!", "?"]: self.message += "." if self.error != None and len( self.error) > 0 and self.error[len(self.error) - 1] not in ["!", "?"]: self.error += "." # check error passed as success response. & reversed if self.message != None and len(self.message) >= len( "Failed") and self.message[:len("Failed")] == "Failed": #_traceback_.print_exc() raise ValueError( "A success response may not start with (failed ...). You most likely called an response.success return while you meant response.error." ) if self.error != None and len(self.error) >= len( "Success") and self.error[:len("Success")] == "Success": #_traceback_.print_exc() raise ValueError( "An error response may not start with (success ...). You most likely called an response.error return while you meant response.success." ) except AttributeError: a = 1
def get( self, # the django request (1). request=None, # the identifiers (#2). # str instance: return the parameters value. # list instance: return a parameters object & return an error response when a parameter is undefined. # dict instance: return a parameters object & return the parameter's value from the dict as a default when undefined. parameters=[], # traceback id. traceback=None, ): if request == None: raise Exceptions.InvalidUsage( "<dev0s.response.paramters.get>: Define parameter: [request].") # single parameter. if isinstance(parameters, (str, String)): # get params & format. parameters = str(parameters) format = None if ":" in parameters: parameters, format = parameters.split(":") while True: if " " in format: format = format.replace(" ", "") else: break # get variable. if request.method in ["post", "POST"]: variable = request.POST.get(parameters) else: variable = request.GET.get(parameters) if variable in ["", None]: if traceback != None: return variable, _response_.error( f"{traceback}: Define parameter: [{parameters}].") else: return variable, _response_.error( f"Define parameter: [{parameters}].") # handle format. if format != None: format_options = format.split(",") found = False for format in format_options: if format.lower() in ["str", "string"]: try: variable = str(variable) found = True except: a = 1 elif format.lower() in ["int", "integer"]: try: variable = int(variable) found = True except: a = 1 elif format.lower() in ["bool", "boolean"]: try: if variable in ["true", "True", "TRUE", True]: variable = True else: variable = False found = True except: a = 1 elif format.lower() in ["float", "double"]: try: variable = float(variable) found = True except: a = 1 elif format.lower() in [ "array", "list", "dict", "dictionary" ]: try: variable = ast.literal_eval(variable) found = True except: try: variable = json.loads(variable) found = True except: a = 1 else: raise Exceptions.InvalidUsage( f"Selected format [{format}] is not a valid format option." ) if found: break if not found: return variable, _response_.error( f"Unable to parse excepted format [{Array(format_options).string(joiner=', ')}] from parameter [{parameters}:{variable}]." ) # normalize. if variable == "None": variable = None # handler. return variable, _response_.success( f"Succesfully retrieved request parameter [{parameters}].", { "key": parameters, "value": variable, }) # list recursive. elif isinstance(parameters, (list, Array)): optional = False params = ResponseObject() for param in parameters: param_value, response = self.get(request, param, traceback=traceback) param = param.split(":")[0] if response["error"] != None: if optional: params[param] = None else: return params, response else: params[param] = param_value if optional: for key in parameters: try: params[key] except: params[key] = None return params, _response_.success( f"Succesfully retrieved {len(params)} request parameter(s).") # dict recursive. elif isinstance(parameters, (dict, Dictionary, ResponseObject)): if isinstance(parameters, (ResponseObject)): parameters = parameters.clean() optional = True params = ResponseObject() for param, default in parameters.items(): param_value, response = self.get(request, param, traceback=traceback) param = param.split(":")[0] if response["error"] != None: if optional: params[param] = default else: return params, response else: params[param] = param_value if optional: for key, default in parameters.items(): try: params[key] except: params[key] = default return params, _response_.success( f"Succesfully retrieved {len(params)} request parameter(s).") # invalid. else: raise Exceptions.InvalidUsage( f"The parameters parameter must be [str, String, list, Array, dict, Dictionary] not [{dictionary.__class__.__name__}]." )
def log( self, # option 1: # the message (#1 param). message=None, # option 2: # the error. error=None, # option 3: # the response dict (leave message None to use). response={}, # print the response as json. json=False, # optionals: # the active log level. log_level=0, # the required log level for when printed to console (leave None to use self.log_level). required_log_level=None, # save to log file. save=False, # save errors always (for options 2 & 3 only). save_errors=None, # the log mode (leave None for default). mode=None, ): if mode != None: mode = str(mode).lower().replace("-", "").replace("_", "") if mode not in [None, "warning", "alert"]: raise Exceptions.InvalidUsage( f"{self.__traceback__(function='log', parameter='mode')}: Selected an invalid mode [{mode}], options: [None, warning, alert]." ) def fill_message(msg, error=False): if mode == None: if error: msg = f"Error: {msg}" else: msg = msg elif mode == "warning": msg = f"&RED&Warning&END&: {msg}" elif mode == "alert": msg = f"&ORANGE&Alert&END&: {msg}" return msg # msg, _error_ = None, False if [message, error, response] == [None, None, {}]: raise Exceptions.InvalidUsage( f"{self.__traceback__(function='log')}: Define either parameter [message:str], [error:str] or [response:dict]." ) if response != {}: if response["error"] != None: _error_ = True msg = f"Error: {response['error']}" else: if response.__class__.__name__ in ["Output"]: msg = response.output else: msg = response["message"] elif isinstance(error, (str, String)): msg = fill_message(error, error=True) else: msg = fill_message(message, error=False) if required_log_level == None: required_log_level = self.log_level try: required_log_level = int(required_log_level) except: required_log_level = 0 try: comparison = log_level != None and log_level >= required_log_level except TypeError as e: if "not supported between instances of 'dict' and 'int'" in f"{e}": raise TypeError( f"You most likely returned a response.error when you meant a response.success, error: {e}" ) else: raise TypeError(e) if comparison: #print(f"{Date().seconds_timestamp} - {color.fill(msg)}") if json: if response != {}: print(response.json()) elif error != None: print(self.error(error)) else: print(self.success(message)) else: if self.log_timestamps: print(f"{Date().seconds_timestamp} - {color.fill(msg)}") else: print(f"{color.fill(msg)}") if save: self.log_to_file(msg) elif save_errors and _error_: self.log_to_file(msg)
def expect( self, # the expected data parameter (#1). # str instantce: expect a single identifier. # list instance: expect one of the provided identifiers & return the found one if success. expect=["Password*"], # the optional data to send (#2). # none instance: do not send anything. # str instance: the data to send. # list/tuple instance: send value of index from expected expect (required expect to be a list, Array & the indexes of [expect, send] be match). send=None, # the timeout (float). timeout=1.0, ): # check none timeout. if timeout == None: timeout = 1.0 # single expect. if isinstance(expect, str): if isinstance(send, (list, Array)): raise Exceptions.InvalidUsage( f"{self.__traceback__(function='expect', parameter='send')}: parameter [send] requires to be be a [str, String] when parameter [expect] is a [{expect.__class__.__name__}], not [{send.__class__.__name__}]." ) """ add to lines to output (before) (adds nothing when empty) (do not use self.expecting before adding the output). """ response = self.read(wait=False) if not response.success: return response """ check expect & send if provided. """ c = 1 try: #if self.async_: # g = yield from self.child.expect(expect, timeout=timeout, async_=True) # r = next(g) #else: r = self.child.expect(expect, timeout=timeout) if not isinstance(r, (int, Integer, float)): return _response_.error( f"Expected [{expect}] is not the child's expected input (#873465)." ) c = 2 if self.log_level >= 8: print(f"Found expected: {expect}") if send != None: if self.log_level >= 8: print(f"Attempting to send: {send}") #if self.async_: # g = yield from self.child.sendline(str(send), async_=True) # r = next(g) #else: r = self.child.sendline(str(send)) self.__secrets__.append(str(send)) if self.log_level >= 8: print(f"Succesfully sended: {send}") except pexpect.exceptions.TIMEOUT: if c == 1: return _response_.error( f"Expected [{expect}] is not the child's expected input, error: Timeout (during epxecting)." ) else: return _response_.error( f"Failed to send expected [{expect}], error: Timeout (during sending input)." ) except pexpect.exceptions.EOF: if c == 1: return _response_.error( f"Expected [{expect}] is not the child's expected input, error: End of file (during epxecting)." ) else: return _response_.error( f"Failed to send expected [{expect}], error: End of file (during sending input)." ) except Exception as e: if c == 1: return _response_.error( f"Expected [{expect}] is not the child's expected input, error: {e}." ) else: return _response_.error( f"Failed to send expected [{expect}], error: {e}.") """ add to lines to output (after) (adds nothing when empty) (do not use self.expecting before adding the output). """ response = self.read(wait=False) if not response.success: return response # handler. if send != None: return _response_.success( f"Successfully send expected input ({expect}).") else: return _response_.success( f"Successfully retrieved expected input ({expect}).") # list expect. elif isinstance(expect, (list, Array)): index = 0 for _expect_ in expect: if isinstance(send, (list, Array)): try: _send_ = str(send[index]) except: raise Exceptions.InvalidUsage( f"{self.__traceback__(function='expect', parameter='send')}: parameter [send] and parameter [expect] do not have the same indexes." ) else: _send_ = str(send) if self.log_level >= 8: print(f"Checking optional expect: {_expect_}") response = self.expect(expect=_expect_, timeout=timeout, send=_send_) if not response.success and "is not the child's expected input" not in response.error: return response elif response.success: return _response_.success( f"Successfully {Boolean(send).string(true='send', false='retrieved')} the expected input(s).", { "expected": _expect_, "index": index, }) index += 1 return _response_.error( f"None of the specified input was expected.") # invalid usage. else: raise Exceptions.InvalidUsage( f"{self.__traceback__(function='expect', parameter='expect')}: parameter [expect] requires to be be a [Dictionary], not [{config.__class__.__name__}]." )
def execute( # Notes: # returns a dev0s.code.OutputObject object (very similair to ResponseObject). # # Mode: # option 1: # the command in str format, the command is saved to a script & then executed). command="ls .", # joiner for when command is in list format. joiner=" ", # option 2: the path to script. path=None, # # Executement: # the executable. executable="sh", # the arguments passed to the (saved) script. arguments=[], # # Options: # asynchronous process. async_=False, # await asynchronous child (sync process always awaits). wait=False, # kill process when finished (async that is not awaited is never killed). kill=True, # the subprocess shell parameter. shell=False, # serialize output to dict (expect literal dictionary / json output). serialize=False, # # Input (sync only): # send input to the command. # undefined: send no input & automatically await the process since input is always sync. # dict instance: selects "and" mode ; send expected inputs and their value & return error when one of them is missing. # list[dict] instance: send all dictionaries in the list (default dict behaviour so one of the keys in each dict is expected). input=None, # the input timeout (float) (list with floats by index from input) timeout=1.0, # do not throw an error when the input is missing or not expected when optional is disabled (bool). optional=False, # # Logging. # the loader (str, Loader). loader=None, # stop the loader at the end of the request (bool). stop_loader=True, # the log level. log_level=defaults.options.log_level, # # System functions. # add additional attributes to the spawn object. __spawn_attributes__={}, # ): # docs. DOCS = { "module": "dev0s.code.execute", "initialized": False, "description": [], "chapter": "Code", } # checks, if input != None and not isinstance(input, (dict, Dictionary, list, Array)): raise Exceptions.InvalidUsage( f"<dev0s.code.execute>: Parameter [input] requires to be be a [dict, Dictionary, list, Array], not [{iput.__class__.__name__}]." ) # loader. if isinstance(loader, (str, String)) and 2 > log_level >= 0: loader = console.Loader(loader) # vars. delete = False if path == None: delete = True path = f"/tmp/tmp_script_{String('').generate()}" if isinstance(command, list): command = Array(array=command).string(joiner=joiner) Files.save(path, command) response_str = f"command ({command})" else: response_str = f"script ({path})" # execute with input. #if isinstance(input, (dict, Dictionary, list, Array)): # checks. #if async_: # raise Exceptions.InvalidUsage(f"<dev0s.code.execute>: Parameters [input] & [async] are not compatible, select either one.") # spawn. l = [] for i in arguments: l.append(f'"{i}"') arguments = Array(l).string(joiner=' ') if log_level >= 8: print(f"Spawn: [ $ {executable} {path} {arguments}]", ) spawn = Spawn( command=f"{executable} {path} {arguments}", #async_=async_, # does not work. response_str=response_str, log_level=log_level, attributes=__spawn_attributes__, ) spawn.echo = False if isinstance(timeout, (int, float, Integer)): spawn.timeout = int(timeout) # start. response = spawn.start() if not response.success: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject( error=f"Failed to start {response_str}, error: {response.error}", log_level=log_level) # check crashed response = spawn.crashed() if not response.success: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject(error=response.error, log_level=log_level) # has already exited. elif spawn.exit_status in [0]: # get output. response = spawn.wait(timeout=1.0) if not response.success: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject(error=response.error, log_level=log_level) # exit status. output = response.output # # proceed if already finished. elif spawn.exit_status not in [0]: # await. #success = False #for i in range(10): # if spawn.running: # success = True # break # time.sleep(1) #if not success: # if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) # return OutputObject(error=f"Unable to start {response_str}.", log_level=log_level) # str input. if isinstance(input, (list, Array)): if len(input) > 0: str_input = Array(list(input[0].keys())).string(joiner=", ") else: str_input = Array(input).string(joiner=", ") elif isinstance(input, (dict, Dictionary)): str_input = Array(list(input.keys())).string(joiner=", ") else: str_input = f"[{input}]" # send optional input. error_end_of_file = None if not async_ and isinstance( input, (list, Array, dict, Dictionary)) and len(input) > 0: # expect one of the keys in the dictionary. def process_dict_input(dictionary): # vars. expect = list(dictionary.keys()) send = list(dictionary.values()) # expect . if log_level >= 8: print(f"Expecting one of the following inputs: {expect}.") response = spawn.expect(expect=expect, send=send, timeout=timeout) if not response.success: if "None of the specified inputs were expected." in response.error: if optional: return _response_.error( f"Unable to find the expected input but still success since it is optional." ) else: return _response_.error( f"Specified input [{Array(expect).string(joiner=', ')}] was not expected." ) else: return response if log_level >= 8: print("Send response message:", response.message) # success. return _response_.success("Success.") """ check expecting. """ expecting = True if not spawn.expecting: expecting = False if not optional: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) if log_level >= 3: return OutputObject( error= f"Failed to send expected input {str_input} to {response_str}, child is not expecting any input [{spawn.child}].", log_level=log_level) else: return OutputObject( error= f"Failed to send expected input {str_input} to {response_str}, child is not expecting any input.", log_level=log_level) # limit not expecting by optional. if expecting: # send all dicts in the list (list instance). error_end_of_file = False if isinstance(input, (list, Array)): for _input_ in input: response = process_dict_input(_input_) if not response.success: if "End of file" in response.error: error_end_of_file = True else: # str input. if isinstance(_input_, (list, Array)): str_input = Array(_input_).string( joiner=", ") elif isinstance(_input_, (dict, Dictionary)): str_input = Array(list( _input_.keys())).string(joiner=", ") else: str_input = f"[{_input_}]" if optional: break else: if stop_loader and isinstance( loader, console.Loader): loader.stop(success=False) return OutputObject( error= f"Failed to send one of the expected input(s) {str_input}, error: {response.error}", log_level=log_level) # send one of the keys (dict instance). elif isinstance(input, (dict, Dictionary)): response = process_dict_input(input) if not response.success: if "End of file" in response.error: error_end_of_file = True elif not optional: if stop_loader and isinstance( loader, console.Loader): loader.stop(success=False) return OutputObject( error= f"Failed to send one of the expected input(s) {str_input}, error: {response.error}", log_level=log_level) """ check no input left (does not work properly). if not error_end_of_file and spawn.expecting: try: after = spawn.child.after.decode() except : after = spawn.child.after if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject(error=f"Failed to execute {response_str}, still expecting: [{after}].", log_level=log_level) """ # do not get or kill when async. output = None if not async_: # check crashed. response = spawn.crashed() if not response.success: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject(error=response.error, log_level=log_level) # always await sync. response = spawn.wait() if not response.success: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject(error=response.error, log_level=log_level) output = response.output if error_end_of_file != None and error_end_of_file: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) if log_level >= 3: return OutputObject( error= f"Failed to send expected input {str_input} to {response_str} (#234343) (output: {output}) (child: {spawn.child}).", log_level=log_level) else: return OutputObject( error= f"Failed to send expected input {str_input} to {response_str} (#234343) (output: {output}).", log_level=log_level) # check kill. if kill and spawn.running: if log_level >= 8: print(f"Killing process {response_str}.") response = spawn.kill() if not response.success: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject( error= f"Failed to kill {response_str}, error: {response.error}", log_level=log_level) # async. elif async_: # check exit status. response = spawn.read(wait=False) if not response.success: if not response.success: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject( error= f"Failed to retrieve output from spawn {response_str}, error: {response.error}", log_level=log_level) if spawn.child.exitstatus not in [0, None]: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject( error= f"{response_str} returned exit status: [{spawn.child.exitstatus}] (output: {self.read(wait=False, __safe__=True).output}).", log_level=log_level) # await async. if wait: # await. response = spawn.wait() if not response.success: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject(error=response.error, log_level=log_level) # exit status. output = response.output if spawn.child.exitstatus not in [0, None]: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject( error= f"{response_str} returned exit status: [{spawn.child.exitstatus}] (output: {self.read(wait=False, __safe__=True).output}).", log_level=log_level) # check kill. if kill and spawn.running: if log_level >= 8: print(f"Killing process {response_str}.") response = spawn.kill() if not response.success: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject( error= f"Failed to kill {response_str}, error: {response.error}", log_level=log_level) # handler. if delete: Files.delete(path) if serialize: try: response = _response_.ResponseObject(output) except Exception as e: if loader != None: loader.stop(success=False) if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject( error=f"Failed to serialize (output: {output}).", log_level=log_level) if not response.success: if stop_loader and isinstance(loader, console.Loader): loader.stop(success=False) return OutputObject( error= f"Encoutered an error in the serialized response, error: {response.error}", log_level=log_level) if stop_loader and isinstance(loader, console.Loader): loader.stop() return OutputObject(message=f"Succesfully executed {response_str}.", log_level=log_level, attributes={ "output": output, "process": spawn, "pid": spawn.child.pid, "running": spawn.running, "exit_status": spawn.exit_status, }) """
def export(self, # the environment to export (dict). env=None, # the export path (str) or paths (list). # the paths must have .json / .sh extension or be named 'json' / 'bash' when parameter [format] is undefined. export=None, # the export format (str) (leave None to be detected by parameter [export]). format=None, ): if env == None: return _response_.error("Define parameter: env.") dictionary = {} if isinstance(env, (dict, Dictionary)): dictionary = env else: return _response_.error(f"Invalid usage, env requires to be a [str, String, FilePath, dict, Dictionary], not [{env.__class__.__name__}].") for key,value in dictionary.items(): os.environ[str(key)] = str(value) if export != None: if isinstance(export, (str,String,FilePath)): exports = [str(export)] elif not isinstance(export, (list, Array)): raise Exceptions.InvalidUsage(f"<dev0s.system.env>: Parameter export requires to be a [str, list, FilePath], not [{export.__class__.__name__}].") else: exports = export c = 0 for export in exports: if isinstance(format, (list, Array)): try: l_format = format[c] except: raise Exceptions.InvalidUsage(f"<dev0s.system.env>: Parameter format [list] does not contain index [{c}] for export [{export}].") else: l_format = format if l_format == "json" or ".json" in export or gfp.name(export) == "json": format = "json" try: exported = Files.load(export, format="json") except FileNotFoundError: exported = {} elif l_format == "bash" or ".sh" in export or gfp.name(export) == "bash": format = "bash" try: exported = Files.load(export, format="str") except FileNotFoundError: exported = "" while True: if "\n\n" in exported: exported = exported.replace("\n\n","\n") elif len(exported) > 0 and String(exported).last("\n") == "\n": exported = str(String(exported).remove_last("\n")) else: break else: raise Exceptions.InvalidUsage(f"Export file [{export}] must contain an .json / .sh extension or must be named 'bash' / 'json'.") for key,value in dictionary.items(): if format == "json": exported[str(key)] = value elif format == "bash": if f'export {key.upper()}="' in exported: l = "" for line in exported.split("\n"): if f'export {key.upper()}="' in line: l += f'export {key.upper()}="{value}"\n' else: l += line+"\n" exported = l else: exported += '\n'+f'export {key.upper()}="{value}"\n' if format == "json": Files.save(export, exported, format="json") elif format == "bash": while True: if "\n\n" in exported: exported = exported.replace("\n\n","\n") elif len(exported) > 0 and String(exported).last("\n") == "\n": exported = str(String(exported).remove_last("\n")) else: break Files.save(export, exported, format="str") c += 1 return _response_.success(f"Successfully exported {len(dictionary)} env variables.")