We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Failures when hook ids are non-ascii
```
$ pre-commit run ☃
An unexpected error has occurred: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
Check the log at ~/.pre-commit/pre-commit.log
$ cat ~/.pre-commit/pre-commit.log 
An unexpected error has occurred: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
Traceback (most recent call last):
  File "/home/asottile/workspace/pre-commit/pre_commit/error_handler.py", line 34, in error_handler
    yield
  File "/home/asottile/workspace/pre-commit/pre_commit/main.py", line 129, in main
    return run(runner, args)
  File "/home/asottile/workspace/pre-commit/pre_commit/commands/run.py", line 163, in run
    return _run_hook(runner, args, write=write)
  File "/home/asottile/workspace/pre-commit/pre_commit/commands/run.py", line 133, in _run_hook
    write('No hook with id `{0}`\n'.format(hook_id))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pre_commit/output.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 import subprocess
4 import sys
5 
6 from pre_commit import color
7 from pre_commit import five
8 
9 
10 # TODO: smell: import side-effects
11 try:
12     COLS = int(
13         subprocess.Popen(
14             ['tput', 'cols'], stdout=subprocess.PIPE,
15         ).communicate()[0] or
16         # Default in the case of no terminal
17         80
18     )
19 except OSError:  # pragma: no cover (windows)
20     COLS = 80
21 
22 
23 def get_hook_message(
24         start,
25         postfix='',
26         end_msg=None,
27         end_len=0,
28         end_color=None,
29         use_color=None,
30         cols=COLS,
31 ):
32     """Prints a message for running a hook.
33 
34     This currently supports three approaches:
35 
36     # Print `start` followed by dots, leaving 6 characters at the end
37     >>> print_hook_message('start', end_len=6)
38     start...............................................................
39 
40     # Print `start` followed by dots with the end message colored if coloring
41     # is specified and a newline afterwards
42     >>> print_hook_message(
43         'start',
44         end_msg='end',
45         end_color=color.RED,
46         use_color=True,
47     )
48     start...................................................................end
49 
50     # Print `start` followed by dots, followed by the `postfix` message
51     # uncolored, followed by the `end_msg` colored if specified and a newline
52     # afterwards
53     >>> print_hook_message(
54         'start',
55         postfix='postfix ',
56         end_msg='end',
57         end_color=color.RED,
58         use_color=True,
59     )
60     start...........................................................postfix end
61     """
62     if bool(end_msg) == bool(end_len):
63         raise ValueError('Expected one of (`end_msg`, `end_len`)')
64     if end_msg is not None and (end_color is None or use_color is None):
65         raise ValueError(
66             '`end_color` and `use_color` are required with `end_msg`'
67         )
68 
69     if end_len:
70         return start + '.' * (cols - len(start) - end_len - 1)
71     else:
72         return '{0}{1}{2}{3}\n'.format(
73             start,
74             '.' * (cols - len(start) - len(postfix) - len(end_msg) - 1),
75             postfix,
76             color.format_color(end_msg, end_color, use_color),
77         )
78 
79 
80 def sys_stdout_write_wrapper(s, stream=sys.stdout):
81     """Python 2.6 chokes on unicode being passed to sys.stdout.write.
82 
83     This is an adapter because PY2 is ok with bytes and PY3 requires text.
84     """
85     assert type(s) is five.text
86     if five.PY2:  # pragma: no cover (PY2)
87         s = s.encode('UTF-8')
88     stream.write(s)
89
```

Path: `pre_commit/five.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 # pylint:disable=invalid-name
4 PY2 = str is bytes
5 PY3 = str is not bytes
6 
7 if PY2:  # pragma: no cover (PY2 only)
8     text = unicode  # flake8: noqa
9 
10     def n(s):
11         if isinstance(s, bytes):
12             return s
13         else:
14             return s.encode('UTF-8')
15 else:  # pragma: no cover (PY3 only)
16     text = str
17 
18     def n(s):
19         if isinstance(s, text):
20             return s
21         else:
22             return s.decode('UTF-8')
23
```

