Example #1
0
def check_user_has_case(testcase, user, case_block, should_have=True,
                        line_by_line=True, restore_id="", version=V1):
    XMLNS = NS_VERSION_MAP.get(version, 'http://openrosa.org/http/response')
    case_block.set('xmlns', XMLNS)
    case_block = ElementTree.fromstring(ElementTree.tostring(case_block))
    payload_string = generate_restore_payload(user, restore_id, version=version)
    payload = ElementTree.fromstring(payload_string)
    
    blocks = payload.findall('{{{0}}}case'.format(XMLNS))
    def get_case_id(block):
        if version == V1:
            return block.findtext('{{{0}}}case_id'.format(XMLNS))
        else:
            return block.get('case_id')
    case_id = get_case_id(case_block)
    n = 0
    def extra_info():
        return "\n%s\n%s" % (ElementTree.tostring(case_block), map(ElementTree.tostring, blocks))
    match = None
    for block in blocks:
        if get_case_id(block) == case_id:
            if should_have:
                if line_by_line:
                    check_xml_line_by_line(testcase, ElementTree.tostring(case_block), ElementTree.tostring(block))
                match = block
                n += 1
                if n == 2:
                    testcase.fail("Block for case_id '%s' appears twice in ota restore for user '%s':%s" % (case_id, user.username, extra_info()))
            else:
                testcase.fail("User '%s' gets case '%s' but shouldn't:%s" % (user.username, case_id, extra_info()))
    if not n and should_have:
        testcase.fail("Block for case_id '%s' doesn't appear in ota restore for user '%s':%s" \
                      % (case_id, user.username, extra_info()))
    return match
Example #2
0
def check_user_has_case(testcase, user, case_blocks, should_have=True,
                        line_by_line=True, restore_id="", version=V2,
                        purge_restore_cache=False, return_single=False):

    if not isinstance(case_blocks, list):
        case_blocks = [case_blocks]
        return_single = True

    XMLNS = NS_VERSION_MAP.get(version, 'http://openrosa.org/http/response')

    if restore_id and purge_restore_cache:
        SyncLog.get(restore_id).invalidate_cached_payloads()

    restore_config = RestoreConfig(
        project=user.project,
        restore_user=user, params=RestoreParams(restore_id, version=version)
    )
    payload_string = restore_config.get_payload().as_string()
    blocks_from_restore = extract_caseblocks_from_xml(payload_string, version)

    def check_block(case_block):
        case_block.set('xmlns', XMLNS)
        case_block = RestoreCaseBlock(ElementTree.fromstring(ElementTree.tostring(case_block)), version=version)
        case_id = case_block.get_case_id()
        n = 0

        def extra_info():
            return "\n%s\n%s" % (case_block.to_string(), map(lambda b: b.to_string(), blocks_from_restore))

        match = None
        for block in blocks_from_restore:
            if block.get_case_id() == case_id:
                if should_have:
                    if line_by_line:
                        check_xml_line_by_line(
                            testcase,
                            case_block.to_string(),
                            block.to_string(),
                        )
                    match = block
                    n += 1
                    if n == 2:
                        testcase.fail(
                            "Block for case_id '%s' appears twice"
                            " in ota restore for user '%s':%s" % (case_id, user.username, extra_info())
                        )
                else:
                    testcase.fail(
                        "User '%s' gets case '%s' "
                        "but shouldn't:%s" % (user.username, case_id, extra_info())
                    )
        if not n and should_have:
            testcase.fail("Block for case_id '%s' doesn't appear in ota restore for user '%s':%s"
                          % (case_id, user.username, extra_info()))

        return match

    matches = [check_block(case_block) for case_block in case_blocks]
    return restore_config, matches[0] if return_single else matches
