<commit_before>#!/usr/bin/env python

"""
This module implements a Unit, which is a subclass of float. It also defines
supported units for some commonly used units for energy, length, temperature,
time and charge. Units also support conversion to one another,
and additions and subtractions perform automatic conversion if units are
detected.
"""

from __future__ import division

__author__ = "<NAME>"
__copyright__ = "Copyright 2011, The Materials Project"
__version__ = "1.0"
__maintainer__ = "<NAME>"
__email__ = "<EMAIL>"
__status__ = "Production"
__date__ = "Aug 30, 2013"


import collections
import numbers
from functools import partial


"""
Definitions of supported units. Values below are essentially scaling and
conversion factors. What matters is the relative values, not the absolute.
"""
SUPPORTED_UNITS = {
    "energy": {
        "eV": 1,
        "Ha": 27.21138386,
        "Ry": 13.605698066,
        "J": 6.24150934e18
    },
    "length": {
        "ang": 1,
        "m": 1e10,
        "cm": 1e8,
        "pm": 1e-2,
        "bohr": 0.5291772083
    },
    "mass": {
        "kg": 1,
        "g": 1e-3,
        "amu": 1.660538921e-27
    },
    "temperature": {
        "K": 1
    },
    "time": {
        "s": 1,
        "min": 60,
        "h": 3600
    },
    "charge": {
        "C": 1,
        "e": 1.602176565e-19
    }
}


class Unit(float):
    """
    Subclasses float to attach a unit type. Typically, you should use the
    pre-defined unit type subclasses such as Energy, Length, etc. instead of
    using Unit directly.

    Supports conversion, addition and subtraction of the same unit type. E.g.,
    1 m + 20 cm will be automatically converted to 1.2 m (units follow the
    leftmost quantity).

    >>> e = Energy(1.1, "Ha")
    >>> a = Energy(1.1, "Ha")
    >>> b = Energy(3, "eV")
    >>> c = a + b
    >>> print c
    1.21024797619 Ha
    >>> c.to("eV")
    32.932522246 eV
    """

    def __new__(cls, val, unit, unit_type):
        return float.__new__(cls, val)

    def __init__(self, val, unit, unit_type):
        self.unit_type = unit_type
        if unit not in SUPPORTED_UNITS[unit_type]:
            raise ValueError(
                "{} is not a supported unit for {}".format(unit, unit_type))
        self.unit = unit
        super(Unit, self).__init__(val)

    def __repr__(self):
        s = super(Unit, self).__repr__()
        return "{} {}".format(s, self.unit)

    def __str__(self):
        return self.__repr__()

    def __add__(self, other):
        if not hasattr(other, "unit_type"):
            return super(Unit, self).__add__(other)
        if other.unit_type != self.unit_type:
            raise ValueError("Adding different types of units is not allowed")
        val = other
        if other.unit != self.unit:
            val = other.to(self.unit)
        return Unit(float(self) + val, unit_type=self.unit_type,
                    unit=self.unit)

    def __sub__(self, other):
        if not hasattr(other, "unit_type"):
            return super(Unit, self).__sub__(other)
        if other.unit_type != self.unit_type:
            raise ValueError("Subtracting different units is not allowed")
        val = other
        if other.unit != self.unit:
            val = other.to(self.unit)
        return Unit(float(self) - val, unit_type=self.unit_type,
                    unit=self.unit)

    def __mul__(self, other):
        val = super(Unit, self).__mul__(other)
        if isinstance(other, (float, int)):
            return Unit(val, unit_type=self.unit_type, unit=self.unit)
        return val

    def __rmul__(self, other):
        val = super(Unit, self).__rmul__(other)
        if isinstance(other, (float, int)):
            return Unit(val, unit_type=self.unit_type, unit=self.unit)
        return val

    def __div__(self, other):
        val = super(Unit, self).__div__(other)
        if isinstance(other, (float, int)):
            return Unit(val, unit_type=self.unit_type, unit=self.unit)
        return val

    def __truediv__(self, other):
        val = super(Unit, self).__truediv__(other)
        if isinstance(other, (float, int)):
            return Unit(val, unit_type=self.unit_type, unit=self.unit)
        return val

    def __neg__(self):
        return Unit(super(Unit, self).__neg__(), unit_type=self.unit_type,
                    unit=self.unit)

    def to(self, new_unit):
        """
        Conversion to a new_unit.

        Args:
            new_unit:
                New unit type.

        Returns:
            A Unit object in the new units.

        Example usage:
        >>> e = Energy(1.1, "eV")
        >>> e = Energy(1.1, "Ha")
        >>> e.to("eV")
        29.932522246 eV
        """
        if new_unit not in SUPPORTED_UNITS[self.unit_type]:
            raise ValueError(
                "{} is not a supported unit for {}".format(new_unit,
                                                           self.unit_type))
        conversion = SUPPORTED_UNITS[self.unit_type]
        return Unit(
            self / conversion[new_unit] * conversion[self.unit],
            unit_type=self.unit_type, unit=new_unit)

    @property
    def supported_units(self):
        """
        Supported units for specific unit type.
        """
        return SUPPORTED_UNITS[self.unit_type]


Energy = partial(Unit, unit_type="energy")

Length = partial(Unit, unit_type="length")

Mass = partial(Unit, unit_type="mass")

Temp = partial(Unit, unit_type="temperature")

Time = partial(Unit, unit_type="time")

Charge = partial(Unit, unit_type="charge")

<commit_msg>Make it less easy to modify internal unit variables.<commit_after>#!/usr/bin/env python

"""
This module implements a Unit, which is a subclass of float. It also defines
supported units for some commonly used units for energy, length, temperature,
time and charge. Units also support conversion to one another,
and additions and subtractions perform automatic conversion if units are
detected.
"""

