def test_flatten_dict(): actual = dictutil.flatten({ 'a': { 'b': { 'c': { 'd': 'e' } } }, 'f': 1, 'g': [1, 2, 3], 'h': { 'i': 1, 'j': 2 } }) assert actual == { 'a.b.c.d': 'e', 'f': 1, 'g': [1, 2, 3], 'h.i': 1, 'h.j': 2, }
def dumps(obj: dict) -> str: obj = dictutil.flatten(obj) def _process(value, key): path = '_'.join(key).upper().replace('.', '_') return f'{path}={value}' return '\n'.join(iterutil.traverse(obj, _process).values())
def inject_settings(environment: Environment, data: dict, components: Iterable[Component] = None, strict: bool = True) -> dict: """ Inject settings keys. """ if components is None: components = Component.objects.all() env_settings = get_environment_settings(environment, components=components) context = dictutil.flatten(env_settings) return tplcontext.inject(template=data, context=context, strict=strict)
def get_context_data(self, **kwargs): data = super().get_context_data(**kwargs) component = self.object # type: Component environment = get_object_or_404( klass=self.request.view_environments, alias=self.kwargs['environment'] ) settings_dict = security.cleanse( data=get_settings( environment=environment, component=component, ), hidden=settings.SECURE_KEYS, ) settings_dict = dictutil.flatten(settings_dict) settings_dict = inject_settings( environment=environment, data=settings_dict, components=self.request.components, strict=False ) form = ComponentSettingsForm( component=component, environment=environment, initial={ 'settings': settings_dict } ) checker = ObjectPermissionChecker(self.request.user) component_perms = checker.get_perms(component) environment_perms = checker.get_perms(environment) data.update({ 'current_environment': environment, 'settings': settings_dict, 'form': form, 'component_perms': component_perms, 'environment_perms': environment_perms }) return data
def _loads(self, data_json): if not data_json: return {} data = json.loads(data_json) if (self.content_type_id and self.content_type.model_class() is Component and 'settings' in data): try: environment_data = data['settings'] environment = list(environment_data.keys())[0] if isinstance(environment_data[environment], str): settings_data = json.loads( decrypt_data(environment_data[environment])) else: settings_data = environment_data[environment] or {} data['settings'][environment] = settings_data except (KeyError, IndexError): return {} return dictutil.flatten(data)
def validate_settings(environment: Environment, component: Component, data: dict): """ Update component settings. """ # Validate settings format try: validate_settings_format(data) except ValidationError as exc: raise InvalidSettingsError(exc.message) # Validate changed component referred keys setting_keys = list(dictutil.flatten({component.alias: data}).keys()) inject_keys = get_settings_inject_keys( environment, override_settings={component.alias: data}) for component_alias, keys in inject_keys.items(): for key in keys: if key.startswith(component.alias) and key not in setting_keys: raise InvalidSettingsError( _('Component `%s` refers to changed key `%s`.') % (component_alias, key), ) # Validate injections try: data = inject_settings(environment=environment, data=data, strict=True) except tplcontext.InvalidKey as exc: raise InvalidSettingsError( _('Injected key `%(key)s` does not exist.') % {'key': exc.key}) except tplcontext.CircularInjectError: raise InvalidSettingsError(_('Circular key injections detected.')) except Exception: raise InvalidSettingsError(_('Unknown settings validation error.')) # Validate JSON schema if component.require_schema: try: jsonschema.validate(instance=data, schema=component.schema) except (jsonschema.ValidationError, jsonschema.SchemaError) as exc: raise InvalidSettingsError( _('Invalid settings schema: %(error)s.') % {'error': exc.message}) # Validate strict keys if component.strict_keys and not environment.is_base: base_settings = get_settings( environment=Environment.objects.base().get(), component=component, ) diff = dictdiffer.diff(base_settings, data) add_keys = [] remove_keys = [] for summary in diff: if 'add' in summary: add_keys = [ add[0] for add in summary[2] if not isinstance(add[0], int) ] if 'remove' in summary: remove_keys = [ remove[0] for remove in summary[2] if not isinstance(remove[0], int) ] if add_keys: raise InvalidSettingsError( _('Cannot add new keys to environment configuration. ' 'New key(s): <b>%(keys)s</b>.') % {'keys': ', '.join(add_keys)}) if remove_keys: raise InvalidSettingsError( _('Cannot remove keys from environment configuration. ' 'Removed key(s): <b>%(keys)s</b>.') % {'keys': ', '.join(remove_keys)})
def get(self, request, environment: str, **kwargs): environment = get_object_or_404(self.environments, alias=environment) data = dictutil.flatten(get_environment_settings(environment)) return Response(data)