<commit_before># Copyright 2007 Google, Inc. All Rights Reserved.
# Licensed to PSF under a Contributor Agreement.

"""Abstract Base Classes (ABCs) for collections, according to PEP 3119.

Unit tests are in test_collections.
"""

from abc import ABCMeta, abstractmethod
import sys

__all__ = ["Hashable", "Iterable", "Iterator",
           "Sized", "Container", "Callable",
           "Set", "MutableSet",
           "Mapping", "MutableMapping",
           "MappingView", "KeysView", "ItemsView", "ValuesView",
           "Sequence", "MutableSequence",
           "ByteString",
           ]

### collection related types which are not exposed through builtin ###
## iterators ##
bytes_iterator = type(iter(b''))
bytearray_iterator = type(iter(bytearray()))
#callable_iterator = ???
dict_keyiterator = type(iter({}.keys()))
dict_valueiterator = type(iter({}.values()))
dict_itemiterator = type(iter({}.items()))
list_iterator = type(iter([]))
list_reverseiterator = type(iter(reversed([])))
range_iterator = type(iter(range(0)))
set_iterator = type(iter(set()))
str_iterator = type(iter(""))
tuple_iterator = type(iter(()))
zip_iterator = type(iter(zip()))
## views ##
dict_keys = type({}.keys())
dict_values = type({}.values())
dict_items = type({}.items())
## misc ##
dict_proxy = type(type.__dict__)

### ONE-TRICK PONIES ###

class Hashable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __hash__(self):
        return 0

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Hashable:
            for B in C.__mro__:
                if "__hash__" in B.__dict__:
                    if B.__dict__["__hash__"]:
                        return True
                    break
        return NotImplemented