Path: `pre_commit/main.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 import argparse
4 import os
5 import sys
6 
7 import pkg_resources
8 
9 from pre_commit import color
10 from pre_commit.commands.autoupdate import autoupdate
11 from pre_commit.commands.clean import clean
12 from pre_commit.commands.install_uninstall import install
13 from pre_commit.commands.install_uninstall import uninstall
14 from pre_commit.commands.run import run
15 from pre_commit.error_handler import error_handler
16 from pre_commit.runner import Runner
17 
18 
19 # https://github.com/pre-commit/pre-commit/issues/217
20 # On OSX, making a virtualenv using pyvenv at . causes `virtualenv` and `pip`
21 # to install packages to the wrong place.  We don't want anything to deal with
22 # pyvenv
23 os.environ.pop('__PYVENV_LAUNCHER__', None)
24 
25 
26 def main(argv=None):
27     argv = argv if argv is not None else sys.argv[1:]
28     parser = argparse.ArgumentParser()
29 
30     # http://stackoverflow.com/a/8521644/812183
31     parser.add_argument(
32         '-V', '--version',
33         action='version',
34         version='%(prog)s {0}'.format(
35             pkg_resources.get_distribution('pre-commit').version
36         )
37     )
38 
39     subparsers = parser.add_subparsers(dest='command')
40 
41     install_parser = subparsers.add_parser(
42         'install', help='Install the pre-commit script.',
43     )
44     install_parser.add_argument(
45         '-f', '--overwrite', action='store_true',
46         help='Overwrite existing hooks / remove migration mode.',
47     )
48     install_parser.add_argument(
49         '--install-hooks', action='store_true',
50         help=(
51             'Whether to install hook environments for all environments '
52             'in the config file.'
53         ),
54     )
55     install_parser.add_argument(
56         '-t', '--hook-type', choices=('pre-commit', 'pre-push'),
57         default='pre-commit',
58     )
59 
60     uninstall_parser = subparsers.add_parser(
61         'uninstall', help='Uninstall the pre-commit script.',
62     )
63     uninstall_parser.add_argument(
64         '-t', '--hook-type', choices=('pre-commit', 'pre-push'),
65         default='pre-commit',
66     )
67 
68     subparsers.add_parser('clean', help='Clean out pre-commit files.')
69 
70     subparsers.add_parser(
71         'autoupdate',
72         help="Auto-update pre-commit config to the latest repos' versions.",
73     )
74 
75     run_parser = subparsers.add_parser('run', help='Run hooks.')
76     run_parser.add_argument('hook', nargs='?', help='A single hook-id to run')
77     run_parser.add_argument(
78         '--color', default='auto', type=color.use_color,
79         help='Whether to use color in output.  Defaults to `auto`',
80     )
81     run_parser.add_argument(
82         '--no-stash', default=False, action='store_true',
83         help='Use this option to prevent auto stashing of unstaged files.',
84     )
85     run_parser.add_argument(
86         '--verbose', '-v', action='store_true', default=False,
87     )
88 
89     run_parser.add_argument(
90         '--origin', '-o',
91         help='The origin branch"s commit_id when using `git push`',
92     )
93     run_parser.add_argument(
94         '--source', '-s',
95         help='The remote branch"s commit_id when using `git push`',
96     )
97     run_parser.add_argument(
98         '--allow-unstaged-config', default=False, action='store_true',
99         help='Allow an unstaged config to be present.  Note that this will'
100         'be stashed before parsing unless --no-stash is specified'
101     )
102     run_mutex_group = run_parser.add_mutually_exclusive_group(required=False)
103     run_mutex_group.add_argument(
104         '--all-files', '-a', action='store_true', default=False,
105         help='Run on all the files in the repo.  Implies --no-stash.',
106     )
107     run_mutex_group.add_argument(
108         '--files', nargs='*', help='Specific filenames to run hooks on.',
109     )
110 
111     help = subparsers.add_parser(
112         'help', help='Show help for a specific command.'
113     )
114     help.add_argument('help_cmd', nargs='?', help='Command to show help for.')
115 
116     # Argparse doesn't really provide a way to use a `default` subparser
117     if len(argv) == 0:
118         argv = ['run']
119     args = parser.parse_args(argv)
120 
121     if args.command == 'help':
122         if args.help_cmd:
123             parser.parse_args([args.help_cmd, '--help'])
124         else:
125             parser.parse_args(['--help'])
126 
127     with error_handler():
128         runner = Runner.create()
129 
130         if args.command == 'install':
131             return install(
132                 runner, overwrite=args.overwrite, hooks=args.install_hooks,
133                 hook_type=args.hook_type,
134             )
135         elif args.command == 'uninstall':
136             return uninstall(runner, hook_type=args.hook_type)
137         elif args.command == 'clean':
138             return clean(runner)
139         elif args.command == 'autoupdate':
140             return autoupdate(runner)
141         elif args.command == 'run':
142             return run(runner, args)
143         else:
144             raise NotImplementedError(
145                 'Command {0} not implemented.'.format(args.command)
146             )
147 
148         raise AssertionError(
149             'Command {0} failed to exit with a returncode'.format(args.command)
150         )
151 
152 
153 if __name__ == '__main__':
154     exit(main())
155
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pre_commit/five.py b/pre_commit/five.py
--- a/pre_commit/five.py
+++ b/pre_commit/five.py
@@ -20,3 +20,11 @@
             return s
         else:
             return s.decode('UTF-8')
+
+
+def to_text(s):
+    return s if isinstance(s, text) else s.decode('UTF-8')
+
+
+def to_bytes(s):
+    return s if isinstance(s, bytes) else s.encode('UTF-8')
diff --git a/pre_commit/main.py b/pre_commit/main.py
--- a/pre_commit/main.py
+++ b/pre_commit/main.py
@@ -7,6 +7,7 @@
 import pkg_resources
 
 from pre_commit import color
+from pre_commit import five
 from pre_commit.commands.autoupdate import autoupdate
 from pre_commit.commands.clean import clean
 from pre_commit.commands.install_uninstall import install
@@ -25,6 +26,7 @@
 
 def main(argv=None):
     argv = argv if argv is not None else sys.argv[1:]
+    argv = [five.to_text(arg) for arg in argv]
     parser = argparse.ArgumentParser()
 
     # http://stackoverflow.com/a/8521644/812183
diff --git a/pre_commit/output.py b/pre_commit/output.py
--- a/pre_commit/output.py
+++ b/pre_commit/output.py
@@ -77,12 +77,8 @@
         )
 
 
-def sys_stdout_write_wrapper(s, stream=sys.stdout):
-    """Python 2.6 chokes on unicode being passed to sys.stdout.write.
+stdout_byte_stream = getattr(sys.stdout, 'buffer', sys.stdout)
 
-    This is an adapter because PY2 is ok with bytes and PY3 requires text.
-    """
-    assert type(s) is five.text
-    if five.PY2:  # pragma: no cover (PY2)
-        s = s.encode('UTF-8')
-    stream.write(s)
+
+def sys_stdout_write_wrapper(s, stream=stdout_byte_stream):
+    stream.write(five.to_bytes(s))

{"golden_diff": "diff --git a/pre_commit/five.py b/pre_commit/five.py\n--- a/pre_commit/five.py\n+++ b/pre_commit/five.py\n@@ -20,3 +20,11 @@\n             return s\n         else:\n             return s.decode('UTF-8')\n+\n+\n+def to_text(s):\n+    return s if isinstance(s, text) else s.decode('UTF-8')\n+\n+\n+def to_bytes(s):\n+    return s if isinstance(s, bytes) else s.encode('UTF-8')\ndiff --git a/pre_commit/main.py b/pre_commit/main.py\n--- a/pre_commit/main.py\n+++ b/pre_commit/main.py\n@@ -7,6 +7,7 @@\n import pkg_resources\n \n from pre_commit import color\n+from pre_commit import five\n from pre_commit.commands.autoupdate import autoupdate\n from pre_commit.commands.clean import clean\n from pre_commit.commands.install_uninstall import install\n@@ -25,6 +26,7 @@\n \n def main(argv=None):\n     argv = argv if argv is not None else sys.argv[1:]\n+    argv = [five.to_text(arg) for arg in argv]\n     parser = argparse.ArgumentParser()\n \n     # http://stackoverflow.com/a/8521644/812183\ndiff --git a/pre_commit/output.py b/pre_commit/output.py\n--- a/pre_commit/output.py\n+++ b/pre_commit/output.py\n@@ -77,12 +77,8 @@\n         )\n \n \n-def sys_stdout_write_wrapper(s, stream=sys.stdout):\n-    \"\"\"Python 2.6 chokes on unicode being passed to sys.stdout.write.\n+stdout_byte_stream = getattr(sys.stdout, 'buffer', sys.stdout)\n \n-    This is an adapter because PY2 is ok with bytes and PY3 requires text.\n-    \"\"\"\n-    assert type(s) is five.text\n-    if five.PY2:  # pragma: no cover (PY2)\n-        s = s.encode('UTF-8')\n-    stream.write(s)\n+\n+def sys_stdout_write_wrapper(s, stream=stdout_byte_stream):\n+    stream.write(five.to_bytes(s))\n", "issue": "Failures when hook ids are non-ascii\n```\n$ pre-commit run \u2603\nAn unexpected error has occurred: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)\nCheck the log at ~/.pre-commit/pre-commit.log\n$ cat ~/.pre-commit/pre-commit.log \nAn unexpected error has occurred: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)\nTraceback (most recent call last):\n  File \"/home/asottile/workspace/pre-commit/pre_commit/error_handler.py\", line 34, in error_handler\n    yield\n  File \"/home/asottile/workspace/pre-commit/pre_commit/main.py\", line 129, in main\n    return run(runner, args)\n  File \"/home/asottile/workspace/pre-commit/pre_commit/commands/run.py\", line 163, in run\n    return _run_hook(runner, args, write=write)\n  File \"/home/asottile/workspace/pre-commit/pre_commit/commands/run.py\", line 133, in _run_hook\n    write('No hook with id `{0}`\\n'.format(hook_id))\nUnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)\n```\n\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nimport subprocess\nimport sys\n\nfrom pre_commit import color\nfrom pre_commit import five\n\n\n# TODO: smell: import side-effects\ntry:\n    COLS = int(\n        subprocess.Popen(\n            ['tput', 'cols'], stdout=subprocess.PIPE,\n        ).communicate()[0] or\n        # Default in the case of no terminal\n        80\n    )\nexcept OSError:  # pragma: no cover (windows)\n    COLS = 80\n\n\ndef get_hook_message(\n        start,\n        postfix='',\n        end_msg=None,\n        end_len=0,\n        end_color=None,\n        use_color=None,\n        cols=COLS,\n):\n    \"\"\"Prints a message for running a hook.\n\n    This currently supports three approaches:\n\n    # Print `start` followed by dots, leaving 6 characters at the end\n    >>> print_hook_message('start', end_len=6)\n    start...............................................................\n\n    # Print `start` followed by dots with the end message colored if coloring\n    # is specified and a newline afterwards\n    >>> print_hook_message(\n        'start',\n        end_msg='end',\n        end_color=color.RED,\n        use_color=True,\n    )\n    start...................................................................end\n\n    # Print `start` followed by dots, followed by the `postfix` message\n    # uncolored, followed by the `end_msg` colored if specified and a newline\n    # afterwards\n    >>> print_hook_message(\n        'start',\n        postfix='postfix ',\n        end_msg='end',\n        end_color=color.RED,\n        use_color=True,\n    )\n    start...........................................................postfix end\n    \"\"\"\n    if bool(end_msg) == bool(end_len):\n        raise ValueError('Expected one of (`end_msg`, `end_len`)')\n    if end_msg is not None and (end_color is None or use_color is None):\n        raise ValueError(\n            '`end_color` and `use_color` are required with `end_msg`'\n        )\n\n    if end_len:\n        return start + '.' * (cols - len(start) - end_len - 1)\n    else:\n        return '{0}{1}{2}{3}\\n'.format(\n            start,\n            '.' * (cols - len(start) - len(postfix) - len(end_msg) - 1),\n            postfix,\n            color.format_color(end_msg, end_color, use_color),\n        )\n\n\ndef sys_stdout_write_wrapper(s, stream=sys.stdout):\n    \"\"\"Python 2.6 chokes on unicode being passed to sys.stdout.write.\n\n    This is an adapter because PY2 is ok with bytes and PY3 requires text.\n    \"\"\"\n    assert type(s) is five.text\n    if five.PY2:  # pragma: no cover (PY2)\n        s = s.encode('UTF-8')\n    stream.write(s)\n", "path": "pre_commit/output.py"}, {"content": "from __future__ import unicode_literals\n\n# pylint:disable=invalid-name\nPY2 = str is bytes\nPY3 = str is not bytes\n\nif PY2:  # pragma: no cover (PY2 only)\n    text = unicode  # flake8: noqa\n\n    def n(s):\n        if isinstance(s, bytes):\n            return s\n        else:\n            return s.encode('UTF-8')\nelse:  # pragma: no cover (PY3 only)\n    text = str\n\n    def n(s):\n        if isinstance(s, text):\n            return s\n        else:\n            return s.decode('UTF-8')\n", "path": "pre_commit/five.py"}, {"content": "from __future__ import unicode_literals\n\nimport argparse\nimport os\nimport sys\n\nimport pkg_resources\n\nfrom pre_commit import color\nfrom pre_commit.commands.autoupdate import autoupdate\nfrom pre_commit.commands.clean import clean\nfrom pre_commit.commands.install_uninstall import install\nfrom pre_commit.commands.install_uninstall import uninstall\nfrom pre_commit.commands.run import run\nfrom pre_commit.error_handler import error_handler\nfrom pre_commit.runner import Runner\n\n\n# https://github.com/pre-commit/pre-commit/issues/217\n# On OSX, making a virtualenv using pyvenv at . causes `virtualenv` and `pip`\n# to install packages to the wrong place.  We don't want anything to deal with\n# pyvenv\nos.environ.pop('__PYVENV_LAUNCHER__', None)\n\n\ndef main(argv=None):\n    argv = argv if argv is not None else sys.argv[1:]\n    parser = argparse.ArgumentParser()\n\n    # http://stackoverflow.com/a/8521644/812183\n    parser.add_argument(\n        '-V', '--version',\n        action='version',\n        version='%(prog)s {0}'.format(\n            pkg_resources.get_distribution('pre-commit').version\n        )\n    )\n\n    subparsers = parser.add_subparsers(dest='command')\n\n    install_parser = subparsers.add_parser(\n        'install', help='Install the pre-commit script.',\n    )\n    install_parser.add_argument(\n        '-f', '--overwrite', action='store_true',\n        help='Overwrite existing hooks / remove migration mode.',\n    )\n    install_parser.add_argument(\n        '--install-hooks', action='store_true',\n        help=(\n            'Whether to install hook environments for all environments '\n            'in the config file.'\n        ),\n    )\n    install_parser.add_argument(\n        '-t', '--hook-type', choices=('pre-commit', 'pre-push'),\n        default='pre-commit',\n    )\n\n    uninstall_parser = subparsers.add_parser(\n        'uninstall', help='Uninstall the pre-commit script.',\n    )\n    uninstall_parser.add_argument(\n        '-t', '--hook-type', choices=('pre-commit', 'pre-push'),\n        default='pre-commit',\n    )\n\n    subparsers.add_parser('clean', help='Clean out pre-commit files.')\n\n    subparsers.add_parser(\n        'autoupdate',\n        help=\"Auto-update pre-commit config to the latest repos' versions.\",\n    )\n\n    run_parser = subparsers.add_parser('run', help='Run hooks.')\n    run_parser.add_argument('hook', nargs='?', help='A single hook-id to run')\n    run_parser.add_argument(\n        '--color', default='auto', type=color.use_color,\n        help='Whether to use color in output.  Defaults to `auto`',\n    )\n    run_parser.add_argument(\n        '--no-stash', default=False, action='store_true',\n        help='Use this option to prevent auto stashing of unstaged files.',\n    )\n    run_parser.add_argument(\n        '--verbose', '-v', action='store_true', default=False,\n    )\n\n    run_parser.add_argument(\n        '--origin', '-o',\n        help='The origin branch\"s commit_id when using `git push`',\n    )\n    run_parser.add_argument(\n        '--source', '-s',\n        help='The remote branch\"s commit_id when using `git push`',\n    )\n    run_parser.add_argument(\n        '--allow-unstaged-config', default=False, action='store_true',\n        help='Allow an unstaged config to be present.  Note that this will'\n        'be stashed before parsing unless --no-stash is specified'\n    )\n    run_mutex_group = run_parser.add_mutually_exclusive_group(required=False)\n    run_mutex_group.add_argument(\n        '--all-files', '-a', action='store_true', default=False,\n        help='Run on all the files in the repo.  Implies --no-stash.',\n    )\n    run_mutex_group.add_argument(\n        '--files', nargs='*', help='Specific filenames to run hooks on.',\n    )\n\n    help = subparsers.add_parser(\n        'help', help='Show help for a specific command.'\n    )\n    help.add_argument('help_cmd', nargs='?', help='Command to show help for.')\n\n    # Argparse doesn't really provide a way to use a `default` subparser\n    if len(argv) == 0:\n        argv = ['run']\n    args = parser.parse_args(argv)\n\n    if args.command == 'help':\n        if args.help_cmd:\n            parser.parse_args([args.help_cmd, '--help'])\n        else:\n            parser.parse_args(['--help'])\n\n    with error_handler():\n        runner = Runner.create()\n\n        if args.command == 'install':\n            return install(\n                runner, overwrite=args.overwrite, hooks=args.install_hooks,\n                hook_type=args.hook_type,\n            )\n        elif args.command == 'uninstall':\n            return uninstall(runner, hook_type=args.hook_type)\n        elif args.command == 'clean':\n            return clean(runner)\n        elif args.command == 'autoupdate':\n            return autoupdate(runner)\n        elif args.command == 'run':\n            return run(runner, args)\n        else:\n            raise NotImplementedError(\n                'Command {0} not implemented.'.format(args.command)\n            )\n\n        raise AssertionError(\n            'Command {0} failed to exit with a returncode'.format(args.command)\n        )\n\n\nif __name__ == '__main__':\n    exit(main())\n", "path": "pre_commit/main.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nimport subprocess\nimport sys\n\nfrom pre_commit import color\nfrom pre_commit import five\n\n\n# TODO: smell: import side-effects\ntry:\n    COLS = int(\n        subprocess.Popen(\n            ['tput', 'cols'], stdout=subprocess.PIPE,\n        ).communicate()[0] or\n        # Default in the case of no terminal\n        80\n    )\nexcept OSError:  # pragma: no cover (windows)\n    COLS = 80\n\n\ndef get_hook_message(\n        start,\n        postfix='',\n        end_msg=None,\n        end_len=0,\n        end_color=None,\n        use_color=None,\n        cols=COLS,\n):\n    \"\"\"Prints a message for running a hook.\n\n    This currently supports three approaches:\n\n    # Print `start` followed by dots, leaving 6 characters at the end\n    >>> print_hook_message('start', end_len=6)\n    start...............................................................\n\n    # Print `start` followed by dots with the end message colored if coloring\n    # is specified and a newline afterwards\n    >>> print_hook_message(\n        'start',\n        end_msg='end',\n        end_color=color.RED,\n        use_color=True,\n    )\n    start...................................................................end\n\n    # Print `start` followed by dots, followed by the `postfix` message\n    # uncolored, followed by the `end_msg` colored if specified and a newline\n    # afterwards\n    >>> print_hook_message(\n        'start',\n        postfix='postfix ',\n        end_msg='end',\n        end_color=color.RED,\n        use_color=True,\n    )\n    start...........................................................postfix end\n    \"\"\"\n    if bool(end_msg) == bool(end_len):\n        raise ValueError('Expected one of (`end_msg`, `end_len`)')\n    if end_msg is not None and (end_color is None or use_color is None):\n        raise ValueError(\n            '`end_color` and `use_color` are required with `end_msg`'\n        )\n\n    if end_len:\n        return start + '.' * (cols - len(start) - end_len - 1)\n    else:\n        return '{0}{1}{2}{3}\\n'.format(\n            start,\n            '.' * (cols - len(start) - len(postfix) - len(end_msg) - 1),\n            postfix,\n            color.format_color(end_msg, end_color, use_color),\n        )\n\n\nstdout_byte_stream = getattr(sys.stdout, 'buffer', sys.stdout)\n\n\ndef sys_stdout_write_wrapper(s, stream=stdout_byte_stream):\n    stream.write(five.to_bytes(s))\n", "path": "pre_commit/output.py"}, {"content": "from __future__ import unicode_literals\n\n# pylint:disable=invalid-name\nPY2 = str is bytes\nPY3 = str is not bytes\n\nif PY2:  # pragma: no cover (PY2 only)\n    text = unicode  # flake8: noqa\n\n    def n(s):\n        if isinstance(s, bytes):\n            return s\n        else:\n            return s.encode('UTF-8')\nelse:  # pragma: no cover (PY3 only)\n    text = str\n\n    def n(s):\n        if isinstance(s, text):\n            return s\n        else:\n            return s.decode('UTF-8')\n\n\ndef to_text(s):\n    return s if isinstance(s, text) else s.decode('UTF-8')\n\n\ndef to_bytes(s):\n    return s if isinstance(s, bytes) else s.encode('UTF-8')\n", "path": "pre_commit/five.py"}, {"content": "from __future__ import unicode_literals\n\nimport argparse\nimport os\nimport sys\n\nimport pkg_resources\n\nfrom pre_commit import color\nfrom pre_commit import five\nfrom pre_commit.commands.autoupdate import autoupdate\nfrom pre_commit.commands.clean import clean\nfrom pre_commit.commands.install_uninstall import install\nfrom pre_commit.commands.install_uninstall import uninstall\nfrom pre_commit.commands.run import run\nfrom pre_commit.error_handler import error_handler\nfrom pre_commit.runner import Runner\n\n\n# https://github.com/pre-commit/pre-commit/issues/217\n# On OSX, making a virtualenv using pyvenv at . causes `virtualenv` and `pip`\n# to install packages to the wrong place.  We don't want anything to deal with\n# pyvenv\nos.environ.pop('__PYVENV_LAUNCHER__', None)\n\n\ndef main(argv=None):\n    argv = argv if argv is not None else sys.argv[1:]\n    argv = [five.to_text(arg) for arg in argv]\n    parser = argparse.ArgumentParser()\n\n    # http://stackoverflow.com/a/8521644/812183\n    parser.add_argument(\n        '-V', '--version',\n        action='version',\n        version='%(prog)s {0}'.format(\n            pkg_resources.get_distribution('pre-commit').version\n        )\n    )\n\n    subparsers = parser.add_subparsers(dest='command')\n\n    install_parser = subparsers.add_parser(\n        'install', help='Install the pre-commit script.',\n    )\n    install_parser.add_argument(\n        '-f', '--overwrite', action='store_true',\n        help='Overwrite existing hooks / remove migration mode.',\n    )\n    install_parser.add_argument(\n        '--install-hooks', action='store_true',\n        help=(\n            'Whether to install hook environments for all environments '\n            'in the config file.'\n        ),\n    )\n    install_parser.add_argument(\n        '-t', '--hook-type', choices=('pre-commit', 'pre-push'),\n        default='pre-commit',\n    )\n\n    uninstall_parser = subparsers.add_parser(\n        'uninstall', help='Uninstall the pre-commit script.',\n    )\n    uninstall_parser.add_argument(\n        '-t', '--hook-type', choices=('pre-commit', 'pre-push'),\n        default='pre-commit',\n    )\n\n    subparsers.add_parser('clean', help='Clean out pre-commit files.')\n\n    subparsers.add_parser(\n        'autoupdate',\n        help=\"Auto-update pre-commit config to the latest repos' versions.\",\n    )\n\n    run_parser = subparsers.add_parser('run', help='Run hooks.')\n    run_parser.add_argument('hook', nargs='?', help='A single hook-id to run')\n    run_parser.add_argument(\n        '--color', default='auto', type=color.use_color,\n        help='Whether to use color in output.  Defaults to `auto`',\n    )\n    run_parser.add_argument(\n        '--no-stash', default=False, action='store_true',\n        help='Use this option to prevent auto stashing of unstaged files.',\n    )\n    run_parser.add_argument(\n        '--verbose', '-v', action='store_true', default=False,\n    )\n\n    run_parser.add_argument(\n        '--origin', '-o',\n        help='The origin branch\"s commit_id when using `git push`',\n    )\n    run_parser.add_argument(\n        '--source', '-s',\n        help='The remote branch\"s commit_id when using `git push`',\n    )\n    run_parser.add_argument(\n        '--allow-unstaged-config', default=False, action='store_true',\n        help='Allow an unstaged config to be present.  Note that this will'\n        'be stashed before parsing unless --no-stash is specified'\n    )\n    run_mutex_group = run_parser.add_mutually_exclusive_group(required=False)\n    run_mutex_group.add_argument(\n        '--all-files', '-a', action='store_true', default=False,\n        help='Run on all the files in the repo.  Implies --no-stash.',\n    )\n    run_mutex_group.add_argument(\n        '--files', nargs='*', help='Specific filenames to run hooks on.',\n    )\n\n    help = subparsers.add_parser(\n        'help', help='Show help for a specific command.'\n    )\n    help.add_argument('help_cmd', nargs='?', help='Command to show help for.')\n\n    # Argparse doesn't really provide a way to use a `default` subparser\n    if len(argv) == 0:\n        argv = ['run']\n    args = parser.parse_args(argv)\n\n    if args.command == 'help':\n        if args.help_cmd:\n            parser.parse_args([args.help_cmd, '--help'])\n        else:\n            parser.parse_args(['--help'])\n\n    with error_handler():\n        runner = Runner.create()\n\n        if args.command == 'install':\n            return install(\n                runner, overwrite=args.overwrite, hooks=args.install_hooks,\n                hook_type=args.hook_type,\n            )\n        elif args.command == 'uninstall':\n            return uninstall(runner, hook_type=args.hook_type)\n        elif args.command == 'clean':\n            return clean(runner)\n        elif args.command == 'autoupdate':\n            return autoupdate(runner)\n        elif args.command == 'run':\n            return run(runner, args)\n        else:\n            raise NotImplementedError(\n                'Command {0} not implemented.'.format(args.command)\n            )\n\n        raise AssertionError(\n            'Command {0} failed to exit with a returncode'.format(args.command)\n        )\n\n\nif __name__ == '__main__':\n    exit(main())\n", "path": "pre_commit/main.py"}]}