def patch(data, patches=None): """ loads a data file into a VSansData obj and returns that. **Inputs** data (raw[]): datafiles with metadata to patch patches (patch_metadata[]:run.filename): patches to be applied, with run.filename used as unique key **Returns** patched (raw[]): datafiles with patched metadata 2019-07-26 Brian Maranville """ if patches is None: return data from jsonpatch import JsonPatch from collections import OrderedDict # make a master dict of metadata from provided key: key="run.filename" master = OrderedDict([(_s(d.metadata[key]), d.metadata) for d in data]) to_apply = JsonPatch(patches) to_apply.apply(master, in_place=True) return data
def _prune_log_message(self, msg): """ If the "splunk_remove_paths" config item is not set or empty, return ``msg`` unaltered. Otherwise, for each RFC6901 JSON Pointer in "splunk_remove_paths" that points to an element present in ``msg``, remove that element. Return the result. :param msg: Splunk-ready message :type msg: dict :return: msg dict with all ``splunk_remove_paths`` elements removed :rtype: dict """ paths = self.config.get('splunk_remove_paths', []) if not paths: return msg patches = [] for path in paths: try: resolve_pointer(msg, path) patches.append({'op': 'remove', 'path': path}) except JsonPointerException: pass if not patches: return msg msg = JsonPatch(patches).apply(msg) return msg
def test_basic_game_info_update(self): """Make sure an update is properly parsed and stored""" borgia_info = read_game_info(self.borgia_game_path) # make some basic changes modified_borgia_info = borgia_info modified_borgia_info["title"] = "Coucou" updated_game_info = update_game_info(self.borgia_game_path, modified_borgia_info) # make sure changes have been done self.assertEquals(modified_borgia_info["title"], updated_game_info["title"]) self.assertEquals(updated_game_info["title"], "Coucou") # make sure there is a new event in history self.assertEquals(len(updated_game_info["history"]), 1) event = updated_game_info["history"][0]["patch"] print event # try to apply patch again new = JsonPatch(event).apply(modified_borgia_info) # make sure the original title is back self.assertEquals(new["title"], "Borgia, le jeu malsain")
def __import_patch(self, bg_only_file: Path, patch_file: Path) -> List[Dict]: with bg_only_file.open() as json_file: bgonly = json.load(json_file) with patch_file.open() as json_file: patch = JsonPatch(json.load(json_file)) return [bgonly, patch]
def patch_action(action): """ :type action: dart.model.action.Action """ p = JsonPatch(request.get_json()) sanitized_action = action.copy() patched_action = Action.from_dict(p.apply(action.to_dict())) # only allow updating fields that are editable sanitized_action.data.name = patched_action.data.name sanitized_action.data.args = patched_action.data.args sanitized_action.data.tags = patched_action.data.tags sanitized_action.data.progress = patched_action.data.progress sanitized_action.data.order_idx = patched_action.data.order_idx sanitized_action.data.on_failure = patched_action.data.on_failure sanitized_action.data.on_failure_email = patched_action.data.on_failure_email sanitized_action.data.on_success_email = patched_action.data.on_success_email sanitized_action.data.extra_data = patched_action.data.extra_data # revalidate sanitized_action = action_service().default_and_validate_action( sanitized_action) return { 'results': action_service().patch_action(action, sanitized_action).to_dict() }
def partial_update(self, request, *args, **kwargs): patch = JsonPatch(request.DATA) obj = self.get_object() serializer = self.get_serializer(instance=obj) doc = serializer.data try: # `jsonpatch` does not force documents to be array of operations # So we have to do it manually if not isinstance(request.DATA, list): raise JsonPatchException( "The patch must be supplied as a list", ) modified = patch.apply(doc) # Set the modified data to the request data # This will allow us to update the object using it request._data = modified return super(JsonPatchMixin, self).update(request, *args, **kwargs) except JsonPatchException as ex: message = force_text(ex) # `jsonpatch` does not handle unicode transparently # So we have to strip out the `u'` in Python 2 if "Unknown operation u'" in message and sys.version_info < (3, 0): message = message.replace("u'", "'") data = { "detail": message, } return response.Response(data, status=400)
def patch_datastore(datastore): """ :type datastore: dart.model.datastore.Datastore """ p = JsonPatch(request.get_json()) sanitized_datastore = datastore.copy() patched_datastore = Datastore.from_dict(p.apply(datastore.to_dict())) # only allow updating fields that are editable sanitized_datastore.data.name = patched_datastore.data.name sanitized_datastore.data.host = patched_datastore.data.host sanitized_datastore.data.port = patched_datastore.data.port sanitized_datastore.data.connection_url = patched_datastore.data.connection_url sanitized_datastore.data.state = patched_datastore.data.state sanitized_datastore.data.concurrency = patched_datastore.data.concurrency sanitized_datastore.data.args = patched_datastore.data.args sanitized_datastore.data.extra_data = patched_datastore.data.extra_data sanitized_datastore.data.tags = patched_datastore.data.tags # revalidate sanitized_datastore = datastore_service().default_and_validate_datastore( sanitized_datastore) return { 'results': datastore_service().patch_datastore(datastore, sanitized_datastore).to_dict() }
def patch_json(site, config, logger): """Update the site JSON configuration file """ patching_config = config.get('patching_config') output_file = os.path.join(config["build_site_dir"], site, \ patching_config["viewer_configs"][site]) input_file = output_file + "_org" logger.info("Backup original config") is_patched = False try: os.remove(input_file) except OSError: pass os.rename(output_file, input_file) with open(input_file) as file_data: json_data_to_patch = json.load(file_data) items_to_patch = [] patch_requests = patching_config.get('patches') for request in patch_requests: op = request.get('op') patch_path = parse(request.get('path')) matching_pattern = request.get('pattern') replacement = request.get('replacement') # Find matches for path matches = [(match.value, str(match.full_path)) for match in patch_path.find(json_data_to_patch)] # Find items matching with value filtered = filter(lambda x: is_matched(x, matching_pattern), matches) # Prepare patch items_to_patch += \ map(lambda x: prepare_patch(x, matching_pattern, replacement, op), filtered) # Patch json if len(items_to_patch) > 0: logger.info("Patches available") patches = JsonPatch(items_to_patch) result = patches.apply(json_data_to_patch) # Save json with open(output_file, 'w') as save_file: json.dump(result, save_file, sort_keys=False) is_patched = True logger.info("Json config of site '%s' patched", site) if not is_patched: os.rename(input_file, output_file) logger.info("Json config of site '%s' not patched", site) logger.info("JSON patch process for site '%s' completed", site)
def diff(self, hash1, hash2=None, txid=None): branch = self._branches[txid] rev1 = branch[hash1] rev2 = branch[hash2] if hash2 else branch._latest if rev1.hash == rev2.hash: return JsonPatch([]) else: dict1 = message_to_dict(rev1.data) dict2 = message_to_dict(rev2.data) return make_patch(dict1, dict2)
def patch(instance, **kwargs): # Create the patch object patch = JsonPatch(request.get_json()) # Get a dictionary instance of the model instance data = instance.asdict(exclude_pk=True, **kwargs) print ('THIS IS THE DATA:', data) # Apply the patch to the dictionary instance of the model data = patch.apply(data) # Apply the patched dictionary back to the model instance.fromdict(data)
def put(self, challenge_id): try: patch = JsonPatch(request.get_json(force=True)) except (KeyError, AttributeError) as e: log("Request missing values", error=e) abort(400) schema = s.ChallengeSchema() challenge = m.Challenge.query.get_or_404(challenge_id) data = schema.dump(challenge) new_data = patch.apply(data) schema.load(new_data, instance=challenge).save() return new_data, 200
def patch(self, request, pk): doc = self.get_doc(pk) # do JSON-Patch patch_data = JsonPatch(request.data) try: patch_data.apply(doc, in_place=True) except Exception as e: return Response({'jsonpatch_error': get_exception_detail(e)}, status=status.HTTP_400_BAD_REQUEST) # validate data after JSON-Patch form = self.form_cls(doc) if form.is_valid(): self.engine.save(form.document) return Response(status=status.HTTP_204_NO_CONTENT) return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)
def patch_predicate(value, patches): patched_value = value for patch in patches: if "unwind" in patch: json_patch_list = [ convert_to_json_patches(p, patched_value) for p in unwind(patch, value) ] json_patch_list = itertools.chain( *json_patch_list) # Flatten list of lists else: json_patch_list = convert_to_json_patches(patch, patched_value) for patch in json_patch_list: try: patched_value = JsonPatch(patch).apply(patched_value) except (JsonPatchTestFailed, JsonPatchConflict): pass return patched_value
def patch(self, request, pk): row = self.get_row(pk) doc = self.as_dict(row) # do JSON-Patch patch_data = JsonPatch(request.data) try: patch_data.apply(doc, in_place=True) except Exception as e: return Response({'jsonpatch_error': get_exception_detail(e)}, status=status.HTTP_400_BAD_REQUEST) # validate data after JSON-Patch form = self.form_cls(doc) if form.is_valid(): self.from_dict(row, doc) self.session.commit() return Response(status=status.HTTP_204_NO_CONTENT) return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)
def load_config( config_content: str, merge_content: Optional[str] = None, patch_content: Optional[str] = None, ) -> _JSONDict: config_data = yaml.safe_load(config_content) if config_data is None: config_data = {} if not isinstance(config_data, dict): raise SystemExit(f"Invalid configuration format: {type(config_data)!r}") if merge_content is not None: merge_data = yaml.safe_load(merge_content) config_data = merge(config_data, merge_data) if patch_content is not None: patch_data = yaml.safe_load(patch_content) json_patch = JsonPatch(patch_data) config_data = json_patch.apply(config_data) return cast(_JSONDict, config_data)
def patch_workflow(workflow): """ :type workflow: dart.model.workflow.Workflow """ p = JsonPatch(request.get_json()) return update_workflow(workflow, Workflow.from_dict(p.apply(workflow.to_dict())))
def from_json(self, json_data): return JsonPatch(json_data)
def patch_action(action): """ :type action: dart.model.action.Action """ p = JsonPatch(request.get_json()) return update_action(action, Action.from_dict(p.apply(action.to_dict())))
def patch_subscription(subscription): """ :type subscription: dart.model.subscription.Subscription """ p = JsonPatch(request.get_json()) return update_subscription( subscription, Subscription.from_dict(p.apply(subscription.to_dict())))
def patch_event(event): """ :type event: dart.model.event.Event """ p = JsonPatch(request.get_json()) return update_event(event, Event.from_dict(p.apply(event.to_dict())))
def patch(self): config_patch = config_patch_schema.load(request.get_json(), many=True) config = self._config_service.get_config() patched_config = JsonPatch(config_patch).apply(config) self._config_service.update_config(patched_config) return self._config_service.get_config(), 200
def update_school_preferences(resp): response_object = {'status': 'fail', 'message': 'School does not exist.'} user = User.query.get(resp) school = School.query.get(user.school_id) if not school: return jsonify(response_object), 400 response_object = {'status': 'fail', 'message': 'Malformed patch.'} # get patch object from client patch_raw = request.get_json() if not patch_raw or not isinstance(patch_raw, list): return jsonify(response_object), 400 # for any times or dates in the patch object, check correct formatting for edit in patch_raw: try: if str(edit['path']) not in EDITABLE_PREFERENCES: return jsonify(response_object), 400 except KeyError: return jsonify(response_object), 400 if edit['path'] == '/term_dates': for halfterm in edit['value']: # dict try: datetime.strptime(halfterm[0], DATE_FORMAT) datetime.strptime(halfterm[1], DATE_FORMAT) except ValueError: return jsonify(response_object), 400 elif edit['path'] == '/period_start_times': for period in edit['value']: try: datetime.strptime(edit['value'][period], TIME_FORMAT) except ValueError: return jsonify(response_object), 400 elif edit['path'] == '/period_length_in_minutes': try: int(edit['value']) except ValueError as e: response_object['message'] = str(e) return jsonify(response_object), 400 elif edit['path'] == '/weeks_timetable': try: assert int(edit['value']) in [1, 2] except (AssertionError): return jsonify(response_object), 400 except (ValueError): return jsonify(response_object), 400 elif edit['path'] == '/days_notice': try: int(edit['value']) except ValueError: return jsonify(response_object), 400 # convert raw JSON from client into JSONPatch format patch = JsonPatch(patch_raw) # get preferences JSON object from school preferences = school.preferences # Apply the patch to the dictionary instance of the model try: preferences_update = patch.apply(preferences) except (JsonPatchConflict, JsonPatchException): return jsonify(response_object), 400 change = diff(preferences, preferences_update) if not change: response_object = { 'status': 'success', 'message': '{} preferences unchanged.'.format(school.name) } return jsonify(response_object), 200 # check new preferences object for consistency, and process try: response_object = process_preferences(preferences_update) except BaseException as e: response_object = {'status': 'fail', 'message': e} school.preferences = preferences_update db.session.commit() response_object = { 'status': 'success', 'message': 'Preferences for {} have been updated.'.format(school.name), 'data': { 'school': school.asdict() } } return jsonify(response_object), 200
def patch_datastore(datastore): """ :type datastore: dart.model.datastore.Datastore """ p = JsonPatch(request.get_json()) return update_datastore(datastore, Datastore.from_dict(p.apply(datastore.to_dict())))
def apply_update_patch(content, event): """Apply JSON diff patches to content""" patch = JsonPatch(event["content"]["changes"]) final_content = patch.apply(content) return final_content
def patch_trigger(trigger): """ :type trigger: dart.model.trigger.Trigger """ p = JsonPatch(request.get_json()) return update_trigger(trigger, Trigger.from_dict(p.apply(trigger.to_dict())))
def update_single_requisition(resp, req_id): # teachers can edit their own requisitions # technicians can make their school's requisitions as done unauthorised = False response_object = { 'status': 'fail', 'message': 'Req does not exist' } user = User.query.get(resp) req = Req.query.get(req_id) if not req: return jsonify(response_object), 400 # get patch object from client patch = JsonPatch(request.get_json()) # convert target req object to dict to allow patching data = req.asdict(exclude_pk=True, exclude=['time']) # Apply the patch to the dictionary instance of the model try: data_update = patch.apply(data) except InvalidJsonPatch: response_object = { 'status': 'fail', 'message': 'Malformed patch.' } return jsonify(response_object), 400 change = diff(data, data_update) if not change: response_object = { 'status': 'success', 'message': 'Req {} unchanged.'.format(req.id), 'data': req_to_JSON(req) } return jsonify(response_object), 200 if user.role_code is TEACHER: if req.isDone is True: response_object = { 'status': 'fail', 'message': 'Req {} has been marked as done ' 'and cannot be edited.'.format(req.id) } return jsonify(response_object), 401 if req.user_id is not user.id: unauthorised = True for c in change: if c not in TEACHER_PATCH_AUTH: unauthorised = True elif user.role_code is TECHNICIAN: for c in change: if c not in TECHNICIAN_PATCH_AUTH: unauthorised = True if unauthorised: response_object = { 'status': 'fail', 'message': 'You are not authorised to do that.' } return jsonify(response_object), 401 req.fromdict(data_update) db.session.commit() req = Req.query.get(req_id) req.last_updated = datetime.now() db.session.commit() response_object = { 'status': 'success', 'message': 'Req {} has been updated.'.format(req.id), 'data': req_to_JSON(req) } return jsonify(response_object), 200