<commit_before># -*- coding: UTF-8 -*-
# Copyright 2009-2017 by <NAME>.
# License: BSD, see LICENSE for more details.

"""
Defines a series of utility classes and functions.

$ python setup.py test -s tests.BasicTests.test_utils

"""

from __future__ import print_function
import six
from builtins import str
from future.types import newstr
# from builtins import input
from builtins import object
# Python 2 and 3:
from future.utils import python_2_unicode_compatible
import six
from six.moves import input

# from __future__ import unicode_literals
# causes problems on Windows where `subprocess.Popen` wants only plain strings

import os
import sys
import locale
import datetime
import subprocess
from dateutil import parser as dateparser
from dateutil.relativedelta import relativedelta
from contextlib import contextmanager


@python_2_unicode_compatible
class AttrDict(dict):

    """
    Dictionary-like helper object.
    
    Usage example:
    
    >>> from atelier.utils import AttrDict
    >>> a = AttrDict()
    >>> a.define('foo', 1)
    >>> a.define('bar', 'baz', 2)
    >>> a == {"bar": {"baz": 2}, "foo": 1}
    True
    >>> print(a.foo)
    1
    >>> print(a.bar.baz)
    2
    >>> print(a.resolve('bar.baz'))
    2
    >>> print(a.bar)
    {'baz': 2}
    
    """
    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            raise AttributeError(
                "AttrDict instance has no key '%s' (keys are %s)" % (
                    name, ', '.join(list(self.keys()))))

    def define2(self, name, value):
        return self.define(*name.split('.') + [value])

    def define(self, *args):
        "args must be a series of names followed by the value"
        assert len(args) >= 2
        d = s = self
        for n in args[:-2]:
            d = s.get(n, None)
            if d is None:
                d = AttrDict()
                s[n] = d
            s = d
        oldvalue = d.get(args[-2], None)
        d[args[-2]] = args[-1]
        return oldvalue

    def resolve(self, name, default=None):
        """
        return an attribute with dotted name
        """
        o = self
        for part in name.split('.'):
            o = getattr(o, part, default)
            # o = o.__getattr__(part)
        return o


def iif(condition, true_value, false_value=None):
    """
    "Inline If" : an ``if`` statement as a function.

    Examples:

    >>> from atelier.utils import iif
    >>> print("Hello, %s world!" % iif(1+1==2, "real", "imaginary"))
    Hello, real world!
    >>> iif(True, "true")
    'true'
    >>> iif(False, "true")

    """
    if condition:
        return true_value
    return false_value


def i2d(i):
    """
    Convert `int` to `date`. Examples:

    >>> i2d(20121224)
    datetime.date(2012, 12, 24)

    """
    s = str(i)
    if len(s) != 8:
        raise Exception("Invalid date specification {0}.".format(i))
    d = dateparser.parse(s)
    d = datetime.date(d.year, d.month, d.day)
    # print(i, "->", v)
    return d


def i2t(s):
    """
    Convert `int` to `time`. Examples:
    
    >>> i2t(815)
    datetime.time(8, 15)
    
    >>> i2t(1230)
    datetime.time(12, 30)
    
    >>> i2t(12)
    datetime.time(12, 0)
    
    >>> i2t(1)
    datetime.time(1, 0)
    
    """
    s = str(s)
    if len(s) == 4:
        return datetime.time(int(s[:2]), int(s[2:]))
    if len(s) == 3:
        return datetime.time(int(s[:1]), int(s[1:]))
    if len(s) <= 2:
        return datetime.time(int(s), 0)
    raise ValueError(s)


def last_day_of_month(d):
    """Return the last day of the month of the given date.

    >>> from atelier.utils import i2d
    >>> last_day_of_month(i2d(20160212))
    datetime.date(2016, 2, 29)
    >>> last_day_of_month(i2d(20161201))
    datetime.date(2016, 12, 31)
    >>> last_day_of_month(i2d(20160123))
    datetime.date(2016, 1, 31)
    >>> last_day_of_month(i2d(20161123))
    datetime.date(2016, 11, 30)

    Thanks to `stackoverflow.com
    <http://stackoverflow.com/questions/42950/get-last-day-of-the-month-in-python>`_.

    """
    return d + relativedelta(day=31)
    # d = datetime.date(d.year, d.month + 1, 1)
    # return relativedelta(d, days=-1)


def ispure(s):
    """
    Returns `True` if the specified string `s` is either a unicode 
    string or contains only ASCII characters.<commit_msg>New function is_string(). For #1877<commit_after># -*- coding: UTF-8 -*-
# Copyright 2009-2017 by <NAME>.
# License: BSD, see LICENSE for more details.

"""
Defines a series of utility classes and functions.

$ python setup.py test -s tests.BasicTests.test_utils

