#!/usr/bin/env python
# -*- coding: utf-8 -*-
ur"""Helper functions for work with collections.

Utils:

`unlist` -- extracts element from one-element collections:
    >>> unlist([]) is None
    True
    >>> unlist(['hello'])
    'hello'
    >>> unlist(['hello', 'world'])
    Traceback (most recent call last):
    ...
    TypeError: Cannot unlist collection: ['hello', 'world']
    Collection size is greater than 1.

`undict` -- extracts element from one-element dict:
    >>> undict({}) is None
    True
    >>> undict({'fruits': ['apple', 'banana']})
    ('fruits', ['apple', 'banana'])
    >>> undict({'fruit_0': 'apple', 'fruit_1': 'banana'})
    Traceback (most recent call last):
    ...
    TypeError: Cannot undict dictionary: {'fruit_0': 'apple', 'fruit_1': 'banana'}
    Dictionary size is greater than 1.

`strlist` -- convert list to readable string.
    >>> print strlist([u'Строки', 'Юникод', 123])
    [Строки, Юникод, 123]
    >>> print strlist(['Строки'])
    [Строки]

    Feel difference:
    >>> print ['Строки']
    ['\xd0\xa1\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb8']
"""


def unlist(collection):
    """Extracts element from @collection if len(collection) 1.

    :returns: element in collection or None.
    :raises: TypeError if len(collection) > 1
    """
    if len(collection) > 1:
        raise TypeError("Cannot unlist collection: {0}\n".format(collection) +
                        "Collection size is greater than 1.")

    return collection[0] if len(collection) == 1 else None


def undict(dictionary):
    """Extracts tuple (key, value) from one-element dict.

    :returns: (key, value) tuple or None.
    :raises: TypeError if len(dictionary) > 1
    """
    if len(dictionary) > 1:
        raise TypeError("Cannot undict dictionary: {0}\n".format(dictionary) +
                        "Dictionary size is greater than 1.")
    return dictionary.items()[0] if len(dictionary) == 1 else None


def strlist(li):
    """:returns: str represintation of list. But elements are represented
    by str(elem), insead of repr(elem).

    Not [u'Строка'], but [Строка]
    """
    result = u'['
    for num, elem in enumerate(li):
        result += elem if isinstance(elem, str) or isinstance(elem, unicode) \
                  else str(elem)
        if num + 1 != len(li):
            result += ', '
    result += ']'
    return result.encode('utf-8')


if __name__ == '__main__':
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')
    import doctest
    doctest.testmod()

@@ -1084,16 +1084,149 @@
 d0%5Cxb8'%5D
+%0A%0A%60join%60 -- join list of iterable to list.%0A    %3E%3E%3E join(%5B%5B1, 2%5D, %22Sasha%22, xrange(4)%5D)%0A    %5B1, 2, 'S', 'a', 's', 'h', 'a', 0, 1, 2, 3%5D
 %0A%22%22%22%0A%0A%0Ad
@@ -2511,16 +2511,283 @@
 f-8')%0A%0A%0A
+def join(li):%0A    %22%22%22:returns: list of objs joined from list of iterable with objs.%0A%0A    %3E%3E%3E join(%5B%5B1,2%5D, %5B3%5D, %5B4,5%5D%5D)%0A    %5B1, 2, 3, 4, 5%5D%0A    %22%22%22%0A    result = %5B%5D%0A    for iterable in li:%0A        for obj in iterable:%0A            result.append(obj)%0A    return result%0A%0A%0A
 if __nam

Add CU.join function