from __future__ import division

__author__ = "<NAME>"
__copyright__ = "Copyright 2011, The Materials Project"
__version__ = "1.0"
__maintainer__ = "<NAME>"
__email__ = "<EMAIL>"
__status__ = "Production"
__date__ = "Aug 30, 2013"


import collections
import numbers
from functools import partial


"""
Definitions of supported units. Values below are essentially scaling and
conversion factors. What matters is the relative values, not the absolute.
"""
SUPPORTED_UNITS = {
    "energy": {
        "eV": 1,
        "Ha": 27.21138386,
        "Ry": 13.605698066,
        "J": 6.24150934e18
    },
    "length": {
        "ang": 1,
        "m": 1e10,
        "cm": 1e8,
        "pm": 1e-2,
        "bohr": 0.5291772083
    },
    "mass": {
        "kg": 1,
        "g": 1e-3,
        "amu": 1.660538921e-27
    },
    "temperature": {
        "K": 1
    },
    "time": {
        "s": 1,
        "min": 60,
        "h": 3600
    },
    "charge": {
        "C": 1,
        "e": 1.602176565e-19
    }
}


class Unit(float):
    """
    Subclasses float to attach a unit type. Typically, you should use the
    pre-defined unit type subclasses such as Energy, Length, etc. instead of
    using Unit directly.

    Supports conversion, addition and subtraction of the same unit type. E.g.,
    1 m + 20 cm will be automatically converted to 1.2 m (units follow the
    leftmost quantity).

    >>> e = Energy(1.1, "Ha")
    >>> a = Energy(1.1, "Ha")
    >>> b = Energy(3, "eV")
    >>> c = a + b
    >>> print c
    1.21024797619 Ha
    >>> c.to("eV")
    32.932522246 eV
    """

    def __new__(cls, val, unit, unit_type):
        return float.__new__(cls, val)

    def __init__(self, val, unit, unit_type):
        self._unit_type = unit_type
        if unit not in SUPPORTED_UNITS[unit_type]:
            raise ValueError(
                "{} is not a supported unit for {}".format(unit, unit_type))
        self._unit = unit
        super(Unit, self).__init__(val)

    def __repr__(self):
        s = super(Unit, self).__repr__()
        return "{} {}".format(s, self._unit)

    def __str__(self):
        return self.__repr__()

    def __add__(self, other):
        if not hasattr(other, "unit_type"):
            return super(Unit, self).__add__(other)
        if other.unit_type != self._unit_type:
            raise ValueError("Adding different types of units is not allowed")
        val = other
        if other.unit != self._unit:
            val = other.to(self._unit)
        return Unit(float(self) + val, unit_type=self._unit_type,
                    unit=self._unit)

    def __sub__(self, other):
        if not hasattr(other, "unit_type"):
            return super(Unit, self).__sub__(other)
        if other.unit_type != self._unit_type:
            raise ValueError("Subtracting different units is not allowed")
        val = other
        if other.unit != self._unit:
            val = other.to(self._unit)
        return Unit(float(self) - val, unit_type=self._unit_type,
                    unit=self._unit)

    def __mul__(self, other):
        val = super(Unit, self).__mul__(other)
        if isinstance(other, (float, int)):
            return Unit(val, unit_type=self._unit_type, unit=self._unit)
        return val

    def __rmul__(self, other):
        val = super(Unit, self).__rmul__(other)
        if isinstance(other, (float, int)):
            return Unit(val, unit_type=self._unit_type, unit=self._unit)
        return val

    def __div__(self, other):
        val = super(Unit, self).__div__(other)
        if isinstance(other, (float, int)):
            return Unit(val, unit_type=self._unit_type, unit=self._unit)
        return val

    def __truediv__(self, other):
        val = super(Unit, self).__truediv__(other)
        if isinstance(other, (float, int)):
            return Unit(val, unit_type=self._unit_type, unit=self._unit)
        return val

    def __neg__(self):
        return Unit(super(Unit, self).__neg__(), unit_type=self._unit_type,
                    unit=self._unit)

    @property
    def unit_type(self):
        return self._unit_type

    @property
    def unit(self):
        return self._unit
    
    def to(self, new_unit):
        """
        Conversion to a new_unit.

        Args:
            new_unit:
                New unit type.

        Returns:
            A Unit object in the new units.

        Example usage:
        >>> e = Energy(1.1, "eV")
        >>> e = Energy(1.1, "Ha")
        >>> e.to("eV")
        29.932522246 eV
        """
        if new_unit not in SUPPORTED_UNITS[self._unit_type]:
            raise ValueError(
                "{} is not a supported unit for {}".format(new_unit,
                                                           self._unit_type))
        conversion = SUPPORTED_UNITS[self._unit_type]
        return Unit(
            self / conversion[new_unit] * conversion[self._unit],
            unit_type=self._unit_type, unit=new_unit)

    @property
    def supported_units(self):
        """
        Supported units for specific unit type.
        """
        return SUPPORTED_UNITS[self._unit_type]


Energy = partial(Unit, unit_type="energy")

Length = partial(Unit, unit_type="length")

Mass = partial(Unit, unit_type="mass")

Temp = partial(Unit, unit_type="temperature")

Time = partial(Unit, unit_type="time")

Charge = partial(Unit, unit_type="charge")


{'fraction_non_alphanumeric': 0.1187082013375572, 'fraction_numerical': 0.026047166490672298, 'mean_word_length': 2.199605855855856, 'pattern_counts': {'":': 48, '<': 9, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6777712', 'n_tokens_mistral': 3730, 'n_tokens_neox': 3453, 'n_words': 988}