<commit_before># -*- coding: utf-8 -*-
"""
Survey module with XForm Survey objects and utility functions.
"""
from __future__ import print_function

import codecs
import os
import re
import tempfile
import xml.etree.ElementTree as ETree
from collections import defaultdict
from datetime import datetime

from pyxform import constants
from pyxform.errors import PyXFormError, ValidationError
from pyxform.external_instance import ExternalInstance
from pyxform.instance import SurveyInstance
from pyxform.instance_info import InstanceInfo
from pyxform.question import Question
from pyxform.section import Section
from pyxform.survey_element import SurveyElement
from pyxform.utils import (
    NSMAP,
    PatchedText,
    basestring,
    get_languages_with_bad_tags,
    node,
    unicode,
)
from pyxform.validators import enketo_validate, odk_validate

try:
    from functools import lru_cache
except ImportError:
    from functools32 import lru_cache

LAST_SAVED_INSTANCE_NAME = "__last-saved"
BRACKETED_TAG_REGEX = re.compile(r"\${(last-saved#)?(.*?)}")
LAST_SAVED_REGEX = re.compile(r"\${last-saved#(.*?)}")


def register_nsmap():
    """Function to register NSMAP namespaces with ETree"""
    for prefix, uri in NSMAP.items():
        prefix_no_xmlns = prefix.replace("xmlns", "").replace(":", "")
        ETree.register_namespace(prefix_no_xmlns, uri)


register_nsmap()


@lru_cache(maxsize=None)
def is_parent_a_repeat(survey, xpath):
    """
    Returns the XPATH of the first repeat of the given xpath in the survey,
    otherwise False will be returned.
    """
    parent_xpath = "/".join(xpath.split("/")[:-1])
    if not parent_xpath:
        return False

    if survey.any_repeat(parent_xpath):
        return parent_xpath

    return is_parent_a_repeat(survey, parent_xpath)


@lru_cache(maxsize=None)
def share_same_repeat_parent(survey, xpath, context_xpath):
    """
    Returns a tuple of the number of steps from the context xpath to the shared
    repeat parent and the xpath to the target xpath from the shared repeat
    parent.

    For example,
        xpath = /data/repeat_a/group_a/name
        context_xpath = /data/repeat_a/group_b/age

        returns (2, '/group_a/name')'
    """
    context_parent = is_parent_a_repeat(survey, context_xpath)
    xpath_parent = is_parent_a_repeat(survey, xpath)
    if context_parent and xpath_parent and xpath_parent in context_parent:
        context_parts = context_xpath[len(xpath_parent) + 1 :].split("/")
        parts = []
        steps = 1
        remainder_xpath = xpath[len(xpath_parent) :]
        xpath_parts = xpath[len(xpath_parent) + 1 :].split("/")
        for index, item in enumerate(context_parts[:-1]):
            try:
                if xpath[len(context_parent) + 1 :].split("/")[index] != item:
                    steps = len(context_parts[index:])
                    parts = xpath_parts[index:]
                    break
                else:
                    parts = remainder_xpath.split("/")[index + 2 :]
            except IndexError:
                steps = len(context_parts[index - 1 :])
                parts = xpath_parts[index - 1 :]
                break

        return (steps, "/" + "/".join(parts) if parts else remainder_xpath)
<commit_msg>Check if xpath_parent and context_parent share a common repeat ancestor<commit_after># -*- coding: utf-8 -*-
"""
Survey module with XForm Survey objects and utility functions.
"""
from __future__ import print_function

import codecs
import os
import re
import tempfile
import xml.etree.ElementTree as ETree
from collections import defaultdict
from datetime import datetime

from pyxform import constants
from pyxform.errors import PyXFormError, ValidationError
from pyxform.external_instance import ExternalInstance
from pyxform.instance import SurveyInstance
from pyxform.instance_info import InstanceInfo
from pyxform.question import Question
from pyxform.section import Section
from pyxform.survey_element import SurveyElement
from pyxform.utils import (
    NSMAP,
    PatchedText,
    basestring,
    get_languages_with_bad_tags,
    node,
    unicode,
)
from pyxform.validators import enketo_validate, odk_validate

try:
    from functools import lru_cache
except ImportError:
    from functools32 import lru_cache

LAST_SAVED_INSTANCE_NAME = "__last-saved"
BRACKETED_TAG_REGEX = re.compile(r"\${(last-saved#)?(.*?)}")
LAST_SAVED_REGEX = re.compile(r"\${last-saved#(.*?)}")


def register_nsmap():
    """Function to register NSMAP namespaces with ETree"""
    for prefix, uri in NSMAP.items():
        prefix_no_xmlns = prefix.replace("xmlns", "").replace(":", "")
        ETree.register_namespace(prefix_no_xmlns, uri)


register_nsmap()


@lru_cache(maxsize=None)
def is_parent_a_repeat(survey, xpath):
    """
    Returns the XPATH of the first repeat of the given xpath in the survey,
    otherwise False will be returned.
    """
    parent_xpath = "/".join(xpath.split("/")[:-1])
    if not parent_xpath:
        return False

    if survey.any_repeat(parent_xpath):
        return parent_xpath

    return is_parent_a_repeat(survey, parent_xpath)


@lru_cache(maxsize=None)
def share_same_repeat_parent(survey, xpath, context_xpath):
    """
    Returns a tuple of the number of steps from the context xpath to the shared
    repeat parent and the xpath to the target xpath from the shared repeat
    parent.

    For example,
        xpath = /data/repeat_a/group_a/name
        context_xpath = /data/repeat_a/group_b/age

        returns (2, '/group_a/name')'
    """

    def _get_steps_and_target_xpath(context_parent, xpath_parent):
        context_parts = context_xpath[len(xpath_parent) + 1 :].split("/")
        parts = []
        steps = 1
        remainder_xpath = xpath[len(xpath_parent) :]
        xpath_parts = xpath[len(xpath_parent) + 1 :].split("/")
        for index, item in enumerate(context_parts[:-1]):
            try:
                if xpath[len(context_parent) + 1 :].split("/")[index] != item:
                    steps = len(context_parts[index:])
                    parts = xpath_parts[index:]
                    break
                else:
                    parts = remainder_xpath.split("/")[index + 2 :]
            except IndexError:
                steps = len(context_parts[index - 1 :])
                parts = xpath_parts[index - 1 :]
                break
        return (steps, "/" + "/".join(parts) if parts else remainder_xpath)

    context_parent = is_parent_a_repeat(survey, context_xpath)
    xpath_parent = is_parent_a_repeat(survey, xpath)
    if context_parent and xpath_parent and xpath_parent in context_parent:
        return _get_steps_and_target_xpath(context_parent, xpath_parent)
    elif context_parent and xpath_parent:
        # Check if context_parent and xpath_parent share a common
        # repeat ancestor
        context_shared_ancestor = is_parent_a_repeat(survey, context_parent)
        xpath_shared_ancestor = is_parent_a_repeat(survey, xpath_parent)

        if (
            xpath_shared_ancestor
            and context_shared_ancestor
            and xpath_shared_ancestor == context_shared_ancestor
        ):
            return _get_steps_and_target_xpath(
                context_shared_ancestor, xpath_shared_ancestor
            )

{'fraction_non_alphanumeric': 0.09043430456294667, 'fraction_numerical': 0.0035733919736118747, 'mean_word_length': 3.0951041080472708, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2437827', 'n_tokens_mistral': 2273, 'n_tokens_neox': 2219, 'n_words': 572}