Example #3
0
def _check_payload_has_cases(testcase,
                             payload_string,
                             username,
                             case_blocks,
                             should_have=True,
                             line_by_line=True,
                             version=V2,
                             return_single=False,
                             restore_config=None):
    """DEPRECATED use <MockDevice>.sync().cases"""

    if not isinstance(case_blocks, list):
        case_blocks = [case_blocks]
        return_single = True

    XMLNS = NS_VERSION_MAP.get(version, 'http://openrosa.org/http/response')
    blocks_from_restore = extract_caseblocks_from_xml(payload_string, version)

    def check_block(case_block):
        case_block.set('xmlns', XMLNS)
        case_block = _RestoreCaseBlock(ElementTree.fromstring(
            ElementTree.tostring(case_block)),
                                       version=version)
        case_id = case_block.get_case_id()
        n = 0

        def extra_info():
            return "\n%s\n%s" % (case_block.to_string(),
                                 [b.to_string() for b in blocks_from_restore])

        match = None
        for block in blocks_from_restore:
            if block.get_case_id() == case_id:
                if should_have:
                    if line_by_line:
                        check_xml_line_by_line(
                            testcase,
                            case_block.to_string(),
                            block.to_string(),
                        )
                    match = block
                    n += 1
                    if n == 2:
                        testcase.fail("Block for case_id '%s' appears twice"
                                      " in ota restore for user '%s':%s" %
                                      (case_id, username, extra_info()))
                else:
                    testcase.fail("User '%s' gets case '%s' "
                                  "but shouldn't:%s" %
                                  (username, case_id, extra_info()))
        if not n and should_have:
            testcase.fail(
                "Block for case_id '%s' doesn't appear in ota restore for user '%s':%s"
                % (case_id, username, extra_info()))

        return match

    matches = [check_block(case_block) for case_block in case_blocks]
    return restore_config, matches[0] if return_single else matches
Example #4
0
def check_user_has_case(testcase, user, case_blocks, should_have=True,
                        line_by_line=True, restore_id="", version=V2,
                        purge_restore_cache=False, return_single=False):

    if not isinstance(case_blocks, list):
        case_blocks = [case_blocks]
        return_single = True

    XMLNS = NS_VERSION_MAP.get(version, 'http://openrosa.org/http/response')

    if restore_id and purge_restore_cache:
        SyncLog.get(restore_id).invalidate_cached_payloads()

    restore_config = RestoreConfig(
        project=user.project,
        restore_user=user, params=RestoreParams(restore_id, version=version)
    )
    payload_string = restore_config.get_payload().as_string()
    blocks_from_restore = extract_caseblocks_from_xml(payload_string, version)

    def check_block(case_block):
        case_block.set('xmlns', XMLNS)
        case_block = RestoreCaseBlock(ElementTree.fromstring(ElementTree.tostring(case_block)), version=version)
        case_id = case_block.get_case_id()
        n = 0

        def extra_info():
            return "\n%s\n%s" % (case_block.to_string(), map(lambda b: b.to_string(), blocks_from_restore))

        match = None
        for block in blocks_from_restore:
            if block.get_case_id() == case_id:
                if should_have:
                    if line_by_line:
                        check_xml_line_by_line(
                            testcase,
                            case_block.to_string(),
                            block.to_string(),
                        )
                    match = block
                    n += 1
                    if n == 2:
                        testcase.fail(
                            "Block for case_id '%s' appears twice"
                            " in ota restore for user '%s':%s" % (case_id, user.username, extra_info())
                        )
                else:
                    testcase.fail(
                        "User '%s' gets case '%s' "
                        "but shouldn't:%s" % (user.username, case_id, extra_info())
                    )
        if not n and should_have:
            testcase.fail("Block for case_id '%s' doesn't appear in ota restore for user '%s':%s"
                          % (case_id, user.username, extra_info()))

        return match

    matches = [check_block(case_block) for case_block in case_blocks]
    return restore_config, matches[0] if return_single else matches
