mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-07 22:09:38 +07:00
165 lines
4.7 KiB
Python
165 lines
4.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright (c) 2016 the Pockets team, see AUTHORS.
|
|
# Licensed under the BSD License, see LICENSE for details.
|
|
|
|
"""A pocket full of useful collection functions!"""
|
|
|
|
from __future__ import absolute_import
|
|
from collections import Sized, Iterable, Mapping
|
|
from inspect import isclass
|
|
|
|
import six
|
|
|
|
__all__ = ["is_listy", "listify", "mappify"]
|
|
|
|
|
|
def is_listy(x):
|
|
"""Return True if `x` is "listy", i.e. a list-like object.
|
|
|
|
"Listy" is defined as a sized iterable which is neither a map nor a string:
|
|
|
|
>>> is_listy(["a", "b"])
|
|
True
|
|
>>> is_listy(set())
|
|
True
|
|
>>> is_listy(iter(["a", "b"]))
|
|
False
|
|
>>> is_listy({"a": "b"})
|
|
False
|
|
>>> is_listy("a regular string")
|
|
False
|
|
|
|
Note:
|
|
Iterables and generators fail the "listy" test because they
|
|
are not sized.
|
|
|
|
Args:
|
|
x (any value): The object to test.
|
|
|
|
Returns:
|
|
bool: True if `x` is "listy", False otherwise.
|
|
|
|
"""
|
|
return (isinstance(x, Sized) and
|
|
isinstance(x, Iterable) and
|
|
not isinstance(x, Mapping) and
|
|
not isinstance(x, six.string_types))
|
|
|
|
|
|
def listify(x, minlen=0, default=None, cls=None):
|
|
"""Return a listified version of `x`.
|
|
|
|
If `x` is a non-string iterable, it is wrapped in a list; otherwise
|
|
a list is returned with `x` as its only element.
|
|
|
|
>>> listify("a regular string")
|
|
['a regular string']
|
|
>>> listify(tuple(["a", "b", "c"]))
|
|
['a', 'b', 'c']
|
|
>>> listify({'a': 'A'})
|
|
[{'a': 'A'}]
|
|
|
|
Note:
|
|
Not guaranteed to return a copy of `x`. If `x` is already a list and
|
|
`cls` is not specified, then `x` itself is returned.
|
|
|
|
Args:
|
|
x (any value): Value to listify.
|
|
|
|
minlen (int): Minimum length of the returned list. If the returned
|
|
list would be shorter than `minlen` it is padded with values from
|
|
`default`. Defaults to 0.
|
|
|
|
>>> listify([], minlen=0)
|
|
[]
|
|
>>> listify([], minlen=1)
|
|
[None]
|
|
>>> listify("item", minlen=3)
|
|
['item', None, None]
|
|
|
|
default (any value): Value that should be used to pad the list if it
|
|
would be shorter than `minlen`:
|
|
|
|
>>> listify([], minlen=1, default="PADDING")
|
|
['PADDING']
|
|
>>> listify("item", minlen=3, default="PADDING")
|
|
['item', 'PADDING', 'PADDING']
|
|
|
|
cls (class or callable): Instead of wrapping `x` in a list, wrap it
|
|
in an instance of `cls`. `cls` should accept an iterable object
|
|
as its single parameter when called:
|
|
|
|
>>> from collections import deque
|
|
>>> listify(["a", "b", "c"], cls=deque)
|
|
deque(['a', 'b', 'c'])
|
|
|
|
Returns:
|
|
list or `cls`: A listified version of `x`.
|
|
|
|
"""
|
|
if x is None:
|
|
x = []
|
|
elif not isinstance(x, list):
|
|
x = list(x) if is_listy(x) else [x]
|
|
|
|
if minlen and len(x) < minlen:
|
|
x.extend([default for i in range(minlen - len(x))])
|
|
|
|
if cls and not (isclass(cls) and issubclass(type(x), cls)):
|
|
x = cls(x)
|
|
return x
|
|
|
|
|
|
def mappify(x, default=True, cls=None):
|
|
"""Return a mappified version of `x`.
|
|
|
|
If `x` is a string, it becomes the only key of the returned dict. If `x`
|
|
is a non-string iterable, the elements of `x` become keys in the returned
|
|
dict. The values of the returned dict are set to `default`.
|
|
|
|
If `x` is a map, it is returned directly.
|
|
|
|
>>> mappify("a regular string")
|
|
{'a regular string': True}
|
|
>>> mappify(["a"])
|
|
{'a': True}
|
|
>>> mappify({'a': "A"})
|
|
{'a': 'A'}
|
|
|
|
Note:
|
|
Not guaranteed to return a copy of `x`. If `x` is already a map and
|
|
`cls` is not specified, then `x` itself is returned.
|
|
|
|
Args:
|
|
x (str, map, or iterable): Value to mappify.
|
|
|
|
default (any value): Value used to fill out missing values of the
|
|
returned dict.
|
|
|
|
cls (class or callable): Instead of wrapping `x` in a dict, wrap it
|
|
in an instance of `cls`. `cls` should accept a map object as
|
|
its single parameter when called:
|
|
|
|
>>> from collections import defaultdict
|
|
>>> mappify("a", cls=lambda x: defaultdict(None, x))
|
|
defaultdict(None, {'a': True})
|
|
|
|
Returns:
|
|
dict or `cls`: A mappified version of `x`.
|
|
|
|
Raises:
|
|
TypeError: If `x` is not a map, iterable, or string.
|
|
|
|
"""
|
|
if not isinstance(x, Mapping):
|
|
if isinstance(x, six.string_types):
|
|
x = {x: default}
|
|
elif isinstance(x, Iterable):
|
|
x = dict([(v, default) for v in x])
|
|
else:
|
|
raise TypeError("Unable to mappify {0}".format(type(x)), x)
|
|
|
|
if cls and not (isclass(cls) and issubclass(type(x), cls)):
|
|
x = cls(x)
|
|
return x
|