"""

from __future__ import print_function
import six
from six.moves import input
from builtins import str
from builtins import object
from future.types import newstr
from future.utils import python_2_unicode_compatible

# from __future__ import unicode_literals
# causes problems on Windows where `subprocess.Popen` wants only plain strings

import os
import sys
import locale
import datetime
import subprocess
from dateutil import parser as dateparser
from dateutil.relativedelta import relativedelta
from contextlib import contextmanager


@python_2_unicode_compatible
class AttrDict(dict):

    """
    Dictionary-like helper object.
    
    Usage example:
    
    >>> from atelier.utils import AttrDict
    >>> a = AttrDict()
    >>> a.define('foo', 1)
    >>> a.define('bar', 'baz', 2)
    >>> a == {"bar": {"baz": 2}, "foo": 1}
    True
    >>> print(a.foo)
    1
    >>> print(a.bar.baz)
    2
    >>> print(a.resolve('bar.baz'))
    2
    >>> print(a.bar)
    {'baz': 2}
    
    """
    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            raise AttributeError(
                "AttrDict instance has no key '%s' (keys are %s)" % (
                    name, ', '.join(list(self.keys()))))

    def define2(self, name, value):
        return self.define(*name.split('.') + [value])

    def define(self, *args):
        "args must be a series of names followed by the value"
        assert len(args) >= 2
        d = s = self
        for n in args[:-2]:
            d = s.get(n, None)
            if d is None:
                d = AttrDict()
                s[n] = d
            s = d
        oldvalue = d.get(args[-2], None)
        d[args[-2]] = args[-1]
        return oldvalue

    def resolve(self, name, default=None):
        """
        return an attribute with dotted name
        """
        o = self
        for part in name.split('.'):
            o = getattr(o, part, default)
            # o = o.__getattr__(part)
        return o


def iif(condition, true_value, false_value=None):
    """
    "Inline If" : an ``if`` statement as a function.

    Examples:

    >>> from atelier.utils import iif
    >>> print("Hello, %s world!" % iif(1+1==2, "real", "imaginary"))
    Hello, real world!
    >>> iif(True, "true")
    'true'
    >>> iif(False, "true")

    """
    if condition:
        return true_value
    return false_value


def i2d(i):
    """
    Convert `int` to `date`. Examples:

    >>> i2d(20121224)
    datetime.date(2012, 12, 24)

    """
    s = str(i)
    if len(s) != 8:
        raise Exception("Invalid date specification {0}.".format(i))
    d = dateparser.parse(s)
    d = datetime.date(d.year, d.month, d.day)
    # print(i, "->", v)
    return d


def i2t(s):
    """
    Convert `int` to `time`. Examples:
    
    >>> i2t(815)
    datetime.time(8, 15)
    
    >>> i2t(1230)
    datetime.time(12, 30)
    
    >>> i2t(12)
    datetime.time(12, 0)
    
    >>> i2t(1)
    datetime.time(1, 0)
    
    """
    s = str(s)
    if len(s) == 4:
        return datetime.time(int(s[:2]), int(s[2:]))
    if len(s) == 3:
        return datetime.time(int(s[:1]), int(s[1:]))
    if len(s) <= 2:
        return datetime.time(int(s), 0)
    raise ValueError(s)


def last_day_of_month(d):
    """Return the last day of the month of the given date.

    >>> from atelier.utils import i2d
    >>> last_day_of_month(i2d(20160212))
    datetime.date(2016, 2, 29)
    >>> last_day_of_month(i2d(20161201))
    datetime.date(2016, 12, 31)
    >>> last_day_of_month(i2d(20160123))
    datetime.date(2016, 1, 31)
    >>> last_day_of_month(i2d(20161123))
    datetime.date(2016, 11, 30)

    Thanks to `stackoverflow.com
    <http://stackoverflow.com/questions/42950/get-last-day-of-the-month-in-python>`_.

    """
    return d + relativedelta(day=31)
    # d = datetime.date(d.year, d.month + 1, 1)
    # return relativedelta(d, days=-1)


def isiterable(x):
    "Returns `True` if the specified object is iterable."
    try:
        iter(x)
    except TypeError:
        return False
    return True


def is_string(s):
    """Return True if the specified value is a string.
    """
    return isinstance(s, six.string_types) or isinstance(s, newstr)
   
def ispure(s):
    """Returns `True` if the specified string `s` is either None, or
    contains only ASCII characters, or is a validly encoded unicode
    string.

{'fraction_non_alphanumeric': 0.14146557449634714, 'fraction_numerical': 0.03608589771972548, 'mean_word_length': 2.3902439024390243, 'pattern_counts': {'":': 6, '<': 9, '<?xml version=': 0, '>': 149, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '6670232', 'n_tokens_mistral': 3288, 'n_tokens_neox': 3017, 'n_words': 849}