Example #5
0
def check_user_has_case(testcase,
                        user,
                        case_block,
                        should_have=True,
                        line_by_line=True,
                        restore_id="",
                        version=V1,
                        caching_enabled=False):
    XMLNS = NS_VERSION_MAP.get(version, 'http://openrosa.org/http/response')
    case_block.set('xmlns', XMLNS)
    case_block = ElementTree.fromstring(ElementTree.tostring(case_block))

    payload_string = RestoreConfig(
        user, restore_id, version=version,
        caching_enabled=caching_enabled).get_payload()
    payload = ElementTree.fromstring(payload_string)

    blocks = payload.findall('{{{0}}}case'.format(XMLNS))

    def get_case_id(block):
        if version == V1:
            return block.findtext('{{{0}}}case_id'.format(XMLNS))
        else:
            return block.get('case_id')

    case_id = get_case_id(case_block)
    n = 0

    def extra_info():
        return "\n%s\n%s" % (ElementTree.tostring(case_block),
                             map(ElementTree.tostring, blocks))

    match = None
    for block in blocks:
        if get_case_id(block) == case_id:
            if should_have:
                if line_by_line:
                    check_xml_line_by_line(testcase,
                                           ElementTree.tostring(case_block),
                                           ElementTree.tostring(block))
                match = block
                n += 1
                if n == 2:
                    testcase.fail(
                        "Block for case_id '%s' appears twice in ota restore for user '%s':%s"
                        % (case_id, user.username, extra_info()))
            else:
                testcase.fail("User '%s' gets case '%s' but shouldn't:%s" %
                              (user.username, case_id, extra_info()))
    if not n and should_have:
        testcase.fail("Block for case_id '%s' doesn't appear in ota restore for user '%s':%s" \
                      % (case_id, user.username, extra_info()))
    return match
Example #6
0
def _check_payload_has_cases(testcase, payload_string, username, case_blocks, should_have=True,
                            line_by_line=True, version=V2, return_single=False, restore_config=None):
    """DEPRECATED use <MockDevice>.sync().cases"""

    if not isinstance(case_blocks, list):
        case_blocks = [case_blocks]
        return_single = True

    XMLNS = NS_VERSION_MAP.get(version, 'http://openrosa.org/http/response')
    blocks_from_restore = extract_caseblocks_from_xml(payload_string, version)

    def check_block(case_block):
        case_block.set('xmlns', XMLNS)
        case_block = _RestoreCaseBlock(ElementTree.fromstring(ElementTree.tostring(case_block)), version=version)
        case_id = case_block.get_case_id()
        n = 0

        def extra_info():
            return "\n%s\n%s" % (case_block.to_string(), [b.to_string() for b in blocks_from_restore])

        match = None
        for block in blocks_from_restore:
            if block.get_case_id() == case_id:
                if should_have:
                    if line_by_line:
                        check_xml_line_by_line(
                            testcase,
                            case_block.to_string(),
                            block.to_string(),
                        )
                    match = block
                    n += 1
                    if n == 2:
                        testcase.fail(
                            "Block for case_id '%s' appears twice"
                            " in ota restore for user '%s':%s" % (case_id, username, extra_info())
                        )
                else:
                    testcase.fail(
                        "User '%s' gets case '%s' "
                        "but shouldn't:%s" % (username, case_id, extra_info())
                    )
        if not n and should_have:
            testcase.fail("Block for case_id '%s' doesn't appear in ota restore for user '%s':%s"
                          % (case_id, username, extra_info()))

        return match

    matches = [check_block(case_block) for case_block in case_blocks]
    return restore_config, matches[0] if return_single else matches
Example #7
0
def get_case_xmlns(version):
    return NS_VERSION_MAP.get(version, 'http://openrosa.org/http/response')
