def test_oneOf_branch_is_chosen_based_on_type_errors(self): schema = { "oneOf": [ { "type": ["string", "array"] }, { "oneOf": [{ "type": "integer" }, { "type": "number", "minimum": 5 }] }, ] } errors = config_schema.process_config(True, schema) # If there are type errors on both sides, it should be a virtual type error with all types assert len(errors) == 1 assert tuple(errors[0].schema_path) == ('oneOf', 'type') # It should have all the types together assert set(errors[0].validator_value) == set( ['string', 'array', 'number', 'integer']) # If there are no type errors going down one branch it should choose it errors = config_schema.process_config(1.5, schema) assert len(errors) == 1 assert errors[0].validator == 'minimum'
def test_custom_error_template(self): schema = { 'type': 'string', 'minLength': 10, 'error': '{{validator}} failed for {{instance}}' } errors = config_schema.process_config(13, schema) assert errors[0].message == "type failed for 13" errors = config_schema.process_config('aoeu', schema) assert errors[0].message == "minLength failed for aoeu"
def test_custom_error_template(self): schema = { 'type': 'string', 'minLength': 10, 'error': '{{validator}} failed for {{instance}}', } errors = config_schema.process_config(13, schema) assert errors[0].message == "type failed for 13" errors = config_schema.process_config('aoeu', schema) assert errors[0].message == "minLength failed for aoeu"
def on_task_start(self, task, config): if not config: return files = config if isinstance(config, basestring): files = [config] for name in files: name = os.path.expanduser(name) if not os.path.isabs(name): name = os.path.join(task.manager.config_base, name) include = yaml.load(io.open(name, encoding='utf-8')) errors = process_config(include, plugin.plugin_schemas(context='task')) if errors: log.error('Included file %s has invalid config:' % name) for error in errors: log.error('[%s] %s', error.json_pointer, error.message) task.abort('Invalid config in included file %s' % name) log.debug('Merging %s into task %s' % (name, task.name)) # merge try: merge_dict_from_to(include, task.config) except MergeException: raise plugin.PluginError('Failed to merge include file to task %s, incompatible datatypes' % task.name)
def validate_config(self): """ Check all root level keywords are valid. :returns: A list of `ValidationError`s """ return config_schema.process_config(self.config)
def on_task_start(self, task, config): if not config: return files = config if isinstance(config, basestring): files = [config] for name in files: name = os.path.expanduser(name) if not os.path.isabs(name): name = os.path.join(task.manager.config_base, name) include = yaml.load(io.open(name, encoding='utf-8')) errors = process_config(include, plugin.plugin_schemas(context='task')) if errors: log.error('Included file %s has invalid config:' % name) for error in errors: log.error('[%s] %s', error.json_pointer, error.message) task.abort('Invalid config in included file %s' % name) log.debug('Merging %s into task %s' % (name, task.name)) # merge try: merge_dict_from_to(include, task.config) except MergeException: raise plugin.PluginError( 'Failed to merge include file to task %s, incompatible datatypes' % task.name)
def on_task_prepare(self, task, config): if not config: return files = config if isinstance(config, str): files = [config] for file_name in files: file = os.path.expanduser(file_name) if not os.path.isabs(file): file = os.path.join(task.manager.config_base, file) with io.open(file, encoding='utf-8') as inc_file: include = yaml.safe_load(inc_file) inc_file.flush() errors = process_config(include, plugin.plugin_schemas(interface='task')) if errors: logger.error('Included file {} has invalid config:', file) for error in errors: logger.error('[{}] {}', error.json_pointer, error.message) task.abort('Invalid config in included file %s' % file) logger.debug('Merging {} into task {}', file, task.name) # merge try: task.merge_config(include) except MergeException: raise plugin.PluginError( 'Failed to merge include file to task %s, incompatible datatypes' % task.name )
def post(self, session=None): """ Add new task """ data = request.json task_name = data["name"] if task_name in self.manager.user_config.get("tasks", {}): return {"error": "task already exists"}, 409 if "tasks" not in self.manager.user_config: self.manager.user_config["tasks"] = {} if "tasks" not in self.manager.config: self.manager.config["tasks"] = {} task_schema_processed = copy.deepcopy(data) errors = process_config(task_schema_processed, schema=task_api_schema.__schema__, set_defaults=True) if errors: return {"error": "problem loading config, raise a BUG as this should not happen!"}, 500 self.manager.user_config["tasks"][task_name] = data["config"] self.manager.config["tasks"][task_name] = task_schema_processed["config"] self.manager.save_config() self.manager.config_changed() return {"name": task_name, "config": self.manager.user_config["tasks"][task_name]}, 201
def post(self, session=None): """ Add new task """ data = request.json task_name = data['name'] if task_name in self.manager.user_config.get('tasks', {}): return {'error': 'task already exists'}, 409 if 'tasks' not in self.manager.user_config: self.manager.user_config['tasks'] = {} if 'tasks' not in self.manager.config: self.manager.config['tasks'] = {} task_schema_processed = copy.deepcopy(data) errors = process_config(task_schema_processed, schema=task_api_schema.__schema__, set_defaults=True) if errors: return { 'error': 'problem loading config, raise a BUG as this should not happen!' }, 500 self.manager.user_config['tasks'][task_name] = data['config'] self.manager.config['tasks'][task_name] = task_schema_processed[ 'config'] self.manager.save_config() self.manager.config_changed() return { 'name': task_name, 'config': self.manager.user_config['tasks'][task_name] }, 201
def on_task_prepare(self, task, config): if not config: return files = config if isinstance(config, str): files = [config] for file_name in files: file = os.path.expanduser(file_name) if not os.path.isabs(file): file = os.path.join(task.manager.config_base, file) with io.open(file, encoding='utf-8') as inc_file: include = yaml.load(inc_file) inc_file.flush() errors = process_config(include, plugin.plugin_schemas(interface='task')) if errors: log.error('Included file %s has invalid config:', file) for error in errors: log.error('[%s] %s', error.json_pointer, error.message) task.abort('Invalid config in included file %s' % file) log.debug('Merging %s into task %s', file, task.name) # merge try: task.merge_config(include) except MergeException: raise plugin.PluginError('Failed to merge include file to task %s, incompatible datatypes' % task.name)
def post(self, session=None): """ Add new task """ data = request.json task_name = data['name'] if task_name in self.manager.user_config.get('tasks', {}): return {'error': 'task already exists'}, 409 if 'tasks' not in self.manager.user_config: self.manager.user_config['tasks'] = {} if 'tasks' not in self.manager.config: self.manager.config['tasks'] = {} task_schema_processed = copy.deepcopy(data) errors = process_config(task_schema_processed, schema=task_api_schema.__schema__, set_defaults=True) if errors: return {'error': 'problem loading config, raise a BUG as this should not happen!'}, 500 self.manager.user_config['tasks'][task_name] = data['config'] self.manager.config['tasks'][task_name] = task_schema_processed['config'] self.manager.save_config() self.manager.config_changed() return {'name': task_name, 'config': self.manager.user_config['tasks'][task_name]}, 201
def post(self, session=None): """ Add new task """ data = request.json task_name = data['name'] if task_name in self.manager.user_config.get('tasks', {}): raise Conflict('task already exists') if 'tasks' not in self.manager.user_config: self.manager.user_config['tasks'] = {} if 'tasks' not in self.manager.config: self.manager.config['tasks'] = {} task_schema_processed = copy.deepcopy(data) errors = process_config( task_schema_processed, schema=task_input_schema.__schema__, set_defaults=True ) if errors: raise APIError('problem loading config, raise a BUG as this should not happen!') self.manager.user_config['tasks'][task_name] = data['config'] self.manager.config['tasks'][task_name] = task_schema_processed['config'] self.manager.save_config() self.manager.config_changed() rsp = jsonify({'name': task_name, 'config': self.manager.user_config['tasks'][task_name]}) rsp.status_code = 201 return rsp
def test_custom_keyword_error_overrides(self): schema = { 'type': 'string', 'error_type': 'This is not okay', 'error': 'This is worse' } errors = config_schema.process_config(13, schema) assert errors[0].message == schema['error_type']
def validate_config(self): """ Check all root level keywords are valid. :returns: A list of `ValidationError`s """ fire_event('manager.before_config_validate', self) return config_schema.process_config(self.config)
def test_oneOf_branch_is_chosen_based_on_type_errors(self): schema = { "oneOf": [ {"type": ["string", "array"]}, {"oneOf": [{"type": "integer"}, {"type": "number", "minimum": 5}]}, ] } errors = config_schema.process_config(True, schema) # If there are type errors on both sides, it should be a virtual type error with all types assert len(errors) == 1 assert tuple(errors[0].schema_path) == ('oneOf', 'type') # It should have all the types together assert set(errors[0].validator_value) == set(['string', 'array', 'number', 'integer']) # If there are no type errors going down one branch it should choose it errors = config_schema.process_config(1.5, schema) assert len(errors) == 1 assert errors[0].validator == 'minimum'
def wrapper(*args, **kwargs): payload = request.json try: errors = process_config(config=payload, schema=model.__schema__, set_defaults=False) if errors: raise ValidationError(errors) except RefResolutionError as e: raise ApiError(str(e)) return func(*args, **kwargs)
def on_task_start(self, task, config): series = {} for input_name, input_config in config.get('from', {}).items(): input = plugin.get_plugin_by_name(input_name) if input.api_ver == 1: raise plugin.PluginError('Plugin %s does not support API v2' % input_name) method = input.phase_handlers['input'] try: result = method(task, input_config) except PluginError as e: log.warning('Error during input plugin %s: %s' % (input_name, e)) continue if not result: log.warning('Input %s did not return anything' % input_name) continue for entry in result: s = series.setdefault(entry['title'], {}) if entry.get('tvdb_id'): s['set'] = {'tvdb_id': entry['tvdb_id']} # Allow configure_series to set anything available to series for key, schema in self.settings_schema['properties'].items(): if 'configure_series_' + key in entry: errors = process_config(entry['configure_series_' + key], schema, set_defaults=False) if errors: log.debug('not setting series option %s for %s. errors: %s' % (key, entry['title'], errors)) else: s[key] = entry['configure_series_' + key] # Set the config_modified flag if the list of shows changed since last time new_hash = str(get_config_hash(series)) with Session() as session: last_hash = session.query(LastHash).filter(LastHash.task == task.name).first() if not last_hash: last_hash = LastHash(task=task.name) session.add(last_hash) if last_hash.hash != new_hash: task.config_changed() last_hash.hash = new_hash if not series: log.info('Did not get any series to generate series configuration') return # Make a series config with the found series # Turn our dict of series with settings into a list of one item dicts series_config = {'generated_series': [dict([x]) for x in series.items()]} # If options were specified, add them to the series config if 'settings' in config: series_config['settings'] = {'generated_series': config['settings']} # Merge our series config in with the base series config self.merge_config(task, series_config)
def on_task_start(self, task, config): series = {} for input_name, input_config in config.get('from', {}).items(): input = plugin.get_plugin_by_name(input_name) if input.api_ver == 1: raise plugin.PluginError('Plugin %s does not support API v2' % input_name) method = input.phase_handlers['input'] try: result = method(task, input_config) except PluginError as e: log.warning('Error during input plugin %s: %s' % (input_name, e)) continue if not result: log.warning('Input %s did not return anything' % input_name) continue for entry in result: s = series.setdefault(entry['title'], {}) if entry.get('tvdb_id'): s['set'] = {'tvdb_id': entry['tvdb_id']} # Allow configure_series to set anything available to series for key, schema in self.settings_schema['properties'].items(): if 'configure_series_' + key in entry: errors = process_config(entry['configure_series_' + key], schema, set_defaults=False) if errors: log.debug('not setting series option %s for %s. errors: %s' % (key, entry['title'], errors)) else: s[key] = entry['configure_series_' + key] # Set the config_modified flag if the list of shows changed since last time new_hash = str(hashlib.md5(str(sorted(series)).encode('utf-8')).hexdigest()) with Session() as session: last_hash = session.query(LastHash).filter(LastHash.task == task.name).first() if not last_hash: last_hash = LastHash(task=task.name) session.add(last_hash) if last_hash.hash != new_hash: task.config_changed() last_hash.hash = new_hash if not series: log.info('Did not get any series to generate series configuration') return # Make a series config with the found series # Turn our dict of series with settings into a list of one item dicts series_config = {'generated_series': [dict([s]) for s in series.items()]} # If options were specified, add them to the series config if 'settings' in config: series_config['settings'] = {'generated_series': config['settings']} # Merge our series config in with the base series config self.merge_config(task, series_config)
def on_task_start(self, task, config): series = {} for input_name, input_config in config.get("from", {}).items(): input = plugin.get_plugin_by_name(input_name) if input.api_ver == 1: raise plugin.PluginError("Plugin %s does not support API v2" % input_name) method = input.phase_handlers["input"] try: result = method(task, input_config) except PluginError as e: log.warning("Error during input plugin %s: %s" % (input_name, e)) continue if not result: log.warning("Input %s did not return anything" % input_name) continue for entry in result: s = series.setdefault(entry["title"], {}) if entry.get("tvdb_id"): s["set"] = {"tvdb_id": entry["tvdb_id"]} # Allow configure_series to set anything available to series for key, schema in self.settings_schema["properties"].items(): if "configure_series_" + key in entry: errors = process_config(entry["configure_series_" + key], schema, set_defaults=False) if errors: log.debug("not setting series option %s for %s. errors: %s" % (key, entry["title"], errors)) else: s[key] = entry["configure_series_" + key] # Set the config_modified flag if the list of shows changed since last time new_hash = str(get_config_hash(series)) with Session() as session: last_hash = session.query(LastHash).filter(LastHash.task == task.name).first() if not last_hash: last_hash = LastHash(task=task.name) session.add(last_hash) if last_hash.hash != new_hash: task.config_changed() last_hash.hash = new_hash if not series: log.info("Did not get any series to generate series configuration") return # Make a series config with the found series # Turn our dict of series with settings into a list of one item dicts series_config = {"generated_series": [dict([x]) for x in series.items()]} # If options were specified, add them to the series config if "settings" in config: series_config["settings"] = {"generated_series": config["settings"]} # Merge our series config in with the base series config self.merge_config(task, series_config)
def on_task_prepare(self, task, config): series = {} for input_name, input_config in config.get('from', {}).items(): input_plugin = plugin.get_plugin_by_name(input_name) method = input_plugin.phase_handlers['input'] try: result = method(task, input_config) except PluginError as e: logger.warning('Error during input plugin {}: {}', input_name, e) continue if not result: logger.warning('Input {} did not return anything', input_name) continue for entry in result: s = series.setdefault(entry['title'], {}) if entry.get('tvdb_id'): s['set'] = {'tvdb_id': entry['tvdb_id']} # Allow configure_series to set anything available to series for key, schema in self.settings_schema['properties'].items(): if 'configure_series_' + key in entry: errors = process_config(entry['configure_series_' + key], schema, set_defaults=False) if errors: logger.debug( 'not setting series option {} for {}. errors: {}', key, entry['title'], errors, ) else: s[key] = entry['configure_series_' + key] if not series: logger.info( 'Did not get any series to generate series configuration') return # Make a series config with the found series # Turn our dict of series with settings into a list of one item dicts series_config = { 'generated_series': [dict([x]) for x in series.items()] } # If options were specified, add them to the series config if 'settings' in config: series_config['settings'] = { 'generated_series': config['settings'] } # Merge our series config in with the base series config self.merge_config(task, series_config)
def wrapper(*args, **kwargs): payload = request.json try: schema = schema_override if schema_override else model.__schema__ errors = process_config(config=payload, schema=schema, set_defaults=False) if errors: raise ValidationError(errors) except RefResolutionError as e: raise APIError(str(e)) return func(*args, **kwargs)
def config_root_key(root_key): if request.method == 'PUT': schema = resolve_ref('/schema/config/%s' % root_key) errors = process_config(request.json, schema, set_defaults=False) if errors: return jsonify({'$errors': errors}), 400 manager.config[root_key] = request.json if root_key not in manager.config: return 'Not found', 404 response = jsonify(manager.config[root_key]) response.headers[b'Content-Type'] += '; profile=/schema/config/%s' % root_key return response
def config_root_key(root_key): if request.method == 'PUT': schema = resolve_ref('/schema/config/%s' % root_key) errors = process_config(request.json, schema, set_defaults=False) if errors: return jsonify({'$errors': errors}), 400 manager.config[root_key] = request.json if root_key not in manager.config: return 'Not found', 404 response = jsonify(manager.config[root_key]) response.headers[ b'Content-Type'] += '; profile=/schema/config/%s' % root_key return response
def test_error_with_path(self): schema = { 'properties': { 'p': { 'items': { 'type': 'string', 'error': 'ERROR' } } } } errors = config_schema.process_config({'p': [13]}, schema) assert errors[0].json_pointer == '/p/0' assert errors[0].message == 'ERROR'
def config_section(section): if request.method == "PUT": schema = resolve_ref("/schema/config/%s" % section) errors = process_config(request.json, schema, set_defaults=False) if errors: return jsonify({"$errors": errors}), 400 manager.config[section] = request.json if section not in manager.config: return jsonify(error="Not found"), 404 if request.method == "DELETE": del manager.config[section] return Response(status=204) response = jsonify(manager.config[section]) response.headers[b"Content-Type"] += "; profile=/schema/config/%s" % section return response
def config_section(section): if request.method == 'PUT': schema = resolve_ref('/schema/config/%s' % section) errors = process_config(request.json, schema, set_defaults=False) if errors: return jsonify({'$errors': errors}), 400 manager.config[section] = request.json if section not in manager.config: return jsonify(error='Not found'), 404 if request.method == 'DELETE': del manager.config[section] return Response(status=204) response = jsonify(manager.config[section]) response.headers[b'Content-Type'] += '; profile=/schema/config/%s' % section return response
def on_task_start(self, task, config): if not config: return files = config if isinstance(config, str): files = [config] for file_name in files: file_name = os.path.expanduser(file_name) if not os.path.isabs(file_name): file_name = os.path.join(task.manager.config_base, file_name) with io.open(file_name, encoding='utf-8') as inc_file: include = yaml.load(inc_file) inc_file.flush() errors = process_config(include, plugin.plugin_schemas(interface='task')) if errors: log.error('Included file %s has invalid config:', file_name) for error in errors: log.error('[%s] %s', error.json_pointer, error.message) task.abort('Invalid config in included file %s' % file_name) new_hash = str(get_config_hash(include)) with Session() as session: last_hash = session.query(LastHash).filter( LastHash.task == task.name).filter( LastHash.file == file_name).first() if not last_hash: log.debug( 'no config hash detected for task %s with file %s, creating', task.name, file_name) last_hash = LastHash(task=task.name, file=file_name) session.add(last_hash) if last_hash.hash != new_hash: log.debug( 'new hash detected, triggering config change event') task.config_changed() last_hash.hash = new_hash log.debug('Merging %s into task %s', file_name, task.name) # merge try: merge_dict_from_to(include, task.config) except MergeException: raise plugin.PluginError( 'Failed to merge include file to task %s, incompatible datatypes' % task.name)
def put(self, task, session: Session = None) -> Response: """ Update tasks config """ data = request.json new_task_name = data['name'] if task not in self.manager.user_config.get('tasks', {}): raise NotFoundError(f'task `{task}` not found') if 'tasks' not in self.manager.user_config: self.manager.user_config['tasks'] = {} if 'tasks' not in self.manager.config: self.manager.config['tasks'] = {} if task != new_task_name: # Rename task if new_task_name in self.manager.user_config['tasks']: raise BadRequest('cannot rename task as it already exist') del self.manager.user_config['tasks'][task] del self.manager.config['tasks'][task] # Process the task config task_schema_processed = copy.deepcopy(data) errors = process_config(task_schema_processed, schema=task_return_schema.__schema__, set_defaults=True) if errors: raise APIError( 'problem loading config, raise a BUG as this should not happen!' ) self.manager.user_config['tasks'][new_task_name] = data['config'] self.manager.config['tasks'][new_task_name] = task_schema_processed[ 'config'] self.manager.save_config() self.manager.config_changed() rsp = jsonify({ 'name': new_task_name, 'config': self.manager.user_config['tasks'][new_task_name] }) rsp.status_code = 200 return rsp
def config_section(section): if request.method == 'PUT': schema = resolve_ref('/schema/config/%s' % section) errors = process_config(request.json, schema, set_defaults=False) if errors: return jsonify({'$errors': errors}), 400 manager.config[section] = request.json if section not in manager.config: return jsonify(error='Not found'), 404 if request.method == 'DELETE': del manager.config[section] return Response(status=204) response = jsonify(manager.config[section]) response.headers[ b'Content-Type'] += '; profile=/schema/config/%s' % section return response
def put(self, task, session=None): """ Update tasks config """ data = request.json new_task_name = data['name'] if task not in self.manager.user_config.get('tasks', {}): return {'error': 'task does not exist'}, 404 if 'tasks' not in self.manager.user_config: self.manager.user_config['tasks'] = {} if 'tasks' not in self.manager.config: self.manager.config['tasks'] = {} code = 200 if task != new_task_name: # Rename task if new_task_name in self.manager.user_config['tasks']: return {'error': 'cannot rename task as it already exist'}, 400 del self.manager.user_config['tasks'][task] del self.manager.config['tasks'][task] code = 201 # Process the task config task_schema_processed = copy.deepcopy(data) errors = process_config(task_schema_processed, schema=task_api_schema.__schema__, set_defaults=True) if errors: return { 'error': 'problem loading config, raise a BUG as this should not happen!' }, 500 self.manager.user_config['tasks'][new_task_name] = data['config'] self.manager.config['tasks'][new_task_name] = task_schema_processed[ 'config'] self.manager.save_config() self.manager.config_changed() return { 'name': new_task_name, 'config': self.manager.user_config['tasks'][new_task_name] }, code
def on_task_prepare(self, task, config): series = {} for input_name, input_config in config.get('from', {}).items(): input_plugin = plugin.get_plugin_by_name(input_name) method = input_plugin.phase_handlers['input'] try: result = method(task, input_config) except PluginError as e: log.warning('Error during input plugin %s: %s' % (input_name, e)) continue if not result: log.warning('Input %s did not return anything' % input_name) continue for entry in result: s = series.setdefault(entry['title'], {}) if entry.get('tvdb_id'): s['set'] = {'tvdb_id': entry['tvdb_id']} # Allow configure_series to set anything available to series for key, schema in self.settings_schema['properties'].items(): if 'configure_series_' + key in entry: errors = process_config( entry['configure_series_' + key], schema, set_defaults=False ) if errors: log.debug( 'not setting series option %s for %s. errors: %s' % (key, entry['title'], errors) ) else: s[key] = entry['configure_series_' + key] if not series: log.info('Did not get any series to generate series configuration') return # Make a series config with the found series # Turn our dict of series with settings into a list of one item dicts series_config = {'generated_series': [dict([x]) for x in series.items()]} # If options were specified, add them to the series config if 'settings' in config: series_config['settings'] = {'generated_series': config['settings']} # Merge our series config in with the base series config self.merge_config(task, series_config)
def validate_config(self, config: dict = None) -> dict: """ Check all root level keywords are valid. Config may be modified by before_config_validate hooks. Modified config will be returned. :param config: Config to check. If not provided, current manager config will be checked. :raises: `ValueError` when config fails validation. There will be an `errors` attribute with the schema errors. :returns: Final validated config. """ conf = config if config else self.config conf = fire_event('manager.before_config_validate', conf, self) errors = config_schema.process_config(conf) if errors: err = ValueError('Did not pass schema validation.') err.errors = errors raise err else: return conf
def validate_config(self, config=None): """ Check all root level keywords are valid. Config may be modified by before_config_validate hooks. Modified config will be returned. :param config: Config to check. If not provided, current manager config will be checked. :raises: `ValueError` when config fails validation. There will be an `errors` attribute with the schema errors. :returns: Final validated config. """ if not config: config = self.config config = fire_event('manager.before_config_validate', config, self) errors = config_schema.process_config(config) if errors: err = ValueError('Did not pass schema validation.') err.errors = errors raise err else: return config
def put(self, task, session=None): """ Update tasks config """ data = request.json new_task_name = data['name'] if task not in self.manager.user_config.get('tasks', {}): raise NotFoundError('task `%s` not found' % task) if 'tasks' not in self.manager.user_config: self.manager.user_config['tasks'] = {} if 'tasks' not in self.manager.config: self.manager.config['tasks'] = {} if task != new_task_name: # Rename task if new_task_name in self.manager.user_config['tasks']: raise BadRequest('cannot rename task as it already exist') del self.manager.user_config['tasks'][task] del self.manager.config['tasks'][task] # Process the task config task_schema_processed = copy.deepcopy(data) errors = process_config( task_schema_processed, schema=task_return_schema.__schema__, set_defaults=True ) if errors: raise APIError('problem loading config, raise a BUG as this should not happen!') self.manager.user_config['tasks'][new_task_name] = data['config'] self.manager.config['tasks'][new_task_name] = task_schema_processed['config'] self.manager.save_config() self.manager.config_changed() rsp = jsonify( {'name': new_task_name, 'config': self.manager.user_config['tasks'][new_task_name]} ) rsp.status_code = 200 return rsp
def post(self, task, session=None): """ Update tasks config """ data = request.json new_task_name = data['name'] if task not in self.manager.user_config.get('tasks', {}): return {'error': 'task does not exist'}, 404 if 'tasks' not in self.manager.user_config: self.manager.user_config['tasks'] = {} if 'tasks' not in self.manager.config: self.manager.config['tasks'] = {} code = 200 if task != new_task_name: # Rename task if new_task_name in self.manager.user_config['tasks']: return {'error': 'cannot rename task as it already exist'}, 400 del self.manager.user_config['tasks'][task] del self.manager.config['tasks'][task] code = 201 # Process the task config task_schema_processed = copy.deepcopy(data) errors = process_config(task_schema_processed, schema=task_api_schema.__schema__, set_defaults=True) if errors: return {'error': 'problem loading config, raise a BUG as this should not happen!'}, 500 self.manager.user_config['tasks'][new_task_name] = data['config'] self.manager.config['tasks'][new_task_name] = task_schema_processed['config'] self.manager.save_config() self.manager.config_changed() return {'name': new_task_name, 'config': self.manager.user_config['tasks'][new_task_name]}, code
def post(self, task, session=None): """ Update tasks config """ data = request.json new_task_name = data["name"] if task not in self.manager.user_config.get("tasks", {}): return {"error": "task does not exist"}, 404 if "tasks" not in self.manager.user_config: self.manager.user_config["tasks"] = {} if "tasks" not in self.manager.config: self.manager.config["tasks"] = {} code = 200 if task != new_task_name: # Rename task if new_task_name in self.manager.user_config["tasks"]: return {"error": "cannot rename task as it already exist"}, 400 del self.manager.user_config["tasks"][task] del self.manager.config["tasks"][task] code = 201 # Process the task config task_schema_processed = copy.deepcopy(data) errors = process_config(task_schema_processed, schema=task_api_schema.__schema__, set_defaults=True) if errors: return {"error": "problem loading config, raise a BUG as this should not happen!"}, 500 self.manager.user_config["tasks"][new_task_name] = data["config"] self.manager.config["tasks"][new_task_name] = task_schema_processed["config"] self.manager.save_config() self.manager.config_changed() return {"name": new_task_name, "config": self.manager.user_config["tasks"][new_task_name]}, code
def test_defaults_are_filled(self): schema = {"properties": {"p": {"default": 5}}} config = {} config_schema.process_config(config, schema) assert config["p"] == 5
def test_defaults_does_not_override_explicit_value(self): schema = {"properties": {"p": {"default": 5}}} config = {"p": "foo"} config_schema.process_config(config, schema) assert config["p"] == "foo"
def test_resolves_local_refs(self): schema = {'$ref': '/schema/plugin/accept_all'} # accept_all schema should be for type boolean assert not config_schema.process_config(True, schema) assert config_schema.process_config(14, schema)
def validate_config(config): schema = plugin_schemas(context='task') # Don't validate commented out plugins schema['patternProperties'] = {'^_': {}} return config_schema.process_config(config, schema)
def validate(self, value): """This is just to unit test backwards compatibility of json schema with old validators""" errors = list(e.message for e in process_config(value, self.schema())) self.errors.messages = errors return not errors
def test_builtin_error_rewriting(self): schema = {'type': 'object'} errors = config_schema.process_config(42, schema) # We don't call them objects around here assert 'object' not in errors[0].message assert 'dict' in errors[0].message
def test_custom_keyword_error_overrides(self): schema = {'type': 'string', 'error_type': 'This is not okay', 'error': 'This is worse'} errors = config_schema.process_config(13, schema) assert errors[0].message == schema['error_type']
def test_error_with_path(self): schema = {'properties': {'p': {'items': {'type': 'string', 'error': 'ERROR'}}}} errors = config_schema.process_config({'p': [13]}, schema) assert errors[0].json_pointer == '/p/0' assert errors[0].message == 'ERROR'
def test_custom_error(self): schema = {'type': 'string', 'error': 'This is not okay'} errors = config_schema.process_config(13, schema) assert errors[0].message == schema['error']
def test_custom_format_checker(self): schema = {'type': 'string', 'format': 'quality'} assert not config_schema.process_config('720p', schema) assert config_schema.process_config('aoeu', schema)