mirror of https://github.com/evilhero/mylar
127 lines
3.3 KiB
Python
127 lines
3.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import (
|
|
print_function,
|
|
division,
|
|
unicode_literals,
|
|
absolute_import
|
|
)
|
|
|
|
import functools
|
|
import sys
|
|
|
|
# These functions are used to make the doctests compatible between
|
|
# python2 and python3, and also provide uniform functionality between
|
|
# the two versions. This code is pretty much lifted from the iPython
|
|
# project's py3compat.py file. Credit to the iPython devs.
|
|
|
|
# Numeric form of version
|
|
PY_VERSION = float(sys.version[:3])
|
|
NEWPY = PY_VERSION >= 3.3
|
|
|
|
# Assume all strings are Unicode in Python 2
|
|
py23_str = str if sys.version[0] == '3' else unicode
|
|
|
|
# Use the range iterator always
|
|
py23_range = range if sys.version[0] == '3' else xrange
|
|
|
|
# Uniform base string type
|
|
py23_basestring = str if sys.version[0] == '3' else basestring
|
|
|
|
# unichr function
|
|
py23_unichr = chr if sys.version[0] == '3' else unichr
|
|
|
|
|
|
def _py23_cmp(a, b):
|
|
return (a > b) - (a < b)
|
|
|
|
|
|
py23_cmp = _py23_cmp if sys.version[0] == '3' else cmp
|
|
|
|
# zip as an iterator
|
|
if sys.version[0] == '3':
|
|
py23_zip = zip
|
|
py23_map = map
|
|
py23_filter = filter
|
|
else:
|
|
import itertools
|
|
py23_zip = itertools.izip
|
|
py23_map = itertools.imap
|
|
py23_filter = itertools.ifilter
|
|
|
|
|
|
# cmp_to_key was not created till 2.7, so require this for 2.6
|
|
try:
|
|
from functools import cmp_to_key
|
|
except ImportError: # pragma: no cover
|
|
def cmp_to_key(mycmp):
|
|
"""Convert a cmp= function into a key= function"""
|
|
class K(object):
|
|
__slots__ = ['obj']
|
|
|
|
def __init__(self, obj):
|
|
self.obj = obj
|
|
|
|
def __lt__(self, other):
|
|
return mycmp(self.obj, other.obj) < 0
|
|
|
|
def __gt__(self, other):
|
|
return mycmp(self.obj, other.obj) > 0
|
|
|
|
def __eq__(self, other):
|
|
return mycmp(self.obj, other.obj) == 0
|
|
|
|
def __le__(self, other):
|
|
return mycmp(self.obj, other.obj) <= 0
|
|
|
|
def __ge__(self, other):
|
|
return mycmp(self.obj, other.obj) >= 0
|
|
|
|
def __ne__(self, other):
|
|
return mycmp(self.obj, other.obj) != 0
|
|
|
|
def __hash__(self):
|
|
raise TypeError('hash not implemented')
|
|
|
|
return K
|
|
|
|
|
|
# This function is intended to decorate other functions that will modify
|
|
# either a string directly, or a function's docstring.
|
|
def _modify_str_or_docstring(str_change_func):
|
|
@functools.wraps(str_change_func)
|
|
def wrapper(func_or_str):
|
|
if isinstance(func_or_str, py23_basestring):
|
|
func = None
|
|
doc = func_or_str
|
|
else:
|
|
func = func_or_str
|
|
doc = func.__doc__
|
|
|
|
if doc is not None:
|
|
doc = str_change_func(doc)
|
|
|
|
if func:
|
|
func.__doc__ = doc
|
|
return func
|
|
return doc
|
|
return wrapper
|
|
|
|
|
|
# Properly modify a doctstring to either have the unicode literal or not.
|
|
if sys.version[0] == '3':
|
|
# Abstract u'abc' syntax:
|
|
@_modify_str_or_docstring
|
|
def u_format(s):
|
|
""""{u}'abc'" --> "'abc'" (Python 3)
|
|
|
|
Accepts a string or a function, so it can be used as a decorator."""
|
|
return s.format(u='')
|
|
else:
|
|
# Abstract u'abc' syntax:
|
|
@_modify_str_or_docstring
|
|
def u_format(s):
|
|
""""{u}'abc'" --> "u'abc'" (Python 2)
|
|
|
|
Accepts a string or a function, so it can be used as a decorator."""
|
|
return s.format(u='u')
|