Example #8
0
    def __init__(self,
            case_id,
            date_modified=None,
            user_id=undefined,
            owner_id=undefined,
            external_id=undefined,
            case_type=undefined,
            case_name=undefined,
            create=False,
            date_opened=undefined,
            update=None,
            close=False,
            # V2 only
            index=None,
            version=V1,
            compatibility_mode=False,
        ):
        """
        From https://bitbucket.org/javarosa/javarosa/wiki/casexml

        <case>
            <case_id/>        <-- Exactly One: The id of the abstract case to be modified (even in the case of creation)
            <date_modified/>  <-- Exactly One: The date of this operation

            <create>         <-- At Most One: Create action
                <case_type_id/>             <-- Exactly One: The ID for the type of case represented
                <user_id/>                  <-- At Most One: The ID for a user who created the case
                <case_name/>                <-- Exactly One: A semantically meaningless but human readable name associated with the case
                <external_id/>              <-- Exactly One: The soft id associated with this record. Generally based on another system's id for this record.
            </create>

            <update/>         <-- At Most One: Updates data for the case
                <case_type_id/>             <-- At Most One: Modifies the Case Type for the case
                <case_name/>                <-- At Most One: A semantically meaningless but human readable name associated with the case
                <date_opened/>              <-- At Most One: Modifies the Date the case was opened
                <*/>                        <-- An Arbitrary Number: Creates or mutates a value identified by the key provided
            </update>

            <close/>          <-- At Most One: Closes the case

        </case>

        https://github.com/dimagi/commcare/wiki/casexml20

        <case xmlns="http://commcarehq.org/case/transaction/v2" case_id="" user_id="" date_modified="" >
            <!-- user_id - At Most One: the GUID of the user responsible for this transaction -->
            <!-- case_id - Exactly One: The id of the abstract case to be modified (even in the case of creation) -->
            <!-- date_modified - Exactly One: The date and time of this operation -->
            <create>         <!-- At Most One: Create action -->
                <case_type/>             <!-- Exactly One: The ID for the type of case represented -->
                <owner_id/>                 <!-- At Most One: The GUID of the current owner of this case -->
                <case_name/>                <!-- Exactly One: A semantically meaningless but human readable name associated with the case -->
            </create>
            <update>         <!-- At Most One: Updates data for the case -->
                <case_type/>             <!-- At Most One: Modifies the Case Type for the case -->
                <case_name/>                <!-- At Most One: A semantically meaningless but human  readable name associated with the case -->
                <date_opened/>              <!-- At Most One: Modifies the Date the case was opened -->
                <owner_id/>                 <!-- At Most One: Modifies the owner of this case -->
                <*/>                        <-- An Arbitrary Number: Creates or mutates a value  identified by the key provided -->
            </update>
            <index/>          <!-- At Most One: Contains a set of referenced GUID's to other cases -->
            <close/>          <!-- At Most One: Closes the case -->
         </case>

        """
        super(CaseBlock, self).__init__()
        self._id = case_id
        date_modified = date_modified or datetime.utcnow()
        update = copy.copy(update) if update else {}
        index = copy.copy(index) if index else {}

        self.XMLNS = NS_VERSION_MAP.get(version)

        if version == V1:
            self.VERSION = V1
            self.CASE_TYPE = "case_type_id"
        elif version == V2:
            self.VERSION = V2
            self.CASE_TYPE = "case_type"
        else:
            raise CaseBlockError("Case XML version must be %s or %s" % (V1, V2))

        if create:
            self['create'] = {}
            # make case_type
            case_type = "" if case_type is CaseBlock.undefined else case_type
            case_name = "" if case_name is CaseBlock.undefined else case_name
            if version == V2:
                owner_id = "" if owner_id is CaseBlock.undefined else owner_id
        self['update'] = update
        self['update'].update({
            'date_opened':                  date_opened
        })
        create_or_update = {
            self.CASE_TYPE:                 case_type,
            'case_name':                    case_name,
        }

        # what to do with case_id, date_modified, user_id, and owner_id, external_id
        if version == V1:
            self.update({
                'case_id':                  case_id, # V1
                'date_modified':            date_modified, # V1
            })
            if create:
                self['create'].update({
                    'user_id':              user_id, # V1
                })
            else:
                if not compatibility_mode and user_id is not CaseBlock.undefined:
                    CaseBlockError("CaseXML V1: You only set user_id when creating a case")
            self['update'].update({
                'owner_id':                 owner_id, # V1
            })
            create_or_update.update({
                'external_id':              external_id # V1
            })
        else:
            self.update({
                '_attrib': {
                    'case_id':              case_id, # V2
                    'date_modified':        date_modified, # V2
                    'user_id':              user_id, # V2
                    'xmlns':                self.XMLNS,
                }
            })
            create_or_update.update({
                'owner_id':                 owner_id, # V2
            })
            self['update'].update({
                'external_id':              external_id, # V2
            })


        # fail if user specifies both, say, case_name='Johnny' and update={'case_name': 'Johnny'}
        for key in create_or_update:
            if create_or_update[key] is not CaseBlock.undefined and self['update'].has_key(key):
                raise CaseBlockError("Key %r specified twice" % key)

        if create:
            self['create'].update(create_or_update)
        else:
            self['update'].update(create_or_update)


        if close:
            self['close'] = {}

        if not ['' for val in self['update'].values() if val is not CaseBlock.undefined]:
                self['update'] = CaseBlock.undefined
        if index and version == V2:
            self['index'] = {}
            for name, (case_type, case_id) in index.items():
                self['index'][name] = {
                    '_attrib': {
                        'case_type': case_type
                    },
                    '_text': case_id
                }
