def create_and_setup_api_routes(self, api_id: str, lambda_arn: str): integration_creation_response = SafeDict(self.api_gateway_client.create_integration(ApiId=api_id, IntegrationType="AWS_PROXY", PayloadFormatVersion="2.0", IntegrationUri=lambda_arn, TimeoutInMillis=10000)) integration_id = integration_creation_response.get("IntegrationId").to_str(default=None) if integration_id is None: raise Exception(f"Error while creating the route integration of the api towards the lambda_function." f"The integration_id was not found in the integration creation response." f"Please delete the api and redo the deployment." f"If the issue persist, create an Issue topic on the github page of the framework.") route_names = ["amazonAlexaV1", "googleAssistantDialogflowV1", "samsungBixbyV1", "appleSiriV1"] route_names_to_settings_keys = {"amazonAlexaV1": "alexaApiEndpointUrlNotRecommendedToUse", "googleAssistantDialogflowV1": "googleAssistantApiEndointUrl", "samsungBixbyV1": "samsungBixbyApiEndointUrl", "appleSiriV1": "siriApiEndointUrl"} api_gateway_root_url = self.api_gateway_v2_url(api_id=api_id) for route_name in route_names: self.boto_session.get_credentials() response = self.api_gateway_client.create_route( ApiId=api_id, AuthorizationType="None", RouteKey=f"ANY /{route_name}", # A space is required between the HTTP method and the / Target=f"integrations/{integration_id}", ) self.add_lambda_permission_to_call_api_resource(lambda_arn=lambda_arn, api_id=api_id, route_key=route_name) api_route_url = f"{api_gateway_root_url}/{route_name}" click.echo(f"Api route {click.style(route_name, fg='green')} creation complete accessible on {api_route_url}") self.settings.settings.get_set("deployment", {}).get_set("endpoints", {}).put( route_names_to_settings_keys[route_name], api_route_url).reset_navigated_dict()
def create_api_gateway(self, lambda_arn: str, lambda_name: str, description: str = None) -> str: # todo: fix bug if id of api gateway is present in file, but the api has been deleted, it will not try to recreate it api_name = lambda_name or lambda_arn.split(":")[-1] api_creation_response = SafeDict(self.api_gateway_client.create_api(Name=api_name, Description=description or self.default_description, Target=lambda_arn, ProtocolType="HTTP")) api_id = api_creation_response.get("ApiId").to_str() self.create_and_setup_api_routes(api_id=api_id, lambda_arn=lambda_arn) return api_id
class LaunchRequestHandler: CLASS_TYPE = "RequestHandler" def __init__(self, node_dict: dict): self.node_safedict = SafeDict(node_dict) self.node_name = self.node_safedict.get("name").to_str() self.class_name = to_class_name(self.node_name) self.code = None self.state_handler_class = None def process(self, parent_core: Core): next_paths = self.node_safedict.get("next").to_list() if len(next_paths) > 0: self.state_handler_class = StateHandler(node_name=self.node_name) for path in next_paths: self.state_handler_class.next_paths.append( path) # all_nodes_classes_dict[next_paths[0]["name"]] def render( self, parent_core: Core): # dict, parent_all_nodes_classes_dict: dict): created_classes = list() next_state_handler_class = None if self.state_handler_class is not None: state_handler = StateHandler(node_name=self.node_name) state_handler.process(parent_core=parent_core) state_handler.render(parent_core=parent_core) created_classes.append(state_handler) next_state_handler_class = f"{self.class_name}StateHandler" self.code = TemplatesAccess().launch_request_handler_template.render( class_name=self.class_name, node_name=self.node_name, next_state_handler_class=next_state_handler_class, code_elements=parent_core.process_on_enter( self.node_safedict.get("onEnter").to_list())) created_classes.insert(0, self) # We always want for the request handler to be the first element in the classes. return created_classes
def process_paths(self, parent_core: Core, paths: list) -> list: processed_paths = list() for i, path in enumerate(paths): path = SafeDict(path) path_condition = path.get("condition").to_str(default=None) path_target_node_name = path.get("node").to_str(default=None) if path_condition is not None and path_target_node_name is not None: current_path_instance = StateHandler.Path( path_index=i, condition=path_condition, target_node_name=path_target_node_name) no_code_generated_for_path = current_path_instance.process( parent_core=parent_core) if no_code_generated_for_path is False: processed_paths.append(current_path_instance) else: print( f"\nWarning ! The node {self.node_name} had a condition {path_condition} that did not generated any code." ) if path_target_node_name == "": print( "It is likely because you did not define a target node for this condition." ) else: print( f"Yet you defined a target node. There is something fishy, you should look in botpress what is strange about the node {self.node_name}" ) if current_path_instance.condition_type == self.Path.CONDITION_TYPE_INTENT_NAME: if current_path_instance.condition_intent_name in self.counts_used_condition_intent_names.keys( ): self.counts_used_condition_intent_names[ current_path_instance.condition_intent_name] += 1 else: self.counts_used_condition_intent_names[ current_path_instance.condition_intent_name] = 1 return processed_paths
def process(self): for message_dict in self.input_messages_items: message_dict = SafeDict(message_dict) speech_items = list() # todo: make multilang (might require the premium version of botpress) main_speech_dict = message_dict.get("formData").to_dict() for key, value in main_speech_dict.items(): if "text" in key: if value is not None and value != "": speech_items.append(prettify_speech_text(value)) if "variations" in key: if isinstance(value, list): for speech_variation in value: if speech_variation is not None and speech_variation != "": speech_items.append( prettify_speech_text(value)) message_item = self.MessageItem( id_value=message_dict.get("id").to_str(), speech_items=speech_items) self.output_messages_dict[message_item.id] = message_item
def handle_any_platform(self, event: dict, context: dict): print(f"Event = {json_dumps(event)}\nContext = {context}") self.check_everything_implemented() event_safedict = SafeDict(classic_dict=event) # The 'rawPath' is for ApiGatewayV2, use the key 'resource' (without the comma) if using ApiGatewayV1 if event_safedict.get( "rawPath").to_str() == "/googleAssistantDialogflowV1": # A google-assistant or dialogflow request always pass trough an API gateway self.handler_input.is_dialogflow_v1 = True event = NestedObjectToDict.get_dict_from_json( event_safedict.get("body").to_str()) elif event_safedict.get("rawPath").to_str() == "/samsungBixbyV1": # A samsung bixby request always pass trough an API gateway self.handler_input.is_bixby_v1 = True from urllib import parse event = { "context": NestedObjectToDict.get_dict_from_json( stringed_json_dict=event_safedict.get("body").to_str()) ["$vivContext"], "parameters": dict( parse.parse_qsl( event_safedict.get("rawQueryString").to_str())) } elif "amzn1." in event_safedict.get("context").get("System").get( "application").get("applicationId").to_str(): # Alexa always go last, since it do not pass trough an api resource, its a less robust identification than the other platforms. self.handler_input.is_alexa_v1 = True else: from inoft_vocal_framework.messages import ERROR_PLATFORM_NOT_SUPPORTED raise Exception(ERROR_PLATFORM_NOT_SUPPORTED) self.handler_input.load_event(event=event) return self.process_request()
import jinja2 from inoft_vocal_framework.bixby_core.templates.templates_access import TemplatesAccess from inoft_vocal_framework.safe_dict import SafeDict from inoft_vocal_framework.utils.general import load_json model_dict = SafeDict(load_json("F:/Inoft/skill_histoire_decryptage_1/inoft_vocal_framework/bixby_core/test_model.json")) intents = model_dict.get("intents").to_dict() class Core: def render(self): out = TemplatesAccess().endpoints_template.render(intents=intents) print(out) @staticmethod def write_to_file(text: str, filepath: str): with open(filepath, "w+") as file: file.write(text) Core().render()
class Core(CoreClients): def __init__(self): # , pool: ThreadPoolExecutor): super().__init__() self.settings = Settings() self.tags = {"framework": "InoftVocalFramework"} self._iam_role = None self._credentials_arn = None self._aws_account_id = None self._session_unix_time = None self._session_count_created_statement_ids = 0 self.role_name = "InoftVocalFrameworkLambdaExecution" self.http_methods = ['ANY'] self.default_description = "Created with the Inoft Vocal Framework" def get_lambda_function_arn(self, function_name: str): return SafeDict(self.lambda_client.get_function(FunctionName=function_name)).get("Configuration").get("FunctionArn").to_str() def api_gateway_v2_url(self, api_id: str): try: return SafeDict(self.api_gateway_client.get_api(ApiId=api_id)).get("ApiEndpoint").to_str(default=None) except Exception as e: return False def get_lambda_function_versions(self, function_name: str) -> list: try: response = self.lambda_client.list_versions_by_function(FunctionName=function_name) return response.get('Versions', list()) except Exception as e: click.echo(f"Lambda function {function_name} not found. Error : {e}") return list() def create_lambda_function(self, bucket=None, s3_key: str = None, local_zip: bytes = None, function_name: str = None, handler=None, description: str = "Inoft Vocal Framework Deployment", timeout: int = 30, memory_size: int = 512, publish: bool = True, runtime=None): """ Given a bucket and key (or a local path) of a valid Lambda-zip, a function name and a handler, register that Lambda function. """ kwargs = dict( FunctionName=function_name, Runtime=runtime, Role=self.credentials_arn, # "arn:aws:iam::631258222318:role/service-role/alexa_hackaton-cite-des-sciences_fakenews-challeng-role-ck3sxsyt", # self.credentials_arn, # todo: make dynamic and create automaticly role if missing Handler=handler, Description=description, Timeout=timeout, MemorySize=memory_size, Publish=publish, Layers=[ "arn:aws:lambda:eu-west-3:631258222318:layer:inoft-vocal-framework_0-38-5:1", ] ) if local_zip is not None: kwargs['Code'] = { 'ZipFile': local_zip } else: kwargs['Code'] = { 'S3Bucket': bucket, 'S3Key': s3_key } response = self.lambda_client.create_function(**kwargs) lambda_arn = response["FunctionArn"] version = response['Version'] click.echo(f"Created new lambda function {function_name} with arn of {lambda_arn}") return lambda_arn def update_lambda_function_code(self, lambda_arn: str, object_key_name: str, bucket_name: str): response = self.lambda_client.update_function_code( FunctionName=lambda_arn, S3Bucket=bucket_name, S3Key=object_key_name, Publish=True, ) def update_lambda_function_configuration(self, function_name: str, handler_function_path: str = None, lambda_layers_arns: list = None): kwargs = dict(FunctionName=function_name) if handler_function_path is not None: kwargs["Handler"] = handler_function_path if lambda_layers_arns is not None and len(lambda_layers_arns) > 0: kwargs["Layers"] = lambda_layers_arns response = self.lambda_client.update_function_configuration(**kwargs) def create_api_gateway(self, lambda_arn: str, lambda_name: str, description: str = None) -> str: # todo: fix bug if id of api gateway is present in file, but the api has been deleted, it will not try to recreate it api_name = lambda_name or lambda_arn.split(":")[-1] api_creation_response = SafeDict(self.api_gateway_client.create_api(Name=api_name, Description=description or self.default_description, Target=lambda_arn, ProtocolType="HTTP")) api_id = api_creation_response.get("ApiId").to_str() self.create_and_setup_api_routes(api_id=api_id, lambda_arn=lambda_arn) return api_id def create_and_setup_api_routes(self, api_id: str, lambda_arn: str): integration_creation_response = SafeDict(self.api_gateway_client.create_integration(ApiId=api_id, IntegrationType="AWS_PROXY", PayloadFormatVersion="2.0", IntegrationUri=lambda_arn, TimeoutInMillis=10000)) integration_id = integration_creation_response.get("IntegrationId").to_str(default=None) if integration_id is None: raise Exception(f"Error while creating the route integration of the api towards the lambda_function." f"The integration_id was not found in the integration creation response." f"Please delete the api and redo the deployment." f"If the issue persist, create an Issue topic on the github page of the framework.") route_names = ["amazonAlexaV1", "googleAssistantDialogflowV1", "samsungBixbyV1", "appleSiriV1"] route_names_to_settings_keys = {"amazonAlexaV1": "alexaApiEndpointUrlNotRecommendedToUse", "googleAssistantDialogflowV1": "googleAssistantApiEndointUrl", "samsungBixbyV1": "samsungBixbyApiEndointUrl", "appleSiriV1": "siriApiEndointUrl"} api_gateway_root_url = self.api_gateway_v2_url(api_id=api_id) for route_name in route_names: self.boto_session.get_credentials() response = self.api_gateway_client.create_route( ApiId=api_id, AuthorizationType="None", RouteKey=f"ANY /{route_name}", # A space is required between the HTTP method and the / Target=f"integrations/{integration_id}", ) self.add_lambda_permission_to_call_api_resource(lambda_arn=lambda_arn, api_id=api_id, route_key=route_name) api_route_url = f"{api_gateway_root_url}/{route_name}" click.echo(f"Api route {click.style(route_name, fg='green')} creation complete accessible on {api_route_url}") self.settings.settings.get_set("deployment", {}).get_set("endpoints", {}).put( route_names_to_settings_keys[route_name], api_route_url).reset_navigated_dict() # We reset the navigated dict after a final put def add_lambda_permission_to_call_api_resource(self, lambda_arn: str, api_id: str, route_key: str): response = self.lambda_client.add_permission( FunctionName=lambda_arn, StatementId=self.get_session_new_statement_id(), Action="lambda:InvokeFunction", Principal="apigateway.amazonaws.com", SourceArn=f"arn:aws:execute-api:{self.boto_session.region_name}:{self.aws_account_id}:{api_id}/*/*/{route_key}", ) @property def iam_role(self) -> SafeDict: if self._iam_role is None: try: self._iam_role = SafeDict(self.iam.get_role(RoleName=self.role_name)["Role"]) except botocore.exceptions.ClientError: # If a ClientError happened while getting the role, it means he do not exist. logging.debug(f"Creating {self.role_name} IAM Role..") attach_policy_obj = json.loads(self.attach_policy) assume_policy_obj = json.loads(self.assume_policy) self._iam_role = SafeDict(self.iam.create_role(RoleName=self.role_name, AssumeRolePolicyDocument=self.assume_policy)["Role"]) # create or update the role's policies if needed policy = self.iam_resource.RolePolicy(self.role_name, "inoft-vocal-permissions") try: if policy.policy_document != attach_policy_obj: logging.debug(f"Updating inoft-vocal-permissions policy on {self.role_name} IAM Role.") policy.put(PolicyDocument=self.attach_policy) except botocore.exceptions.ClientError: logging.debug(f"Creating inoft-vocal-permissions policy on {self.role_name} IAM Role.") policy.put(PolicyDocument=self.attach_policy) role_policy_dict = self._iam_role.get("AssumeRolePolicyDocument").to_dict() if role_policy_dict != assume_policy_obj: if (SafeDict(role_policy_dict["Statement"][0]).get("Principal").get("Service").to_any() != assume_policy_obj["Statement"][0]["Principal"]["Service"]): logging.debug(f"Updating assume role policy on {self.role_name} IAM Role.") self.iam_client.update_assume_role_policy(RoleName=self.role_name, PolicyDocument=self.assume_policy) return self._iam_role @property def credentials_arn(self): if self._credentials_arn is None: self._credentials_arn = self.iam_role.get("Arn").to_str() return self._credentials_arn @credentials_arn.setter def credentials_arn(self, credentials_arn) -> None: self._credentials_arn = credentials_arn @property def aws_account_id(self) -> str: if self._aws_account_id is None: self._aws_account_id = boto3.client("sts").get_caller_identity().get("Account") return self._aws_account_id def get_session_new_statement_id(self) -> str: # No restriction is set on the statement id. To created my type of ids, i take the same unix # time across the session, and each time we generated a new statement id, i add 1 to the unix time. # Dumb and simple, but it assure that i will never have the same id twice. if self._session_unix_time is None: self._session_unix_time = time.time() self._session_count_created_statement_ids += 1 # After turning the modified unix time into a string, we remove any point, that would have # been used to separate the decimals, because AWS cannot accept a point in a id string. return str(self._session_unix_time + self._session_count_created_statement_ids).replace(".", "") def create_s3_bucket_if_missing(self, bucket_name: str, region_name: str): try: self.s3_client.head_bucket(Bucket=bucket_name) except ClientError as e: click.echo(f"Trying to create a new S3 Bucket with name {click.style(text=bucket_name, fg='yellow', bold=True)}" f" in region {click.style(text=region_name, fg='yellow', bold=True)}") available_regions_for_s3 = self.boto_session.get_available_regions(service_name="s3") if region_name not in available_regions_for_s3: raise Exception(f"The region {region_name} was not available for s3. Here is the available regions : {available_regions_for_s3}") self.s3_client.create_bucket(Bucket=bucket_name, CreateBucketConfiguration={"LocationConstraint": region_name}) click.echo(f"Completed creation of the new bucket.") def upload_to_s3(self, filepath: str, object_key_name: str, bucket_name: str, region_name: str) -> bool: # If an error happen while uploading to S3, then the upload will not be # successful. We use that as our way to send a success response. try: self.create_s3_bucket_if_missing(bucket_name=bucket_name, region_name=region_name) self.s3_client.upload_file(Filename=filepath, Bucket=bucket_name, Key=object_key_name) return True except NoCredentialsError as e: click.echo(f"Almost there ! You just need to configure your AWS credentials." f"\nYou can follow the official documentation (you will need to install the awscli by running pip install awscli) " f"then go to https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration" f"\nOr you can follow a video made by Robinson Labourdette from Inoft, as a guide to configure your credentials.") if click.confirm("Press Y to access the video."): selected_language = click.prompt("Type the language in which you would like the video. The followings are available :", type=click.Choice(["English", "French"])) if selected_language == "English": click.echo("English here you go !") elif selected_language == "French": click.echo("Français la voila !") click.echo("Follow the instructions that is available in the video, then when you are all set up, redo the command you just tried") while True: if click.confirm("Press y to exit"): exit(201) break # A little break, just to make sure that if the exit do not work, we do not stay stuck in this loop. else: click.echo("Ok, then follow the boto documentation, and once you have configured your credentials, relaunch the cli command that you were trying to use" " (https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration)") except Exception as e: click.echo(f"Error while getting/creating/uploading to the S3 bucket : {e}") return False def remove_from_s3(self, file_name: str, bucket_name: str): try: self.s3_client.head_bucket(Bucket=bucket_name) except botocore.exceptions.ClientError as e: # If a client error is thrown, then check that it was a 404 error. # If it was a 404 error, then the bucket does not exist. error_code = int(e.response["Error"]["Code"]) if error_code == 404: return False try: self.s3_client.delete_object(Bucket=bucket_name, Key=file_name) return True except (botocore.exceptions.ParamValidationError, botocore.exceptions.ClientError): return False
def from_dict(self, speech_safedict: SafeDict): self.probability_value = speech_safedict.get("probability").to_float( default=None) self.speech = speech_safedict.get("speech").to_str() return self
def _process_and_set_list_to_object( object_class_to_set_to, list_object: list, key_names_identifier_objects_to_go_into: list): unprocessed_vars_dict = vars(object_class_to_set_to) from types import MappingProxyType if isinstance(unprocessed_vars_dict, MappingProxyType): # Sometimes the vars dict is put in a MappingProxy object instead of a dict. A MappingProxy is like a dict, # but cannot have its values modified, so we convert it back to a dict since we will need to modify the values. unprocessed_vars_dict = dict(unprocessed_vars_dict) vars_safedict_key_processed_keys_names_with_value_unprocessed_variables_names = SafeDict( ) for key_unprocessed_var in unprocessed_vars_dict.keys(): processed_current_key_name = NestedObjectToDict.get_json_key_from_variable_name( variable_name=key_unprocessed_var) vars_safedict_key_processed_keys_names_with_value_unprocessed_variables_names.put( dict_key=processed_current_key_name, value_to_put=key_unprocessed_var) for child_item in list_object: if isinstance(child_item, dict): for key_child_item, value_child_item in child_item.items(): current_unprocessed_variable_name = vars_safedict_key_processed_keys_names_with_value_unprocessed_variables_names.get( key_child_item).to_any() if current_unprocessed_variable_name is not None: current_child_element_object = unprocessed_vars_dict[ current_unprocessed_variable_name] if current_child_element_object is not None: found_accepted_key_name_in_vars_of_current_object = False for accepted_child_key_name in key_names_identifier_objects_to_go_into: if hasattr(current_child_element_object, accepted_child_key_name): found_accepted_key_name_in_vars_of_current_object = True NestedObjectToDict.process_and_set_json_to_object( object_class_to_set_to= unprocessed_vars_dict[ current_unprocessed_variable_name], request_json_dict_stringed_dict_or_list =value_child_item, key_names_identifier_objects_to_go_into= key_names_identifier_objects_to_go_into ) if not found_accepted_key_name_in_vars_of_current_object: do_not_include_current_item = False if (isinstance(value_child_item, str) or (type(value_child_item) == type and "str" in value_child_item.__bases__)): if value_child_item.replace(" ", "") == "": do_not_include_current_item = True elif ( isinstance(value_child_item, dict) or isinstance(value_child_item, list) or (type(value_child_item) == type and ("dict" in value_child_item.__bases__ or "list" in value_child_item.__bases__))): if not len(value_child_item) > 0: do_not_include_current_item = True if not do_not_include_current_item: custom_set_from_function = getattr( current_child_element_object, "custom_set_from", None) if custom_set_from_function is None: unprocessed_vars_dict[ current_unprocessed_variable_name] = value_child_item else: custom_set_from_function( value_child_item) elif isinstance(child_item, list) or (type(child_item) == type and "list" in child_item.__bases__): NestedObjectToDict._process_and_set_list_to_object( object_class_to_set_to=child_item, list_object=child_item, key_names_identifier_objects_to_go_into= key_names_identifier_objects_to_go_into)
def _process_and_set_dict_to_object( object_class_to_set_to, dict_object: dict, key_names_identifier_objects_to_go_into: list): from inoft_vocal_framework.platforms_handlers.alexa_v1.context import Context unprocessed_vars_dict = vars(object_class_to_set_to) from types import MappingProxyType if isinstance(unprocessed_vars_dict, MappingProxyType): # Sometimes the vars dict is put in a MappingProxy object instead of a dict. A MappingProxy is like a dict, # but cannot have its values modified, so we convert it back to a dict since we will need to modify the values. unprocessed_vars_dict = dict(unprocessed_vars_dict) vars_safedict_key_processed_keys_names_with_value_unprocessed_variables_names = SafeDict( ) for key_unprocessed_var, value_var_object in unprocessed_vars_dict.items( ): found_accepted_key_name = False for accepted_child_key_name in key_names_identifier_objects_to_go_into: if hasattr(value_var_object, accepted_child_key_name): # If the object contains an accepted child key name, we use it as the processed variable name. Like that, we have a # total freedom to respect Python convention for the variable names, and still handle any type of object child name. vars_safedict_key_processed_keys_names_with_value_unprocessed_variables_names.put( dict_key=getattr(value_var_object, accepted_child_key_name), value_to_put=key_unprocessed_var) found_accepted_key_name = True if found_accepted_key_name is False: # Otherwise we do a bit of processing on the variable name itself (like removing underscores) then we use it. processed_current_key_name = NestedObjectToDict.get_json_key_from_variable_name( variable_name=key_unprocessed_var) vars_safedict_key_processed_keys_names_with_value_unprocessed_variables_names.put( dict_key=processed_current_key_name, value_to_put=key_unprocessed_var) keys_to_pop_after_loop_finished = list() for key_request_element, value_request_element in dict_object.items(): key_request_element = str(key_request_element).replace(" ", "") # In the received requests, there can sometimes be spaces in a key before closing it with an apostrophe. # Having a single empty space at the end of a key would not be the same as the key without the space. current_unprocessed_variable_name = vars_safedict_key_processed_keys_names_with_value_unprocessed_variables_names.get( key_request_element).to_any() if current_unprocessed_variable_name is not None: current_child_element_object = unprocessed_vars_dict[ current_unprocessed_variable_name] found_accepted_key_name_in_vars_of_current_object = False if current_child_element_object is not None: for accepted_child_key_name in key_names_identifier_objects_to_go_into: if hasattr(current_child_element_object, accepted_child_key_name): found_accepted_key_name_in_vars_of_current_object = True NestedObjectToDict.process_and_set_json_to_object( object_class_to_set_to=unprocessed_vars_dict[ current_unprocessed_variable_name], request_json_dict_stringed_dict_or_list= value_request_element, key_names_identifier_objects_to_go_into= key_names_identifier_objects_to_go_into) # Even if the current child element object is None we will try to set a value to it, because a None value is just # a variable not initialized (like how often after an init). It does not means that it should not contain a value. if not found_accepted_key_name_in_vars_of_current_object: do_not_include_current_item = False if (isinstance(value_request_element, str) or (type(value_request_element) == type and "str" in value_request_element.__bases__)): if value_request_element.replace(" ", "") == "": do_not_include_current_item = True elif (isinstance(value_request_element, dict) or isinstance(value_request_element, list) or (type(value_request_element) == type and ("dict" in value_request_element.__bases__ or "list" in value_request_element.__bases__))): if not len(value_request_element) > 0: do_not_include_current_item = True if not do_not_include_current_item: # if (type(value_request_element) == type(current_child_element_object) # or (((isinstance(value_request_element, float) or isinstance(value_request_element, int)) # and type(current_child_element_object) in [int, float]))): # For some variables, we might receive them in int or float, where the framework would store # them with the other variable type. So we say that if the received variable is an int or a float, # its considered compatible with the variable in the object if it is also a float or an int. custom_set_from_function = getattr( current_child_element_object, "custom_set_from", None) if custom_set_from_function is None: unprocessed_vars_dict[ current_unprocessed_variable_name] = value_request_element # elif type(value_request_element) in current_child_element_object.__bases__: else: custom_set_from_function(value_request_element) for key_to_pop in keys_to_pop_after_loop_finished: unprocessed_vars_dict.pop(key_to_pop)