<commit_before># Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Storage for package compatibility information."""

from contextlib import closing
import datetime
from distutils import version
import enum
import itertools
import os
from typing import Any, FrozenSet, Iterable, List, Mapping, Optional, Tuple

import pymysql

from compatibility_lib import configs
from compatibility_lib import package

_DATABASE_NAME = 'compatibility_data'
_SELF_COMPATIBILITY_STATUS_TABLE_NAME = 'self_compatibility_status'
_PAIRWISE_COMPATIBILITY_STATUS_TABLE_NAME = 'pairwise_compatibility_status'
_RELEASE_TIME_FOR_DEPENDENCIES_TABLE_NAME = 'release_time_for_dependencies'


class Status(enum.Enum):
    UNKNOWN = "UNKNOWN"
    SUCCESS = "SUCCESS"
    INSTALL_ERROR = "INSTALL_ERROR"
    CHECK_WARNING = "CHECK_WARNING"


class CompatibilityResult:
    """The result of checking the compatibility between packages.

    Attributes:
        packages: The list of packages there were checked for compatibility.
        python_major_version: The major Python version used for the
            compatibility check i.e. 2 or 3.
        status: The overall result of the compatibility check.
        details: A text description of the compatibility check. Will be None
            if the check succeeded.
        dependency_info: The dict contains the dependency version info and
            release time info. For example:
            'six':
              {'current_time': datetime.datetime(...),
               'installed_version': '1.13.0',
               'installed_version_time': datetime.datetime(...),
               'is_latest': 1,
               'latest_version': '1.13.0',
               'latest_version_time': datetime.datetime(...)},
        timestamp: The time at which the compatibility check was performed.
    """

    def __init__(self,
                 packages: Iterable[package.Package],
                 python_major_version: int,
                 status: Status = Status.UNKNOWN,
                 details: Optional[str] = None,
                 dependency_info: Optional[Mapping[str, Any]] = None,
                 timestamp: Optional[datetime.datetime] = None):
        self._packages = list(packages)
        self._python_major_version = python_major_version
        self._status = status
        self._details = details
        self._dependency_info = dependency_info
        if timestamp:
            self._timestamp = timestamp
        else:
            self._timestamp = datetime.datetime.utcnow()

    def __repr__(self):
        return ('CompatibilityResult({}, {}, {}, {}, {}, {})'.format(
            self.packages, self.python_major_version, self.status,
            self.details, self.timestamp, self.dependency_info))

    def __hash__(self):
        return hash((tuple(self.packages), self.status, self.timestamp))

    def __eq__(self, o):
        if isinstance(o, CompatibilityResult):
            return (frozenset(self.packages) == frozenset(o.packages) and
                    self.python_major_version == o.python_major_version and
                    self.status == o.status and
                    self.details == o.details and
                    self.dependency_info == o.dependency_info and
                    self.timestamp == o.timestamp)
        return NotImplemented

    @property
    def packages(self) -> List[package.Package]:
        return self._packages

    @property
    def python_major_version(self) -> int:
        return self._python_major_version

    @property
    def status(self) -> Status:
        return self._status

    @status.setter
    def status(self, status: Status):
        self._status = status

    @property
    def details(self) -> Optional[str]:
        return self._details

    @property
    def dependency_info(self) -> Optional[Mapping[str, Any]]:
        return self._dependency_info

    @property
    def timestamp(self) -> datetime.datetime:
        return self._timestamp

    @timestamp.setter
    def timestamp(self, timestamp: datetime.datetime):
        self._timestamp = timestamp

    def get_package_version(self) -> str:
        """Returns the version of the single package in a CompatibilityResult.

        The CompatibilityResult must have `dependency_info` set that includes
        the package.

        Returns:
            A string containing the version of the single package found in the
            CompatibilityResult `packages` attribute. For example:

            cr1 = CompatibilityResult(
                packages=[Package('package1')],
                dependency_info={'package1': {'installed_version': '1.2.3' ..})
            cr1.get_package_version(cr1) => '1.2.3'
        """<commit_msg>Remove the ability to mutate the timestamp of a CompatibilityResult (#296)<commit_after># Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Storage for package compatibility information."""

from contextlib import closing
import datetime
from distutils import version
import enum
import itertools
import os
from typing import Any, FrozenSet, Iterable, List, Mapping, Optional, Tuple

import pymysql

from compatibility_lib import configs
from compatibility_lib import package

_DATABASE_NAME = 'compatibility_data'
_SELF_COMPATIBILITY_STATUS_TABLE_NAME = 'self_compatibility_status'
_PAIRWISE_COMPATIBILITY_STATUS_TABLE_NAME = 'pairwise_compatibility_status'
_RELEASE_TIME_FOR_DEPENDENCIES_TABLE_NAME = 'release_time_for_dependencies'


class Status(enum.Enum):
    UNKNOWN = "UNKNOWN"
    SUCCESS = "SUCCESS"
    INSTALL_ERROR = "INSTALL_ERROR"
    CHECK_WARNING = "CHECK_WARNING"


class CompatibilityResult:
    """The result of checking the compatibility between packages.

    Attributes:
        packages: The list of packages there were checked for compatibility.
        python_major_version: The major Python version used for the
            compatibility check i.e. 2 or 3.
        status: The overall result of the compatibility check.
        details: A text description of the compatibility check. Will be None
            if the check succeeded.
        dependency_info: The dict contains the dependency version info and
            release time info. For example:
            'six':
              {'current_time': datetime.datetime(...),
               'installed_version': '1.13.0',
               'installed_version_time': datetime.datetime(...),
               'is_latest': 1,
               'latest_version': '1.13.0',
               'latest_version_time': datetime.datetime(...)},
        timestamp: The time at which the compatibility check was performed.
    """

    def __init__(self,
                 packages: Iterable[package.Package],
                 python_major_version: int,
                 status: Status = Status.UNKNOWN,
                 details: Optional[str] = None,
                 dependency_info: Optional[Mapping[str, Any]] = None,
                 timestamp: Optional[datetime.datetime] = None):
        self._packages = list(packages)
        self._python_major_version = python_major_version
        self._status = status
        self._details = details
        self._dependency_info = dependency_info
        if timestamp:
            self._timestamp = timestamp
        else:
            self._timestamp = datetime.datetime.utcnow()

    def __repr__(self):
        return ('CompatibilityResult({}, {}, {}, {}, {}, {})'.format(
            self.packages, self.python_major_version, self.status,
            self.details, self.timestamp, self.dependency_info))

    def __hash__(self):
        return hash((tuple(self.packages), self.status, self.timestamp))

    def __eq__(self, o):
        if isinstance(o, CompatibilityResult):
            return (frozenset(self.packages) == frozenset(o.packages) and
                    self.python_major_version == o.python_major_version and
                    self.status == o.status and
                    self.details == o.details and
                    self.dependency_info == o.dependency_info and
                    self.timestamp == o.timestamp)
        return NotImplemented

    @property
    def packages(self) -> List[package.Package]:
        return self._packages

    @property
    def python_major_version(self) -> int:
        return self._python_major_version

    @property
    def status(self) -> Status:
        return self._status

    @status.setter
    def status(self, status: Status):
        self._status = status

    @property
    def details(self) -> Optional[str]:
        return self._details

    @property
    def dependency_info(self) -> Optional[Mapping[str, Any]]:
        return self._dependency_info

    @property
    def timestamp(self) -> datetime.datetime:
        return self._timestamp

    def get_package_version(self) -> str:
        """Returns the version of the single package in a CompatibilityResult.

        The CompatibilityResult must have `dependency_info` set that includes
        the package.

        Returns:
            A string containing the version of the single package found in the
            CompatibilityResult `packages` attribute. For example:

            cr1 = CompatibilityResult(
                packages=[Package('package1')],
                dependency_info={'package1': {'installed_version': '1.2.3' ..})
            cr1.get_package_version(cr1) => '1.2.3'
        """
{'fraction_non_alphanumeric': 0.08332530584722088, 'fraction_numerical': 0.006068779501011463, 'mean_word_length': 2.6389765159481247, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6984779', 'n_tokens_mistral': 2694, 'n_tokens_neox': 2588, 'n_words': 835}