Example #9
0
    def __init__(
        self,
        case_id,
        date_modified=None,
        user_id=undefined,
        owner_id=undefined,
        external_id=undefined,
        case_type=undefined,
        case_name=undefined,
        create=False,
        date_opened=undefined,
        update=None,
        close=False,
        # referrals currently not supported
        # V2 only
        index=None,
        version=V1,
        compatibility_mode=False,
    ):
        """
        From https://bitbucket.org/javarosa/javarosa/wiki/casexml

        <case>
            <case_id/>        <-- Exactly One: The id of the abstract case to be modified (even in the case of creation)
            <date_modified/>  <-- Exactly One: The date of this operation

            <create>         <-- At Most One: Create action
                <case_type_id/>             <-- Exactly One: The ID for the type of case represented
                <user_id/>                  <-- At Most One: The ID for a user who created the case
                <case_name/>                <-- Exactly One: A semantically meaningless but human readable name associated with the case
                <external_id/>              <-- Exactly One: The soft id associated with this record. Generally based on another system's id for this record.
            </create>

            <update/>         <-- At Most One: Updates data for the case
                <case_type_id/>             <-- At Most One: Modifies the Case Type for the case
                <case_name/>                <-- At Most One: A semantically meaningless but human readable name associated with the case
                <date_opened/>              <-- At Most One: Modifies the Date the case was opened
                <*/>                        <-- An Arbitrary Number: Creates or mutates a value identified by the key provided
            </update>

            <close/>          <-- At Most One: Closes the case

#            <referral>       <-- At Most One: Referral actions
#                <referral_id/>              <-- Exactly One: The unique ID. No two referrals should be open with both the same referral_id and referral_type
#                <followup_date/>            <-- At Most One: The due date for all followups referenced in this action
#                <open>
#                    <referral_types/>       <-- Exactly One: A space separated list of referral types which should be opened.
#                </open>
#                <update>
#                    <referral_type/>        <-- Exactly One: The referral type to be changed
#                    <date_closed/>          <-- At Most One: The date the referral was closed. If this element exists, the abstract referral matching the referral_id and referral_type should be closed.
#                </update>
#            </referral>
        </case>

        https://bitbucket.org/commcare/commcare/wiki/casexml20

        <case xmlns="http://commcarehq.org/case/transaction/v2" case_id="" user_id="" date_modified="" >
            <!-- user_id - At Most One: the GUID of the user responsible for this transaction -->
            <!-- case_id - Exactly One: The id of the abstract case to be modified (even in the case of creation) -->
            <!-- date_modified - Exactly One: The date and time of this operation -->
            <create>         <!-- At Most One: Create action -->
                <case_type/>             <!-- Exactly One: The ID for the type of case represented -->
                <owner_id/>                 <!-- At Most One: The GUID of the current owner of this case -->
                <case_name/>                <!-- Exactly One: A semantically meaningless but human readable name associated with the case -->
            </create>
            <update>         <!-- At Most One: Updates data for the case -->
                <case_type/>             <!-- At Most One: Modifies the Case Type for the case -->
                <case_name/>                <!-- At Most One: A semantically meaningless but human  readable name associated with the case -->
                <date_opened/>              <!-- At Most One: Modifies the Date the case was opened -->
                <owner_id/>                 <!-- At Most One: Modifies the owner of this case -->
                <*/>                        <-- An Arbitrary Number: Creates or mutates a value  identified by the key provided -->
            </update>
            <index/>          <!-- At Most One: Contains a set of referenced GUID's to other cases -->
            <close/>          <!-- At Most One: Closes the case -->
         </case>

        """
        super(CaseBlock, self).__init__()
        self._id = case_id
        date_modified = date_modified or datetime.utcnow()
        update = copy.copy(update) if update else {}
        index = copy.copy(index) if index else {}

        self.XMLNS = NS_VERSION_MAP.get(version)

        if version == V1:
            self.VERSION = V1
            self.CASE_TYPE = "case_type_id"
        elif version == V2:
            self.VERSION = V2
            self.CASE_TYPE = "case_type"
        else:
            raise CaseBlockError("Case XML version must be %s or %s" %
                                 (V1, V2))

        if create:
            self['create'] = {}
            # make case_type
            case_type = "" if case_type is CaseBlock.undefined else case_type
            case_name = "" if case_name is CaseBlock.undefined else case_name
            if version == V2:
                owner_id = "" if owner_id is CaseBlock.undefined else owner_id
        self['update'] = update
        self['update'].update({'date_opened': date_opened})
        create_or_update = {
            self.CASE_TYPE: case_type,
            'case_name': case_name,
        }

        # what to do with case_id, date_modified, user_id, and owner_id, external_id
        if version == V1:
            self.update({
                'case_id': case_id,  # V1
                'date_modified': date_modified,  # V1
            })
            if create:
                self['create'].update({
                    'user_id': user_id,  # V1
                })
            else:
                if not compatibility_mode and user_id is not CaseBlock.undefined:
                    CaseBlockError(
                        "CaseXML V1: You only set user_id when creating a case"
                    )
            self['update'].update({
                'owner_id': owner_id,  # V1
            })
            create_or_update.update({
                'external_id': external_id  # V1
            })
        else:
            self.update({
                '_attrib': {
                    'case_id': case_id,  # V2
                    'date_modified': date_modified,  # V2
                    'user_id': user_id,  # V2
                    'xmlns': self.XMLNS,
                }
            })
            create_or_update.update({
                'owner_id': owner_id,  # V2
            })
            self['update'].update({
                'external_id': external_id,  # V2
            })

        # fail if user specifies both, say, case_name='Johnny' and update={'case_name': 'Johnny'}
        for key in create_or_update:
            if create_or_update[key] is not CaseBlock.undefined and self[
                    'update'].has_key(key):
                raise CaseBlockError("Key %r specified twice" % key)

        if create:
            self['create'].update(create_or_update)
        else:
            self['update'].update(create_or_update)

        if close:
            self['close'] = {}

        if not [
                '' for val in self['update'].values()
                if val is not CaseBlock.undefined
        ]:
            self['update'] = CaseBlock.undefined
        if index and version == V2:
            self['index'] = {}
            for name, (case_type, case_id) in index.items():
                self['index'][name] = {
                    '_attrib': {
                        'case_type': case_type
                    },
                    '_text': case_id
                }
