Pockets full of useful Python tools!

Let me check my pockets…

The Pockets library pulls together many of the Python helper functions I’ve found useful over the years.

If you’ve worked on a project that exports an API and accesses a data store, you’ve probably seen some code that looks like this:

# Receive a data type with underscores from some API
data_type = 'user_preference'

# Convert underscored data type to CamelCase to match the data model
model_name = camel(data_type)

# Resolve the model name into a model class
model_class = resolve(model_name, modules=["webapp.model.admin",
                                           "webapp.model.user",
                                           "webapp.model.businesslogic"]

# Instantiate the model class and do stuff with the instance...
instance = model_class()

There’s an impedance mismatch any time you work with two different frameworks; especially when you want to update your back-end while maintaining legacy compatibility with an external API.

Pockets is full of highly tested, well maintained functions that help bridge the gap. Here are just a few examples…

Easily get the right logger no matter where you are

>>> from pockets.autolog import log
>>> log.error("Always log from the correct module.Class!")
mymodule.MyClass: Always log from the correct module.Class!

Convert underscore_separated string to CamelCase

>>> from pockets import camel
>>> camel("xml_http_request", upper_segments=[1])
'XmlHTTPRequest'

Convert CamelCase string to underscore_separated

>>> from pockets import uncamel
>>> uncamel("XmlHTTPRequest")
'xml_http_request'

Resolve a string into an object

>>> from pockets import resolve
>>> resolve("calendar.TextCalendar")
<class 'calendar.TextCalendar'>

Peek ahead iterator

>>> from pockets import iterpeek
>>> p = iterpeek(["a", "b", "c", "d", "e"])
>>> p.peek()
'a'
>>> p.next()
'a'
>>> p.peek(3)
['b', 'c', 'd']

Downloads and Docs

Full documentation is available on Read the Docs.

Built packages are available on PyPI.

Source code is available on GitHub. Feel free to:

  • Create an issue to request a feature or a report a bug.
  • Fork the repository and make changes to the master branch for next release.
  • Send a pull request and pester the maintainer until it’s merged. Make sure to add yourself to AUTHORS and update CHANGES.

Package Contents

pockets package

Let me check my pockets…

Functions available in the pockets.* submodules are also imported to the base package for easy access, so:

from pockets import camel, iterpeek, resolve

works just as well as:

from pockets.inspect import resolve
from pockets.iterators import iterpeek
from pockets.string import camel

pockets.autolog module

An easy to import AutoLogger instance!

>>> import logging, sys
>>> logging.basicConfig(format="%(name)s: %(message)s", stream=sys.stdout)
>>> from pockets.autolog import log
>>> log.error("Always log from the correct module.Class!") # doctest: +SKIP
pockets.autolog: Always log from the correct module.Class!

See also

pockets.logger.AutoLogger

pockets.collections module

A pocket full of useful collection tools!

pockets.collections.groupify(items, keys, val_key=None)[source]

Groups a list of items into nested OrderedDicts based on the given keys.

Note

On Python 2.6 the return value will use regular dicts instead of OrderedDicts.

>>> from __future__ import print_function
>>> from json import dumps
>>>
>>> ex = lambda x: print(dumps(x, indent=2, sort_keys=True, default=repr))
>>>
>>> class Reminder:
...   def __init__(self, when, where, what):
...     self.when = when
...     self.where = where
...     self.what = what
...   def __repr__(self):
...     return 'Reminder({0.when}, {0.where}, {0.what})'.format(self)
...
>>> reminders = [
...   Reminder('Fri', 'Home', 'Eat cereal'),
...   Reminder('Fri', 'Work', 'Feed Ivan'),
...   Reminder('Sat', 'Home', 'Sleep in'),
...   Reminder('Sat', 'Home', 'Play Zelda'),
...   Reminder('Sun', 'Home', 'Sleep in'),
...   Reminder('Sun', 'Work', 'Reset database')]
>>>
>>> ex(groupify(reminders, 'when'))
{
  "Fri": [
    "Reminder(Fri, Home, Eat cereal)",
    "Reminder(Fri, Work, Feed Ivan)"
  ],
  "Sat": [
    "Reminder(Sat, Home, Sleep in)",
    "Reminder(Sat, Home, Play Zelda)"
  ],
  "Sun": [
    "Reminder(Sun, Home, Sleep in)",
    "Reminder(Sun, Work, Reset database)"
  ]
}
>>>
>>> ex(groupify(reminders, ['when', 'where']))
{
  "Fri": {
    "Home": [
      "Reminder(Fri, Home, Eat cereal)"
    ],
    "Work": [
      "Reminder(Fri, Work, Feed Ivan)"
    ]
  },
  "Sat": {
    "Home": [
      "Reminder(Sat, Home, Sleep in)",
      "Reminder(Sat, Home, Play Zelda)"
    ]
  },
  "Sun": {
    "Home": [
      "Reminder(Sun, Home, Sleep in)"
    ],
    "Work": [
      "Reminder(Sun, Work, Reset database)"
    ]
  }
}
>>>
>>> ex(groupify(reminders, ['when', 'where'], 'what'))
{
  "Fri": {
    "Home": [
      "Eat cereal"
    ],
    "Work": [
      "Feed Ivan"
    ]
  },
  "Sat": {
    "Home": [
      "Sleep in",
      "Play Zelda"
    ]
  },
  "Sun": {
    "Home": [
      "Sleep in"
    ],
    "Work": [
      "Reset database"
    ]
  }
}
>>>
>>> ex(groupify(reminders, lambda r: '{0.when} - {0.where}'.format(r), 'what'))
{
  "Fri - Home": [
    "Eat cereal"
  ],
  "Fri - Work": [
    "Feed Ivan"
  ],
  "Sat - Home": [
    "Sleep in",
    "Play Zelda"
  ],
  "Sun - Home": [
    "Sleep in"
  ],
  "Sun - Work": [
    "Reset database"
  ]
}
Parameters:
  • items (list) – The list of items to arrange in groups.
  • keys (str|callable|list) – The key or keys that should be used to group items. If multiple keys are given, then each will correspond to an additional level of nesting in the order they are given.
  • val_key (str|callable) – A key or callable used to generate the leaf values in the nested OrderedDicts. If val_key is None, then the item itself is used. Defaults to None.
Returns:

Nested OrderedDicts with items grouped by keys.

Return type:

OrderedDict

class pockets.collections.keydefaultdict(*args, **kwargs)[source]

Bases: collections.defaultdict

A defaultdict that passes the missed key to the factory function.

>>> def echo_factory(missing_key):
...     return missing_key
...
>>> d = keydefaultdict(echo_factory)
>>> d['Hello World']
'Hello World'
>>> d['Hello World'] = 'Goodbye'
>>> d['Hello World']
'Goodbye'
pockets.collections.is_listy(x)[source]

Return True if x is “listy”, i.e. a list-like object.

“Listy” is defined as a sized iterable which is neither a map nor a string:

>>> is_listy(['a', 'b'])
True
>>> is_listy(set())
True
>>> is_listy(iter(['a', 'b']))
False
>>> is_listy({'a': 'b'})
False
>>> is_listy('a regular string')
False

Note

Iterables and generators fail the “listy” test because they are not sized.

Parameters:x (any value) – The object to test.
Returns:True if x is “listy”, False otherwise.
Return type:bool
pockets.collections.listify(x, minlen=0, default=None, cls=None)[source]

Return a listified version of x.

If x is a non-string iterable, it is wrapped in a list; otherwise a list is returned with x as its only element. If x is None, an empty list is returned.

>>> listify('a regular string')
['a regular string']
>>> listify(tuple(['a', 'b', 'c']))
['a', 'b', 'c']
>>> listify({'a': 'A'})
[{'a': 'A'}]
>>> listify(None)
[]

Note

Not guaranteed to return a copy of x. If x is already a list and cls is not specified, then x itself is returned.

Parameters:
  • x (any value) – Value to listify.
  • minlen (int) –

    Minimum length of the returned list. If the returned list would be shorter than minlen it is padded with values from default. Defaults to 0.

    >>> listify([], minlen=0)
    []
    >>> listify([], minlen=1)
    [None]
    >>> listify('item', minlen=3)
    ['item', None, None]
    
  • default (any value) –

    Value that should be used to pad the list if it would be shorter than minlen:

    >>> listify([], minlen=1, default='PADDING')
    ['PADDING']
    >>> listify('item', minlen=3, default='PADDING')
    ['item', 'PADDING', 'PADDING']
    
  • cls (class or callable) –

    Instead of wrapping x in a list, wrap it in an instance of cls. cls should accept an iterable object as its single parameter when called:

    >>> from collections import deque
    >>> listify(['a', 'b', 'c'], cls=deque)
    deque(['a', 'b', 'c'])
    
Returns:

A listified version of x.

Return type:

list or cls

pockets.collections.is_mappy(x)[source]

Return True if x is “mappy”, i.e. a map-like object.

“Mappy” is defined as any instance of collections.Mapping:

>>> is_mappy({'a': 'b'})
True
>>> from collections import defaultdict
>>> is_mappy(defaultdict(list))
True
>>> is_mappy('a regular string')
False
>>> is_mappy(['a', 'b'])
False
>>> is_listy(iter({'a': 'b'}))
False

Note

Iterables and generators fail the “mappy” test.

Parameters:x (any value) – The object to test.
Returns:True if x is “mappy”, False otherwise.
Return type:bool
pockets.collections.mappify(x, default=True, cls=None)[source]

Return a mappified version of x.

If x is a string, it becomes the only key of the returned dict. If x is a non-string iterable, the elements of x become keys in the returned dict. The values of the returned dict are set to default. If x is None, an empty dict is returned.

If x is a map, it is returned directly.

>>> mappify('a regular string')
{'a regular string': True}
>>> mappify(['a'])
{'a': True}
>>> mappify({'a': 'A'})
{'a': 'A'}
>>> mappify(None)
{}

Note

Not guaranteed to return a copy of x. If x is already a map and cls is not specified, then x itself is returned.

Parameters:
  • x (str, map, or iterable) – Value to mappify.
  • default (any value) – Value used to fill out missing values of the returned dict.
  • cls (class or callable) –

    Instead of wrapping x in a dict, wrap it in an instance of cls. cls should accept a map object as its single parameter when called:

    >>> from collections import defaultdict
    >>> mappify('a', cls=lambda x: defaultdict(None, x))
    defaultdict(None, {'a': True})
    
Returns:

A mappified version of x.

Return type:

dict or cls

Raises:

TypeError – If x is not a map, iterable, or string.

pockets.collections.nesteddefaultdict()[source]

A defaultdict that returns nested defaultdicts as the default value.

Each defaultdict returned as the default value will also return nested defaultdicts, and so on.

>>> nested = nesteddefaultdict()
>>> nested_child = nested['New Key 1']
>>> nested_child
defaultdict(...)
>>> nested_grandchild = nested_child['New Key 2']
>>> nested_grandchild
defaultdict(...)
pockets.collections.readable_join(xs, conjunction='and', sep=', ')[source]

Accepts a list of strings and separates them with commas as grammatically appropriate with a conjunction before the final entry. Any input strings containing only whitespace will not be included in the result.

>>> readable_join(['foo'])
'foo'
>>> readable_join(['foo', 'bar'])
'foo and bar'
>>> readable_join(['foo', 'bar', 'baz'])
'foo, bar, and baz'
>>> readable_join(['foo', '  ', '', 'bar', '', '  ', 'baz'])
'foo, bar, and baz'
>>> readable_join(['foo', 'bar', 'baz'], 'or')
'foo, bar, or baz'
>>> readable_join(['foo', 'bar', 'baz'], 'but never')
'foo, bar, but never baz'
pockets.collections.uniquify(x, key=<function <lambda>>, cls=None)[source]

Returns an order-preserved copy of x with duplicate items removed.

>>> uniquify(['a', 'z', 'a', 'b', 'a', 'y', 'a', 'c', 'a', 'x'])
['a', 'z', 'b', 'y', 'c', 'x']
Parameters:
  • x (Sequence) – Sequence to uniquify.
  • key (str or callable) –

    Similar to sorted, specifies an attribute or function of one argument that is used to extract a comparison key from each list element: key=str.lower. By default, compares the elements directly.

    >>> strings = ['ASDF', 'asdf', 'ZXCV', 'zxcv']
    >>> uniquify(strings, key=str.lower)
    ['ASDF', 'ZXCV']
    
  • cls (class or callable) –

    Instead of wrapping x in a list, wrap it in an instance of cls. cls should accept an iterable object as its single parameter when called:

    >>> from collections import deque
    >>> listify(['a', 'b', 'c'], cls=deque)
    deque(['a', 'b', 'c'])
    
Returns:

An order-preserved copy of x with duplicate items removed.

Return type:

list

Raises:

TypeError – If x is not “listy”.

pockets.datetime module

A pocket full of useful datetime tools!

pockets.datetime.timedelta_total_seconds(td)[source]

Python 2.6 replacement function for timedelta.total_seconds().

Parameters:td (datetime.timedelta) – A datetime.timedelta instance.
Returns:
The total number of seconds plus the fractional
number of microseconds in td.
Return type:float
pockets.datetime.ceil_datetime(dt, nearest)[source]

Rounds the given datetime up to the nearest timedelta increment.

Note

dt.microsecond is always set to zero and ignored.

Parameters:
Returns:

A copy of dt ceiled to nearest.

Return type:

datetime.datetime

pockets.datetime.floor_datetime(dt, nearest)[source]

Rounds the given datetime down to the nearest timedelta increment.

Note

dt.microsecond is always set to zero and ignored.

Parameters:
Returns:

A copy of dt floored to nearest.

Return type:

datetime.datetime

pockets.datetime.round_datetime(dt, nearest)[source]

Rounds the given datetime up/down to the nearest timedelta increment.

Note

dt.microsecond is always set to zero and ignored.

Parameters:
Returns:

A copy of dt rounded to nearest.

Return type:

datetime.datetime

pockets.inspect module

A pocket full of useful reflection functions!

pockets.inspect.collect_subclasses(cls)[source]

Recursively collects all descendant subclasses that inherit from the given class, not including the class itself.

Note

Does not include cls itself.

Parameters:cls (class) – The class object from which the collection should begin.
Returns:
A list of class objects that inherit from cls. This list
will not include cls itself.
Return type:list
pockets.inspect.collect_superclasses(cls, terminal_class=None, modules=None)[source]

Recursively collects all ancestor superclasses in the inheritance hierarchy of the given class, including the class itself.

Note

Inlcudes cls itself. Will not include terminal_class.

Parameters:
  • cls (class) – The class object from which the collection should begin.
  • terminal_class (class or list) – If terminal_class is encountered in the hierarchy, we stop ascending the tree. terminal_class will not be included in the returned list.
  • modules (string, module, or list) – If modules is passed, we only return classes that are in the given module/modules. This can be used to exclude base classes that come from external libraries.
Returns:

A list of class objects from which cls inherits. This list

will include cls itself.

Return type:

list

pockets.inspect.collect_superclass_attr_names(cls, terminal_class=None, modules=None)[source]

Recursively collects all attribute names of ancestor superclasses in the inheritance hierarchy of the given class, including the class itself.

Note

Inlcudes cls itself. Will not include terminal_class.

Parameters:
  • cls (class) – The class object from which the collection should begin.
  • terminal_class (class or list) – If terminal_class is encountered in the hierarchy, we stop ascending the tree. Attributes from terminal_class will not be included in the returned list.
  • modules (string, module, or list) – If modules is passed, we only return classes that are in the given module/modules. This can be used to exclude base classes that come from external libraries.
Returns:

A list of str attribute names for every class in the

inheritance hierarchy.

Return type:

list

pockets.inspect.hoist_submodules(package, extend_all=True)[source]

Sets __all__ attrs from submodules of package as attrs on package.

Note

This only considers attributes exported by __all__. If a submodule does not define __all__, then it is ignored.

Effectively does:

from package.* import *
Parameters:
  • package (str or module) – The parent package into which submodule exports should be hoisted.
  • extend_all (bool) – If True, package.__all__ will be extended to include the hoisted attributes. Defaults to True.
Returns:

List of all hoisted attribute names.

Return type:

list

pockets.inspect.import_star(module)[source]

Imports all exported attributes of module and returns them in a dict.

Note

This only considers attributes exported by __all__. If module does not define __all__, then nothing is imported.

Effectively does:

from module import *
Parameters:module (str or module) – The module from which a wildcard import should be done.
Returns:Map of all imported attributes.
Return type:dict
pockets.inspect.import_submodules(package)[source]

Imports all submodules of package.

Effectively does:

__import__(package.*)
Parameters:package (str or module) – The parent package from which submodules should be imported.
Yields:module – The next submodule of package.
pockets.inspect.is_data(obj)[source]

Returns True if obj is a “data like” object.

Strongly inspired by inspect.classify_class_attrs. This function is useful when trying to determine if an attribute has a meaningful docstring or not. In general, a routine can have meaningful docstrings, whereas non-routines cannot.

See also

  • inspect.classify_class_attrs
  • inspect.isroutine
Parameters:obj (object) – The object in question.
Returns:True if obj is “data like”, False otherwise.
Return type:bool
pockets.inspect.resolve(name, modules=None)[source]

Resolve a dotted name to an object (usually class, module, or function).

If name is a string, attempt to resolve it according to Python dot notation, e.g. “path.to.MyClass”. If name is anything other than a string, return it immediately:

>>> resolve("calendar.TextCalendar")
<class 'calendar.TextCalendar'>
>>> resolve(object())
<object object at 0x...>

If modules is specified, then resolution of name is restricted to the given modules. Leading dots are allowed in name, but they are ignored. Resolution will not traverse up the module path if modules is specified.

If modules is not specified and name has leading dots, then resolution is first attempted relative to the calling function’s module, and then absolutely. Resolution will traverse up the module path. If name has no leading dots, resolution is first attempted absolutely and then relative to the calling module.

Warning

Do not resolve strings supplied by an end user without specifying modules. Instantiating an arbitrary object specified by an end user can introduce a potential security risk.

To avoid this, restrict the search path by explicitly specifying modules.

Restricting name resolution to a set of modules:

>>> resolve("pockets.camel")
<function camel at 0x...>
>>> resolve("pockets.camel", modules=["re", "six"])
Traceback (most recent call last):
ValueError: Unable to resolve 'pockets.camel' in modules: ['re', 'six']
  ...
Parameters:
  • name (str or object) – A dotted name.
  • modules (str, module, or list, optional) – A module or list of modules, under which to search for name.
Returns:

The object specified by name.

Return type:

object

Raises:

ValueError – If name can’t be resolved.

pockets.inspect.unwrap(func)[source]

Finds the innermost function that has been wrapped using functools.wrap.

Note

This function relies on the existence of the __wrapped__ attribute, which was not automatically added until Python 3.2. If you are using an older version of Python, you’ll have to manually add the __wrapped__ attribute in order to use unwrap:

def my_decorator(func):
    @wraps(func)
    def with_my_decorator(*args, **kwargs):
        return func(*args, **kwargs)

    if not hasattr(with_my_decorator, '__wrapped__'):
        with_my_decorator.__wrapped__ = func

    return with_my_decorator
Parameters:func (function) – A function that may or may not have been wrapped using functools.wrap.
Returns:
The original function before it was wrapped using
functools.wrap. func is returned directly, if it was never wrapped using functools.wrap.
Return type:function

pockets.iterators module

A pocket full of useful iterators!

class pockets.iterators.iterpeek(*args)[source]

Bases: object

An iterator object that supports peeking ahead.

>>> p = iterpeek(["a", "b", "c", "d", "e"])
>>> p.peek()
'a'
>>> p.next()
'a'
>>> p.peek(3)
['b', 'c', 'd']
Parameters:
  • o (iterable or callable) –

    o is interpreted very differently depending on the presence of sentinel.

    If sentinel is not given, then o must be a collection object which supports either the iteration protocol or the sequence protocol.

    If sentinel is given, then o must be a callable object.

  • sentinel (any value, optional) – If given, the iterator will call o with no arguments for each call to its next method; if the value returned is equal to sentinel, StopIteration will be raised, otherwise the value will be returned.

See also

iterpeek can operate as a drop in replacement for the built-in iter function.

Variables:sentinel (any value) – The value used to indicate the iterator is exhausted. If sentinel was not given when the iterpeek was instantiated, then it will be set to a new object instance: object().
has_next()[source]

Determine if iterator is exhausted.

Returns:True if iterator has more items, False otherwise.
Return type:bool

Note

Will never raise StopIteration.

next(n=None)[source]

Get the next item or n items of the iterator.

Parameters:n (int, optional) – The number of items to retrieve. Defaults to None.
Returns:The next item or n items of the iterator. If n is None, the item itself is returned. If n is an int, the items will be returned in a list. If n is 0, an empty list is returned:
>>> p = iterpeek(["a", "b", "c", "d", "e"])
>>> p.next()
'a'
>>> p.next(0)
[]
>>> p.next(1)
['b']
>>> p.next(2)
['c', 'd']
Return type:item or list of items
Raises:StopIteration – Raised if the iterator is exhausted, even if n is 0.
peek(n=None)[source]

Preview the next item or n items of the iterator.

The iterator is not advanced when peek is called.

Parameters:n (int, optional) – The number of items to retrieve. Defaults to None.
Returns:The next item or n items of the iterator. If n is None, the item itself is returned. If n is an int, the items will be returned in a list. If n is 0, an empty list is returned.

If the iterator is exhausted, iterpeek.sentinel is returned, or placed as the last item in the returned list:

>>> p = iterpeek(["a", "b", "c"])
>>> p.sentinel = "END"
>>> p.peek()
'a'
>>> p.peek(0)
[]
>>> p.peek(1)
['a']
>>> p.peek(2)
['a', 'b']
>>> p.peek(4)
['a', 'b', 'c', 'END']
Return type:item or list of items

Note

Will never raise StopIteration.

pockets.iterators.peek_iter

alias of pockets.iterators.iterpeek

class pockets.iterators.itermod(*args, **kwargs)[source]

Bases: pockets.iterators.iterpeek

An iterator object that supports modifying items as they are returned.

>>> a = ["     A list    ",
...      "   of strings  ",
...      "      with     ",
...      "      extra    ",
...      "   whitespace. "]
>>> modifier = lambda s: s.strip().replace('with', 'without')
>>> for s in itermod(a, modifier=modifier):
...   print('"%s"' % s)
"A list"
"of strings"
"without"
"extra"
"whitespace."
Parameters:
  • o (iterable or callable) –

    o is interpreted very differently depending on the presence of sentinel.

    If sentinel is not given, then o must be a collection object which supports either the iteration protocol or the sequence protocol.

    If sentinel is given, then o must be a callable object.

  • sentinel (any value, optional) – If given, the iterator will call o with no arguments for each call to its next method; if the value returned is equal to sentinel, StopIteration will be raised, otherwise the value will be returned.
  • modifier (callable, optional) –

    The function that will be used to modify each item returned by the iterator. modifier should take a single argument and return a single value. Defaults to lambda x: x.

    If sentinel is not given, modifier must be passed as a keyword argument.

Variables:

modifier (callable) –

modifier is called with each item in o as it is iterated. The return value of modifier is returned in lieu of the item.

Values returned by peek as well as next are affected by modifier. However, itermod.sentinel is never passed through modifier; it will always be returned from peek unmodified.

pockets.iterators.modify_iter

alias of pockets.iterators.itermod

pockets.logging module

A pocket full of useful logging tools!

The pockets.logging module adds a logging.TRACE level and a logging.Logger.trace method, so messages can be logged at a lower priority level than logging.DEBUG.

pockets.logging.log_exceptions(fn)[source]

Decorator that wraps a function and logs any raised exceptions.

The exception will still be raised after being logged. Also logs the arguments to every call at the trace level.

class pockets.logging.AutoLogger(adapter_class=None, adapter_args=None, adapter_kwargs=None)[source]

Bases: object

A logger proxy object with all of the methods and attributes of Logger.

When an attribute (e.g., “debug”) is requested, inspects the stack for the calling module’s name, and passes that name to logging.getLogger.

What this means is that you can instantiate an AutoLogger anywhere, and when you call it, the log entry shows the module where you called it, not where it was created.

AutoLogger also inspects the local variables where it is called, looking for self. If self exists, its classname is added to the module name.

Parameters:
  • adapter_class (LoggerAdapter) – optional LoggerAdapter class to use.
  • adapter_args (list) – optional args to use when instantiating an instance of adapter_class.
  • adapter_kwargs (dict) – optional kwargs to use when instantiating an instance of adapter_class.
class pockets.logging.EagerFormattingAdapter(logger, extra=None)[source]

Bases: logging.LoggerAdapter

A LoggerAdapter that immediately interpolates message arguments if the appropriate loglevel is set.

This is useful because many log handlers generate log output on a separate thread, and the value of the log arguments may have changed by the time the handler interpolates them. This can lead to confusion when debugging difficult bugs, as the log output will not reflect what was actually happening when the log message was originally generated.

For performance reasons, the interpolation ONLY happens if the appropriate loglevel is set. This prevents unnecessary string formatting on log messages that will just be thrown out anyway.

Parameters:
  • logger (Logger) – The underlying Logger instance to use.
  • extra (dict) – Extra args, ignored by this implementation.
trace(msg, *args, **kwargs)[source]

Delegate a trace call to the underlying logger, after adding contextual information from this adapter instance.

debug(msg, *args, **kwargs)[source]

Delegate a debug call to the underlying logger, after adding contextual information from this adapter instance.

info(msg, *args, **kwargs)[source]

Delegate an info call to the underlying logger, after adding contextual information from this adapter instance.

warn(msg, *args, **kwargs)[source]

Delegate a warning call to the underlying logger, after adding contextual information from this adapter instance.

warning(msg, *args, **kwargs)[source]

Delegate a warning call to the underlying logger, after adding contextual information from this adapter instance.

error(msg, *args, **kwargs)[source]

Delegate an error call to the underlying logger, after adding contextual information from this adapter instance.

exception(msg, *args, **kwargs)[source]

Delegate an exception call to the underlying logger, after adding contextual information from this adapter instance.

critical(msg, *args, **kwargs)[source]

Delegate a critical call to the underlying logger, after adding contextual information from this adapter instance.

fatal(msg, *args, **kwargs)[source]

Delegate a fatal call to the underlying logger, after adding contextual information from this adapter instance.

log(level, msg, *args, **kwargs)[source]

Delegate a log call to the underlying logger, after adding contextual information from this adapter instance.

class pockets.logging.IndentMultilineLogFormatter(fmt=None, datefmt=None, style='%')[source]

Bases: logging.Formatter

Formatter which indents messages that are split across multiple lines.

Indents all lines that start with a newline so they are easier for external log programs to parse.

format(record)[source]

Formats the given LogRecord by indenting all newlines.

Parameters:record (LogRecord) – The LogRecord to format.
Returns:The formatted message with all newlines indented.
Return type:str

pockets.string module

A pocket full of useful string manipulation tools!

pockets.string.camel(s, sep='_', lower_initial=False, upper_segments=None, preserve_upper=False)[source]

Convert underscore_separated string (aka snake_case) to CamelCase.

Works on full sentences as well as individual words:

>>> camel("hello_world!")
'HelloWorld!'
>>> camel("Totally works as_expected, even_with_whitespace!")
'Totally Works AsExpected, EvenWithWhitespace!'
Parameters:
  • sep (string, optional) –

    Delineates segments of s that will be CamelCased. Defaults to an underscore “_”.

    For example, if you want to CamelCase a dash separated word:

    >>> camel("xml-http-request", sep="-")
    'XmlHttpRequest'
    
  • lower_initial (bool, int, or list, optional) –

    If True, the initial character of each camelCased word will be lowercase. If False, the initial character of each CamelCased word will be uppercase. Defaults to False:

    >>> camel("http_request http_response")
    'HttpRequest HttpResponse'
    >>> camel("http_request http_response", lower_initial=True)
    'httpRequest httpResponse'
    

    Optionally, lower_initial can be an int or a list of ints, indicating which individual segments of each CamelCased word should start with a lowercase. Supports negative numbers to index segments from the right:

    >>> camel("xml_http_request", lower_initial=0)
    'xmlHttpRequest'
    >>> camel("xml_http_request", lower_initial=-1)
    'XmlHttprequest'
    >>> camel("xml_http_request", lower_initial=[0, 1])
    'xmlhttpRequest'
    
  • upper_segments (int or list, optional) –

    Indicates which segments of CamelCased words should be fully uppercased, instead of just capitalizing the first letter.

    Can be an int, indicating a single segment, or a list of ints, indicating multiple segments. Supports negative numbers to index segments from the right.

    upper_segments is helpful when dealing with acronyms:

    >>> camel("tcp_socket_id", upper_segments=0)
    'TCPSocketId'
    >>> camel("tcp_socket_id", upper_segments=[0, -1])
    'TCPSocketID'
    >>> camel("tcp_socket_id", upper_segments=[0, -1], lower_initial=1)
    'TCPsocketID'
    
  • preserve_upper (bool) –

    If True, existing uppercase characters will not be automatically lowercased. Defaults to False.

    >>> camel("xml_HTTP_reQuest")
    'XmlHttpRequest'
    >>> camel("xml_HTTP_reQuest", preserve_upper=True)
    'XmlHTTPReQuest'
    
Returns:

CamelCased version of s.

Return type:

str

pockets.string.uncamel(s, sep='_')[source]

Convert CamelCase string to underscore_separated (aka snake_case).

A CamelCase word is considered to be any uppercase letter followed by zero or more lowercase letters. Contiguous groups of uppercase letters – like you would find in an acronym – are also considered part of a single word:

>>> uncamel("Request")
'request'
>>> uncamel("HTTP")
'http'
>>> uncamel("HTTPRequest")
'http_request'
>>> uncamel("xmlHTTPRequest")
'xml_http_request'

Works on full sentences as well as individual words:

>>> uncamel("HelloWorld!")
'hello_world!'
>>> uncamel("Totally works AsExpected, EvenWithWhitespace!")
'totally works as_expected, even_with_whitespace!'
Parameters:sep (str, optional) –

String used to separate CamelCase words. Defaults to an underscore “_”.

For example, if you want dash separated words:

>>> uncamel("XmlHttpRequest", sep="-")
'xml-http-request'
Returns:uncamel_cased version of s.
Return type:str
pockets.string.fieldify(s, sep='_')[source]

Convert a string into a valid “field-like” variable name.

Converts s from camel case to underscores, and replaces all spaces and non-word characters with sep:

>>> fieldify('The XmlHTTPRequest Contained, "DATA..."')
'the_xml_http_request_contained_data'
Parameters:
  • s (str) – The string to fieldify.
  • sep (str) – The string to use as a word separator in the returned field. Defaults to ‘_’.
Returns:

The field version of s.

Return type:

str

pockets.string.unfieldify(s, sep='_')[source]

Makes a best effort to reverse the algorithm from fieldify.

Replaces instances of sep in s with a space and converts the result to title case:

>>> unfieldify('the_xml_http_request_contained_data')
'The Xml Http Request Contained Data'
Parameters:
  • s (str) – The string to fieldify.
  • sep (str) – The string to consider a word separator in s. Defaults to ‘_’.
Returns:

The unfieldified version of s.

Return type:

str

pockets.string.sluggify(s, sep='-')[source]

Convert a string into a “slug” suitable for use in a URL.

Converts s to lower case, and replaces all spaces and non-word characters with sep:

>>> sluggify('The ANGRY Wizard Shouted, "HEY..."')
'the-angry-wizard-shouted-hey'
Parameters:
  • s (str) – The string to convert into a slug.
  • sep (str) – The string to use as a word separator in the slug. Defaults to ‘-‘.
Returns:

The sluggify version of s.

Return type:

str

pockets.string.splitcaps(s, pattern=None, maxsplit=None, flags=0)[source]

Intelligently split a string on capitalized words.

A capitalized word is considered to be any uppercase letter followed by zero or more lowercase letters. Contiguous groups of uppercase letters – like you would find in an acronym – are also considered part of a single word:

>>> splitcaps("Request")
['Request']
>>> splitcaps("HTTP")
['HTTP']
>>> splitcaps("HTTPRequest")
['HTTP', 'Request']
>>> splitcaps("HTTP/1.1Request")
['HTTP/1.1', 'Request']
>>> splitcaps("xmlHTTPRequest")
['xml', 'HTTP', 'Request']

If no capitalized words are found in s, the whole string is returned in a single element list:

>>> splitcaps("")
['']
>>> splitcaps("lower case words")
['lower case words']

Does not split on whitespace by default. To also split on whitespace, pass “\s+” for pattern:

>>> splitcaps("Without whiteSpace pattern")
['Without white', 'Space pattern']
>>> splitcaps("With whiteSpace pattern", pattern=r"\s+")
['With', 'white', 'Space', 'pattern']
>>> splitcaps("With whiteSpace group", pattern=r"(\s+)")
['With', ' ', 'white', 'Space', ' ', 'group']
Parameters:
  • s (str) – The string to split.
  • pattern (str, optional) – In addition to splitting on capital letters, also split by the occurrences of pattern. If capturing parentheses are used in pattern, then the text of all groups in pattern are also returned as part of the resulting list. Defaults to None.
  • maxsplit (int, optional) – If maxsplit is not specified or -1, then there is no limit on the number of splits (all possible splits are made). If maxsplit is >= 0, at most maxsplit splits occur, and the remainder of the string is returned as the final element of the list.
  • flags (int, optional) – Flags to pass to the regular expression created using pattern. Ignored if pattern is not specified. Defaults to (re.LOCALE | re.MULTILINE | re.UNICODE).
Returns:

List of capitalized substrings in s.

Return type:

list

pockets.string.splitify(value, separator=', ', strip=True, include_empty=False)[source]

Convert a value to a list using a supercharged split().

If value is a string, it is split by separator. If separator is None or empty, no attempt to split is made, and value is returned as the only item in a list.

If strip is True, then the split strings will be stripped of whitespace. If strip is a string, then the split strings will be stripped of the given string.

If include_empty is False, then empty split strings will not be included in the returned list.

If value is None an empty list is returned.

If value is already “listy”, it is returned as-is.

If value is any other type, it is returned as the only item in a list.

>>> splitify("first item, second item")
['first item', 'second item']
>>> splitify("first path: second path: :skipped empty path", ":")
['first path', 'second path', 'skipped empty path']
>>> splitify(["already", "split"])
['already', 'split']
>>> splitify(None)
[]
>>> splitify(1969)
[1969]
class pockets.string.UnicodeMixin(*args, **kwargs)[source]

Bases: object

Mixin class to define proper __str__/__unicode__ methods in Python 2 or 3.

Originally found on the Porting Python 2 Code to Python 3 HOWTO.

Indices and tables