def get_form_xml_metadata(meta): try: couch_form._unsafe_get_xml() assert meta is not None, couch_form.form_id return meta except MissingFormXml: pass log.warning("Rebuilding missing form XML: %s", couch_form.form_id) metas = get_blob_metadata(couch_form.form_id)[(CODES.form_xml, "form.xml")] if len(metas) == 1: couch_meta = couch_form.blobs.get("form.xml") if couch_meta is None: assert not metas[0].blob_exists(), metas else: assert metas[0].key == couch_meta.key, (metas, couch_meta) blobdb.delete(metas[0].key) metas.remove(metas[0]) else: assert not metas, metas # protect against yet another duplicate xml = convert_form_to_xml(couch_form.to_json()["form"]) att = Attachment("form.xml", xml.encode("utf-8"), content_type="text/xml") return att.write(blobdb, sql_form)
def create_form_for_test(domain, case_id=None, attachments=None, save=True, state=XFormInstanceSQL.NORMAL, received_on=None, user_id='user1', edited_on=None): """ Create the models directly so that these tests aren't dependent on any other apps. Not testing form processing here anyway. :param case_id: create case with ID if supplied :param attachments: additional attachments dict :param save: if False return the unsaved form :return: form object """ from corehq.form_processor.utils import get_simple_form_xml form_id = uuid4().hex utcnow = received_on or datetime.utcnow() form_xml = get_simple_form_xml(form_id, case_id) form = XFormInstanceSQL( form_id=form_id, xmlns='http://openrosa.org/formdesigner/form-processor', received_on=utcnow, user_id=user_id, domain=domain, state=state, edited_on=edited_on, ) attachments = attachments or {} attachment_tuples = [ Attachment(name=a[0], raw_content=a[1], content_type=a[1].content_type) for a in attachments.items() ] attachment_tuples.append(Attachment('form.xml', form_xml, 'text/xml')) FormProcessorSQL.store_attachments(form, attachment_tuples) cases = [] if case_id: case = CommCareCaseSQL( case_id=case_id, domain=domain, type='', owner_id=user_id, opened_on=utcnow, modified_on=utcnow, modified_by=user_id, server_modified_on=utcnow, ) case.track_create(CaseTransaction.form_transaction(case, form, utcnow)) cases = [case]
def _create_new_xform(domain, instance_xml, attachments=None, auth_context=None): """ create but do not save an XFormInstance from an xform payload (xml_string) optionally set the doc _id to a predefined value (_id) return doc _id of the created doc `process` is transformation to apply to the form right before saving This is to avoid having to save multiple times If xml_string is bad xml - raise couchforms.XMLSyntaxError :param domain: """ from corehq.form_processor.interfaces.processor import FormProcessorInterface interface = FormProcessorInterface(domain) assert attachments is not None form_data = convert_xform_to_json(instance_xml) if not form_data.get('@xmlns'): raise MissingXMLNSError("Form is missing a required field: XMLNS") adjust_datetimes(form_data) xform = interface.new_xform(form_data) xform.domain = domain xform.auth_context = auth_context # Maps all attachments to uniform format and adds form.xml to list before storing attachments = map( lambda a: Attachment( name=a[0], raw_content=a[1], content_type=a[1].content_type), attachments.items()) attachments.append( Attachment(name='form.xml', raw_content=instance_xml, content_type='text/xml')) interface.store_attachments(xform, attachments) result = LockedFormProcessingResult(xform) with ReleaseOnError(result.lock): if interface.is_duplicate(xform.form_id): raise DuplicateError(xform) return result
def get_form_ready_to_save(metadata, is_db_test=False): from corehq.form_processor.parsers.form import process_xform_xml from corehq.form_processor.utils import get_simple_form_xml, convert_xform_to_json from corehq.form_processor.interfaces.processor import FormProcessorInterface from corehq.form_processor.models import Attachment assert metadata is not None metadata.domain = metadata.domain or uuid.uuid4().hex form_id = uuid.uuid4().hex form_xml = get_simple_form_xml(form_id=form_id, metadata=metadata) if is_db_test: wrapped_form = process_xform_xml(metadata.domain, form_xml).submitted_form else: interface = FormProcessorInterface(domain=metadata.domain) form_json = convert_xform_to_json(form_xml) wrapped_form = interface.new_xform(form_json) wrapped_form.domain = metadata.domain interface.store_attachments(wrapped_form, [ Attachment( name='form.xml', raw_content=form_xml, content_type='text/xml') ]) wrapped_form.received_on = metadata.received_on wrapped_form.app_id = metadata.app_id return wrapped_form
def update_responses(self, xform, value_responses_map, user_id): """ Update a set of question responses. Returns a list of any questions that were not found in the xform. """ from corehq.form_processor.interfaces.dbaccessors import FormAccessors from corehq.form_processor.utils.xform import update_response errors = [] xml = xform.get_xml_element() for question, response in six.iteritems(value_responses_map): try: update_response(xml, question, response, xmlns=xform.xmlns) except XFormQuestionValueNotFound: errors.append(question) existing_form = FormAccessors(xform.domain).get_with_attachments( xform.get_id) existing_form, new_form = self.processor.new_form_from_old( existing_form, xml, value_responses_map, user_id) new_xml = etree.tostring(xml) interface = FormProcessorInterface(xform.domain) interface.store_attachments(new_form, [ Attachment(name=ATTACHMENT_NAME, raw_content=new_xml, content_type='text/xml') ]) interface.save_processed_models([new_form, existing_form]) return errors
def update_responses(self, xform, value_responses_map, user_id): from corehq.form_processor.utils.xform import update_response xml = xform.get_xml_element() dirty = False for question, response in six.iteritems(value_responses_map): if update_response(xml, question, response, xmlns=xform.xmlns): dirty = True if dirty: from couchforms.const import ATTACHMENT_NAME from corehq.form_processor.interfaces.dbaccessors import FormAccessors from corehq.form_processor.models import Attachment existing_form = FormAccessors(xform.domain).get_with_attachments(xform.get_id) existing_form, new_form = self.processor.new_form_from_old(existing_form, xml, value_responses_map, user_id) new_xml = etree.tostring(xml) interface = FormProcessorInterface(xform.domain) interface.store_attachments(new_form, [ Attachment(name=ATTACHMENT_NAME, raw_content=new_xml, content_type='text/xml') ]) interface.save_processed_models([new_form, existing_form]) return True return False
def get_simple_wrapped_form(form_id, case_id=None, metadata=None, save=True): from corehq.form_processor.interfaces.processor import FormProcessorInterface metadata = metadata or TestFormMetadata() xml = get_simple_form_xml(form_id=form_id, metadata=metadata) form_json = convert_xform_to_json(xml) interface = FormProcessorInterface(domain=metadata.domain) wrapped_form = interface.new_xform(form_json) wrapped_form.domain = metadata.domain interface.store_attachments(wrapped_form, [Attachment('form.xml', xml, 'text/xml')]) if save: interface.save_processed_models([wrapped_form]) return wrapped_form
def submission_error_form_instance(cls, domain, instance, message): xform = XFormInstanceSQL( domain=domain, form_id=uuid.uuid4().hex, received_on=datetime.datetime.utcnow(), problem=message, state=XFormInstanceSQL.SUBMISSION_ERROR_LOG ) cls.store_attachments(xform, [Attachment( name=ATTACHMENT_NAME, raw_content=instance, content_type='text/xml', )]) return xform
def get_simple_wrapped_form(form_id, metadata=None, save=True, simple_form=SIMPLE_FORM): from corehq.form_processor.interfaces.processor import FormProcessorInterface from corehq.form_processor.interfaces.dbaccessors import FormAccessors metadata = metadata or TestFormMetadata() xml = get_simple_form_xml(form_id=form_id, metadata=metadata, simple_form=simple_form) form_json = convert_xform_to_json(xml) interface = FormProcessorInterface(domain=metadata.domain) wrapped_form = interface.new_xform(form_json) wrapped_form.domain = metadata.domain wrapped_form.received_on = metadata.received_on interface.store_attachments(wrapped_form, [Attachment('form.xml', xml, 'text/xml')]) if save: interface.save_processed_models([wrapped_form]) wrapped_form = FormAccessors(metadata.domain).get_form(wrapped_form.form_id) return wrapped_form
def new_form_from_old(cls, existing_form, xml, value_responses_map, user_id): from corehq.form_processor.parsers.form import apply_deprecation new_xml = etree.tostring(xml) form_json = convert_xform_to_json(new_xml) new_form = cls.new_xform(form_json) new_form.user_id = user_id new_form.domain = existing_form.domain new_form.app_id = existing_form.app_id cls.store_attachments(new_form, [Attachment( name=ATTACHMENT_NAME, raw_content=new_xml, content_type='text/xml', )]) existing_form, new_form = apply_deprecation(existing_form, new_form) return (existing_form, new_form)
def add_form_xml(sql_form, patch_form): xml = patch_form.get_xml() att = Attachment("form.xml", xml.encode("utf-8"), content_type="text/xml") xml_meta = att.write(get_blob_db(), sql_form) sql_form.attachments_list = [xml_meta]
def create_attachment_with_content(content): return Attachment(name='test_attachment', raw_content=content, content_type='text')