Example #10
0
def check_user_has_case(testcase, user, case_blocks, should_have=True,
                        line_by_line=True, restore_id="", version=V1,
                        purge_restore_cache=False, return_single=False):

    if not isinstance(case_blocks, list):
        case_blocks = [case_blocks]
        return_single = True

    XMLNS = NS_VERSION_MAP.get(version, 'http://openrosa.org/http/response')

    if restore_id and purge_restore_cache:
        SyncLog.get(restore_id).invalidate_cached_payloads()
    restore_config = RestoreConfig(user, restore_id, version=version)
    payload_string = restore_config.get_payload().as_string()
    payload = ElementTree.fromstring(payload_string)

    blocks = payload.findall('{{{0}}}case'.format(XMLNS))

    def get_case_id(block):
        if version == V1:
            return block.findtext('{{{0}}}case_id'.format(XMLNS))
        else:
            return block.get('case_id')

    def check_block(case_block):
        case_block.set('xmlns', XMLNS)
        case_block = ElementTree.fromstring(ElementTree.tostring(case_block))
        case_id = get_case_id(case_block)
        n = 0

        def extra_info():
            return "\n%s\n%s" % (ElementTree.tostring(case_block), map(ElementTree.tostring, blocks))
        match = None
        for block in blocks:
            if get_case_id(block) == case_id:
                if should_have:
                    if line_by_line:
                        check_xml_line_by_line(
                            testcase,
                            ElementTree.tostring(case_block),
                            ElementTree.tostring(block)
                        )
                    match = block
                    n += 1
                    if n == 2:
                        testcase.fail(
                            "Block for case_id '%s' appears twice"
                            " in ota restore for user '%s':%s" % (case_id, user.username, extra_info())
                        )
                else:
                    testcase.fail(
                        "User '%s' gets case '%s' "
                        "but shouldn't:%s" % (user.username, case_id, extra_info())
                    )
        if not n and should_have:
            testcase.fail("Block for case_id '%s' doesn't appear in ota restore for user '%s':%s"
                          % (case_id, user.username, extra_info()))

        return match

    matches = [check_block(case_block) for case_block in case_blocks]
    return restore_config, matches[0] if return_single else matches