class Iterable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __iter__(self):
        while False:
            yield None

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterable:
            if any("__iter__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

class Iterator(Iterable):

    __slots__ = ()

    @abstractmethod
    def __next__(self):
        raise StopIteration

    def __iter__(self):
        return self

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterator:
            if (any("__next__" in B.__dict__ for B in C.__mro__) and
                any("__iter__" in B.__dict__ for B in C.__mro__)):
                return True
        return NotImplemented

Iterator.register(bytes_iterator)
Iterator.register(bytearray_iterator)
#Iterator.register(callable_iterator)
Iterator.register(dict_keyiterator)
Iterator.register(dict_valueiterator)
Iterator.register(dict_itemiterator)
Iterator.register(list_iterator)
Iterator.register(list_reverseiterator)
Iterator.register(range_iterator)
Iterator.register(set_iterator)
Iterator.register(str_iterator)
Iterator.register(tuple_iterator)
Iterator.register(zip_iterator)

class Sized(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __len__(self):
        return 0

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Sized:
            if any("__len__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

class Container(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __contains__(self, x):
        return False

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Container:
            if any("__contains__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

class Callable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __call__(self, *args, **kwds):
        return False

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Callable:
            if any("__call__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

### SETS ###

class Set(Sized, Iterable, Container):

    """A set is a finite, iterable container.

    This class provides concrete generic implementations of all
    methods except for __contains__, __iter__ and __len__.

    To override the comparisons (presumably for speed, as the
    semantics are fixed), all you have to do is redefine __le__ and
    then the other operations will automatically follow suit.
    """

    __slots__ = ()

    def __le__(self, other):
        if not isinstance(other, Set):
            return NotImplemented
        if len(self) > len(other):
            return False
        for elem in self:
            if elem not in other:
                return False
        return True

    def __lt__(self, other):
        if not isinstance(other, Set):
            return NotImplemented
        return len(self) < len(other) and self.__le__(other)

    def __gt__(self, other):
        if not isinstance(other, Set):
            return NotImplemented
        return other < self

    def __ge__(self, other):
        if not isinstance(other, Set):
            return NotImplemented
        return other <= self

    def __eq__(self, other):
        if not isinstance(other, Set):
            return NotImplemented
        return len(self) == len(other) and self.__le__(other)

    def __ne__(self, other):
        return not (self == other)

    @classmethod
    def _from_iterable(cls, it):
        '''Construct an instance of the class from any iterable input.

        Must override this method if the class constructor signature
        does not accept an iterable for an input.
        '''
        return cls(it)

    def __and__(self, other):
        if not isinstance(other, Iterable):
            return NotImplemented
        return self._from_iterable(value for value in other if value in self)

    def isdisjoint(self, other):
        for value in other:
            if value in self:
                return False
        return True

    def __or__(self, other):
        if not isinstance(other, Iterable):
            return NotImplemented
        chain = (e for s in (self, other) for e in s)
        return self._from_iterable(chain)

    def __sub__(self, other):
        if not isinstance(other, Set):
            if not isinstance(other, Iterable):
                return NotImplemented
            other = self._from_iterable(other)
        return self._from_iterable(value for value in self
                                   if value not in other)

    def __xor__(self, other):
        if not isinstance(other, Set):
            if not isinstance(other, Iterable):
                return NotImplemented
            other = self._from_iterable(other)
        return (self - other) | (other - self)

    def _hash(self):
        """Compute the hash value of a set.

        Note that we don't define __hash__: not all sets are hashable.
        But if you define a hashable set type, its __hash__ should
        call this function.

        This must be compatible __eq__.

        All sets ought to compare equal if they contain the same
        elements, regardless of how they are implemented, and
        regardless of the order of the elements; so there's not much
        freedom for __eq__ or __hash__.  We match the algorithm used
        by the built-in frozenset type.
        """
        MAX = sys.maxsize
        MASK = 2 * MAX + 1
        n = len(self)
        h = 1927868237 * (n + 1)
        h &= MASK
        for x in self:
            hx = hash(x)
            h ^= (hx ^ (hx << 16) ^ 89869747)  * 3644798167
            h &= MASK
        h = h * 69069 + 907133923
        h &= MASK
        if h > MAX:
            h -= MASK + 1
        if h == -1:
            h = 590923713
        return h

Set.register(frozenset)

class MutableSet(Set):

    __slots__ = ()

    @abstractmethod
    def add(self, value):
        """Add an element."""
        raise NotImplementedError

    @abstractmethod
    def discard(self, value):
        """Remove an element.  Do not raise an exception if absent."""
        raise NotImplementedError

    def remove(self, value):
        """Remove an element. If not a member, raise a KeyError."""
        if value not in self:
            raise KeyError(value)
        self.discard(value)

    def pop(self):
        """Return the popped value.  Raise KeyError if empty."""
        it = iter(self)
        try:
            value = next(it)
        except StopIteration:
            raise KeyError
        self.discard(value)
        return value

    def clear(self):
        """This is slow (creates N new iterators!) but effective."""
        try:
            while True:
                self.pop()
        except KeyError:
            pass

    def __ior__(self, it):
        for value in it:
            self.add(value)
        return self

    def __iand__(self, it):
        for value in (self - it):
            self.discard(value)
        return self

    def __ixor__(self, it):
        if it is self:
            self.clear()
        else:
            if not isinstance(it, Set):
                it = self._from_iterable(it)
            for value in it:
                if value in self:
                    self.discard(value)
                else:
                    self.add(value)
        return self

    def __isub__(self, it):
        if it is self:
            self.clear()
        else:
            for value in it:
                self.discard(value)
        return self

MutableSet.register(set)

### MAPPINGS ###

class Mapping(Sized, Iterable, Container):

    __slots__ = ()

    @abstractmethod
    def __getitem__(self, key):
        raise KeyError

    def get(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            return default

    def __contains__(self, key):
        try:
            self[key]
        except KeyError:
            return False
        else:
            return True

    def keys(self):
        return KeysView(self)

    def items(self):
        return ItemsView(self)

    def values(self):
        return ValuesView(self)

    def __eq__(self, other):
        if not isinstance(other, Mapping):
            return NotImplemented
        return dict(self.items()) == dict(other.items())

    def __ne__(self, other):
        return not (self == other)

class MappingView(Sized):

    def __init__(self, mapping):
        self._mapping = mapping

    def __len__(self):
        return len(self._mapping)

    def __repr__(self):
        return '{0.__class__.__name__}({0._mapping!r})'.format(self)

class KeysView(MappingView, Set):

    @classmethod
    def _from_iterable(self, it):
        return set(it)

    def __contains__(self, key):
        return key in self._mapping

    def __iter__(self):
        for key in self._mapping:
            yield key

KeysView.register(dict_keys)

class ItemsView(MappingView, Set):

    @classmethod
    def _from_iterable(self, it):
        return set(it)

    def __contains__(self, item):
        key, value = item
        try:
            v = self._mapping[key]
        except KeyError:
            return False
        else:
            return v == value

    def __iter__(self):
        for key in self._mapping:
            yield (key, self._mapping[key])

ItemsView.register(dict_items)

class ValuesView(MappingView):

    def __contains__(self, value):
        for key in self._mapping:
            if value == self._mapping[key]:
                return True
        return False

    def __iter__(self):
        for key in self._mapping:
            yield self._mapping[key]

ValuesView.register(dict_values)

class MutableMapping(Mapping):

    __slots__ = ()

    @abstractmethod
    def __setitem__(self, key, value):
        raise KeyError

    @abstractmethod
    def __delitem__(self, key):
        raise KeyError

    __marker = object()

    def pop(self, key, default=__marker):
        try:
            value = self[key]
        except KeyError:
            if default is self.__marker:
                raise
            return default
        else:
            del self[key]
            return value

    def popitem(self):
        try:
            key = next(iter(self))
        except StopIteration:
            raise KeyError
        value = self[key]
        del self[key]
        return key, value

    def clear(self):
        try:
            while True:
                self.popitem()
        except KeyError:
            pass

    def update(*args, **kwds):
        if len(args) > 2:
            raise TypeError("update() takes at most 2 positional "
                            "arguments ({} given)".format(len(args)))
        elif not args:
            raise TypeError("update() takes at least 1 argument (0 given)")
        self = args[0]
        other = args[1] if len(args) >= 2 else ()

        if isinstance(other, Mapping):
            for key in other:
                self[key] = other[key]
        elif hasattr(other, "keys"):
            for key in other.keys():
                self[key] = other[key]
        else:
            for key, value in other:
                self[key] = value
        for key, value in kwds.items():
            self[key] = value

    def setdefault(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            self[key] = default
        return default

MutableMapping.register(dict)

### SEQUENCES ###

class Sequence(Sized, Iterable, Container):

    """All the operations on a read-only sequence.

    Concrete subclasses must override __new__ or __init__,
    __getitem__, and __len__.
    """

    __slots__ = ()

    @abstractmethod
    def __getitem__(self, index):
        raise IndexError

    def __iter__(self):
        i = 0
        try:
            while True:
                v = self[i]
                yield v
                i += 1
        except IndexError:
            return

    def __contains__(self, value):
        for v in self:
            if v == value:
                return True
        return False

    def __reversed__(self):
        for i in reversed(range(len(self))):
            yield self[i]

    def index(self, value):
        for i, v in enumerate(self):
            if v == value:
                return i
        raise ValueError

    def count(self, value):
        return sum(1 for v in self if v == value)

Sequence.register(tuple)
Sequence.register(str)
Sequence.register(range)

class ByteString(Sequence):

    """This unifies bytes and bytearray.

    XXX Should add all their methods.
    """

    __slots__ = ()

ByteString.register(bytes)
ByteString.register(bytearray)

class MutableSequence(Sequence):

    __slots__ = ()

    @abstractmethod
    def __setitem__(self, index, value):
        raise IndexError

    @abstractmethod
    def __delitem__(self, index):
        raise IndexError

    @abstractmethod
    def insert(self, index, value):
        raise IndexError

    def append(self, value):
        self.insert(len(self), value)

    def clear(self):
        try:
            while True:
                self.pop()
        except IndexError:
            pass

    def reverse(self):
        n = len(self)
        for i in range(n//2):
            self[i], self[n-i-1] = self[n-i-1], self[i]

    def extend(self, values):
        for v in values:
            self.append(v)

    def pop(self, index=-1):
        v = self[index]
        del self[index]
        return v

    def remove(self, value):
        del self[self.index(value)]

    def __iadd__(self, values):
        self.extend(values)
        return self

MutableSequence.register(list)
MutableSequence.register(bytearray)  # Multiply inheriting, see ByteString
<commit_msg>Clarify that the purpose of computing all the miscellaneous collection types is to register them with the appropriate ABCs.<commit_after># Copyright 2007 Google, Inc. All Rights Reserved.
# Licensed to PSF under a Contributor Agreement.

"""Abstract Base Classes (ABCs) for collections, according to PEP 3119.

Unit tests are in test_collections.
"""

from abc import ABCMeta, abstractmethod
import sys

__all__ = ["Hashable", "Iterable", "Iterator",
           "Sized", "Container", "Callable",
           "Set", "MutableSet",
           "Mapping", "MutableMapping",
           "MappingView", "KeysView", "ItemsView", "ValuesView",
           "Sequence", "MutableSequence",
           "ByteString",
           ]

# Private list of types that we want to register with the various ABCs
# so that they will pass tests like:
#       it = iter(somebytearray)
#       assert isinstance(it, Iterable)
# Note:  in other implementations, these types many not be distinct
# and they make have their own implementation specific types that
# are not included on this list.
bytes_iterator = type(iter(b''))
bytearray_iterator = type(iter(bytearray()))
#callable_iterator = ???
dict_keyiterator = type(iter({}.keys()))
dict_valueiterator = type(iter({}.values()))
dict_itemiterator = type(iter({}.items()))
list_iterator = type(iter([]))
list_reverseiterator = type(iter(reversed([])))
range_iterator = type(iter(range(0)))
set_iterator = type(iter(set()))
str_iterator = type(iter(""))
tuple_iterator = type(iter(()))
zip_iterator = type(iter(zip()))
## views ##
dict_keys = type({}.keys())
dict_values = type({}.values())
dict_items = type({}.items())
## misc ##
dict_proxy = type(type.__dict__)

### ONE-TRICK PONIES ###

class Hashable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __hash__(self):
        return 0

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Hashable:
            for B in C.__mro__:
                if "__hash__" in B.__dict__:
                    if B.__dict__["__hash__"]:
                        return True
                    break
        return NotImplemented

class Iterable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __iter__(self):
        while False:
            yield None

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterable:
            if any("__iter__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

class Iterator(Iterable):

    __slots__ = ()

    @abstractmethod
    def __next__(self):
        raise StopIteration

    def __iter__(self):
        return self

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterator:
            if (any("__next__" in B.__dict__ for B in C.__mro__) and
                any("__iter__" in B.__dict__ for B in C.__mro__)):
                return True
        return NotImplemented

Iterator.register(bytes_iterator)
Iterator.register(bytearray_iterator)
#Iterator.register(callable_iterator)
Iterator.register(dict_keyiterator)
Iterator.register(dict_valueiterator)
Iterator.register(dict_itemiterator)
Iterator.register(list_iterator)
Iterator.register(list_reverseiterator)
Iterator.register(range_iterator)
Iterator.register(set_iterator)
Iterator.register(str_iterator)
Iterator.register(tuple_iterator)
Iterator.register(zip_iterator)

class Sized(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __len__(self):
        return 0

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Sized:
            if any("__len__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

class Container(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __contains__(self, x):
        return False

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Container:
            if any("__contains__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

class Callable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __call__(self, *args, **kwds):
        return False

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Callable:
            if any("__call__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

### SETS ###

class Set(Sized, Iterable, Container):

    """A set is a finite, iterable container.

    This class provides concrete generic implementations of all
    methods except for __contains__, __iter__ and __len__.

    To override the comparisons (presumably for speed, as the
    semantics are fixed), all you have to do is redefine __le__ and
    then the other operations will automatically follow suit.
    """

    __slots__ = ()

    def __le__(self, other):
        if not isinstance(other, Set):
            return NotImplemented
        if len(self) > len(other):
            return False
        for elem in self:
            if elem not in other:
                return False
        return True

    def __lt__(self, other):
        if not isinstance(other, Set):
            return NotImplemented
        return len(self) < len(other) and self.__le__(other)

    def __gt__(self, other):
        if not isinstance(other, Set):
            return NotImplemented
        return other < self

    def __ge__(self, other):
        if not isinstance(other, Set):
            return NotImplemented
        return other <= self

    def __eq__(self, other):
        if not isinstance(other, Set):
            return NotImplemented
        return len(self) == len(other) and self.__le__(other)

    def __ne__(self, other):
        return not (self == other)

    @classmethod
    def _from_iterable(cls, it):
        '''Construct an instance of the class from any iterable input.

        Must override this method if the class constructor signature
        does not accept an iterable for an input.
        '''
        return cls(it)

    def __and__(self, other):
        if not isinstance(other, Iterable):
            return NotImplemented
        return self._from_iterable(value for value in other if value in self)

    def isdisjoint(self, other):
        for value in other:
            if value in self:
                return False
        return True

    def __or__(self, other):
        if not isinstance(other, Iterable):
            return NotImplemented
        chain = (e for s in (self, other) for e in s)
        return self._from_iterable(chain)

    def __sub__(self, other):
        if not isinstance(other, Set):
            if not isinstance(other, Iterable):
                return NotImplemented
            other = self._from_iterable(other)
        return self._from_iterable(value for value in self
                                   if value not in other)

    def __xor__(self, other):
        if not isinstance(other, Set):
            if not isinstance(other, Iterable):
                return NotImplemented
            other = self._from_iterable(other)
        return (self - other) | (other - self)

    def _hash(self):
        """Compute the hash value of a set.

        Note that we don't define __hash__: not all sets are hashable.
        But if you define a hashable set type, its __hash__ should
        call this function.

        This must be compatible __eq__.

        All sets ought to compare equal if they contain the same
        elements, regardless of how they are implemented, and
        regardless of the order of the elements; so there's not much
        freedom for __eq__ or __hash__.  We match the algorithm used
        by the built-in frozenset type.
        """
        MAX = sys.maxsize
        MASK = 2 * MAX + 1
        n = len(self)
        h = 1927868237 * (n + 1)
        h &= MASK
        for x in self:
            hx = hash(x)
            h ^= (hx ^ (hx << 16) ^ 89869747)  * 3644798167
            h &= MASK
        h = h * 69069 + 907133923
        h &= MASK
        if h > MAX:
            h -= MASK + 1
        if h == -1:
            h = 590923713
        return h

Set.register(frozenset)

class MutableSet(Set):

    __slots__ = ()

    @abstractmethod
    def add(self, value):
        """Add an element."""
        raise NotImplementedError

    @abstractmethod
    def discard(self, value):
        """Remove an element.  Do not raise an exception if absent."""
        raise NotImplementedError

    def remove(self, value):
        """Remove an element. If not a member, raise a KeyError."""
        if value not in self:
            raise KeyError(value)
        self.discard(value)

    def pop(self):
        """Return the popped value.  Raise KeyError if empty."""
        it = iter(self)
        try:
            value = next(it)
        except StopIteration:
            raise KeyError
        self.discard(value)
        return value

    def clear(self):
        """This is slow (creates N new iterators!) but effective."""
        try:
            while True:
                self.pop()
        except KeyError:
            pass

    def __ior__(self, it):
        for value in it:
            self.add(value)
        return self

    def __iand__(self, it):
        for value in (self - it):
            self.discard(value)
        return self

    def __ixor__(self, it):
        if it is self:
            self.clear()
        else:
            if not isinstance(it, Set):
                it = self._from_iterable(it)
            for value in it:
                if value in self:
                    self.discard(value)
                else:
                    self.add(value)
        return self

    def __isub__(self, it):
        if it is self:
            self.clear()
        else:
            for value in it:
                self.discard(value)
        return self

MutableSet.register(set)

### MAPPINGS ###

class Mapping(Sized, Iterable, Container):

    __slots__ = ()

    @abstractmethod
    def __getitem__(self, key):
        raise KeyError

    def get(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            return default

    def __contains__(self, key):
        try:
            self[key]
        except KeyError:
            return False
        else:
            return True

    def keys(self):
        return KeysView(self)

    def items(self):
        return ItemsView(self)

    def values(self):
        return ValuesView(self)

    def __eq__(self, other):
        if not isinstance(other, Mapping):
            return NotImplemented
        return dict(self.items()) == dict(other.items())

    def __ne__(self, other):
        return not (self == other)

class MappingView(Sized):

    def __init__(self, mapping):
        self._mapping = mapping

    def __len__(self):
        return len(self._mapping)

    def __repr__(self):
        return '{0.__class__.__name__}({0._mapping!r})'.format(self)

class KeysView(MappingView, Set):

    @classmethod
    def _from_iterable(self, it):
        return set(it)

    def __contains__(self, key):
        return key in self._mapping

    def __iter__(self):
        for key in self._mapping:
            yield key

KeysView.register(dict_keys)

class ItemsView(MappingView, Set):

    @classmethod
    def _from_iterable(self, it):
        return set(it)

    def __contains__(self, item):
        key, value = item
        try:
            v = self._mapping[key]
        except KeyError:
            return False
        else:
            return v == value

    def __iter__(self):
        for key in self._mapping:
            yield (key, self._mapping[key])

ItemsView.register(dict_items)

class ValuesView(MappingView):

    def __contains__(self, value):
        for key in self._mapping:
            if value == self._mapping[key]:
                return True
        return False

    def __iter__(self):
        for key in self._mapping:
            yield self._mapping[key]

ValuesView.register(dict_values)

class MutableMapping(Mapping):

    __slots__ = ()

    @abstractmethod
    def __setitem__(self, key, value):
        raise KeyError

    @abstractmethod
    def __delitem__(self, key):
        raise KeyError

    __marker = object()

    def pop(self, key, default=__marker):
        try:
            value = self[key]
        except KeyError:
            if default is self.__marker:
                raise
            return default
        else:
            del self[key]
            return value

    def popitem(self):
        try:
            key = next(iter(self))
        except StopIteration:
            raise KeyError
        value = self[key]
        del self[key]
        return key, value

    def clear(self):
        try:
            while True:
                self.popitem()
        except KeyError:
            pass

    def update(*args, **kwds):
        if len(args) > 2:
            raise TypeError("update() takes at most 2 positional "
                            "arguments ({} given)".format(len(args)))
        elif not args:
            raise TypeError("update() takes at least 1 argument (0 given)")
        self = args[0]
        other = args[1] if len(args) >= 2 else ()

        if isinstance(other, Mapping):
            for key in other:
                self[key] = other[key]
        elif hasattr(other, "keys"):
            for key in other.keys():
                self[key] = other[key]
        else:
            for key, value in other:
                self[key] = value
        for key, value in kwds.items():
            self[key] = value

    def setdefault(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            self[key] = default
        return default

MutableMapping.register(dict)

### SEQUENCES ###

class Sequence(Sized, Iterable, Container):

    """All the operations on a read-only sequence.

    Concrete subclasses must override __new__ or __init__,
    __getitem__, and __len__.
    """

    __slots__ = ()

    @abstractmethod
    def __getitem__(self, index):
        raise IndexError

    def __iter__(self):
        i = 0
        try:
            while True:
                v = self[i]
                yield v
                i += 1
        except IndexError:
            return

    def __contains__(self, value):
        for v in self:
            if v == value:
                return True
        return False

    def __reversed__(self):
        for i in reversed(range(len(self))):
            yield self[i]

    def index(self, value):
        for i, v in enumerate(self):
            if v == value:
                return i
        raise ValueError

    def count(self, value):
        return sum(1 for v in self if v == value)

Sequence.register(tuple)
Sequence.register(str)
Sequence.register(range)

class ByteString(Sequence):

    """This unifies bytes and bytearray.

    XXX Should add all their methods.
    """

    __slots__ = ()

ByteString.register(bytes)
ByteString.register(bytearray)

class MutableSequence(Sequence):

    __slots__ = ()

    @abstractmethod
    def __setitem__(self, index, value):
        raise IndexError

    @abstractmethod
    def __delitem__(self, index):
        raise IndexError

    @abstractmethod
    def insert(self, index, value):
        raise IndexError

    def append(self, value):
        self.insert(len(self), value)

    def clear(self):
        try:
            while True:
                self.pop()
        except IndexError:
            pass

    def reverse(self):
        n = len(self)
        for i in range(n//2):
            self[i], self[n-i-1] = self[n-i-1], self[i]

    def extend(self, values):
        for v in values:
            self.append(v)

    def pop(self, index=-1):
        v = self[index]
        del self[index]
        return v

    def remove(self, value):
        del self[self.index(value)]

    def __iadd__(self, values):
        self.extend(values)
        return self

MutableSequence.register(list)
MutableSequence.register(bytearray)  # Multiply inheriting, see ByteString
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
    flask.config
    ~~~~~~~~~~~~

    Implements the configuration related objects.

    :copyright: (c) 2014 by Armin Ronacher.
    :license: BSD, see LICENSE for more details.
"""

import imp
import os
import errno

from werkzeug.utils import import_string
from ._compat import string_types, iteritems
from . import json

class ConfigAttribute(object):
    """Makes an attribute forward to the config"""

    def __init__(self, name, get_converter=None):
        self.__name__ = name
        self.get_converter = get_converter

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        rv = obj.config[self.__name__]
        if self.get_converter is not None:
            rv = self.get_converter(rv)
        return rv

    def __set__(self, obj, value):
        obj.config[self.__name__] = value

class Config(dict):
    """Works exactly like a dict but provides ways to fill it from files
    or special dictionaries.  There are two common patterns to populate the
    config.

    Either you can fill the config from a config file::

        app.config.from_pyfile('yourconfig.cfg')

    Or alternatively you can define the configuration options in the
    module that calls :meth:`from_object` or provide an import path to
    a module that should be loaded.  It is also possible to tell it to
    use the same module and with that provide the configuration values
    just before the call::

        DEBUG = True
        SECRET_KEY = 'development key'
        app.config.from_object(__name__)

    In both cases (loading from any Python file or loading from modules),
    only uppercase keys are added to the config.  This makes it possible to use
    lowercase values in the config file for temporary values that are not added
    to the config or to define the config keys in the same file that implements
    the application.

    Probably the most interesting way to load configurations is from an
    environment variable pointing to a file::

        app.config.from_envvar('YOURAPPLICATION_SETTINGS')

    In this case before launching the application you have to set this
    environment variable to the file you want to use.  On Linux and OS X
    use the export statement::

        export YOURAPPLICATION_SETTINGS='/path/to/config/file'

    On windows use `set` instead.

    :param root_path: path to which files are read relative from.  When the
                      config object is created by the application, this is
                      the application's :attr:`~flask.Flask.root_path`.
    :param defaults: an optional dictionary of default values
    """

    def __init__(self, root_path, defaults=None):
        dict.__init__(self, defaults or {})
        self.root_path = root_path

    def from_envvar(self, variable_name, silent=False):
        """Loads a configuration from an environment variable pointing to
        a configuration file.  This is basically just a shortcut with nicer
        error messages for this line of code::

            app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS'])

        :param variable_name: name of the environment variable
        :param silent: set to `True` if you want silent failure for missing
                       files.
        :return: bool. `True` if able to load config, `False` otherwise.
        """
        rv = os.environ.get(variable_name)
        if not rv:
            if silent:
                return False
            raise RuntimeError('The environment variable %r is not set '
                               'and as such configuration could not be '
                               'loaded.  Set this variable and make it '
                               'point to a configuration file' %
                               variable_name)
        return self.from_pyfile(rv, silent=silent)

    def from_pyfile(self, filename, silent=False):
        """Updates the values in the config from a Python file.  This function
        behaves as if the file was imported as module with the
        :meth:`from_object` function.

        :param filename: the filename of the config.  This can either be an
                         absolute filename or a filename relative to the
                         root path.
        :param silent: set to `True` if you want silent failure for missing
                       files.

        .. versionadded:: 0.7
           `silent` parameter.
        """
        filename = os.path.join(self.root_path, filename)
        d = imp.new_module('config')
        d.__file__ = filename
        try:
            with open(filename) as config_file:
                exec(compile(config_file.read(), filename, 'exec'), d.__dict__)
        except IOError as e:
            if silent and e.errno in (errno.ENOENT, errno.EISDIR):
                return False
            e.strerror = 'Unable to load configuration file (%s)' % e.strerror
            raise
        self.from_object(d)
        return True

    def from_object(self, obj):
        """Updates the values from the given object.  An object can be of one
        of the following two types:

        -   a string: in this case the object with that name will be imported
        -   an actual object reference: that object is used directly

        Objects are usually either modules or classes.

        Just the uppercase variables in that object are stored in the config.
        Example usage::

            app.config.from_object('yourapplication.default_config')
            from yourapplication import default_config
            app.config.from_object(default_config)

        You should not use this function to load the actual configuration but
        rather configuration defaults.  The actual config should be loaded
        with :meth:`from_pyfile` and ideally from a location not within the
        package because the package might be installed system wide.

        :param obj: an import name or object
        """
        if isinstance(obj, string_types):
            obj = import_string(obj)
        for key in dir(obj):
            if key.isupper():
                self[key] = getattr(obj, key)

    def from_json(self, filename, silent=False):
        """Updates the values in the config from a JSON file. This function
        behaves as if the JSON object was a dictionary and passed ot the
        :meth:`from_object` function.

        :param filename: the filename of the JSON file.  This can either be an
                         absolute filename or a filename relative to the
                         root path.
        :param silent: set to `True` if you want silent failure for missing
                       files.

        .. versionadded:: 1.0
        """
        filename = os.path.join(self.root_path, filename)

        try:
            with open(filename) as json_file:
                obj = json.loads(json_file.read())
        except IOError as e:
            if silent and e.errno in (errno.ENOENT, errno.EISDIR):
                return False
            e.strerror = 'Unable to load configuration file (%s)' % e.strerror
            raise
        for key in obj.keys():
            if key.isupper():
                self[key] = obj[key]
        return True

    def from_mapping(self, *mapping, **kwargs):
        """Updates the config like :meth:`update` ignoring items with non-upper
        keys.

        .. versionadded:: 1.0
        """
        mappings = []
        if len(mapping) == 1:
            if hasattr(mapping[0], 'items'):
                mappings.append(mapping[0].items())
            else:
                mappings.append(mapping[0])
        elif len(mapping) > 1:
            raise TypeError(
                'expected at most 1 positional argument, got %d' % len(mapping)
            )
        mappings.append(kwargs.items())
        for mapping in mappings:
            for (key, value) in mapping:
                if key.isupper():
                    self[key] = value

    def get_namespace(self, namespace, lowercase=True):
        """Returns a dictionary containing a subset of configuration options
        that match the specified namespace/prefix. Example usage::

            app.config['IMAGE_STORE_TYPE'] = 'fs'
            app.config['IMAGE_STORE_PATH'] = '/var/app/images'
            app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com'
            image_store_config = app.config.get_namespace('IMAGE_STORE_')

        The resulting dictionary `image_store` would look like::

            {
                'type': 'fs',
                'path': '/var/app/images',
                'base_url': 'http://img.website.com'
            }

        This is often useful when configuration options map directly to
        keyword arguments in functions or class constructors.

        :param namespace: a configuration namespace
        :param lowercase: a flag indicating if the keys of the resulting
                          dictionary should be lowercase

        .. versionadded:: 1.0
        """
        rv = {}
        for k, v in iteritems(self):
            if not k.startswith(namespace):
                continue
            key = k[len(namespace):]
            if lowercase:
                key = key.lower()
            rv[key] = v
        return rv

    def __repr__(self):
        return '<%s %s>' % (self.__class__.__name__, dict.__repr__(self))
<commit_msg>Base from_json on from_mapping<commit_after># -*- coding: utf-8 -*-
"""
    flask.config
    ~~~~~~~~~~~~

    Implements the configuration related objects.

    :copyright: (c) 2014 by Armin Ronacher.
    :license: BSD, see LICENSE for more details.
"""

import imp
import os
import errno

from werkzeug.utils import import_string
from ._compat import string_types, iteritems
from . import json

class ConfigAttribute(object):
    """Makes an attribute forward to the config"""

    def __init__(self, name, get_converter=None):
        self.__name__ = name
        self.get_converter = get_converter

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        rv = obj.config[self.__name__]
        if self.get_converter is not None:
            rv = self.get_converter(rv)
        return rv

    def __set__(self, obj, value):
        obj.config[self.__name__] = value

class Config(dict):
    """Works exactly like a dict but provides ways to fill it from files
    or special dictionaries.  There are two common patterns to populate the
    config.

    Either you can fill the config from a config file::

        app.config.from_pyfile('yourconfig.cfg')

    Or alternatively you can define the configuration options in the
    module that calls :meth:`from_object` or provide an import path to
    a module that should be loaded.  It is also possible to tell it to
    use the same module and with that provide the configuration values
    just before the call::

        DEBUG = True
        SECRET_KEY = 'development key'
        app.config.from_object(__name__)

    In both cases (loading from any Python file or loading from modules),
    only uppercase keys are added to the config.  This makes it possible to use
    lowercase values in the config file for temporary values that are not added
    to the config or to define the config keys in the same file that implements
    the application.

    Probably the most interesting way to load configurations is from an
    environment variable pointing to a file::

        app.config.from_envvar('YOURAPPLICATION_SETTINGS')

    In this case before launching the application you have to set this
    environment variable to the file you want to use.  On Linux and OS X
    use the export statement::

        export YOURAPPLICATION_SETTINGS='/path/to/config/file'

    On windows use `set` instead.

    :param root_path: path to which files are read relative from.  When the
                      config object is created by the application, this is
                      the application's :attr:`~flask.Flask.root_path`.
    :param defaults: an optional dictionary of default values
    """

    def __init__(self, root_path, defaults=None):
        dict.__init__(self, defaults or {})
        self.root_path = root_path

    def from_envvar(self, variable_name, silent=False):
        """Loads a configuration from an environment variable pointing to
        a configuration file.  This is basically just a shortcut with nicer
        error messages for this line of code::

            app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS'])

        :param variable_name: name of the environment variable
        :param silent: set to `True` if you want silent failure for missing
                       files.
        :return: bool. `True` if able to load config, `False` otherwise.
        """
        rv = os.environ.get(variable_name)
        if not rv:
            if silent:
                return False
            raise RuntimeError('The environment variable %r is not set '
                               'and as such configuration could not be '
                               'loaded.  Set this variable and make it '
                               'point to a configuration file' %
                               variable_name)
        return self.from_pyfile(rv, silent=silent)

    def from_pyfile(self, filename, silent=False):
        """Updates the values in the config from a Python file.  This function
        behaves as if the file was imported as module with the
        :meth:`from_object` function.

        :param filename: the filename of the config.  This can either be an
                         absolute filename or a filename relative to the
                         root path.
        :param silent: set to `True` if you want silent failure for missing
                       files.

        .. versionadded:: 0.7
           `silent` parameter.
        """
        filename = os.path.join(self.root_path, filename)
        d = imp.new_module('config')
        d.__file__ = filename
        try:
            with open(filename) as config_file:
                exec(compile(config_file.read(), filename, 'exec'), d.__dict__)
        except IOError as e:
            if silent and e.errno in (errno.ENOENT, errno.EISDIR):
                return False
            e.strerror = 'Unable to load configuration file (%s)' % e.strerror
            raise
        self.from_object(d)
        return True

    def from_object(self, obj):
        """Updates the values from the given object.  An object can be of one
        of the following two types:

        -   a string: in this case the object with that name will be imported
        -   an actual object reference: that object is used directly

        Objects are usually either modules or classes.

        Just the uppercase variables in that object are stored in the config.
        Example usage::

            app.config.from_object('yourapplication.default_config')
            from yourapplication import default_config
            app.config.from_object(default_config)

        You should not use this function to load the actual configuration but
        rather configuration defaults.  The actual config should be loaded
        with :meth:`from_pyfile` and ideally from a location not within the
        package because the package might be installed system wide.

        :param obj: an import name or object
        """
        if isinstance(obj, string_types):
            obj = import_string(obj)
        for key in dir(obj):
            if key.isupper():
                self[key] = getattr(obj, key)

    def from_json(self, filename, silent=False):
        """Updates the values in the config from a JSON file. This function
        behaves as if the JSON object was a dictionary and passed to the
        :meth:`from_mapping` function.

        :param filename: the filename of the JSON file.  This can either be an
                         absolute filename or a filename relative to the
                         root path.
        :param silent: set to `True` if you want silent failure for missing
                       files.

        .. versionadded:: 1.0
        """
        filename = os.path.join(self.root_path, filename)

        try:
            with open(filename) as json_file:
                obj = json.loads(json_file.read())
        except IOError as e:
            if silent and e.errno in (errno.ENOENT, errno.EISDIR):
                return False
            e.strerror = 'Unable to load configuration file (%s)' % e.strerror
            raise
        return self.from_mapping(obj)

    def from_mapping(self, *mapping, **kwargs):
        """Updates the config like :meth:`update` ignoring items with non-upper
        keys.

        .. versionadded:: 1.0
        """
        mappings = []
        if len(mapping) == 1:
            if hasattr(mapping[0], 'items'):
                mappings.append(mapping[0].items())
            else:
                mappings.append(mapping[0])
        elif len(mapping) > 1:
            raise TypeError(
                'expected at most 1 positional argument, got %d' % len(mapping)
            )
        mappings.append(kwargs.items())
        for mapping in mappings:
            for (key, value) in mapping:
                if key.isupper():
                    self[key] = value
        return True

    def get_namespace(self, namespace, lowercase=True):
        """Returns a dictionary containing a subset of configuration options
        that match the specified namespace/prefix. Example usage::

            app.config['IMAGE_STORE_TYPE'] = 'fs'
            app.config['IMAGE_STORE_PATH'] = '/var/app/images'
            app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com'
            image_store_config = app.config.get_namespace('IMAGE_STORE_')

        The resulting dictionary `image_store` would look like::

            {
                'type': 'fs',
                'path': '/var/app/images',
                'base_url': 'http://img.website.com'
            }

        This is often useful when configuration options map directly to
        keyword arguments in functions or class constructors.

        :param namespace: a configuration namespace
        :param lowercase: a flag indicating if the keys of the resulting
                          dictionary should be lowercase

        .. versionadded:: 1.0
        """
        rv = {}
        for k, v in iteritems(self):
            if not k.startswith(namespace):
                continue
            key = k[len(namespace):]
            if lowercase:
                key = key.lower()
            rv[key] = v
        return rv

    def __repr__(self):
        return '<%s %s>' % (self.__class__.__name__, dict.__repr__(self))
<|endoftext|>


<commit_before>#! /usr/bin/env python3
"""Main entrypoint for clowder command"""

if __name__ == '__main__':
    raise SystemExit(main())

import argcomplete, argparse, colorama, os, signal, sys
from termcolor import cprint
from clowder.model.clowder_repo import ClowderRepo
from clowder.model.clowder_yaml import ClowderYAML
from clowder.utility.print_utilities import (
    print_clowder_not_found_message
)

class Command(object):
    """Command class for parsing commandline options"""

    def __init__(self):
        self.root_directory = os.getcwd()
        self.clowder = None
        self.versions = None
        self.group_names = ''
        # Load current clowder.yml config if it exists
        if os.path.isdir(os.path.join(self.root_directory, 'clowder')):
            self.clowder = ClowderYAML(self.root_directory)
            self.versions = self.clowder.get_fixed_version_names()
            if self.clowder.group_names is not None:
                self.group_names = self.clowder.group_names
        # clowder argparse setup
        command_description = 'Utility for managing multiple git repositories'
        parser = argparse.ArgumentParser(description=command_description)
        subparsers = parser.add_subparsers(dest='command')
        self._configure_subparsers(subparsers)
        # Argcomplete and arguments parsing
        argcomplete.autocomplete(parser)
        self.args = parser.parse_args()

        print('')
        if not hasattr(self, self.args.command):
            exit_unrecognized_command(parser)
        # use dispatch pattern to invoke method with same name
        getattr(self, self.args.command)()
        print('')

    def _configure_subparsers(self, subparsers):
        """Configure all clowder command subparsers and arguments"""
        # clowder breed
        breed_help = 'Clone repository to clowder directory and create clowder.yaml symlink'
        parser_breed = subparsers.add_parser('breed', help=breed_help)
        parser_breed.add_argument('url', help='URL of repo containing clowder.yaml')
        # clowder herd
        herd_help = 'Clone and sync latest changes for projects'
        parser_herd = subparsers.add_parser('herd', help=herd_help)
        group = parser_herd.add_mutually_exclusive_group()
        group.add_argument('--version', '-v', choices=self.versions,
                           help='Version name to herd')
        group.add_argument('--groups', '-g', choices=self.group_names,
                           nargs='+', help='Groups to herd')
        # clowder forall
        forall_help = 'Run command in all clowder projects'
        parser_forall = subparsers.add_parser('forall', help=forall_help)
        forall_cmd_help = 'Command to run in clowder projects'
        parser_forall.add_argument('--command', '-c', dest='cmd', required=True,
                                   help=forall_cmd_help)
        parser_forall.add_argument('--groups', '-g', choices=self.group_names,
                                   nargs='+', help='Groups to herd')
        # clowder meow
        parser_meow = subparsers.add_parser('meow', add_help=False,
                                            help='Print status for projects')
        parser_meow.add_argument('--verbose', '-v', action='store_true',
                                 help='Print detailed diff status')
        # clowder fix
        fix_help = 'Create version of clowder.yaml for current repos'
        parser_fix = subparsers.add_parser('fix', help=fix_help)
        parser_fix.add_argument('-version', '-v',
                                required=True, help='Version name to fix')
        # clowder groom
        groom_help = 'Discard current changes in all projects and clowder repo'
        subparsers.add_parser('groom', add_help=False, help=groom_help)
        # clowder stash
        stash_help = 'Stash current changes in all projects and clowder repo'
        subparsers.add_parser('stash', add_help=False, help=stash_help)
        # clowder sync
        subparsers.add_parser('sync', add_help=False, help='Sync clowder repo')

    def breed(self):
        """clowder breed command"""
        if self.clowder is None:
            cprint('Breed from %s\n' % self.args.url, 'yellow')
            clowder_repo = ClowderRepo(self.root_directory)
            clowder_repo.breed(self.args.url)
        else:
            cprint('Clowder already bred in this directory, exiting...\n', 'red')
            sys.exit()

    def fix(self):
        """clowder fix command"""
        if self.clowder is not None:
            cprint('Fix...\n', 'yellow')
            self.clowder.fix_version(self.args.version)
        else:
            exit_clowder_not_found()

    def forall(self):
        """clowder forall command"""
        if self.clowder is not None:
            cprint('Forall...\n', 'yellow')
            if self.args.groups is None:
                self.clowder.forall(self.args.cmd)
            else:
                self.clowder.forall_groups(self.args.cmd, self.args.groups)
        else:
            exit_clowder_not_found()

    def groom(self):
        """clowder groom command"""
        if self.clowder is not None:
            cprint('Groom...\n', 'yellow')
            self.clowder.groom()
        else:
            exit_clowder_not_found()

    def herd(self):
        """clowder herd command"""
        if self.clowder is not None:
            cprint('Herd...\n', 'yellow')
            clowder_repo = ClowderRepo(self.root_directory)
            clowder_repo.symlink_yaml(self.args.version)
            clowder = ClowderYAML(self.root_directory)
            if self.args.version is None:
                if self.args.groups is None:
                    clowder.herd_all()
                else:
                    clowder.herd_groups(self.args.groups)
            else:
                clowder.herd_version(self.args.version)
        else:
            exit_clowder_not_found()

    def meow(self):
        """clowder meow command"""
        if self.clowder is not None:
            cprint('Meow...\n', 'yellow')
            if self.args.verbose:
                self.clowder.meow_verbose()
            else:
                self.clowder.meow()
        else:
            exit_clowder_not_found()

    def stash(self):
        """clowder stash command"""
        if self.clowder is not None:
            cprint('Stash...\n', 'yellow')
            self.clowder.stash()
        else:
            exit_clowder_not_found()

    def sync(self):
        """clowder sync command"""
        if self.clowder is not None:
            cprint('Sync...\n', 'yellow')
            clowder_repo = ClowderRepo(self.root_directory)
            clowder_repo.sync()
        else:
            exit_clowder_not_found()

def main():
    """Main entrypoint for clowder command"""
    signal.signal(signal.SIGINT, signal_handler)
    colorama.init()
    Command()

# Disable errors shown by pylint for unused arguments
# pylint: disable=W0613
def signal_handler(sig, frame):
    """Signal handler for Ctrl+C trap"""
    print('')
    sys.exit(0)

def exit_unrecognized_command(parser):
    """Print unrecognized command message and exit"""
    cprint('Unrecognized command\n', 'red')
    parser.print_help()
    print('')
    sys.exit(1)

def exit_clowder_not_found():
    """Print clowder not found message and exit"""
    print_clowder_not_found_message()
    sys.exit(1)
<commit_msg>Refactor: Move command with silenced warnings to bottom of file<commit_after>#! /usr/bin/env python3
"""Main entrypoint for clowder command"""

if __name__ == '__main__':
    raise SystemExit(main())

import argcomplete, argparse, colorama, os, signal, sys
from termcolor import cprint
from clowder.model.clowder_repo import ClowderRepo
from clowder.model.clowder_yaml import ClowderYAML
from clowder.utility.print_utilities import (
    print_clowder_not_found_message
)

class Command(object):
    """Command class for parsing commandline options"""

    def __init__(self):
        self.root_directory = os.getcwd()
        self.clowder = None
        self.versions = None
        self.group_names = ''
        # Load current clowder.yml config if it exists
        if os.path.isdir(os.path.join(self.root_directory, 'clowder')):
            self.clowder = ClowderYAML(self.root_directory)
            self.versions = self.clowder.get_fixed_version_names()
            if self.clowder.group_names is not None:
                self.group_names = self.clowder.group_names
        # clowder argparse setup
        command_description = 'Utility for managing multiple git repositories'
        parser = argparse.ArgumentParser(description=command_description)
        subparsers = parser.add_subparsers(dest='command')
        self._configure_subparsers(subparsers)
        # Argcomplete and arguments parsing
        argcomplete.autocomplete(parser)
        self.args = parser.parse_args()

        print('')
        if not hasattr(self, self.args.command):
            exit_unrecognized_command(parser)
        # use dispatch pattern to invoke method with same name
        getattr(self, self.args.command)()
        print('')

    def _configure_subparsers(self, subparsers):
        """Configure all clowder command subparsers and arguments"""
        # clowder breed
        breed_help = 'Clone repository to clowder directory and create clowder.yaml symlink'
        parser_breed = subparsers.add_parser('breed', help=breed_help)
        parser_breed.add_argument('url', help='URL of repo containing clowder.yaml')
        # clowder herd
        herd_help = 'Clone and sync latest changes for projects'
        parser_herd = subparsers.add_parser('herd', help=herd_help)
        group = parser_herd.add_mutually_exclusive_group()
        group.add_argument('--version', '-v', choices=self.versions,
                           help='Version name to herd')
        group.add_argument('--groups', '-g', choices=self.group_names,
                           nargs='+', help='Groups to herd')
        # clowder forall
        forall_help = 'Run command in all clowder projects'
        parser_forall = subparsers.add_parser('forall', help=forall_help)
        forall_cmd_help = 'Command to run in clowder projects'
        parser_forall.add_argument('--command', '-c', dest='cmd', required=True,
                                   help=forall_cmd_help)
        parser_forall.add_argument('--groups', '-g', choices=self.group_names,
                                   nargs='+', help='Groups to herd')
        # clowder meow
        parser_meow = subparsers.add_parser('meow', add_help=False,
                                            help='Print status for projects')
        parser_meow.add_argument('--verbose', '-v', action='store_true',
                                 help='Print detailed diff status')
        # clowder fix
        fix_help = 'Create version of clowder.yaml for current repos'
        parser_fix = subparsers.add_parser('fix', help=fix_help)
        parser_fix.add_argument('-version', '-v',
                                required=True, help='Version name to fix')
        # clowder groom
        groom_help = 'Discard current changes in all projects and clowder repo'
        subparsers.add_parser('groom', add_help=False, help=groom_help)
        # clowder stash
        stash_help = 'Stash current changes in all projects and clowder repo'
        subparsers.add_parser('stash', add_help=False, help=stash_help)
        # clowder sync
        subparsers.add_parser('sync', add_help=False, help='Sync clowder repo')

    def breed(self):
        """clowder breed command"""
        if self.clowder is None:
            cprint('Breed from %s\n' % self.args.url, 'yellow')
            clowder_repo = ClowderRepo(self.root_directory)
            clowder_repo.breed(self.args.url)
        else:
            cprint('Clowder already bred in this directory, exiting...\n', 'red')
            sys.exit()

    def fix(self):
        """clowder fix command"""
        if self.clowder is not None:
            cprint('Fix...\n', 'yellow')
            self.clowder.fix_version(self.args.version)
        else:
            exit_clowder_not_found()

    def forall(self):
        """clowder forall command"""
        if self.clowder is not None:
            cprint('Forall...\n', 'yellow')
            if self.args.groups is None:
                self.clowder.forall(self.args.cmd)
            else:
                self.clowder.forall_groups(self.args.cmd, self.args.groups)
        else:
            exit_clowder_not_found()

    def groom(self):
        """clowder groom command"""
        if self.clowder is not None:
            cprint('Groom...\n', 'yellow')
            self.clowder.groom()
        else:
            exit_clowder_not_found()

    def herd(self):
        """clowder herd command"""
        if self.clowder is not None:
            cprint('Herd...\n', 'yellow')
            clowder_repo = ClowderRepo(self.root_directory)
            clowder_repo.symlink_yaml(self.args.version)
            clowder = ClowderYAML(self.root_directory)
            if self.args.version is None:
                if self.args.groups is None:
                    clowder.herd_all()
                else:
                    clowder.herd_groups(self.args.groups)
            else:
                clowder.herd_version(self.args.version)
        else:
            exit_clowder_not_found()

    def meow(self):
        """clowder meow command"""
        if self.clowder is not None:
            cprint('Meow...\n', 'yellow')
            if self.args.verbose:
                self.clowder.meow_verbose()
            else:
                self.clowder.meow()
        else:
            exit_clowder_not_found()

    def stash(self):
        """clowder stash command"""
        if self.clowder is not None:
            cprint('Stash...\n', 'yellow')
            self.clowder.stash()
        else:
            exit_clowder_not_found()

    def sync(self):
        """clowder sync command"""
        if self.clowder is not None:
            cprint('Sync...\n', 'yellow')
            clowder_repo = ClowderRepo(self.root_directory)
            clowder_repo.sync()
        else:
            exit_clowder_not_found()

def main():
    """Main entrypoint for clowder command"""
    signal.signal(signal.SIGINT, signal_handler)
    colorama.init()
    Command()

def exit_unrecognized_command(parser):
    """Print unrecognized command message and exit"""
    cprint('Unrecognized command\n', 'red')
    parser.print_help()
    print('')
    sys.exit(1)

def exit_clowder_not_found():
    """Print clowder not found message and exit"""
    print_clowder_not_found_message()
    sys.exit(1)

# Disable errors shown by pylint for unused arguments
# pylint: disable=W0613
def signal_handler(sig, frame):
    """Signal handler for Ctrl+C trap"""
    print('')
    sys.exit(0)
<|endoftext|>


<commit_before># -*- coding: UTF-8 -*-
from celery.app import App
from celery.bin.celery import CeleryCommand as _CeleryCommand
from flask.ext.script import Command, Option, Manager

import argparse

class _CeleryConfig(object):

    def __init__(self, celery):
        self.celery = celery

class Celery(App):

    def __init__(self, app=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        self.conf.update(app.config)
        if not hasattr(app, 'extensions'):
            app.extensions = {}
        app.extensions['celery'] = _CeleryConfig(self)

    def __reduce_args__(self):
        return super().__reduce_args__()

def option_optparse_to_argparse(opt_option):
    opt_option_dict = vars(opt_option)
    # args name_or_flag
    arg_args = opt_option_dict['_short_opts'] + opt_option_dict['_long_opts']
    # kwargs
    arg_kwargs = {}
    # dest
    arg_kwargs['dest'] = opt_option_dict['dest']
    # help
    arg_kwargs['help'] = opt_option_dict['help']
    # nargs
    arg_kwargs['nargs'] = opt_option_dict['nargs']
    # const
    arg_kwargs['const'] = opt_option_dict['const']
    # default
    if opt_option_dict['default'] != ('NO', 'DEFAULT'):
        arg_kwargs['default'] = opt_option_dict['default']
    # type
    type_transfer = {
        'string': str,
        'int': int,
        'choice': str,
        'float': float,
        'complex': complex,
    }
    if opt_option_dict['type']:
        arg_kwargs['type'] = type_transfer[opt_option_dict['type']]
    else:
        arg_kwargs['type'] = None
    # choices
    arg_kwargs['choices'] = opt_option_dict['choices']
    # metavar
    arg_kwargs['metavar'] = opt_option_dict['metavar']
    # action
    arg_kwargs['action'] = opt_option_dict['action']
    if arg_kwargs['action'] == 'store_true':
        for key in ['const', 'type', 'nargs', 'metavar', 'choices']:
            arg_kwargs.pop(key)
    elif arg_kwargs['action'] == 'store':
        arg_kwargs.pop('nargs')
    if arg_kwargs['action'] == 'callback':
        callback_func = opt_option_dict['callback']
        callback_args = opt_option_dict['callback_args']
        callback_kwargs = opt_option_dict['callback_kwargs']

        class _action_cls(argparse.Action):

            def __call__(self, parser, namespace, values, option_string=None):
                return callback_func(*callback_args, **callback_kwargs)

        arg_kwargs['action'] = _action_cls
        arg_kwargs['nargs'] = 0

    return Option(*arg_args, **arg_kwargs)

class TransferCommand(Command):

    def __init__(self, celery_command):
        super().__init__()
        self.celery_command = celery_command
        for celery_option in list(celery_command.get_options()):
            transfer_option = option_optparse_to_argparse(celery_option)
            self.add_option(transfer_option)

    def run(self, **kwargs):
        self.celery_command.run(**kwargs)

def CeleryCommand(app):
    command_manager = Manager(usage='Perform celery command')
    for name, command_class in _CeleryCommand.commands.items():
        command_class_instance = command_class(app=app)
        command_manager.add_command(name, TransferCommand(command_class_instance))
    return command_manager
<commit_msg>Upgrade CeleryCommand, from function to class.<commit_after># -*- coding: UTF-8 -*-
from celery import Celery as _Celery
from celery.bin.celery import CeleryCommand as _CeleryCommand
from flask.ext.script import Command, Option, Manager

import argparse

__all__ = ['Celery', 'CeleryCommand']

class _CeleryConfig(object):

    def __init__(self, celery):
        self.celery = celery

class Celery(_Celery):

    def __init__(self, app=None, *args, **kwargs):
        super(_Celery, self).__init__(*args, **kwargs)
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        self.conf.update(app.config)
        if not hasattr(app, 'extensions'):
            app.extensions = {}
        app.extensions['celery'] = _CeleryConfig(self)

    def __reduce_args__(self):
        return super().__reduce_args__()

class _TransferCommand(Command):

    def __init__(self, celery_command):
        super(Command, self).__init__()
        self.celery_command = celery_command
        for celery_option in list(celery_command.get_options()):
            self.add_option(self._transfer_option(celery_option))

    def _transfer_option(self, opt_option):
        option_kwargs = vars(opt_option)
        # args name_or_flag
        option_args = option_kwargs.pop('_short_opts') + option_kwargs.pop('_long_opts')
        # default
        if option_kwargs['default'] == ('NO', 'DEFAULT'):
            option_kwargs['default'] = None
        # type
        type_transfer = {
            'string': str,
            'int': int,
            'choice': str,
            'float': float,
            'complex': complex,
        }
        if option_kwargs['type']:
            option_kwargs['type'] = type_transfer.get(option_kwargs['type'], option_kwargs['type'])
        # action
        if option_kwargs['action'] == 'store_true':
            for key in ['const', 'type', 'nargs', 'metavar', 'choices']:
                option_kwargs.pop(key)
        elif option_kwargs['action'] == 'store':
            option_kwargs.pop('nargs')
        if option_kwargs['action'] == 'callback':
            callback_func = option_kwargs.pop('callback')
            callback_args = option_kwargs.pop('callback_args')
            callback_kwargs = option_kwargs.pop('callback_kwargs')

            class _action_cls(argparse.Action):

                def __call__(self, parser, namespace, values, option_string=None):
                    return callback_func(*callback_args, **callback_kwargs)

            arg_kwargs['action'] = _action_cls
            arg_kwargs['nargs'] = 0

        return Option(*option_args, **option_kwargs)

    def run(self, **kwargs):
        self.celery_command.run(**kwargs)

class CeleryCommand(Manager):

    def __init__(self, celery):
        super(Manager, self).__init__(usage='Perform celery command')
        for name, command_class in _CeleryCommand.commands.items():
            command_class_instance = command_class(app=celery)
            self.add_command(name, _TransferCommand(command_class_instance))

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
    flaskext.wtf
    ~~~~~~~~~~~~

    Description of the module goes here...

    :copyright: (c) 2010 by Dan Jacob.
    :license: BSD, see LICENSE for more details.
"""
import uuid

from wtforms.fields import BooleanField, DecimalField, DateField, \
    DateTimeField, FieldList, FileField, FloatField, FormField,\
    HiddenField, IntegerField, PasswordField, RadioField, SelectField, \
    SelectMultipleField, SubmitField, TextField, TextAreaField

from wtforms.validators import Email, email, EqualTo, equal_to, \
    IPAddress, ip_address, Length, length, NumberRange, number_range, \
    Optional, optional, Required, required, Regexp, regexp, \
    URL, url, AnyOf, any_of, NoneOf, none_of

try:
    # try to import sqlalchemy-based fields
    # otherwise ignore
    from wtforms.ext.sqlalchemy.fields import QuerySelectField, \
        QuerySelectMultipleField, ModelSelectField
    _is_sqlalchemy = True
except ImportError:
    _is_sqlalchemy = False

from wtforms import Form as BaseForm
from wtforms import fields, validators, ValidationError

from flask import request, session, current_app

from jinja2 import Markup

__all__  = ['Form', 'ValidationForm', 'fields', 'validators']
__all__ += fields.__all__
__all__ += validators.__all__

if _is_sqlalchemy:
    __all__ += ['QuerySelectField', 'QuerySelectMultipleField',
                'ModelSelectField']

def _generate_csrf_token():
    return str(uuid.uuid4())

class Form(BaseForm):

    csrf = fields.HiddenField()

    def __init__(self, formdata=None, *args, **kwargs):

        if formdata is None:
            formdata = request.form

        self.csrf_enabled = kwargs.pop('csrf_enabled', True)
        self.csrf_enabled = self.csrf_enabled and \
            current_app.config.get('CSRF_ENABLED', True)

        csrf_token = session.get('_csrf_token')
        if csrf_token is None:
            csrf_token = _generate_csrf_token()
            session['_csrf_token'] = csrf_token

        super(Form, self).__init__(formdata, csrf=csrf_token, *args, **kwargs)

    @property
    def csrf_token(self):
        """
        Renders CSRF field inside a hidden DIV.
        """
        return Markup('
%s
' % self.csrf)

    def validate_csrf(self, field):
        if not self.csrf_enabled or request.is_xhr:
            return
        csrf_token = session.pop('_csrf_token', None)
        if not field.data or field.data != csrf_token:
            raise ValidationError, "Missing or invalid CSRF token"

    def validate_on_POST(self):
        return request.method == "POST" and self.validate()

<commit_msg>widgets added<commit_after># -*- coding: utf-8 -*-
"""
    flaskext.wtf
    ~~~~~~~~~~~~

    Description of the module goes here...

    :copyright: (c) 2010 by Dan Jacob.
    :license: BSD, see LICENSE for more details.
"""
import uuid

from wtforms.fields import BooleanField, DecimalField, DateField, \
    DateTimeField, FieldList, FileField, FloatField, FormField,\
    HiddenField, IntegerField, PasswordField, RadioField, SelectField, \
    SelectMultipleField, SubmitField, TextField, TextAreaField

from wtforms.validators import Email, email, EqualTo, equal_to, \
    IPAddress, ip_address, Length, length, NumberRange, number_range, \
    Optional, optional, Required, required, Regexp, regexp, \
    URL, url, AnyOf, any_of, NoneOf, none_of

from wtforms.widgets import CheckboxInput, FileInput, HiddenInput, \
    ListWidget, PasswordInput, RadioInput, Select, SubmitInput, \
    TableWidget, TextArea, TextInput

try:
    # try to import sqlalchemy-based fields
    # otherwise ignore
    from wtforms.ext.sqlalchemy.fields import QuerySelectField, \
        QuerySelectMultipleField, ModelSelectField
    _is_sqlalchemy = True
except ImportError:
    _is_sqlalchemy = False

from wtforms import Form as BaseForm
from wtforms import fields, widgets, validators, ValidationError

from flask import request, session, current_app

from jinja2 import Markup

__all__  = ['Form', 'ValidationForm', 'fields', 'validators', 'widget']
__all__ += fields.__all__
__all__ += validators.__all__
__all__ += widgets.__all__

if _is_sqlalchemy:
    __all__ += ['QuerySelectField', 'QuerySelectMultipleField',
                'ModelSelectField']

def _generate_csrf_token():
    return str(uuid.uuid4())

class Form(BaseForm):

    csrf = fields.HiddenField()

    def __init__(self, formdata=None, *args, **kwargs):

        if formdata is None:
            formdata = request.form

        self.csrf_enabled = kwargs.pop('csrf_enabled', True)
        self.csrf_enabled = self.csrf_enabled and \
            current_app.config.get('CSRF_ENABLED', True)

        csrf_token = session.get('_csrf_token')
        if csrf_token is None:
            csrf_token = _generate_csrf_token()
            session['_csrf_token'] = csrf_token

        super(Form, self).__init__(formdata, csrf=csrf_token, *args, **kwargs)

    @property
    def csrf_token(self):
        """
        Renders CSRF field inside a hidden DIV.
        """
        return Markup('
%s
' % self.csrf)

    def validate_csrf(self, field):
        if not self.csrf_enabled or request.is_xhr:
            return
        csrf_token = session.pop('_csrf_token', None)
        if not field.data or field.data != csrf_token:
            raise ValidationError, "Missing or invalid CSRF token"

    def validate_on_POST(self):
        return request.method == "POST" and self.validate()

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
    flaskext.wtf
    ~~~~~~~~~~~~

    Description of the module goes here...

    :copyright: (c) 2010 by Dan Jacob.
    :license: BSD, see LICENSE for more details.
"""
import uuid

from wtforms.fields import BooleanField, DecimalField, DateField, \
    DateTimeField, FieldList, FloatField, FileField, FormField,\
    HiddenField, IntegerField, PasswordField, RadioField, SelectField, \
    SelectMultipleField, SubmitField, TextField, TextAreaField

from wtforms.validators import Email, email, EqualTo, equal_to, \
    IPAddress, ip_address, Length, length, NumberRange, number_range, \
    Optional, optional, Required, required, Regexp, regexp, \
    URL, url, AnyOf, any_of, NoneOf, none_of

from wtforms.widgets import CheckboxInput, FileInput, HiddenInput, \
    ListWidget, PasswordInput, RadioInput, Select, SubmitInput, \
    TableWidget, TextArea, TextInput

try:
    # try to import sqlalchemy-based fields
    # otherwise ignore
    from wtforms.ext.sqlalchemy.fields import QuerySelectField, \
        QuerySelectMultipleField, ModelSelectField
    _is_sqlalchemy = True
except ImportError:
    _is_sqlalchemy = False

from wtforms import Form as BaseForm
from wtforms import fields, widgets, validators, ValidationError

from flask import request, session, current_app

from jinja2 import Markup

import recaptcha

from recaptcha.fields import RecaptchaField
from recaptcha.widgets import RecaptchaWidget
from recaptcha.validators import Recaptcha

__all__  = ['Form', 'ValidationForm', 'fields', 'validators', 'widgets']
__all__ += fields.__all__
__all__ += validators.__all__
__all__ += widgets.__all__
__all__ += recaptcha.__all__

if _is_sqlalchemy:
    __all__ += ['QuerySelectField',
                'QuerySelectMultipleField',
                'ModelSelectField']

def _generate_csrf_token():
    return str(uuid.uuid4())

class Form(BaseForm):

    csrf = fields.HiddenField()

    def __init__(self, formdata=None, *args, **kwargs):

        csrf_enabled = kwargs.pop('csrf_enabled', None)

        if csrf_enabled is None:
            csrf_enabled = current_app.config.get('CSRF_ENABLED', True)

        self.csrf_enabled = csrf_enabled

        self.csrf_session_key = kwargs.pop('csrf_session_key', None)

        if self.csrf_session_key is None:
            self.csrf_session_key = \
                current_app.config.get('CSRF_SESSION_KEY', '_csrf_token')

        csrf_token = session.get(self.csrf_session_key, None)

        if csrf_token is None:
            csrf_token = self.reset_csrf()

        super(Form, self).__init__(formdata, csrf=csrf_token, *args, **kwargs)

    def is_submitted(self):

        return request and request.method in ("PUT", "POST")

    def process(self, formdata=None, obj=None, **kwargs):

        if self.is_submitted():

            if formdata is None:
                formdata = request.form

            if request.files:

                for name, field in self._fields.iteritems():
                    if isinstance(field, FileField):
                        field.file = request.files.get(name)

        super(Form, self).process(formdata, obj, **kwargs)

    @property
    def csrf_token(self):
        """
        Renders CSRF field inside a hidden DIV.
        """
        return Markup('
%s
' % self.csrf)

    def reset_csrf(self):
        """
        Resets the CSRF token in the session. If you are reusing the form
        in the same view (i.e. you are not redirecting somewhere else)
        it's recommended you call this before rendering the form.
        """

        csrf_token = _generate_csrf_token()
        session[self.csrf_session_key] = csrf_token
        return csrf_token

    def validate_csrf(self, field):
        if not self.csrf_enabled or request.is_xhr:
            return

        csrf_token = session.pop(self.csrf_session_key, None)
        is_valid = field.data and field.data == csrf_token

        # reset this field, otherwise stale token is displayed
        field.data = self.reset_csrf()

        if not is_valid:
            raise ValidationError, "Missing or invalid CSRF token"

    def validate_on_submit(self):
        return self.is_submitted() and self.validate()

<commit_msg>rolled back previous change<commit_after># -*- coding: utf-8 -*-
"""
    flaskext.wtf
    ~~~~~~~~~~~~

    Description of the module goes here...

    :copyright: (c) 2010 by Dan Jacob.
    :license: BSD, see LICENSE for more details.
"""
import uuid

from wtforms.fields import BooleanField, DecimalField, DateField, \
    DateTimeField, FieldList, FloatField, FileField, FormField,\
    HiddenField, IntegerField, PasswordField, RadioField, SelectField, \
    SelectMultipleField, SubmitField, TextField, TextAreaField

from wtforms.validators import Email, email, EqualTo, equal_to, \
    IPAddress, ip_address, Length, length, NumberRange, number_range, \
    Optional, optional, Required, required, Regexp, regexp, \
    URL, url, AnyOf, any_of, NoneOf, none_of

from wtforms.widgets import CheckboxInput, FileInput, HiddenInput, \
    ListWidget, PasswordInput, RadioInput, Select, SubmitInput, \
    TableWidget, TextArea, TextInput

try:
    # try to import sqlalchemy-based fields
    # otherwise ignore
    from wtforms.ext.sqlalchemy.fields import QuerySelectField, \
        QuerySelectMultipleField, ModelSelectField
    _is_sqlalchemy = True
except ImportError:
    _is_sqlalchemy = False

from wtforms import Form as BaseForm
from wtforms import fields, widgets, validators, ValidationError

from flask import request, session, current_app

from jinja2 import Markup

import recaptcha

from recaptcha.fields import RecaptchaField
from recaptcha.widgets import RecaptchaWidget
from recaptcha.validators import Recaptcha

__all__  = ['Form', 'ValidationForm', 'fields', 'validators', 'widgets']
__all__ += fields.__all__
__all__ += validators.__all__
__all__ += widgets.__all__
__all__ += recaptcha.__all__

if _is_sqlalchemy:
    __all__ += ['QuerySelectField',
                'QuerySelectMultipleField',
                'ModelSelectField']

def _generate_csrf_token():
    return str(uuid.uuid4())

class Form(BaseForm):

    csrf = fields.HiddenField()

    def __init__(self, formdata=None, *args, **kwargs):

        csrf_enabled = kwargs.pop('csrf_enabled', None)

        if csrf_enabled is None:
            csrf_enabled = current_app.config.get('CSRF_ENABLED', True)

        self.csrf_enabled = csrf_enabled

        self.csrf_session_key = kwargs.pop('csrf_session_key', None)

        if self.csrf_session_key is None:
            self.csrf_session_key = \
                current_app.config.get('CSRF_SESSION_KEY', '_csrf_token')

        csrf_token = session.get(self.csrf_session_key, None)

        if csrf_token is None:
            csrf_token = self.reset_csrf()

        super(Form, self).__init__(formdata, csrf=csrf_token, *args, **kwargs)

    def is_submitted(self):

        return request and request.method in ("PUT", "POST")

    def process(self, formdata=None, obj=None, **kwargs):

        if self.is_submitted():

            if formdata is None:
                formdata = request.form

            if request.files:

                for name, field in self._fields.iteritems():
                    if isinstance(field, FileField) and name in request.files:
                        field.file = request.files[name]

        super(Form, self).process(formdata, obj, **kwargs)

    @property
    def csrf_token(self):
        """
        Renders CSRF field inside a hidden DIV.
        """
        return Markup('
%s
' % self.csrf)

    def reset_csrf(self):
        """
        Resets the CSRF token in the session. If you are reusing the form
        in the same view (i.e. you are not redirecting somewhere else)
        it's recommended you call this before rendering the form.
        """

        csrf_token = _generate_csrf_token()
        session[self.csrf_session_key] = csrf_token
        return csrf_token

    def validate_csrf(self, field):
        if not self.csrf_enabled or request.is_xhr:
            return

        csrf_token = session.pop(self.csrf_session_key, None)
        is_valid = field.data and field.data == csrf_token

        # reset this field, otherwise stale token is displayed
        field.data = self.reset_csrf()

        if not is_valid:
            raise ValidationError, "Missing or invalid CSRF token"

    def validate_on_submit(self):
        return self.is_submitted() and self.validate()

<|endoftext|>


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

import sys
import flickr

from optparse import OptionParser

def main():
    opt, args = parse_args()
    f = flickr.Flickr()

    try:
        num = int(opt.num)
    except (ValueError, TypeError):
        num = 5

    results = None
    if opt.query is not None:
        results = f.search_photos(opt.query, num)
    elif opt.interesting:
        results = f.interesting_photos(num)
    elif opt.recent:
        results = f.recent_photos(num)
    else:
        print 'Usage: ./flickr_fetch.py <options> or --help for info'

    if results is not None:
        show_photos(results)

def show_photos(results):
    for id, title in results:
        print id, ': ', title

def parse_args():
    """ Parce command-line arguments """
    parser = OptionParser()

    parser.add_option('-q', '--query', dest='query',
        help='flickr search QUERY', metavar='QUERY')

    parser.add_option('-i', '--interesting', action='store_true',
        dest='interesting', default=False, help='interesting photos')

    parser.add_option('-r', '--recent', action='store_true',
        dest='recent', default=False, help='recent photos')

    parser.add_option('-n', '--num', dest='num',
        help='result SIZE', metavar='SIZE')

    return parser.parse_args()

if __name__ == '__main__':
    sys.exit(main())

<commit_msg>also display picture url<commit_after>#! /usr/bin/env python

import sys
import flickr

from optparse import OptionParser

def main():
    opt, args = parse_args()
    f = flickr.Flickr()

    try:
        num = int(opt.num)
    except (ValueError, TypeError):
        num = 5

    results = None
    if opt.query is not None:
        results = f.search_photos(opt.query, num)
    elif opt.interesting:
        results = f.interesting_photos(num)
    elif opt.recent:
        results = f.recent_photos(num)
    else:
        print 'Usage: ./flickr_fetch.py <options> or --help for info'

    if results is not None:
        show_photos(f, results)

def show_photos(f, results):
    for id, title in results:
        print id, ': ', title
        print f.get_photo_urls(id)['Medium']

def parse_args():
    """ Parce command-line arguments """
    parser = OptionParser()

    parser.add_option('-q', '--query', dest='query',
        help='flickr search QUERY', metavar='QUERY')

    parser.add_option('-i', '--interesting', action='store_true',
        dest='interesting', default=False, help='interesting photos')

    parser.add_option('-r', '--recent', action='store_true',
        dest='recent', default=False, help='recent photos')

    parser.add_option('-n', '--num', dest='num',
        help='result SIZE', metavar='SIZE')

    return parser.parse_args()

if __name__ == '__main__':
    sys.exit(main())

<|endoftext|>


<commit_before>"""
A py23 shim to plistlib. Reimplements plistlib under py2 naming.
"""
from __future__ import absolute_import
import sys
try:
	from plistlib import (
		load as readPlist, dump as writePlist,
		loads as readPlistFromString, dumps as writePlistToString)
	from plistlib import _PlistParser, _PlistWriter
	# Public API changed in Python 3.4
	if sys.version_info >= (3, 4):
		class PlistWriter(_PlistWriter):

			def __init__(self, *args, **kwargs):
				if "indentLevel" in kwargs:
					kwargs["indent_level"] = kwargs["indentLevel"]
					del kwargs["indentLevel"]
				super().__init__(*args, **kwargs)

			def writeValue(self, *args, **kwargs):
				super().write_value(*args, **kwargs)

			def writeData(self, *args, **kwargs):
				super().write_data(*args, **kwargs)

			def writeDict(self, *args, **kwargs):
				super().write_dict(*args, **kwargs)

			def writeArray(self, *args, **kwargs):
				super().write_array(*args, **kwargs)

		class PlistParser(_PlistParser):

			def __init__(self):
				super().__init__(use_builtin_types=True, dict_type=dict)

			def parseElement(self, *args, **kwargs):
				super().parse_element(*args, **kwargs)

			def handleBeginElement(self, *args, **kwargs):
				super().handle_begin_element(*args, **kwargs)

			def handleData(self, *args, **kwargs):
				super().handle_data(*args, **kwargs)

			def handleEndElement(self, *args, **kwargs):
				super().handle_end_element(*args, **kwargs)
	else:
		PlistWriter = _PlistWriter
		PlistParser = _PlistParser
except ImportError:
	from plistlib import readPlist, writePlist, readPlistFromString, writePlistToString
	from plistlib import PlistParser, PlistWriter
<commit_msg>Add plistlib module from ufoLib2<commit_after>from __future__ import absolute_import, unicode_literals
import re
from io import BytesIO
from datetime import datetime
from base64 import b64encode, b64decode
from numbers import Integral

try:
    from functools import singledispatch
except ImportError:
    from singledispatch import singledispatch
from lxml import etree
from fontTools.misc.py23 import unicode, basestring, tounicode

PLIST_DOCTYPE = (
    '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" '
    '"http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
)

# Date should conform to a subset of ISO 8601:
# YYYY '-' MM '-' DD 'T' HH ':' MM ':' SS 'Z'
_date_parser = re.compile(
    r"(?P<year>\d\d\d\d)"
    r"(?:-(?P<month>\d\d)"
    r"(?:-(?P<day>\d\d)"
    r"(?:T(?P<hour>\d\d)"
    r"(?::(?P<minute>\d\d)"
    r"(?::(?P<second>\d\d))"
    r"?)?)?)?)?Z",
    getattr(re, "ASCII", 0),  # py3-only
)

def _date_from_string(s):
    order = ("year", "month", "day", "hour", "minute", "second")
    gd = _date_parser.match(s).groupdict()
    lst = []
    for key in order:
        val = gd[key]
        if val is None:
            break
        lst.append(int(val))
    return datetime(*lst)

def _date_to_string(d):
    return "%04d-%02d-%02dT%02d:%02d:%02dZ" % (
        d.year,
        d.month,
        d.day,
        d.hour,
        d.minute,
        d.second,
    )

class PlistTarget(object):
    """ Event handler using the ElementTree Target API that can be
    passed to a XMLParser to produce property list objects from XML.
    It is based on the CPython plistlib module's _PlistParser class,
    but does not use the expat parser.

    >>> from lxml import etree
    >>> parser = etree.XMLParser(target=PlistTarget())
    >>> result = etree.XML(
    ...     "<dict>"
    ...     "    <key>something</key>"
    ...     "    <string>blah</string>"
    ...     "</dict>",
    ...     parser=parser)
    >>> result == {"something": "blah"}
    True

    Links:
    https://github.com/python/cpython/blob/master/Lib/plistlib.py
    http://lxml.de/parsing.html#the-target-parser-interface
    """

    def __init__(self, dict_type=dict):
        self.stack = []
        self.current_key = None
        self.root = None
        self._dict_type = dict_type

    def start(self, tag, attrib):
        self._data = []
        handler = _TARGET_START_HANDLERS.get(tag)
        if handler is not None:
            handler(self)

    def end(self, tag):
        handler = _TARGET_END_HANDLERS.get(tag)
        if handler is not None:
            handler(self)

    def data(self, data):
        self._data.append(data)

    def close(self):
        return self.root

    # helpers

    def add_object(self, value):
        if self.current_key is not None:
            if not isinstance(self.stack[-1], type({})):
                raise ValueError("unexpected element: %r" % self.stack[-1])
            self.stack[-1][self.current_key] = value
            self.current_key = None
        elif not self.stack:
            # this is the root object
            self.root = value
        else:
            if not isinstance(self.stack[-1], type([])):
                raise ValueError("unexpected element: %r" % self.stack[-1])
            self.stack[-1].append(value)

    def get_data(self):
        data = "".join(self._data)
        self._data = []
        return data

# event handlers

def start_dict(self):
    d = self._dict_type()
    self.add_object(d)
    self.stack.append(d)

def end_dict(self):
    if self.current_key:
        raise ValueError("missing value for key '%s'" % self.current_key)
    self.stack.pop()

def end_key(self):
    if self.current_key or not isinstance(self.stack[-1], type({})):
        raise ValueError("unexpected key")
    self.current_key = self.get_data()

def start_array(self):
    a = []
    self.add_object(a)
    self.stack.append(a)

def end_array(self):
    self.stack.pop()

def end_true(self):
    self.add_object(True)

def end_false(self):
    self.add_object(False)

def end_integer(self):
    self.add_object(int(self.get_data()))

def end_real(self):
    self.add_object(float(self.get_data()))

def end_string(self):
    self.add_object(self.get_data())

def end_data(self):
    self.add_object(b64decode(self.get_data()))

def end_date(self):
    self.add_object(_date_from_string(self.get_data()))

_TARGET_START_HANDLERS = {"dict": start_dict, "array": start_array}

_TARGET_END_HANDLERS = {
    "dict": end_dict,
    "array": end_array,
    "key": end_key,
    "true": end_true,
    "false": end_false,
    "integer": end_integer,
    "real": end_real,
    "string": end_string,
    "data": end_data,
    "date": end_date,
}

# single-dispatch generic function and overloaded implementations based
# on the type of argument, to build an element tree from a plist data

@singledispatch
def _make_element(value, **options):
    raise TypeError("unsupported type: %s" % type(value))

@_make_element.register(unicode)
def _unicode_element(value, **options):
    el = etree.Element("string")
    el.text = value
    return el

@_make_element.register(bool)
def _bool_element(value, **options):
    if value:
        return etree.Element("true")
    else:
        return etree.Element("false")

@_make_element.register(Integral)
def _integer_element(value, **options):
    if -1 << 63 <= value < 1 << 64:
        el = etree.Element("integer")
        el.text = "%d" % value
        return el
    else:
        raise OverflowError(value)

@_make_element.register(float)
def _float_element(value, **options):
    el = etree.Element("real")
    el.text = repr(value)
    return el

@_make_element.register(dict)
def _dict_element(d, **options):
    el = etree.Element("dict")
    items = d.items()
    if options.get("sort_keys", True):
        items = sorted(items)
    for key, value in items:
        if not isinstance(key, basestring):
            if options.get("skipkeys", False):
                continue
            raise TypeError("keys must be strings")
        k = etree.SubElement(el, "key")
        k.text = tounicode(key, "utf-8")
        el.append(totree(value, **options))
    return el

@_make_element.register(list)
@_make_element.register(tuple)
def _array_element(array, **options):
    el = etree.Element("array")
    if len(array) == 0:
        return el
    for value in array:
        el.append(totree(value, **options))
    return el

@_make_element.register(datetime)
def _date_element(date, **options):
    el = etree.Element("date")
    el.text = _date_to_string(date)
    return el

@_make_element.register(bytes)
@_make_element.register(bytearray)
def _data_element(data, **options):
    el = etree.Element("data")
    el.text = b64encode(data)
    return el

# Public functions to create element tree from plist-compatible python
# data structures and viceversa, for use when (de)serializing GLIF xml.

def totree(value, sort_keys=True, skipkeys=False):
    return _make_element(value, sort_keys=sort_keys, skipkeys=skipkeys)

def fromtree(tree, dict_type=dict):
    target = PlistTarget(dict_type=dict_type)
    for action, element in etree.iterwalk(tree, events=("start", "end")):
        if action == "start":
            target.start(element.tag, element.attrib)
        elif action == "end":
            # if there are no children, parse the leaf's data
            if not len(element):
                # always pass str, not None
                target.data(element.text or "")
            target.end(element.tag)
    return target.close()

# python3 plistlib API

def load(fp, dict_type=dict):
    if not hasattr(fp, "read"):
        raise AttributeError(
            "'%s' object has no attribute 'read'" % type(fp).__name__
        )
    target = PlistTarget(dict_type=dict_type)
    parser = etree.XMLParser(target=target)
    return etree.parse(fp, parser=parser)

def loads(value, dict_type=dict):
    fp = BytesIO(value)
    return load(fp, dict_type=dict_type)

def dump(value, fp, sort_keys=True, skipkeys=False, _pretty_print=True):
    if not hasattr(fp, "write"):
        raise AttributeError(
            "'%s' object has no attribute 'write'" % type(fp).__name__
        )
    root = etree.Element("plist", version="1.0")
    root.append(totree(value, sort_keys=sort_keys, skipkeys=skipkeys))
    tree = etree.ElementTree(root)
    tree.write(
        fp,
        encoding="utf-8",
        pretty_print=_pretty_print,
        xml_declaration=True,
        doctype=PLIST_DOCTYPE,
    )

def dumps(value, sort_keys=True, skipkeys=False, _pretty_print=True):
    fp = BytesIO()
    dump(
        value,
        fp,
        sort_keys=sort_keys,
        skipkeys=skipkeys,
        _pretty_print=_pretty_print,
    )
    return fp.getvalue()
<|endoftext|>