Ejemplo n.º 1
0
    def testBasicEdit(self):
        first_file = os.path.join(os.path.dirname(__file__), "data", "duplicate.xml")
        edit_file = os.path.join(os.path.dirname(__file__), "data", "edit.xml")

        with open(first_file, "rb") as f:
            xml_data1 = f.read()
        with open(edit_file, "rb") as f:
            xml_data2 = f.read()

        doc = post_xform_to_couch(xml_data1)
        self.assertEqual("7H46J37FGH3", doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("", doc.form['vitals']['height'])
        self.assertEqual("other", doc.form['assessment']['categories'])

        doc = post_xform_to_couch(xml_data2)
        self.assertEqual("7H46J37FGH3", doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("100", doc.form['vitals']['height'])
        self.assertEqual("Edited Baby!", doc.form['assessment']['categories'])

        doc = XFormDeprecated.view('couchforms/edits', include_docs=True).first()
        self.assertEqual("7H46J37FGH3", doc.orig_id)
        self.assertNotEqual("7H46J37FGH3", doc.get_id)
        self.assertEqual(XFormDeprecated.__name__, doc.doc_type)
        self.assertEqual("", doc.form['vitals']['height'])
        self.assertEqual("other", doc.form['assessment']['categories'])
Ejemplo n.º 2
0
    def test_basic_edit(self):
        xml_data1, xml_data2 = self._get_files()

        docs = []

        doc = post_xform_to_couch(xml_data1)
        self.assertEqual(self.ID, doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("", doc.form["vitals"]["height"])
        self.assertEqual("other", doc.form["assessment"]["categories"])
        doc.domain = "test-domain"
        doc.save()

        doc = post_xform_to_couch(xml_data2, domain="test-domain")
        self.assertEqual(self.ID, doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("100", doc.form["vitals"]["height"])
        self.assertEqual("Edited Baby!", doc.form["assessment"]["categories"])

        docs.append(doc)

        doc = XFormDeprecated.view("couchforms/edits", include_docs=True).first()
        self.assertEqual(self.ID, doc.orig_id)
        self.assertNotEqual(self.ID, doc.get_id)
        self.assertEqual(XFormDeprecated.__name__, doc.doc_type)
        self.assertEqual("", doc.form["vitals"]["height"])
        self.assertEqual("other", doc.form["assessment"]["categories"])

        self.assertEqual(XFormInstance.get_db().fetch_attachment(doc.get_id, "form.xml"), xml_data1)
        self.assertEqual(XFormInstance.get_db().fetch_attachment(self.ID, "form.xml"), xml_data2)

        for doc in docs:
            doc.delete()
Ejemplo n.º 3
0
    def testBasicEdit(self):
        first_file = os.path.join(os.path.dirname(__file__), "data",
                                  "duplicate.xml")
        edit_file = os.path.join(os.path.dirname(__file__), "data", "edit.xml")

        with open(first_file, "rb") as f:
            xml_data1 = f.read()
        with open(edit_file, "rb") as f:
            xml_data2 = f.read()

        doc = post_xform_to_couch(xml_data1)
        self.assertEqual("7H46J37FGH3", doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("", doc.form['vitals']['height'])
        self.assertEqual("other", doc.form['assessment']['categories'])

        doc = post_xform_to_couch(xml_data2)
        self.assertEqual("7H46J37FGH3", doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("100", doc.form['vitals']['height'])
        self.assertEqual("Edited Baby!", doc.form['assessment']['categories'])

        doc = XFormDeprecated.view('couchforms/edits',
                                   include_docs=True).first()
        self.assertEqual("7H46J37FGH3", doc.orig_id)
        self.assertNotEqual("7H46J37FGH3", doc.get_id)
        self.assertEqual(XFormDeprecated.__name__, doc.doc_type)
        self.assertEqual("", doc.form['vitals']['height'])
        self.assertEqual("other", doc.form['assessment']['categories'])
Ejemplo n.º 4
0
 def tearDown(self):
     try:
         XFormInstance.get_db().delete_doc(self.ID)
     except ResourceNotFound:
         pass
     deprecated_xforms = XFormDeprecated.view("couchforms/edits", include_docs=True).all()
     for form in deprecated_xforms:
         form.delete()
Ejemplo n.º 5
0
 def tearDown(self):
     deprecated_xforms = XFormDeprecated.view(
         'couchforms/edits',
         include_docs=True,
     ).all()
     for form in deprecated_xforms:
         form.delete()
         pass
Ejemplo n.º 6
0
 def tearDown(self):
     deprecated_xforms = XFormDeprecated.view(
         'couchforms/edits',
         include_docs=True,
     ).all()
     for form in deprecated_xforms:
         form.delete()
         pass
Ejemplo n.º 7
0
def access_edits(**kwargs):
    return XFormDeprecated.temp_view({'map': """
        function (doc) {
            //function to reveal prior edits of xforms.
            if(doc['doc_type'] == "XFormDeprecated") {
                emit(doc.orig_id, null);
            }
        }
    """}, **kwargs)
Ejemplo n.º 8
0
 def apply_deprecation(cls, existing_xform, new_xform):
     # swap the revs
     new_xform._rev, existing_xform._rev = existing_xform._rev, new_xform._rev
     existing_xform.doc_type = XFormDeprecated.__name__
     deprecated = XFormDeprecated.wrap(existing_xform.to_json())
     assert not existing_xform.persistent_blobs, "some blobs would be lost"
     if existing_xform._deferred_blobs:
         deprecated._deferred_blobs = existing_xform._deferred_blobs.copy()
     return deprecated, new_xform
Ejemplo n.º 9
0
 def apply_deprecation(cls, existing_xform, new_xform):
     # swap the revs
     new_xform._rev, existing_xform._rev = existing_xform._rev, new_xform._rev
     existing_xform.doc_type = XFormDeprecated.__name__
     deprecated = XFormDeprecated.wrap(existing_xform.to_json())
     assert not existing_xform.persistent_blobs, "some blobs would be lost"
     if existing_xform._deferred_blobs:
         deprecated._deferred_blobs = existing_xform._deferred_blobs.copy()
     return deprecated, new_xform
Ejemplo n.º 10
0
def access_edits(**kwargs):
    return XFormDeprecated.temp_view({'map': """
        function (doc) {
            //function to reveal prior edits of xforms.
            if(doc['doc_type'] == "XFormDeprecated") {
                emit(doc.orig_id, null);
            }
        }
    """}, **kwargs)
Ejemplo n.º 11
0
 def tearDown(self):
     try:
         XFormInstance.get_db().delete_doc("7H46J37FGH3")
     except:
         pass
     deprecated_xforms = XFormDeprecated.view(
         'couchforms/edits',
         include_docs=True,
     ).all()
     for form in deprecated_xforms:
         form.delete()
Ejemplo n.º 12
0
 def tearDown(self):
     try:
         XFormInstance.get_db().delete_doc("7H46J37FGH3")
     except:
         pass
     deprecated_xforms = XFormDeprecated.view(
         'couchforms/edits',
         include_docs=True,
     ).all()
     for form in deprecated_xforms:
         form.delete()
Ejemplo n.º 13
0
    def apply_deprecation(cls, existing_xform, new_xform):
        # swap the revs
        new_xform._rev, existing_xform._rev = existing_xform._rev, new_xform._rev
        existing_xform.doc_type = XFormDeprecated.__name__
        deprecated = XFormDeprecated.wrap(existing_xform.to_json())
        assert not existing_xform.persistent_blobs, "some blobs would be lost"
        if existing_xform._deferred_blobs:
            deprecated._deferred_blobs = existing_xform._deferred_blobs.copy()

        user_id = (new_xform.auth_context and new_xform.auth_context.get('user_id')) or 'unknown'
        operation = XFormOperation(user=user_id, date=new_xform.edited_on, operation='edit')
        new_xform.history.append(operation)
        return deprecated, new_xform
Ejemplo n.º 14
0
    def apply_deprecation(cls, existing_xform, new_xform):
        # swap the revs
        new_xform._rev, existing_xform._rev = existing_xform._rev, new_xform._rev
        existing_xform.doc_type = XFormDeprecated.__name__
        deprecated = XFormDeprecated.wrap(existing_xform.to_json())
        assert not existing_xform.persistent_blobs, "some blobs would be lost"
        if existing_xform._deferred_blobs:
            deprecated._deferred_blobs = existing_xform._deferred_blobs.copy()

        user_id = (new_xform.auth_context
                   and new_xform.auth_context.get('user_id')) or 'unknown'
        operation = XFormOperation(user=user_id,
                                   date=new_xform.edited_on,
                                   operation='edit')
        new_xform.history.append(operation)
        return deprecated, new_xform
Ejemplo n.º 15
0
    def test_basic_edit(self):
        first_file = os.path.join(os.path.dirname(__file__), "data",
                                  "duplicate.xml")
        edit_file = os.path.join(os.path.dirname(__file__), "data", "edit.xml")

        with open(first_file, "rb") as f:
            xml_data1 = f.read()
        with open(edit_file, "rb") as f:
            xml_data2 = f.read()

        docs = []

        doc = post_xform_to_couch(xml_data1)
        self.assertEqual(self.ID, doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("", doc.form['vitals']['height'])
        self.assertEqual("other", doc.form['assessment']['categories'])
        doc.domain = 'test-domain'
        doc.save()

        doc = post_xform_to_couch(xml_data2, domain='test-domain')
        self.assertEqual(self.ID, doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("100", doc.form['vitals']['height'])
        self.assertEqual("Edited Baby!", doc.form['assessment']['categories'])

        docs.append(doc)

        doc = XFormDeprecated.view('couchforms/edits',
                                   include_docs=True).first()
        self.assertEqual(self.ID, doc.orig_id)
        self.assertNotEqual(self.ID, doc.get_id)
        self.assertEqual(XFormDeprecated.__name__, doc.doc_type)
        self.assertEqual("", doc.form['vitals']['height'])
        self.assertEqual("other", doc.form['assessment']['categories'])

        for doc in docs:
            doc.delete()
Ejemplo n.º 16
0
    def test_basic_edit(self):
        xml_data1, xml_data2 = self._get_files()
        yesterday = datetime.utcnow() - timedelta(days=1)
        docs = []

        doc = post_xform_to_couch(xml_data1)
        self.assertEqual(self.ID, doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("", doc.form['vitals']['height'])
        self.assertEqual("other", doc.form['assessment']['categories'])
        doc.domain = self.domain
        doc.received_on = yesterday  # set this back in time to simulate an edit
        doc.save()

        doc = post_xform_to_couch(xml_data2, domain=self.domain)
        self.assertEqual(self.ID, doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("100", doc.form['vitals']['height'])
        self.assertEqual("Edited Baby!", doc.form['assessment']['categories'])

        docs.append(doc)

        deprecated_doc = XFormDeprecated.view('couchforms/edits', include_docs=True).first()
        self.assertEqual(self.ID, deprecated_doc.orig_id)
        self.assertNotEqual(self.ID, deprecated_doc._id)
        self.assertEqual(XFormDeprecated.__name__, deprecated_doc.doc_type)
        self.assertEqual("", deprecated_doc.form['vitals']['height'])
        self.assertEqual("other", deprecated_doc.form['assessment']['categories'])

        self.assertEqual(doc.received_on, deprecated_doc.received_on)
        self.assertEqual(doc.deprecated_form_id, deprecated_doc._id)
        self.assertTrue(doc.edited_on > doc.received_on)

        self.assertEqual(XFormInstance.get_db().fetch_attachment(deprecated_doc._id, 'form.xml'), xml_data1)
        self.assertEqual(XFormInstance.get_db().fetch_attachment(self.ID, 'form.xml'), xml_data2)

        for doc in docs:
            doc.delete()
Ejemplo n.º 17
0
    def deprecate_xform(cls, existing_xform, new_xform):
        # if the form contents are not the same:
        #  - "Deprecate" the old form by making a new document with the same contents
        #    but a different ID and a doc_type of XFormDeprecated
        #  - Save the new instance to the previous document to preserve the ID

        old_id = existing_xform._id
        new_xform = cls.assign_new_id(new_xform)

        # swap the two documents so the original ID now refers to the new one
        # and mark original as deprecated
        new_xform._id, existing_xform._id = old_id, new_xform._id
        new_xform._rev, existing_xform._rev = existing_xform._rev, new_xform._rev

        # flag the old doc with metadata pointing to the new one
        existing_xform.doc_type = deprecation_type()
        existing_xform.orig_id = old_id

        # and give the new doc server data of the old one and some metadata
        new_xform.received_on = existing_xform.received_on
        new_xform.deprecated_form_id = existing_xform._id
        new_xform.edited_on = datetime.datetime.utcnow()
        return XFormDeprecated.wrap(existing_xform.to_json()), new_xform
Ejemplo n.º 18
0
    def test_basic_edit(self):
        first_file = os.path.join(os.path.dirname(__file__), "data", "duplicate.xml")
        edit_file = os.path.join(os.path.dirname(__file__), "data", "edit.xml")

        with open(first_file, "rb") as f:
            xml_data1 = f.read()
        with open(edit_file, "rb") as f:
            xml_data2 = f.read()

        docs = []

        doc = post_xform_to_couch(xml_data1)
        self.assertEqual(self.ID, doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("", doc.form['vitals']['height'])
        self.assertEqual("other", doc.form['assessment']['categories'])
        doc.domain = 'test-domain'
        doc.save()

        doc = post_xform_to_couch(xml_data2, domain='test-domain')
        self.assertEqual(self.ID, doc.get_id)
        self.assertEqual("XFormInstance", doc.doc_type)
        self.assertEqual("100", doc.form['vitals']['height'])
        self.assertEqual("Edited Baby!", doc.form['assessment']['categories'])

        docs.append(doc)

        doc = XFormDeprecated.view('couchforms/edits', include_docs=True).first()
        self.assertEqual(self.ID, doc.orig_id)
        self.assertNotEqual(self.ID, doc.get_id)
        self.assertEqual(XFormDeprecated.__name__, doc.doc_type)
        self.assertEqual("", doc.form['vitals']['height'])
        self.assertEqual("other", doc.form['assessment']['categories'])

        for doc in docs:
            doc.delete()
Ejemplo n.º 19
0
 def get_previous_versions(form_id):
     form_ = XFormDeprecated.get(form_id)
     if getattr(form_, 'deprecated_form_id', None):
         return get_previous_versions(form_.deprecated_form_id) + [form_]
     else:
         return [form_]
Ejemplo n.º 20
0
 def apply_deprecation(cls, existing_xform, new_xform):
     # swap the revs
     new_xform._rev, existing_xform._rev = existing_xform._rev, new_xform._rev
     existing_xform.doc_type = XFormDeprecated.__name__
     return XFormDeprecated.wrap(existing_xform.to_json()), new_xform
Ejemplo n.º 21
0
 def setUp(self):
     for form in XFormDeprecated.view('couchforms/edits', include_docs=True).all():
         form.delete()
Ejemplo n.º 22
0
 def setUp(self):
     for form in XFormDeprecated.view('couchforms/edits',
                                      include_docs=True).all():
         form.delete()
Ejemplo n.º 23
0
def _handle_id_conflict(instance, attachments):
    """
    For id conflicts, we check if the files contain exactly the same content,
    If they do, we just log this as a dupe. If they don't, we deprecate the 
    previous form and overwrite it with the new form's contents.
    """
    def _extract_id_from_raw_xml(xml):
        
        # this is the standard openrosa way of doing things
        parsed = etree.XML(xml)
        meta_ns = "http://openrosa.org/jr/xforms"
        val = parsed.find("{%(ns)s}meta/{%(ns)s}instanceID" % \
                          {"ns": meta_ns})
        if val is not None and val.text:
            return val.text
        
        # if we get here search more creatively for some of the older
        # formats
        _PATTERNS = (r"<instanceID>([\w-]+)</instanceID>",
                     r"<uid>([\w-]+)</uid>",
                     r"<uuid>([\w-]+)</uuid>")
        for pattern in _PATTERNS:
            if re.search(pattern, xml): 
                return re.search(pattern, xml).groups()[0]
        
        logging.error("Unable to find conflicting matched uid in form: %s" % xml)
        return ""
    
    conflict_id = _extract_id_from_raw_xml(instance)
    
    # get old document
    existing_doc = XFormInstance.get(conflict_id)

    # compare md5s
    existing_md5 = existing_doc.xml_md5()
    new_md5 = hashlib.md5(instance).hexdigest()

    # if not same:
    # Deprecate old form (including changing ID)
    # to deprecate, copy new instance into a XFormDeprecated
    if existing_md5 != new_md5:
        doc_copy = XFormInstance.get_db().copy_doc(conflict_id)
        # get the doc back to avoid any potential bigcouch race conditions.
        # r=3 implied by class
        xfd = XFormDeprecated.get(doc_copy['id'])
        xfd.orig_id = conflict_id
        xfd.doc_type=XFormDeprecated.__name__
        xfd.save()

        # after that delete the original document and resubmit.
        XFormInstance.get_db().delete_doc(conflict_id)
        return post_xform_to_couch(instance, attachments=attachments)
    else:
        # follow standard dupe handling
        new_doc_id = uid.new()
        response, errors = post_from_settings(instance, {"uid": new_doc_id})
        if not _has_errors(response, errors):
            # create duplicate doc
            # get and save the duplicate to ensure the doc types are set correctly
            # so that it doesn't show up in our reports
            dupe = XFormDuplicate.get(response)
            dupe.problem = "Form is a duplicate of another! (%s)" % conflict_id
            dupe.save()
            return dupe
        else:
            # how badly do we care about this?
            raise CouchFormException("Problem POSTing form to couch! errors/response: %s/%s" % (errors, response))
Ejemplo n.º 24
0
 def get_previous_versions(form_id):
     form_ = XFormDeprecated.get(form_id)
     if getattr(form_, 'deprecated_form_id', None):
         return get_previous_versions(form_.deprecated_form_id) + [form_]
     else:
         return [form_]
Ejemplo n.º 25
0
                return ""

            conflict_id = _extract_id_from_raw_xml(instance)
            # get old document
            existing_doc = XFormInstance.get(conflict_id)

            # compare md5s
            existing_md5 = existing_doc.xml_md5()
            new_md5 = hashlib.md5(instance).hexdigest()

            # if not same:
            # Deprecate old form (including changing ID)
            # to deprecate, copy new instance into a XFormDeprecated
            if existing_md5 != new_md5:
                doc_copy = XFormInstance.get_db().copy_doc(conflict_id)
                xfd = XFormDeprecated.get(doc_copy['id'])
                xfd.orig_id = conflict_id
                xfd.doc_type = XFormDeprecated.__name__
                xfd.save()

                # after that delete the original document and resubmit.
                XFormInstance.get_db().delete_doc(conflict_id)
                return post_xform_to_couch(instance, attachments=attachments)
            else:
                # follow standard dupe handling
                new_doc_id = uid.new()
                response, errors = post_from_settings(instance,
                                                      {"uid": new_doc_id})
                if not _has_errors(response, errors):
                    # create duplicate doc
                    # get and save the duplicate to ensure the doc types are set correctly
Ejemplo n.º 26
0
                logging.error("Unable to find conflicting matched uid in form: %s" % xml)
                return ""
            conflict_id = _extract_id_from_raw_xml(instance)
            # get old document
            existing_doc = XFormInstance.get(conflict_id)

            # compare md5s
            existing_md5 = existing_doc.xml_md5()
            new_md5 = hashlib.md5(instance).hexdigest()

            # if not same:
            # Deprecate old form (including changing ID)
            # to deprecate, copy new instance into a XFormDeprecated
            if existing_md5 != new_md5:
                doc_copy = XFormInstance.get_db().copy_doc(conflict_id)
                xfd = XFormDeprecated.get(doc_copy['id'])
                xfd.orig_id = conflict_id
                xfd.doc_type=XFormDeprecated.__name__
                xfd.save()

                # after that delete the original document and resubmit.
                XFormInstance.get_db().delete_doc(conflict_id)
                return post_xform_to_couch(instance, attachments=attachments)
            else:
                # follow standard dupe handling
                new_doc_id = uid.new()
                response, errors = post_from_settings(instance, {"uid": new_doc_id})
                if not _has_errors(response, errors):
                    # create duplicate doc
                    # get and save the duplicate to ensure the doc types are set correctly
                    # so that it doesn't show up in our reports