Example #11
0
    def __init__(
        self,
        case_id,
        date_modified=None,
        user_id=undefined,
        owner_id=undefined,
        external_id=undefined,
        case_type=undefined,
        case_name=undefined,
        create=False,
        date_opened=undefined,
        update=None,
        close=False,
        index=None,
        strict=True,
    ):
        """
        https://github.com/dimagi/commcare/wiki/casexml20

        <case xmlns="http://commcarehq.org/case/transaction/v2" case_id="" user_id="" date_modified="" >
            <!-- user_id - At Most One: the GUID of the user responsible for this transaction -->
            <!-- case_id - Exactly One: The id of the abstract case to be modified (even in the case of creation) -->
            <!-- date_modified - Exactly One: The date and time of this operation -->
            <create>         <!-- At Most One: Create action -->
                <case_type/>             <!-- Exactly One: The ID for the type of case represented -->
                <owner_id/>                 <!-- At Most One: The GUID of the current owner of this case -->
                <case_name/>                <!-- Exactly One: A semantically meaningless but human readable name associated with the case -->
            </create>
            <update>         <!-- At Most One: Updates data for the case -->
                <case_type/>             <!-- At Most One: Modifies the Case Type for the case -->
                <case_name/>                <!-- At Most One: A semantically meaningless but human  readable name associated with the case -->
                <date_opened/>              <!-- At Most One: Modifies the Date the case was opened -->
                <owner_id/>                 <!-- At Most One: Modifies the owner of this case -->
                <*/>                        <-- An Arbitrary Number: Creates or mutates a value  identified by the key provided -->
            </update>
            <index/>          <!-- At Most One: Contains a set of referenced GUID's to other cases -->
            <close/>          <!-- At Most One: Closes the case -->
         </case>

        """
        super(CaseBlock, self).__init__()
        self._id = case_id
        now = datetime.utcnow()
        date_modified = date_modified or now
        if date_opened == CaseBlock.undefined and create:
            date_opened = now.date()
        update = copy.copy(update) if update else {}
        index = copy.copy(index) if index else {}

        self.XMLNS = NS_VERSION_MAP.get(V2)

        self.VERSION = V2
        self.CASE_TYPE = "case_type"

        if create:
            self['create'] = {}
            # make case_type
            case_type = "" if case_type is CaseBlock.undefined else case_type
            case_name = "" if case_name is CaseBlock.undefined else case_name
            owner_id = "" if owner_id is CaseBlock.undefined else owner_id
        self['update'] = update

        create_or_update = {
            self.CASE_TYPE: case_type,
            'case_name': case_name,
        }

        self.update({
            '_attrib': {
                'case_id': case_id,
                'date_modified': date_modified,
                'user_id': user_id,
                'xmlns': self.XMLNS,
            }
        })
        if owner_id is not None:
            create_or_update.update({
                'owner_id': owner_id,
            })
        self['update'].update({
            'external_id': external_id,
            'date_opened': date_opened,
        })

        # fail if user specifies both, say, case_name='Johnny' and update={'case_name': 'Johnny'}
        if strict:
            for key in create_or_update:
                if create_or_update[
                        key] is not CaseBlock.undefined and key in self[
                            'update']:
                    raise CaseBlockError("Key %r specified twice" % key)

        create_or_update = {
            key: val
            for key, val in create_or_update.items()
            if val is not CaseBlock.undefined
        }
        if create:
            self['create'].update(create_or_update)
        else:
            self['update'].update(create_or_update)

        if close:
            self['close'] = {}

        if not [
                '' for val in self['update'].values()
                if val is not CaseBlock.undefined
        ]:
            self['update'] = CaseBlock.undefined
        if index:
            self['index'] = {}
            for name in index.keys():
                case_type = index[name][0]
                case_id = index[name][1]
                # relationship = "child" for index to a parent case (default)
                # relationship = "extension" for index to a host case
                relationship = index[name][2] if len(
                    index[name]) > 2 else 'child'
                if relationship not in ('child', 'extension'):
                    raise CaseBlockError(
                        'Valid values for an index relationship are "child" and "extension"'
                    )
                _attrib = {'case_type': case_type}
                if relationship != 'child':
                    _attrib['relationship'] = relationship
                self['index'][name] = {'_attrib': _attrib, '_text': case_id}
