diff --git a/pre_commit/five.py b/pre_commit/five.py new file mode 100644 index 00000000..e3bab85e --- /dev/null +++ b/pre_commit/five.py @@ -0,0 +1,78 @@ +"""five: six, redux""" +# pylint:disable=invalid-name +PY2 = (str is bytes) +PY3 = (str is not bytes) + +# provide a symettrical `text` type to `bytes` +if PY2: + text = unicode # flake8: noqa +else: + text = str + + +def n(obj): + """Produce a native string. + + Similar in behavior to str(), but uses US-ASCII encoding when necessary. + """ + if isinstance(obj, str): + return obj + elif PY2 and isinstance(obj, text): + return obj.encode('US-ASCII') + elif PY3 and isinstance(obj, bytes): + return obj.decode('US-ASCII') + else: + return str(obj) + + +def u(obj): + """Produces text. + + Similar in behavior to str() in python3 or unicode() in python2, + but uses US-ASCII encoding when necessary. + """ + if isinstance(obj, text): + return obj + elif isinstance(obj, bytes): + return obj.decode('US-ASCII') + else: + return text(obj) + + +def b(obj): + """Produces bytes. + + Similar in behavior to bytes(), but uses US-ASCII encoding when necessary. + """ + if isinstance(obj, bytes): + return obj + elif isinstance(obj, text): + return obj.encode('US-ASCII') + else: + return bytes(obj) + + +def udict(*args, **kwargs): + """Similar to dict(), but keyword-keys are text.""" + kwargs = dict([ + (u(key), val) + for key, val in kwargs.items() + ]) + + return dict(*args, **kwargs) + +def ndict(*args, **kwargs): + """Similar to dict(), but keyword-keys are forced to native strings.""" + # I hate this :( + kwargs = dict([ + (n(key), val) + for key, val in kwargs.items() + ]) + + return dict(*args, **kwargs) + +def open(*args, **kwargs): + """Override the builtin open() to return text and use utf8 by default.""" + from io import open + kwargs.setdefault('encoding', 'UTF-8') + return open(*args, **kwargs) diff --git a/pre_commit/repository.py b/pre_commit/repository.py index f94336cb..b1ac4821 100644 --- a/pre_commit/repository.py +++ b/pre_commit/repository.py @@ -4,6 +4,7 @@ from asottile.ordereddict import OrderedDict from plumbum import local import pre_commit.constants as C +from pre_commit import five from pre_commit.clientlib.validate_manifest import load_manifest from pre_commit.hooks_workspace import in_hooks_workspace from pre_commit.languages.all import languages @@ -70,7 +71,7 @@ class Repository(object): logger.info('Installing environment for {0}.'.format(self.repo_url)) logger.info('Once installed this environment will be reused.') logger.info('This may take a few minutes...') - with clean_path_on_failure(str(local.path(self.sha))): + with clean_path_on_failure(five.u(local.path(self.sha))): local['git']['clone', '--no-checkout', self.repo_url, self.sha]() with self.in_checkout(): local['git']['checkout', self.sha]()