<commit_before>import os
from copy import copy
from .base import AnnotatedNineMLObject
from nineml.xml import (
    E, ALL_NINEML, unprocessed_xml, get_xml_attr, extract_xmlns, NINEMLv1)
from nineml.annotations import read_annotations
from nineml.exceptions import NineMLRuntimeError, NineMLXMLAttributeError
from nineml.exceptions import NineMLNameError


class BaseReference(AnnotatedNineMLObject):

    """
    Base class for references to model components that are defined in the
    abstraction layer.
    """

    defining_attributes = ('url', '_referred_to')

    def __init__(self, name, document, url=None):
        super(BaseReference, self).__init__()
        document_url = document.url if document is not None else None
        if url is not None and url != document_url:
            if url.startswith('.'):
                if document_url is None:
                    raise NineMLRuntimeError(
                        "Must supply a document with a non-None URL that is "
                        "being referenced from if definition is a relative URL"
                        " string, '{}'".format(url))
                relative_to = os.path.dirname(document.url)
            else:
                relative_to = None
            remote_doc = read(url, relative_to=relative_to)
        else:
            remote_doc = document
        self._referred_to = remote_doc[name]

    @property
    def url(self):
        return self._referred_to.url

    @property
    def key(self):
        return (self._referred_to.key +
                self.url if self.url is not None else '')

    def equals(self, other, **kwargs):
        """
        Parameters
        ----------
        other : BaseReference
            The other object to determine equality with
        ignore_none_urls : bool
            A bit of a hack to ignore urls that are None (i.e. defined inline)
            during unittesting.
        """
        if not isinstance(other, self.__class__):
            return False
        return (self._referred_to == other._referred_to and
                self.url == other.url and
                self.annotations_equal(other, **kwargs))

    def __hash__(self):
        return (hash(self.__class__) ^ hash(self._referred_to.name) ^
                hash(self.url))

    def __repr__(self):
            return ('{}(name="{}"{})'
                    .format(self.__class__.__name__, self._referred_to.name,
                            ' in "{}"'.format(self.url) if self.url else ''))

    def to_xml(self, document, E=E, **kwargs):  # @UnusedVariable
        name = self._referred_to.name
        if E._namespace == NINEMLv1:
            attrs = {}
            body = [name]
        else:
            attrs = {'name': name}
            body = []
        if self.url is not None and self.url != document.url:
            attrs['url'] = self.url
        element = E(self.nineml_type, *body, **attrs)
        return element

    @classmethod
    @read_annotations
    @unprocessed_xml
    def from_xml(cls, element, document, **kwargs):  # @UnusedVariable
        xmlns = extract_xmlns(element.tag)
        if xmlns == NINEMLv1:
            name = element.text
            if name is None:
                raise NineMLXMLAttributeError(
                    "References require the element name provided in the XML "
                    "element text")
        else:
            name = get_xml_attr(element, 'name', document, **kwargs)
        url = get_xml_attr(element, 'url', document, default=None, **kwargs)
        return cls(name=name, document=document, url=url)

    def serialize_node(self, node, **options):  # @UnusedVariable
        name = self._referred_to.name
        if node.later_version('2.0', equal=True):
            node.attr('name', name)
        else:
            node.body(name)
        if self.url is not None and self.url != node.document.url:
            node.attr('url', self.url)

    @classmethod
    def unserialize_node(cls, node, **options):  # @UnusedVariable
        if node.later_version('2.0', equal=True):
            name = node.attr('name')
        else:
            name = node.body()
        url = node.attr('url', default=None)
        return cls(name=name, document=node.document, url=url)


class Reference(BaseReference):
    """<commit_msg>specified that reference body should not be sole<commit_after>import os
from copy import copy
from .base import AnnotatedNineMLObject
from nineml.xml import (
    E, ALL_NINEML, unprocessed_xml, get_xml_attr, extract_xmlns, NINEMLv1)
from nineml.annotations import read_annotations
from nineml.exceptions import NineMLRuntimeError, NineMLXMLAttributeError
from nineml.exceptions import NineMLNameError


class BaseReference(AnnotatedNineMLObject):

    """
    Base class for references to model components that are defined in the
    abstraction layer.
    """

    defining_attributes = ('url', '_referred_to')

    def __init__(self, name, document, url=None):
        super(BaseReference, self).__init__()
        document_url = document.url if document is not None else None
        if url is not None and url != document_url:
            if url.startswith('.'):
                if document_url is None:
                    raise NineMLRuntimeError(
                        "Must supply a document with a non-None URL that is "
                        "being referenced from if definition is a relative URL"
                        " string, '{}'".format(url))
                relative_to = os.path.dirname(document.url)
            else:
                relative_to = None
            remote_doc = read(url, relative_to=relative_to)
        else:
            remote_doc = document
        self._referred_to = remote_doc[name]

    @property
    def url(self):
        return self._referred_to.url

    @property
    def key(self):
        return (self._referred_to.key +
                self.url if self.url is not None else '')

    def equals(self, other, **kwargs):
        """
        Parameters
        ----------
        other : BaseReference
            The other object to determine equality with
        ignore_none_urls : bool
            A bit of a hack to ignore urls that are None (i.e. defined inline)
            during unittesting.
        """
        if not isinstance(other, self.__class__):
            return False
        return (self._referred_to == other._referred_to and
                self.url == other.url and
                self.annotations_equal(other, **kwargs))

    def __hash__(self):
        return (hash(self.__class__) ^ hash(self._referred_to.name) ^
                hash(self.url))

    def __repr__(self):
            return ('{}(name="{}"{})'
                    .format(self.__class__.__name__, self._referred_to.name,
                            ' in "{}"'.format(self.url) if self.url else ''))

    def to_xml(self, document, E=E, **kwargs):  # @UnusedVariable
        name = self._referred_to.name
        if E._namespace == NINEMLv1:
            attrs = {}
            body = [name]
        else:
            attrs = {'name': name}
            body = []
        if self.url is not None and self.url != document.url:
            attrs['url'] = self.url
        element = E(self.nineml_type, *body, **attrs)
        return element

    @classmethod
    @read_annotations
    @unprocessed_xml
    def from_xml(cls, element, document, **kwargs):  # @UnusedVariable
        xmlns = extract_xmlns(element.tag)
        if xmlns == NINEMLv1:
            name = element.text
            if name is None:
                raise NineMLXMLAttributeError(
                    "References require the element name provided in the XML "
                    "element text")
        else:
            name = get_xml_attr(element, 'name', document, **kwargs)
        url = get_xml_attr(element, 'url', document, default=None, **kwargs)
        return cls(name=name, document=document, url=url)

    def serialize_node(self, node, **options):  # @UnusedVariable
        name = self._referred_to.name
        if node.later_version('2.0', equal=True):
            node.attr('name', name)
        else:
            node.body(name, sole=False)
        if self.url is not None and self.url != node.document.url:
            node.attr('url', self.url)

    @classmethod
    def unserialize_node(cls, node, **options):  # @UnusedVariable
        if node.later_version('2.0', equal=True):
            name = node.attr('name')
        else:
            name = node.body(sole=False)
        url = node.attr('url', default=None)
        return cls(name=name, document=node.document, url=url)


class Reference(BaseReference):
    """
{'fraction_non_alphanumeric': 0.10065873107592742, 'fraction_numerical': 0.0016179359759620942, 'mean_word_length': 2.024816497728067, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 24}, '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': '5588644', 'n_tokens_mistral': 2463, 'n_tokens_neox': 2399, 'n_words': 666}