Example #12
0
def get_case_xmlns(version):
    return NS_VERSION_MAP.get(version, 'http://openrosa.org/http/response')
Example #13
0
    def __init__(self,
            case_id,
            date_modified=None,
            user_id=undefined,
            owner_id=undefined,
            external_id=undefined,
            case_type=undefined,
            case_name=undefined,
            create=False,
            date_opened=undefined,
            update=None,
            close=False,
            index=None,
            strict=True,
        ):
        """
        https://github.com/dimagi/commcare/wiki/casexml20

        <case xmlns="http://commcarehq.org/case/transaction/v2" case_id="" user_id="" date_modified="" >
            <!-- user_id - At Most One: the GUID of the user responsible for this transaction -->
            <!-- case_id - Exactly One: The id of the abstract case to be modified (even in the case of creation) -->
            <!-- date_modified - Exactly One: The date and time of this operation -->
            <create>         <!-- At Most One: Create action -->
                <case_type/>             <!-- Exactly One: The ID for the type of case represented -->
                <owner_id/>                 <!-- At Most One: The GUID of the current owner of this case -->
                <case_name/>                <!-- Exactly One: A semantically meaningless but human readable name associated with the case -->
            </create>
            <update>         <!-- At Most One: Updates data for the case -->
                <case_type/>             <!-- At Most One: Modifies the Case Type for the case -->
                <case_name/>                <!-- At Most One: A semantically meaningless but human  readable name associated with the case -->
                <date_opened/>              <!-- At Most One: Modifies the Date the case was opened -->
                <owner_id/>                 <!-- At Most One: Modifies the owner of this case -->
                <*/>                        <-- An Arbitrary Number: Creates or mutates a value  identified by the key provided -->
            </update>
            <index/>          <!-- At Most One: Contains a set of referenced GUID's to other cases -->
            <close/>          <!-- At Most One: Closes the case -->
         </case>

        """
        super(CaseBlock, self).__init__()
        self._id = case_id
        date_modified = date_modified or datetime.utcnow()
        update = copy.copy(update) if update else {}
        index = copy.copy(index) if index else {}

        self.XMLNS = NS_VERSION_MAP.get(V2)

        self.VERSION = V2
        self.CASE_TYPE = "case_type"

        if create:
            self['create'] = {}
            # make case_type
            case_type = "" if case_type is CaseBlock.undefined else case_type
            case_name = "" if case_name is CaseBlock.undefined else case_name
            owner_id = "" if owner_id is CaseBlock.undefined else owner_id
        self['update'] = update
        self['update'].update({
            'date_opened':                  date_opened
        })
        create_or_update = {
            self.CASE_TYPE:                 case_type,
            'case_name':                    case_name,
        }

        self.update({
            '_attrib': {
                'case_id':              case_id,
                'date_modified':        date_modified,
                'user_id':              user_id,
                'xmlns':                self.XMLNS,
            }
        })
        if owner_id is not None:
            create_or_update.update({
                'owner_id':                 owner_id,
            })
        self['update'].update({
            'external_id':              external_id,
        })

        # fail if user specifies both, say, case_name='Johnny' and update={'case_name': 'Johnny'}
        if strict:
            for key in create_or_update:
                if create_or_update[key] is not CaseBlock.undefined and key in self['update']:
                    raise CaseBlockError("Key %r specified twice" % key)

        if create:
            self['create'].update(create_or_update)
        else:
            self['update'].update(create_or_update)

        if close:
            self['close'] = {}

        if not ['' for val in self['update'].values() if val is not CaseBlock.undefined]:
                self['update'] = CaseBlock.undefined
        if index:
            self['index'] = {}
            for name in index.keys():
                case_type = index[name][0]
                case_id = index[name][1]
                # relationship = "child" for index to a parent case (default)
                # relationship = "extension" for index to a host case
                relationship = index[name][2] if len(index[name]) > 2 else 'child'
                if relationship not in ('child', 'extension'):
                    raise CaseBlockError('Valid values for an index relationship are "child" and "extension"')
                _attrib = {'case_type': case_type}
                if relationship != 'child':
                    _attrib['relationship'] = relationship
                self['index'][name] = {
                    '_attrib': _attrib,
                    '_text': case_id
                }