<commit_before># encoding: utf-8
import collections
from numbers import Number
from operator import and_
from ..base import BaseULObject, E, NINEML
from ..utility import check_tag
from ..random import RandomDistribution
from .base import get_or_create_component


class Parameter(BaseULObject):

    """
    Representation of a numerical- or string-valued parameter.

    A numerical parameter is a (name, value, unit) triplet, a string parameter
    is a (name, value) pair.

    Numerical values may either be numbers, or a component that generates
    numbers, e.g. a RandomDistribution instance.
    """
    element_name = "property"
    defining_attributes = ("name", "value", "unit")

    def __init__(self, name, value, unit=None):
        self.name = name
        if (not isinstance(value, (Number, list, RandomDistribution, str)) or
            isinstance(value, bool)):
            raise TypeError("Parameter values may not be of type %s" %
                            type(value))
        self.value = value
        self.unit = unit

    def __repr__(self):
        units = self.unit
        if u"µ" in units:
            units = units.replace(u"µ", "u")
        return "Parameter(name=%s, value=%s, unit=%s)" % (self.name,
                                                          self.value, units)

    def __eq__(self, other):
        return isinstance(other, self.__class__) and \
            reduce(and_, (self.name == other.name,
                          self.value == other.value,
                          self.unit == other.unit))  # FIXME: obviously we should resolve the units, so 0.001 V == 1 mV @IgnorePep8

    def __hash__(self):
        return hash(self.name) ^ hash(self.value) ^ hash(self.unit)

    def is_random(self):
        return isinstance(self.value, RandomDistribution)

    def to_xml(self):
        if isinstance(self.value, RandomDistribution):
            value_element = E.reference(self.value.name)
        elif (isinstance(self.value, collections.Iterable) and
              isinstance(self.value[0], Number)):
            value_element = E.array(" ".join(repr(x) for x in self.value))
        else:  # need to handle Function
            value_element = E.scalar(repr(self.value))
        return E(Parameter.element_name,
                 E.quantity(
                 E.value(   # this extra level of tags is pointless, no?
                 value_element,
                 E.unit(self.unit or "dimensionless"))),
                 name=self.name)

    @classmethod
    def from_xml(cls, element, components):
        check_tag(element, cls)
        quantity_element = element.find(NINEML +
                                        "quantity").find(NINEML + "value")
        value, unit = Value.from_xml(quantity_element, components)
        return Parameter(name=element.attrib["name"],<commit_msg>quantity units are now output as an attribute rather than a separate tag<commit_after># encoding: utf-8
import collections
from numbers import Number
from operator import and_
from ..base import BaseULObject, E, NINEML
from ..utility import check_tag
from ..random import RandomDistribution
from .base import get_or_create_component


class Parameter(BaseULObject):

    """
    Representation of a numerical- or string-valued parameter.

    A numerical parameter is a (name, value, unit) triplet, a string parameter
    is a (name, value) pair.

    Numerical values may either be numbers, or a component that generates
    numbers, e.g. a RandomDistribution instance.
    """
    element_name = "property"
    defining_attributes = ("name", "value", "unit")

    def __init__(self, name, value, unit=None):
        self.name = name
        if (not isinstance(value, (Number, list, RandomDistribution, str)) or
            isinstance(value, bool)):
            raise TypeError("Parameter values may not be of type %s" %
                            type(value))
        self.value = value
        self.unit = unit

    def __repr__(self):
        units = self.unit
        if u"µ" in units:
            units = units.replace(u"µ", "u")
        return "Parameter(name=%s, value=%s, unit=%s)" % (self.name,
                                                          self.value, units)

    def __eq__(self, other):
        return isinstance(other, self.__class__) and \
            reduce(and_, (self.name == other.name,
                          self.value == other.value,
                          self.unit == other.unit))  # FIXME: obviously we should resolve the units, so 0.001 V == 1 mV @IgnorePep8

    def __hash__(self):
        return hash(self.name) ^ hash(self.value) ^ hash(self.unit)

    def is_random(self):
        return isinstance(self.value, RandomDistribution)

    def to_xml(self):
        if isinstance(self.value, RandomDistribution):
            value_element = E.reference(self.value.name)
        elif (isinstance(self.value, collections.Iterable) and
              isinstance(self.value[0], Number)):
            value_element = E.array(" ".join(repr(x) for x in self.value))
        else:  # need to handle Function
            value_element = E.scalar(repr(self.value))
        return E(Parameter.element_name,
                 E.quantity(
#                  E.value(   # this extra level of tags is pointless, no?
                 value_element,
                 units=(self.unit or "dimensionless")),#),
                 name=self.name)

    @classmethod
    def from_xml(cls, element, components):
        check_tag(element, cls)
        quantity_element = element.find(NINEML +
                                        "quantity").find(NINEML + "value")
        value, unit = Value.from_xml(quantity_element, components)
        return Parameter(name=element.attrib["name"],
{'fraction_non_alphanumeric': 0.10137367414362719, 'fraction_numerical': 0.0027821248478525473, 'mean_word_length': 2.1726420297848867, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3735836', 'n_tokens_mistral': 1568, 'n_tokens_neox': 1523, 'n_words': 465}