{
    "file_diffs": [
        {
            "old_file_content": "# emacs: -*- mode: python-mode; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\"\"\"\"\"\"\n\nfrom six.moves import StringIO as SIO\nfrom os.path import exists\nfrom nose import SkipTest\ntry:\n    import formatters as fmt\nexcept ImportError:  # pragma: no cover\n    # must be running from installed version where formatters is not present\n    # These tests can be ran only with formatters, which is outside of the\n    # datalad module space in the root of the sourcebase\n    if not exists('formatters.py'):\n        raise SkipTest\n\nfrom ..main import setup_parser\nfrom datalad.tests.utils import ok_, assert_in, ok_startswith\n\ndemo_example = \"\"\"\n#!/bin/sh\n\nset -e\nset -u\n\n# BOILERPLATE\n\nHOME=IS_MY_CASTLE\n\n#% EXAMPLE START\n#\n# A simple start (on the command line)\n# ====================================\n#\n# Lorem ipsum\n#%\n\ndatalad install http://the.world.com\n\n#%\n# Epilog -- with multiline rubish sdoifpwjefw\n# vsdokvpsokdvpsdkv spdokvpskdvpoksd\n# pfdsvja329u0fjpdsv sdpf9p93qk\n#%\n\ndatalad imagine --too \\\\\n        --much \\\\\n        --too say \\\\\n        yes=no\n\n#%\n# The result is not comprehensible.\n#%\n\n#% EXAMPLE END\n\n# define shunit test cases below, or just anything desired\n\"\"\"\n\n\ndef test_cmdline_example_to_rst():\n    # don't puke on nothing\n    out = fmt.cmdline_example_to_rst(SIO(''))\n    out.seek(0)\n    ok_startswith(out.read(), '.. AUTO-GENERATED')\n    out = fmt.cmdline_example_to_rst(SIO(''), ref='dummy')\n    out.seek(0)\n    assert_in('.. dummy:', out.read())\n    # full scale test\n    out = fmt.cmdline_example_to_rst(\n        SIO(demo_example), ref='mydemo')\n    out.seek(0)\n    assert_in('.. code-block:: sh', out.read())\n\ndef test_parser_access():\n    parsers = setup_parser(return_subparsers=True)\n    # we have a bunch\n    ok_(len(parsers) > 3)\n    assert_in('install', parsers.keys())\n\n\ndef test_manpage_formatter():\n    addonsections = {'mytest': \"uniquedummystring\"}\n\n    parsers = setup_parser(return_subparsers=True)\n    for p in parsers:\n        mp = fmt.ManPageFormatter(\n            p, ext_sections=addonsections).format_man_page(parsers[p])\n        for section in ('SYNOPSIS', 'DESCRIPTION', 'OPTIONS', 'MYTEST'):\n            assert_in('.SH {0}'.format(section), mp)\n        assert_in('uniquedummystring', mp)\n\n\ndef test_rstmanpage_formatter():\n    parsers = setup_parser(return_subparsers=True)\n    for p in parsers:\n        mp = fmt.RSTManPageFormatter(p).format_man_page(parsers[p])\n        for section in ('Synopsis', 'Description', 'Options'):\n            assert_in('\\n{0}'.format(section), mp)\n        assert_in('{0}\\n{1}'.format(p, '=' * len(p)), mp)\n",
            "new_file_content": "# emacs: -*- mode: python-mode; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\"\"\"\"\"\"\n\nfrom six.moves import StringIO as SIO\nfrom os.path import exists\nfrom nose import SkipTest\ntry:\n    import formatters as fmt\nexcept ImportError:  # pragma: no cover\n    # must be running from installed version where formatters is not present\n    # These tests can be ran only with formatters, which is outside of the\n    # datalad module space in the root of the sourcebase\n    if not exists('formatters.py'):\n        raise SkipTest\n\nfrom ..main import setup_parser\nfrom datalad.tests.utils import ok_, assert_in, ok_startswith\nfrom datalad.tests.utils import assert_not_in\n\ndemo_example = \"\"\"\n#!/bin/sh\n\nset -e\nset -u\n\n# BOILERPLATE\n\nHOME=IS_MY_CASTLE\n\n#% EXAMPLE START\n#\n# A simple start (on the command line)\n# ====================================\n#\n# Lorem ipsum\n#%\n\ndatalad install http://the.world.com\n\n#%\n# Epilog -- with multiline rubish sdoifpwjefw\n# vsdokvpsokdvpsdkv spdokvpskdvpoksd\n# pfdsvja329u0fjpdsv sdpf9p93qk\n#%\n\ndatalad imagine --too \\\\\n        --much \\\\\n        --too say \\\\\n        yes=no\n\ndatalad shameful-command  #% SKIP\n#%\n# The result is not comprehensible.\n#%\n\n#% EXAMPLE END\n\n# define shunit test cases below, or just anything desired\n\"\"\"\n\n\ndef test_cmdline_example_to_rst():\n    # don't puke on nothing\n    out = fmt.cmdline_example_to_rst(SIO(''))\n    out.seek(0)\n    ok_startswith(out.read(), '.. AUTO-GENERATED')\n    out = fmt.cmdline_example_to_rst(SIO(''), ref='dummy')\n    out.seek(0)\n    assert_in('.. dummy:', out.read())\n    # full scale test\n    out = fmt.cmdline_example_to_rst(\n        SIO(demo_example), ref='mydemo')\n    out.seek(0)\n    out_text = out.read()\n    assert_in('.. code-block:: sh', out_text)\n    assert_not_in('shame', out_text)  # no SKIP'ed\n    assert_not_in('#', out_text)      # no comments\n\ndef test_parser_access():\n    parsers = setup_parser(return_subparsers=True)\n    # we have a bunch\n    ok_(len(parsers) > 3)\n    assert_in('install', parsers.keys())\n\n\ndef test_manpage_formatter():\n    addonsections = {'mytest': \"uniquedummystring\"}\n\n    parsers = setup_parser(return_subparsers=True)\n    for p in parsers:\n        mp = fmt.ManPageFormatter(\n            p, ext_sections=addonsections).format_man_page(parsers[p])\n        for section in ('SYNOPSIS', 'DESCRIPTION', 'OPTIONS', 'MYTEST'):\n            assert_in('.SH {0}'.format(section), mp)\n        assert_in('uniquedummystring', mp)\n\n\ndef test_rstmanpage_formatter():\n    parsers = setup_parser(return_subparsers=True)\n    for p in parsers:\n        mp = fmt.RSTManPageFormatter(p).format_man_page(parsers[p])\n        for section in ('Synopsis', 'Description', 'Options'):\n            assert_in('\\n{0}'.format(section), mp)\n        assert_in('{0}\\n{1}'.format(p, '=' * len(p)), mp)\n",
            "header": {
                "file": {
                    "path": "datalad/cmdline/tests/test_formatters.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "41a782822",
                "new_commit_hash": "ad3b46956",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/datalad/cmdline/tests/test_formatters.py"
            },
            "plus_file": {
                "path": "b/datalad/cmdline/tests/test_formatters.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 22,
                            "length": 6
                        },
                        "new_range": {
                            "start": 22,
                            "length": 7
                        },
                        "section": "except ImportError:  # pragma: no cover"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "from ..main import setup_parser",
                                "type": "context"
                            },
                            {
                                "content": "from datalad.tests.utils import ok_, assert_in, ok_startswith",
                                "type": "context"
                            },
                            {
                                "content": "from datalad.tests.utils import assert_not_in",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "demo_example = \"\"\"",
                                "type": "context"
                            },
                            {
                                "content": "#!/bin/sh",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "datalad/cmdline/tests/test_formatters.py",
                            "type": "statement",
                            "name": "",
                            "content": "from datalad.tests.utils import assert_not_in",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 25,
                            "end_lineno": 25,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 54,
                            "length": 6
                        },
                        "new_range": {
                            "start": 55,
                            "length": 7
                        },
                        "section": "datalad imagine --too \\\\"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        --too say \\\\",
                                "type": "context"
                            },
                            {
                                "content": "        yes=no",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "datalad shameful-command  #% SKIP",
                                "type": "added"
                            },
                            {
                                "content": "#%",
                                "type": "context"
                            },
                            {
                                "content": "# The result is not comprehensible.",
                                "type": "context"
                            },
                            {
                                "content": "#%",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "datalad/cmdline/tests/test_formatters.py",
                            "type": "statement",
                            "name": "",
                            "content": "demo_example = \"\"\"\n#!/bin/sh\n\nset -e\nset -u\n\n# BOILERPLATE\n\nHOME=IS_MY_CASTLE\n\n#% EXAMPLE START\n#\n# A simple start (on the command line)\n# ====================================\n#\n# Lorem ipsum\n#%\n\ndatalad install http://the.world.com\n\n#%\n# Epilog -- with multiline rubish sdoifpwjefw\n# vsdokvpsokdvpsdkv spdokvpskdvpoksd\n# pfdsvja329u0fjpdsv sdpf9p93qk\n#%\n\ndatalad imagine --too \\\\\n        --much \\\\\n        --too say \\\\\n        yes=no\n\ndatalad shameful-command  #% SKIP\n#%\n# The result is not comprehensible.\n#%\n\n#% EXAMPLE END\n\n# define shunit test cases below, or just anything desired\n\"\"\"",
                            "ast_type_str": "Assign",
                            "start_lineno": 27,
                            "end_lineno": 66,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 76,
                            "length": 7
                        },
                        "new_range": {
                            "start": 78,
                            "length": 10
                        },
                        "section": "def test_cmdline_example_to_rst():"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    out = fmt.cmdline_example_to_rst(",
                                "type": "context"
                            },
                            {
                                "content": "        SIO(demo_example), ref='mydemo')",
                                "type": "context"
                            },
                            {
                                "content": "    out.seek(0)",
                                "type": "context"
                            },
                            {
                                "content": "    assert_in('.. code-block:: sh', out.read())",
                                "type": "deleted"
                            },
                            {
                                "content": "    out_text = out.read()",
                                "type": "added"
                            },
                            {
                                "content": "    assert_in('.. code-block:: sh', out_text)",
                                "type": "added"
                            },
                            {
                                "content": "    assert_not_in('shame', out_text)  # no SKIP'ed",
                                "type": "added"
                            },
                            {
                                "content": "    assert_not_in('#', out_text)      # no comments",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_parser_access():",
                                "type": "context"
                            },
                            {
                                "content": "    parsers = setup_parser(return_subparsers=True)",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "datalad/cmdline/tests/test_formatters.py",
                            "type": "function",
                            "name": "test_cmdline_example_to_rst",
                            "content": "def test_cmdline_example_to_rst():\n    # don't puke on nothing\n    out = fmt.cmdline_example_to_rst(SIO(''))\n    out.seek(0)\n    ok_startswith(out.read(), '.. AUTO-GENERATED')\n    out = fmt.cmdline_example_to_rst(SIO(''), ref='dummy')\n    out.seek(0)\n    assert_in('.. dummy:', out.read())\n    # full scale test\n    out = fmt.cmdline_example_to_rst(\n        SIO(demo_example), ref='mydemo')\n    out.seek(0)\n    assert_in('.. code-block:: sh', out.read())",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 67,
                            "end_lineno": 79,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the DataLad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\nimport argparse\nimport datetime\nimport re\n\n\nclass ManPageFormatter(argparse.HelpFormatter):\n    # This code was originally distributed\n    # under the same License of Python\n    # Copyright (c) 2014 Oz Nahum Tiram  <nahumoz@gmail.com>\n    def __init__(self,\n                 prog,\n                 indent_increment=2,\n                 max_help_position=4,\n                 width=1000000,\n                 section=1,\n                 ext_sections=None,\n                 authors=None,\n                 version=None\n                 ):\n\n        super(ManPageFormatter, self).__init__(\n            prog,\n            indent_increment=indent_increment,\n            max_help_position=max_help_position,\n            width=width)\n\n        self._prog = prog\n        self._section = 1\n        self._today = datetime.date.today().strftime('%Y\\\\-%m\\\\-%d')\n        self._ext_sections = ext_sections\n        self._version = version\n\n    def _get_formatter(self, **kwargs):\n        return self.formatter_class(prog=self.prog, **kwargs)\n\n    def _markup(self, txt):\n        return txt.replace('-', '\\\\-')\n\n    def _underline(self, string):\n        return \"\\\\fI\\\\s-1\" + string + \"\\\\s0\\\\fR\"\n\n    def _bold(self, string):\n        if not string.strip().startswith('\\\\fB'):\n            string = '\\\\fB' + string\n        if not string.strip().endswith('\\\\fR'):\n            string = string + '\\\\fR'\n        return string\n\n    def _mk_synopsis(self, parser):\n        self.add_usage(parser.usage, parser._actions,\n                       parser._mutually_exclusive_groups, prefix='')\n        usage = self._format_usage(None, parser._actions,\n                                   parser._mutually_exclusive_groups, '')\n        # replace too long list of commands with a single placeholder\n        usage = re.sub(r'{[^]]*?create,.*?}', ' COMMAND ', usage, flags=re.MULTILINE)\n        # take care of proper wrapping\n        usage = re.sub(r'\\[([-a-zA-Z0-9]*)\\s([a-zA-Z0-9{}|_]*)\\]', r'[\\1\\~\\2]', usage)\n\n        usage = usage.replace('%s ' % self._prog, '')\n        usage = '.SH SYNOPSIS\\n.nh\\n.HP\\n\\\\fB%s\\\\fR %s\\n.hy\\n' % (self._markup(self._prog),\n                                                    usage)\n        return usage\n\n    def _mk_title(self, prog):\n        name_version = \"\\\"{0} {1}\\\"\".format(prog, self._version)\n        return '.TH {0} {1} {2} {3}\\n'.format(prog, self._section,\n                                              self._today, name_version)\n\n    def _make_name(self, parser):\n        \"\"\"\n        this method is in consitent with others ... it relies on\n        distribution\n        \"\"\"\n        return '.SH NAME\\n%s \\\\- %s\\n' % (parser.prog,\n                                          parser.description)\n\n    def _mk_description(self, parser):\n        desc = parser.description\n        if not desc:\n            return ''\n        desc = desc.replace('\\n\\n', '\\n.PP\\n')\n        # sub-section headings\n        desc = re.sub(r'^\\*(.*)\\*$', r'.SS \\1', desc, flags=re.MULTILINE)\n        # italic commands\n        desc = re.sub(r'^  ([-a-z]*)$', r'.TP\\n\\\\fI\\1\\\\fR', desc, flags=re.MULTILINE)\n        # deindent body text, leave to troff viewer\n        desc = re.sub(r'^      (\\S.*)\\n', '\\\\1\\n', desc, flags=re.MULTILINE)\n        # format NOTEs as indented paragraphs\n        desc = re.sub(r'^NOTE\\n', '.TP\\nNOTE\\n', desc, flags=re.MULTILINE)\n        # deindent indented paragraphs after heading setup\n        desc = re.sub(r'^  (.*)$', '\\\\1', desc, flags=re.MULTILINE)\n\n        return '.SH DESCRIPTION\\n%s\\n' % self._markup(desc)\n\n    def _mk_footer(self, sections):\n        if not hasattr(sections, '__iter__'):\n            return ''\n\n        footer = []\n        for section, value in sections.items():\n            part = \".SH {}\\n {}\".format(section.upper(), value)\n            footer.append(part)\n\n        return '\\n'.join(footer)\n\n    def format_man_page(self, parser):\n        page = []\n        page.append(self._mk_title(self._prog))\n        page.append(self._mk_synopsis(parser))\n        page.append(self._mk_description(parser))\n        page.append(self._mk_options(parser))\n        page.append(self._mk_footer(self._ext_sections))\n\n        return ''.join(page)\n\n    def _mk_options(self, parser):\n\n        formatter = parser._get_formatter()\n\n        # positionals, optionals and user-defined groups\n        for action_group in parser._action_groups:\n            formatter.start_section(None)\n            formatter.add_text(None)\n            formatter.add_arguments(action_group._group_actions)\n            formatter.end_section()\n\n        # epilog\n        formatter.add_text(parser.epilog)\n\n        # determine help from format above\n        help = formatter.format_help()\n        # add spaces after comma delimiters for easier reformatting\n        help = re.sub(r'([a-z]),([a-z])', '\\\\1, \\\\2', help)\n        # get proper indentation for argument items\n        help = re.sub(r'^  (\\S.*)\\n', '.TP\\n\\\\1\\n', help, flags=re.MULTILINE)\n        # deindent body text, leave to troff viewer\n        help = re.sub(r'^    (\\S.*)\\n', '\\\\1\\n', help, flags=re.MULTILINE)\n        return '.SH OPTIONS\\n' + help\n\n    def _format_action_invocation(self, action):\n        if not action.option_strings:\n            metavar, = self._metavar_formatter(action, action.dest)(1)\n            return metavar\n\n        else:\n            parts = []\n\n            # if the Optional doesn't take a value, format is:\n            #    -s, --long\n            if action.nargs == 0:\n                parts.extend([self._bold(action_str) for action_str in\n                              action.option_strings])\n\n            # if the Optional takes a value, format is:\n            #    -s ARGS, --long ARGS\n            else:\n                default = self._underline(action.dest.upper())\n                args_string = self._format_args(action, default)\n                for option_string in action.option_strings:\n                    parts.append('%s %s' % (self._bold(option_string),\n                                            args_string))\n\n            return ', '.join(parts)\n\n\nclass RSTManPageFormatter(ManPageFormatter):\n    def _get_formatter(self, **kwargs):\n        return self.formatter_class(prog=self.prog, **kwargs)\n\n    def _markup(self, txt):\n        # put general tune-ups here\n        return txt\n\n    def _underline(self, string):\n        return \"*{0}*\".format(string)\n\n    def _bold(self, string):\n        return \"**{0}**\".format(string)\n\n    def _mk_synopsis(self, parser):\n        self.add_usage(parser.usage, parser._actions,\n                       parser._mutually_exclusive_groups, prefix='')\n        usage = self._format_usage(None, parser._actions,\n                                   parser._mutually_exclusive_groups, '')\n\n        usage = usage.replace('%s ' % self._prog, '')\n        usage = 'Synopsis\\n--------\\n::\\n\\n  %s %s\\n' \\\n                % (self._markup(self._prog), usage)\n        return usage\n\n    def _mk_title(self, prog):\n        title = \"{0}\".format(prog)\n        title += '\\n{0}\\n\\n'.format('=' * len(title))\n        return title\n\n    def _make_name(self, parser):\n        return ''\n\n    def _mk_description(self, parser):\n        desc = parser.description\n        if not desc:\n            return ''\n        return 'Description\\n-----------\\n%s\\n' % self._markup(desc)\n\n    def _mk_footer(self, sections):\n        if not hasattr(sections, '__iter__'):\n            return ''\n\n        footer = []\n        for section, value in sections.items():\n            part = \"\\n{0}\\n{1}\\n{2}\\n\".format(\n                section,\n                '-' * len(section),\n                value)\n            footer.append(part)\n\n        return '\\n'.join(footer)\n\n    def _mk_options(self, parser):\n\n        # this non-obvious maneuver is really necessary!\n        formatter = self.__class__(self._prog)\n\n        # positionals, optionals and user-defined groups\n        for action_group in parser._action_groups:\n            formatter.start_section(None)\n            formatter.add_text(None)\n            formatter.add_arguments(action_group._group_actions)\n            formatter.end_section()\n\n        # epilog\n        formatter.add_text(parser.epilog)\n\n        # determine help from format above\n        option_sec = formatter.format_help()\n\n        return '\\n\\nOptions\\n-------\\n{0}'.format(option_sec)\n\n    def _format_action(self, action):\n        # determine the required width and the entry label\n        action_header = self._format_action_invocation(action)\n\n        if action.help:\n            help_text = self._expand_help(action)\n            help_lines = self._split_lines(help_text, 80)\n            help = ' '.join(help_lines)\n        else:\n            help = ''\n\n        # return a single string\n        return '{0}\\n{1}\\n{2}\\n\\n'.format(\n            action_header,\n\n            '~' * len(action_header),\n            help)\n\n\ndef cmdline_example_to_rst(src, out=None, ref=None):\n    if out is None:\n        from six.moves import StringIO\n        out = StringIO()\n\n    # place header\n    out.write('.. AUTO-GENERATED FILE -- DO NOT EDIT!\\n\\n')\n    if ref:\n        # place cross-ref target\n        out.write('.. {0}:\\n\\n'.format(ref))\n\n    # parser status vars\n    inexample = False\n    incodeblock = False\n\n    for line in src:\n        if line.startswith('#% EXAMPLE START'):\n            inexample = True\n            incodeblock = False\n            continue\n        if not inexample:\n            continue\n        if line.startswith('#% EXAMPLE END'):\n            break\n        if not inexample:\n            continue\n        if line.startswith('#%'):\n            incodeblock = not incodeblock\n            if incodeblock:\n                out.write('\\n.. code-block:: sh\\n\\n')\n            continue\n        if not incodeblock and line.startswith('#'):\n            out.write(line[(min(2, len(line) - 1)):])\n            continue\n        if incodeblock:\n            out.write('  %s' % line)\n            continue\n        if not len(line.strip()):\n            continue\n        else:\n            raise RuntimeError(\"this should not happen\")\n\n    return out\n",
            "new_file_content": "# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the DataLad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\nimport argparse\nimport datetime\nimport re\n\n\nclass ManPageFormatter(argparse.HelpFormatter):\n    # This code was originally distributed\n    # under the same License of Python\n    # Copyright (c) 2014 Oz Nahum Tiram  <nahumoz@gmail.com>\n    def __init__(self,\n                 prog,\n                 indent_increment=2,\n                 max_help_position=4,\n                 width=1000000,\n                 section=1,\n                 ext_sections=None,\n                 authors=None,\n                 version=None\n                 ):\n\n        super(ManPageFormatter, self).__init__(\n            prog,\n            indent_increment=indent_increment,\n            max_help_position=max_help_position,\n            width=width)\n\n        self._prog = prog\n        self._section = 1\n        self._today = datetime.date.today().strftime('%Y\\\\-%m\\\\-%d')\n        self._ext_sections = ext_sections\n        self._version = version\n\n    def _get_formatter(self, **kwargs):\n        return self.formatter_class(prog=self.prog, **kwargs)\n\n    def _markup(self, txt):\n        return txt.replace('-', '\\\\-')\n\n    def _underline(self, string):\n        return \"\\\\fI\\\\s-1\" + string + \"\\\\s0\\\\fR\"\n\n    def _bold(self, string):\n        if not string.strip().startswith('\\\\fB'):\n            string = '\\\\fB' + string\n        if not string.strip().endswith('\\\\fR'):\n            string = string + '\\\\fR'\n        return string\n\n    def _mk_synopsis(self, parser):\n        self.add_usage(parser.usage, parser._actions,\n                       parser._mutually_exclusive_groups, prefix='')\n        usage = self._format_usage(None, parser._actions,\n                                   parser._mutually_exclusive_groups, '')\n        # replace too long list of commands with a single placeholder\n        usage = re.sub(r'{[^]]*?create,.*?}', ' COMMAND ', usage, flags=re.MULTILINE)\n        # take care of proper wrapping\n        usage = re.sub(r'\\[([-a-zA-Z0-9]*)\\s([a-zA-Z0-9{}|_]*)\\]', r'[\\1\\~\\2]', usage)\n\n        usage = usage.replace('%s ' % self._prog, '')\n        usage = '.SH SYNOPSIS\\n.nh\\n.HP\\n\\\\fB%s\\\\fR %s\\n.hy\\n' % (self._markup(self._prog),\n                                                    usage)\n        return usage\n\n    def _mk_title(self, prog):\n        name_version = \"\\\"{0} {1}\\\"\".format(prog, self._version)\n        return '.TH {0} {1} {2} {3}\\n'.format(prog, self._section,\n                                              self._today, name_version)\n\n    def _make_name(self, parser):\n        \"\"\"\n        this method is in consitent with others ... it relies on\n        distribution\n        \"\"\"\n        return '.SH NAME\\n%s \\\\- %s\\n' % (parser.prog,\n                                          parser.description)\n\n    def _mk_description(self, parser):\n        desc = parser.description\n        if not desc:\n            return ''\n        desc = desc.replace('\\n\\n', '\\n.PP\\n')\n        # sub-section headings\n        desc = re.sub(r'^\\*(.*)\\*$', r'.SS \\1', desc, flags=re.MULTILINE)\n        # italic commands\n        desc = re.sub(r'^  ([-a-z]*)$', r'.TP\\n\\\\fI\\1\\\\fR', desc, flags=re.MULTILINE)\n        # deindent body text, leave to troff viewer\n        desc = re.sub(r'^      (\\S.*)\\n', '\\\\1\\n', desc, flags=re.MULTILINE)\n        # format NOTEs as indented paragraphs\n        desc = re.sub(r'^NOTE\\n', '.TP\\nNOTE\\n', desc, flags=re.MULTILINE)\n        # deindent indented paragraphs after heading setup\n        desc = re.sub(r'^  (.*)$', '\\\\1', desc, flags=re.MULTILINE)\n\n        return '.SH DESCRIPTION\\n%s\\n' % self._markup(desc)\n\n    def _mk_footer(self, sections):\n        if not hasattr(sections, '__iter__'):\n            return ''\n\n        footer = []\n        for section, value in sections.items():\n            part = \".SH {}\\n {}\".format(section.upper(), value)\n            footer.append(part)\n\n        return '\\n'.join(footer)\n\n    def format_man_page(self, parser):\n        page = []\n        page.append(self._mk_title(self._prog))\n        page.append(self._mk_synopsis(parser))\n        page.append(self._mk_description(parser))\n        page.append(self._mk_options(parser))\n        page.append(self._mk_footer(self._ext_sections))\n\n        return ''.join(page)\n\n    def _mk_options(self, parser):\n\n        formatter = parser._get_formatter()\n\n        # positionals, optionals and user-defined groups\n        for action_group in parser._action_groups:\n            formatter.start_section(None)\n            formatter.add_text(None)\n            formatter.add_arguments(action_group._group_actions)\n            formatter.end_section()\n\n        # epilog\n        formatter.add_text(parser.epilog)\n\n        # determine help from format above\n        help = formatter.format_help()\n        # add spaces after comma delimiters for easier reformatting\n        help = re.sub(r'([a-z]),([a-z])', '\\\\1, \\\\2', help)\n        # get proper indentation for argument items\n        help = re.sub(r'^  (\\S.*)\\n', '.TP\\n\\\\1\\n', help, flags=re.MULTILINE)\n        # deindent body text, leave to troff viewer\n        help = re.sub(r'^    (\\S.*)\\n', '\\\\1\\n', help, flags=re.MULTILINE)\n        return '.SH OPTIONS\\n' + help\n\n    def _format_action_invocation(self, action):\n        if not action.option_strings:\n            metavar, = self._metavar_formatter(action, action.dest)(1)\n            return metavar\n\n        else:\n            parts = []\n\n            # if the Optional doesn't take a value, format is:\n            #    -s, --long\n            if action.nargs == 0:\n                parts.extend([self._bold(action_str) for action_str in\n                              action.option_strings])\n\n            # if the Optional takes a value, format is:\n            #    -s ARGS, --long ARGS\n            else:\n                default = self._underline(action.dest.upper())\n                args_string = self._format_args(action, default)\n                for option_string in action.option_strings:\n                    parts.append('%s %s' % (self._bold(option_string),\n                                            args_string))\n\n            return ', '.join(parts)\n\n\nclass RSTManPageFormatter(ManPageFormatter):\n    def _get_formatter(self, **kwargs):\n        return self.formatter_class(prog=self.prog, **kwargs)\n\n    def _markup(self, txt):\n        # put general tune-ups here\n        return txt\n\n    def _underline(self, string):\n        return \"*{0}*\".format(string)\n\n    def _bold(self, string):\n        return \"**{0}**\".format(string)\n\n    def _mk_synopsis(self, parser):\n        self.add_usage(parser.usage, parser._actions,\n                       parser._mutually_exclusive_groups, prefix='')\n        usage = self._format_usage(None, parser._actions,\n                                   parser._mutually_exclusive_groups, '')\n\n        usage = usage.replace('%s ' % self._prog, '')\n        usage = 'Synopsis\\n--------\\n::\\n\\n  %s %s\\n' \\\n                % (self._markup(self._prog), usage)\n        return usage\n\n    def _mk_title(self, prog):\n        title = \"{0}\".format(prog)\n        title += '\\n{0}\\n\\n'.format('=' * len(title))\n        return title\n\n    def _make_name(self, parser):\n        return ''\n\n    def _mk_description(self, parser):\n        desc = parser.description\n        if not desc:\n            return ''\n        return 'Description\\n-----------\\n%s\\n' % self._markup(desc)\n\n    def _mk_footer(self, sections):\n        if not hasattr(sections, '__iter__'):\n            return ''\n\n        footer = []\n        for section, value in sections.items():\n            part = \"\\n{0}\\n{1}\\n{2}\\n\".format(\n                section,\n                '-' * len(section),\n                value)\n            footer.append(part)\n\n        return '\\n'.join(footer)\n\n    def _mk_options(self, parser):\n\n        # this non-obvious maneuver is really necessary!\n        formatter = self.__class__(self._prog)\n\n        # positionals, optionals and user-defined groups\n        for action_group in parser._action_groups:\n            formatter.start_section(None)\n            formatter.add_text(None)\n            formatter.add_arguments(action_group._group_actions)\n            formatter.end_section()\n\n        # epilog\n        formatter.add_text(parser.epilog)\n\n        # determine help from format above\n        option_sec = formatter.format_help()\n\n        return '\\n\\nOptions\\n-------\\n{0}'.format(option_sec)\n\n    def _format_action(self, action):\n        # determine the required width and the entry label\n        action_header = self._format_action_invocation(action)\n\n        if action.help:\n            help_text = self._expand_help(action)\n            help_lines = self._split_lines(help_text, 80)\n            help = ' '.join(help_lines)\n        else:\n            help = ''\n\n        # return a single string\n        return '{0}\\n{1}\\n{2}\\n\\n'.format(\n            action_header,\n\n            '~' * len(action_header),\n            help)\n\n\ndef cmdline_example_to_rst(src, out=None, ref=None):\n    if out is None:\n        from six.moves import StringIO\n        out = StringIO()\n\n    # place header\n    out.write('.. AUTO-GENERATED FILE -- DO NOT EDIT!\\n\\n')\n    if ref:\n        # place cross-ref target\n        out.write('.. {0}:\\n\\n'.format(ref))\n\n    # parser status vars\n    inexample = False\n    incodeblock = False\n\n    for line in src:\n        if line.startswith('#% EXAMPLE START'):\n            inexample = True\n            incodeblock = False\n            continue\n        if not inexample:\n            continue\n        if line.startswith('#% EXAMPLE END'):\n            break\n        if not inexample:\n            continue\n        if line.startswith('#%'):\n            incodeblock = not incodeblock\n            if incodeblock:\n                out.write('\\n.. code-block:: sh\\n\\n')\n            continue\n        if not incodeblock and line.startswith('#'):\n            out.write(line[(min(2, len(line) - 1)):])\n            continue\n        if incodeblock:\n            if not line.rstrip().endswith('#% SKIP'):\n                out.write('  %s' % line)\n            continue\n        if not len(line.strip()):\n            continue\n        else:\n            raise RuntimeError(\"this should not happen\")\n\n    return out\n",
            "header": {
                "file": {
                    "path": "formatters.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "7fdf3e03e",
                "new_commit_hash": "3e7bc9d41",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/formatters.py"
            },
            "plus_file": {
                "path": "b/formatters.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 297,
                            "length": 7
                        },
                        "new_range": {
                            "start": 297,
                            "length": 8
                        },
                        "section": "def cmdline_example_to_rst(src, out=None, ref=None):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            out.write(line[(min(2, len(line) - 1)):])",
                                "type": "context"
                            },
                            {
                                "content": "            continue",
                                "type": "context"
                            },
                            {
                                "content": "        if incodeblock:",
                                "type": "context"
                            },
                            {
                                "content": "            out.write('  %s' % line)",
                                "type": "deleted"
                            },
                            {
                                "content": "            if not line.rstrip().endswith('#% SKIP'):",
                                "type": "added"
                            },
                            {
                                "content": "                out.write('  %s' % line)",
                                "type": "added"
                            },
                            {
                                "content": "            continue",
                                "type": "context"
                            },
                            {
                                "content": "        if not len(line.strip()):",
                                "type": "context"
                            },
                            {
                                "content": "            continue",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "formatters.py",
                            "type": "function",
                            "name": "cmdline_example_to_rst",
                            "content": "def cmdline_example_to_rst(src, out=None, ref=None):\n    if out is None:\n        from six.moves import StringIO\n        out = StringIO()\n\n    # place header\n    out.write('.. AUTO-GENERATED FILE -- DO NOT EDIT!\\n\\n')\n    if ref:\n        # place cross-ref target\n        out.write('.. {0}:\\n\\n'.format(ref))\n\n    # parser status vars\n    inexample = False\n    incodeblock = False\n\n    for line in src:\n        if line.startswith('#% EXAMPLE START'):\n            inexample = True\n            incodeblock = False\n            continue\n        if not inexample:\n            continue\n        if line.startswith('#% EXAMPLE END'):\n            break\n        if not inexample:\n            continue\n        if line.startswith('#%'):\n            incodeblock = not incodeblock\n            if incodeblock:\n                out.write('\\n.. code-block:: sh\\n\\n')\n            continue\n        if not incodeblock and line.startswith('#'):\n            out.write(line[(min(2, len(line) - 1)):])\n            continue\n        if incodeblock:\n            out.write('  %s' % line)\n            continue\n        if not len(line.strip()):\n            continue\n        else:\n            raise RuntimeError(\"this should not happen\")\n\n    return out",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 265,
                            "end_lineno": 307,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "c7c3dce52cd10cac20fdb31b26d136ff1822a224^",
    "new_commit_hash": "c7c3dce52cd10cac20fdb31b26d136ff1822a224",
    "commit_message": "ENH: allow to have #% SKIP lines",
    "commit_date": "2017-03-23T19:44:57-04:00",
    "metadata": {}
}
{
    "repo_name": "datalad",
    "new_commit_hash": "c7c3dce52cd10cac20fdb31b26d136ff1822a224",
    "test_file_codes": [
        "# emacs: -*- mode: python-mode; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\"\"\"\"\"\"\n\nfrom six.moves import StringIO as SIO\nfrom os.path import exists\nfrom nose import SkipTest\ntry:\n    import formatters as fmt\nexcept ImportError:  # pragma: no cover\n    # must be running from installed version where formatters is not present\n    # These tests can be ran only with formatters, which is outside of the\n    # datalad module space in the root of the sourcebase\n    if not exists('formatters.py'):\n        raise SkipTest\n\nfrom datalad.cmdline.main import setup_parser\nfrom datalad.tests.utils import ok_, assert_in, ok_startswith\nfrom datalad.tests.utils import assert_not_in\n\ndemo_example = \"\"\"\n#!/bin/sh\n\nset -e\nset -u\n\n# BOILERPLATE\n\nHOME=IS_MY_CASTLE\n\n#% EXAMPLE START\n#\n# A simple start (on the command line)\n# ====================================\n#\n# Lorem ipsum\n#%\n\ndatalad install http://the.world.com\n\n#%\n# Epilog -- with multiline rubish sdoifpwjefw\n# vsdokvpsokdvpsdkv spdokvpskdvpoksd\n# pfdsvja329u0fjpdsv sdpf9p93qk\n#%\n\ndatalad imagine --too \\\\\n        --much \\\\\n        --too say \\\\\n        yes=no\n\ndatalad shameful-command  #% SKIP\n#%\n# The result is not comprehensible.\n#%\n\n#% EXAMPLE END\n\n# define shunit test cases below, or just anything desired\n\"\"\"\n\n\ndef test_cmdline_example_to_rst():\n    # don't puke on nothing\n    out = fmt.cmdline_example_to_rst(SIO(''))\n    out.seek(0)\n    ok_startswith(out.read(), '.. AUTO-GENERATED')\n    out = fmt.cmdline_example_to_rst(SIO(''), ref='dummy')\n    out.seek(0)\n    assert_in('.. dummy:', out.read())\n    # full scale test\n    out = fmt.cmdline_example_to_rst(\n        SIO(demo_example), ref='mydemo')\n    out.seek(0)\n    out_text = out.read()\n    assert_in('.. code-block:: sh', out_text)\n    assert_not_in('shame', out_text)  # no SKIP'ed\n    assert_not_in('#', out_text)      # no comments\n\ndef test_parser_access():\n    parsers = setup_parser(return_subparsers=True)\n    # we have a bunch\n    ok_(len(parsers) > 3)\n    assert_in('install', parsers.keys())\n\n\ndef test_manpage_formatter():\n    addonsections = {'mytest': \"uniquedummystring\"}\n\n    parsers = setup_parser(return_subparsers=True)\n    for p in parsers:\n        mp = fmt.ManPageFormatter(\n            p, ext_sections=addonsections).format_man_page(parsers[p])\n        for section in ('SYNOPSIS', 'DESCRIPTION', 'OPTIONS', 'MYTEST'):\n            assert_in('.SH {0}'.format(section), mp)\n        assert_in('uniquedummystring', mp)\n\n\ndef test_rstmanpage_formatter():\n    parsers = setup_parser(return_subparsers=True)\n    for p in parsers:\n        mp = fmt.RSTManPageFormatter(p).format_man_page(parsers[p])\n        for section in ('Synopsis', 'Description', 'Options'):\n            assert_in('\\n{0}'.format(section), mp)\n        assert_in('{0}\\n{1}'.format(p, '=' * len(p)), mp)\n",
        "import pytest\nimport tempfile\nimport os\n\n\n@pytest.fixture\ndef path():\n    with tempfile.TemporaryDirectory() as tmpdir:\n        yield tmpdir\n\n\n@pytest.fixture(autouse=True)\ndef setup_git_config():\n    with tempfile.TemporaryDirectory() as home:\n        old_home = os.environ.get(\"HOME\")\n        os.environ[\"HOME\"] = home\n        os.system('git config --global user.name \"DataLad Tester\"')\n        os.system('git config --global user.email \"test@example.com\"')\n        yield\n        if old_home:\n            os.environ[\"HOME\"] = old_home\n"
    ],
    "test_file_names": [
        "test_1.py",
        "conftest.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Starting Datalad installation attempts...\nVerifying installation...\n❌ Verification failed\nPython 3.9 installation failed, trying Python 3.7...\nVerifying installation...\nDatalad version: 0.5.0.dev25\n✅ Installation successful!\nSuccessfully installed Datalad using Python 3.7\n",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 25 packages in 82ms\nInstalled 25 packages in 6.15s\n + coverage==7.6.10\n + docopt==0.6.2\n + exceptiongroup==1.2.2\n + grabbit==0.2.6\n + importlib-resources==6.4.5\n + iniconfig==2.0.0\n + nibabel==5.3.2\n + num2words==0.5.14\n + numpy==2.0.2\n + packaging==24.2\n + pandas==2.2.3\n + patsy==1.0.1\n + pluggy==1.5.0\n + pybids==0.6.5\n + pytest==8.3.4\n + pytest-cov==6.0.0\n + python-dateutil==2.9.0.post0\n + pytz==2024.2\n + scipy==1.13.1\n + setuptools==75.6.0\n + six==1.17.0\n + tomli==2.2.1\n + typing-extensions==4.12.2\n + tzdata==2024.2\n + zipp==3.21.0\nerror: The build backend returned an error\n  Caused by: Call to `setuptools.build_meta:__legacy__.build_editable` failed (exit status: 1)\n\n[stderr]\nTraceback (most recent call last):\n  File \"<string>\", line 14, in <module>\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpfdDQCF/lib/python3.9/site-packages/setuptools/build_meta.py\", line 483, in get_requires_for_build_editable\n    return self.get_requires_for_build_wheel(config_settings)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpfdDQCF/lib/python3.9/site-packages/setuptools/build_meta.py\", line 334, in get_requires_for_build_wheel\n    return self._get_build_requires(config_settings, requirements=[])\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpfdDQCF/lib/python3.9/site-packages/setuptools/build_meta.py\", line 304, in _get_build_requires\n    self.run_setup()\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpfdDQCF/lib/python3.9/site-packages/setuptools/build_meta.py\", line 522, in run_setup\n    super().run_setup(setup_script=setup_script)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpfdDQCF/lib/python3.9/site-packages/setuptools/build_meta.py\", line 320, in run_setup\n    exec(code, locals())\n  File \"<string>\", line 48, in <module>\nAttributeError: module 'platform' has no attribute 'dist'\n\nhint: This usually indicates a problem with the package or the build environment.\nerror: The build backend returned an error\n  Caused by: Call to `setuptools.build_meta:__legacy__.build_editable` failed (exit status: 1)\n\n[stderr]\nTraceback (most recent call last):\n  File \"<string>\", line 14, in <module>\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpJTBP43/lib/python3.9/site-packages/setuptools/build_meta.py\", line 483, in get_requires_for_build_editable\n    return self.get_requires_for_build_wheel(config_settings)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpJTBP43/lib/python3.9/site-packages/setuptools/build_meta.py\", line 334, in get_requires_for_build_wheel\n    return self._get_build_requires(config_settings, requirements=[])\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpJTBP43/lib/python3.9/site-packages/setuptools/build_meta.py\", line 304, in _get_build_requires\n    self.run_setup()\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpJTBP43/lib/python3.9/site-packages/setuptools/build_meta.py\", line 522, in run_setup\n    super().run_setup(setup_script=setup_script)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpJTBP43/lib/python3.9/site-packages/setuptools/build_meta.py\", line 320, in run_setup\n    exec(code, locals())\n  File \"<string>\", line 48, in <module>\nAttributeError: module 'platform' has no attribute 'dist'\n\nhint: This usually indicates a problem with the package or the build environment.\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_c7c3dce52cd10cac20fdb31b26d136ff1822a224/datalad/__init__.py\", line 30, in <module>\n    ssh_manager = SSHManager()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_c7c3dce52cd10cac20fdb31b26d136ff1822a224/datalad/support/sshconnector.py\", line 333, in __init__\n    for p in listdir(self.socket_dir)\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_c7c3dce52cd10cac20fdb31b26d136ff1822a224/datalad/support/sshconnector.py\", line 342, in socket_dir\n    self._socket_dir = opj(cfg.obtain('datalad.locations.cache'),\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_c7c3dce52cd10cac20fdb31b26d136ff1822a224/datalad/config.py\", line 233, in obtain\n    from datalad.interface.common_cfg import definitions as cfg_defs\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_c7c3dce52cd10cac20fdb31b26d136ff1822a224/datalad/interface/common_cfg.py\", line 15, in <module>\n    from appdirs import AppDirs\nModuleNotFoundError: No module named 'appdirs'\nUsing CPython 3.7.9\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 26 packages in 371ms\nInstalled 26 packages in 1.98s\n + bids==0.0\n + coverage==7.2.7\n + docopt==0.6.2\n + exceptiongroup==1.2.2\n + fasteners==0.19\n + grabbit==0.2.6\n + importlib-metadata==6.7.0\n + iniconfig==2.0.0\n + nibabel==4.0.2\n + num2words==0.5.14\n + numpy==1.21.6\n + packaging==24.0\n + pandas==1.3.5\n + patsy==1.0.1\n + pluggy==1.2.0\n + pybids==0.6.5\n + pytest==7.4.4\n + pytest-cov==4.1.0\n + python-dateutil==2.9.0.post0\n + pytz==2024.2\n + scipy==1.7.3\n + setuptools==68.0.0\n + six==1.17.0\n + tomli==2.0.1\n + typing-extensions==4.7.1\n + zipp==3.15.0\nResolved 77 packages in 1.45s\nPrepared 1 package in 1.33s\nInstalled 71 packages in 120ms\n + appdirs==1.4.4\n + attrs==24.2.0\n + automat==22.10.0\n + beautifulsoup4==4.12.3\n + boto==2.49.0\n + cachetools==5.5.0\n + certifi==2024.12.14\n + cffi==1.15.1\n + charset-normalizer==3.4.1\n + constantly==15.1.0\n + cryptography==44.0.0\n + cssselect==1.2.0\n + datalad==0.5.0.dev1 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_c7c3dce52cd10cac20fdb31b26d136ff1822a224)\n + deprecated==1.2.15\n + filelock==3.12.2\n + frozendict==2.4.6\n + gitdb==4.0.12\n + gitpython==3.1.44\n + httpretty==1.1.4\n + humanize==4.6.0\n + hyperlink==21.0.0\n + idna==3.10\n + importlib-resources==5.12.0\n + incremental==22.10.0\n + iso8601==2.1.0\n + itemadapter==0.8.0\n + itemloaders==1.1.0\n + jaraco-classes==3.2.3\n + jeepney==0.8.0\n + jmespath==1.0.1\n + jsmin==3.0.1\n + keyring==24.1.1\n + keyrings-alt==4.2.0\n + lxml==5.3.0\n + mock==5.1.0\n + more-itertools==9.1.0\n + msgpack-python==0.5.6\n + multidict==6.0.5\n + nose==1.3.7\n + parsel==1.8.1\n + patool==1.12\n + protego==0.3.0\n + pyasn1==0.5.1\n + pyasn1-modules==0.3.0\n + pycparser==2.21\n + pydispatcher==2.0.7\n + pygithub==2.3.0\n + pyjwt==2.8.0\n + pyld==2.0.4\n + pynacl==1.5.0\n + pyopenssl==24.3.0\n + pyyaml==6.0.1\n + queuelib==1.6.2\n + requests==2.31.0\n + requests-file==2.1.0\n + requests-ftp==0.3.1\n + scrapy==2.9.0\n + secretstorage==3.3.3\n + service-identity==21.1.0\n + simplejson==3.19.3\n + smmap==5.0.2\n + soupsieve==2.4.1\n + tldextract==4.0.0\n + tqdm==4.67.1\n + twisted==23.8.0\n + urllib3==2.0.7\n + vcrpy==4.3.0\n + w3lib==2.1.2\n + wrapt==1.16.0\n + yarl==1.9.4\n + zope-interface==6.4.post2\nResolved 100 packages in 120ms\nInstalled 20 packages in 40ms\n + alabaster==0.7.13\n + babel==2.14.0\n + docutils==0.19\n + imagesize==1.4.1\n + jinja2==3.1.5\n + line-profiler==4.1.3\n + markupsafe==2.1.5\n + nose-timer==1.0.1\n + pygments==2.17.2\n + pypandoc==1.14\n + snowballstemmer==2.2.0\n + sphinx==5.3.0\n + sphinx-rtd-theme==2.0.0\n + sphinxcontrib-applehelp==1.0.2\n + sphinxcontrib-devhelp==1.0.2\n + sphinxcontrib-htmlhelp==2.0.0\n + sphinxcontrib-jquery==4.1\n + sphinxcontrib-jsmath==1.0.1\n + sphinxcontrib-qthelp==1.0.3\n + sphinxcontrib-serializinghtml==1.1.5\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_c7c3dce52cd10cac20fdb31b26d136ff1822a224\nplugins: cov-4.1.0\ncollected 4 items\n\nr2e_tests/test_1.py ....                                                 [100%]\n\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_cmdline_example_to_rst\nPASSED r2e_tests/test_1.py::test_parser_access\nPASSED r2e_tests/test_1.py::test_manpage_formatter\nPASSED r2e_tests/test_1.py::test_rstmanpage_formatter\n============================== 4 passed in 0.84s ===============================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_c7c3dce52cd10cac20fdb31b26d136ff1822a224\nplugins: cov-4.1.0\ncollected 4 items\n\nr2e_tests/test_1.py F...                                                 [100%]\n\n=================================== FAILURES ===================================\n_________________________ test_cmdline_example_to_rst __________________________\n\n    def test_cmdline_example_to_rst():\n        # don't puke on nothing\n        out = fmt.cmdline_example_to_rst(SIO(''))\n        out.seek(0)\n        ok_startswith(out.read(), '.. AUTO-GENERATED')\n        out = fmt.cmdline_example_to_rst(SIO(''), ref='dummy')\n        out.seek(0)\n        assert_in('.. dummy:', out.read())\n        # full scale test\n        out = fmt.cmdline_example_to_rst(\n            SIO(demo_example), ref='mydemo')\n        out.seek(0)\n        out_text = out.read()\n        assert_in('.. code-block:: sh', out_text)\n>       assert_not_in('shame', out_text)  # no SKIP'ed\n\nr2e_tests/test_1.py:83: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n../../../../.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib/python3.7/unittest/case.py:1126: in assertNotIn\n    self.fail(self._formatMessage(msg, standardMsg))\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <nose.tools.trivial.Dummy testMethod=nop>\nmsg = \"'shame' unexpectedly found in '.. AUTO-GENERATED FILE -- DO NOT EDIT!\\\\n\\\\n.. mydemo:\\\\n\\\\n\\\\nA simple start (on the ...=no\\\\n  \\\\n  datalad shameful-command  #% SKIP\\\\nThe result is not comprehensible.\\\\n\\\\n.. code-block:: sh\\\\n\\\\n  \\\\n'\"\n\n    def fail(self, msg=None):\n        \"\"\"Fail immediately, with the given message.\"\"\"\n>       raise self.failureException(msg)\nE       AssertionError: 'shame' unexpectedly found in '.. AUTO-GENERATED FILE -- DO NOT EDIT!\\n\\n.. mydemo:\\n\\n\\nA simple start (on the command line)\\n====================================\\n\\nLorem ipsum\\n\\n.. code-block:: sh\\n\\n  \\n  datalad install http://the.world.com\\n  \\nEpilog -- with multiline rubish sdoifpwjefw\\nvsdokvpsokdvpsdkv spdokvpskdvpoksd\\npfdsvja329u0fjpdsv sdpf9p93qk\\n\\n.. code-block:: sh\\n\\n  \\n  datalad imagine --too \\\\\\n          --much \\\\\\n          --too say \\\\\\n          yes=no\\n  \\n  datalad shameful-command  #% SKIP\\nThe result is not comprehensible.\\n\\n.. code-block:: sh\\n\\n  \\n'\n\n../../../../.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib/python3.7/unittest/case.py:693: AssertionError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_parser_access\nPASSED r2e_tests/test_1.py::test_manpage_formatter\nPASSED r2e_tests/test_1.py::test_rstmanpage_formatter\nFAILED r2e_tests/test_1.py::test_cmdline_example_to_rst - AssertionError: 'sh...\n========================= 1 failed, 3 passed in 0.54s ==========================\n",
    "old_commit_res_stderr": ""
}
datalad/cmdline/tests/test_formatters.py formatters.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** Lines Ending with `#% SKIP` Are Not Ignored in Command Line Example Conversion

**Description:**
When converting command line examples to reStructuredText (RST), lines that end with `#% SKIP` are intended to be excluded from the output. However, currently, these lines are still being included, which leads to unwanted content in the generated documentation.

**Example Buggy Code:**
```python
demo_example = """
#!/bin/sh
datalad install http://the.world.com

datalad shameful-command  #% SKIP
#%
# The result is not comprehensible.
#%
"""
out_text = fmt.cmdline_example_to_rst(SIO(demo_example), ref='mydemo').read()
print(out_text)
```

**Expected Behavior:**
Lines ending with `#% SKIP`, such as `datalad shameful-command  #% SKIP`, should be excluded from the RST output. The generated documentation should not contain any references to these skipped commands or the accompanying comments.

**Actual Behavior:**
The line `datalad shameful-command  #% SKIP` and related comments are still present in the RST output. This results in cluttered and confusing documentation, as unintended lines are displayed.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### formatters.py
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
#
#   See COPYING file distributed along with the DataLad package for the
#   copyright and license terms.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##

import argparse
import datetime
import re


class ManPageFormatter(argparse.HelpFormatter):
    # This code was originally distributed
    # under the same License of Python
    # Copyright (c) 2014 Oz Nahum Tiram  <nahumoz@gmail.com>
    def __init__(self,
                 prog,
                 indent_increment=2,
                 max_help_position=4,
                 width=1000000,
                 section=1,
                 ext_sections=None,
                 authors=None,
                 version=None
                 ):

        super(ManPageFormatter, self).__init__(
            prog,
            indent_increment=indent_increment,
            max_help_position=max_help_position,
            width=width)

        self._prog = prog
        self._section = 1
        self._today = datetime.date.today().strftime('%Y\\-%m\\-%d')
        self._ext_sections = ext_sections
        self._version = version

    def _get_formatter(self, **kwargs):
        return self.formatter_class(prog=self.prog, **kwargs)

    def _markup(self, txt):
        return txt.replace('-', '\\-')

    def _underline(self, string):
        return "\\fI\\s-1" + string + "\\s0\\fR"

    def _bold(self, string):
        if not string.strip().startswith('\\fB'):
            string = '\\fB' + string
        if not string.strip().endswith('\\fR'):
            string = string + '\\fR'
        return string

    def _mk_synopsis(self, parser):
        self.add_usage(parser.usage, parser._actions,
                       parser._mutually_exclusive_groups, prefix='')
        usage = self._format_usage(None, parser._actions,
                                   parser._mutually_exclusive_groups, '')
        # replace too long list of commands with a single placeholder
        usage = re.sub(r'{[^]]*?create,.*?}', ' COMMAND ', usage, flags=re.MULTILINE)
        # take care of proper wrapping
        usage = re.sub(r'\[([-a-zA-Z0-9]*)\s([a-zA-Z0-9{}|_]*)\]', r'[\1\~\2]', usage)

        usage = usage.replace('%s ' % self._prog, '')
        usage = '.SH SYNOPSIS\n.nh\n.HP\n\\fB%s\\fR %s\n.hy\n' % (self._markup(self._prog),
                                                    usage)
        return usage

    def _mk_title(self, prog):
        name_version = "\"{0} {1}\"".format(prog, self._version)
        return '.TH {0} {1} {2} {3}\n'.format(prog, self._section,
                                              self._today, name_version)

    def _make_name(self, parser):
        """
        this method is in consitent with others ... it relies on
        distribution
        """
        return '.SH NAME\n%s \\- %s\n' % (parser.prog,
                                          parser.description)

    def _mk_description(self, parser):
        desc = parser.description
        if not desc:
            return ''
        desc = desc.replace('\n\n', '\n.PP\n')
        # sub-section headings
        desc = re.sub(r'^\*(.*)\*$', r'.SS \1', desc, flags=re.MULTILINE)
        # italic commands
        desc = re.sub(r'^  ([-a-z]*)$', r'.TP\n\\fI\1\\fR', desc, flags=re.MULTILINE)
        # deindent body text, leave to troff viewer
        desc = re.sub(r'^      (\S.*)\n', '\\1\n', desc, flags=re.MULTILINE)
        # format NOTEs as indented paragraphs
        desc = re.sub(r'^NOTE\n', '.TP\nNOTE\n', desc, flags=re.MULTILINE)
        # deindent indented paragraphs after heading setup
        desc = re.sub(r'^  (.*)$', '\\1', desc, flags=re.MULTILINE)

        return '.SH DESCRIPTION\n%s\n' % self._markup(desc)

    def _mk_footer(self, sections):
        if not hasattr(sections, '__iter__'):
            return ''

        footer = []
        for section, value in sections.items():
            part = ".SH {}\n {}".format(section.upper(), value)
            footer.append(part)

        return '\n'.join(footer)

    def format_man_page(self, parser):
        page = []
        page.append(self._mk_title(self._prog))
        page.append(self._mk_synopsis(parser))
        page.append(self._mk_description(parser))
        page.append(self._mk_options(parser))
        page.append(self._mk_footer(self._ext_sections))

        return ''.join(page)

    def _mk_options(self, parser):

        formatter = parser._get_formatter()

        # positionals, optionals and user-defined groups
        for action_group in parser._action_groups:
            formatter.start_section(None)
            formatter.add_text(None)
            formatter.add_arguments(action_group._group_actions)
            formatter.end_section()

        # epilog
        formatter.add_text(parser.epilog)

        # determine help from format above
        help = formatter.format_help()
        # add spaces after comma delimiters for easier reformatting
        help = re.sub(r'([a-z]),([a-z])', '\\1, \\2', help)
        # get proper indentation for argument items
        help = re.sub(r'^  (\S.*)\n', '.TP\n\\1\n', help, flags=re.MULTILINE)
        # deindent body text, leave to troff viewer
        help = re.sub(r'^    (\S.*)\n', '\\1\n', help, flags=re.MULTILINE)
        return '.SH OPTIONS\n' + help

    def _format_action_invocation(self, action):
        if not action.option_strings:
            metavar, = self._metavar_formatter(action, action.dest)(1)
            return metavar

        else:
            parts = []

            # if the Optional doesn't take a value, format is:
            #    -s, --long
            if action.nargs == 0:
                parts.extend([self._bold(action_str) for action_str in
                              action.option_strings])

            # if the Optional takes a value, format is:
            #    -s ARGS, --long ARGS
            else:
                default = self._underline(action.dest.upper())
                args_string = self._format_args(action, default)
                for option_string in action.option_strings:
                    parts.append('%s %s' % (self._bold(option_string),
                                            args_string))

            return ', '.join(parts)


class RSTManPageFormatter(ManPageFormatter):
    def _get_formatter(self, **kwargs):
        return self.formatter_class(prog=self.prog, **kwargs)

    def _markup(self, txt):
        # put general tune-ups here
        return txt

    def _underline(self, string):
        return "*{0}*".format(string)

    def _bold(self, string):
        return "**{0}**".format(string)

    def _mk_synopsis(self, parser):
        self.add_usage(parser.usage, parser._actions,
                       parser._mutually_exclusive_groups, prefix='')
        usage = self._format_usage(None, parser._actions,
                                   parser._mutually_exclusive_groups, '')

        usage = usage.replace('%s ' % self._prog, '')
        usage = 'Synopsis\n--------\n::\n\n  %s %s\n' \
                % (self._markup(self._prog), usage)
        return usage

    def _mk_title(self, prog):
        title = "{0}".format(prog)
        title += '\n{0}\n\n'.format('=' * len(title))
        return title

    def _make_name(self, parser):
        return ''

    def _mk_description(self, parser):
        desc = parser.description
        if not desc:
            return ''
        return 'Description\n-----------\n%s\n' % self._markup(desc)

    def _mk_footer(self, sections):
        if not hasattr(sections, '__iter__'):
            return ''

        footer = []
        for section, value in sections.items():
            part = "\n{0}\n{1}\n{2}\n".format(
                section,
                '-' * len(section),
                value)
            footer.append(part)

        return '\n'.join(footer)

    def _mk_options(self, parser):

        # this non-obvious maneuver is really necessary!
        formatter = self.__class__(self._prog)

        # positionals, optionals and user-defined groups
        for action_group in parser._action_groups:
            formatter.start_section(None)
            formatter.add_text(None)
            formatter.add_arguments(action_group._group_actions)
            formatter.end_section()

        # epilog
        formatter.add_text(parser.epilog)

        # determine help from format above
        option_sec = formatter.format_help()

        return '\n\nOptions\n-------\n{0}'.format(option_sec)

    def _format_action(self, action):
        # determine the required width and the entry label
        action_header = self._format_action_invocation(action)

        if action.help:
            help_text = self._expand_help(action)
            help_lines = self._split_lines(help_text, 80)
            help = ' '.join(help_lines)
        else:
            help = ''

        # return a single string
        return '{0}\n{1}\n{2}\n\n'.format(
            action_header,

            '~' * len(action_header),
            help)


def cmdline_example_to_rst(src, out=None, ref=None):
    if out is None:
        from six.moves import StringIO
        out = StringIO()

    # place header
    out.write('.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n')
    if ref:
        # place cross-ref target
        out.write('.. {0}:\n\n'.format(ref))

    # parser status vars
    inexample = False
    incodeblock = False

    for line in src:
        if line.startswith('#% EXAMPLE START'):
            inexample = True
            incodeblock = False
            continue
        if not inexample:
            continue
        if line.startswith('#% EXAMPLE END'):
            break
        if not inexample:
            continue
        if line.startswith('#%'):
            incodeblock = not incodeblock
            if incodeblock:
                out.write('\n.. code-block:: sh\n\n')
            continue
        if not incodeblock and line.startswith('#'):
            out.write(line[(min(2, len(line) - 1)):])
            continue
        if incodeblock:
            out.write('  %s' % line)
            continue
        if not len(line.strip()):
            continue
        else:
            raise RuntimeError("this should not happen")

    return out

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]

**Title:** Lines Ending with `#% SKIP` Are Not Ignored in Command Line Example Conversion

**Description:**
When converting command line examples to reStructuredText (RST), lines that end with `#% SKIP` are intended to be excluded from the output. However, currently, these lines are still being included, which leads to unwanted content in the generated documentation.

**Example Buggy Code:**
```python
demo_example = """
#!/bin/sh
datalad install http://the.world.com

datalad shameful-command  #% SKIP
#%
# The result is not comprehensible.
#%
"""
out_text = fmt.cmdline_example_to_rst(SIO(demo_example), ref='mydemo').read()
print(out_text)
```

**Expected Behavior:**
Lines ending with `#% SKIP`, such as `datalad shameful-command  #% SKIP`, should be excluded from the RST output. The generated documentation should not contain any references to these skipped commands or the accompanying comments.

**Actual Behavior:**
The line `datalad shameful-command  #% SKIP` and related comments are still present in the RST output. This results in cluttered and confusing documentation, as unintended lines are displayed.

[/ISSUE]
{
    "test_cmdline_example_to_rst": "PASSED",
    "test_parser_access": "PASSED",
    "test_manpage_formatter": "PASSED",
    "test_rstmanpage_formatter": "PASSED"
}
diff --git a/formatters.py b/formatters.py
index 7fdf3e03e..3e7bc9d41 100644
--- a/formatters.py
+++ b/formatters.py
@@ -297,7 +297,8 @@ def cmdline_example_to_rst(src, out=None, ref=None):
             out.write(line[(min(2, len(line) - 1)):])
             continue
         if incodeblock:
-            out.write('  %s' % line)
+            if not line.rstrip().endswith('#% SKIP'):
+                out.write('  %s' % line)
             continue
         if not len(line.strip()):
             continue
 

{"formatters.py": "# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the DataLad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\nimport argparse\nimport datetime\nimport re\n\n\nclass ManPageFormatter(argparse.HelpFormatter):\n    # This code was originally distributed\n    # under the same License of Python\n    # Copyright (c) 2014 Oz Nahum Tiram  <nahumoz@gmail.com>\n    def __init__(self,\n                 prog,\n                 indent_increment=2,\n                 max_help_position=4,\n                 width=1000000,\n                 section=1,\n                 ext_sections=None,\n                 authors=None,\n                 version=None\n                 ):\n\n        super(ManPageFormatter, self).__init__(\n            prog,\n            indent_increment=indent_increment,\n            max_help_position=max_help_position,\n            width=width)\n\n        self._prog = prog\n        self._section = 1\n        self._today = datetime.date.today().strftime('%Y\\\\-%m\\\\-%d')\n        self._ext_sections = ext_sections\n        self._version = version\n\n    def _get_formatter(self, **kwargs):\n        return self.formatter_class(prog=self.prog, **kwargs)\n\n    def _markup(self, txt):\n        return txt.replace('-', '\\\\-')\n\n    def _underline(self, string):\n        return \"\\\\fI\\\\s-1\" + string + \"\\\\s0\\\\fR\"\n\n    def _bold(self, string):\n        if not string.strip().startswith('\\\\fB'):\n            string = '\\\\fB' + string\n        if not string.strip().endswith('\\\\fR'):\n            string = string + '\\\\fR'\n        return string\n\n    def _mk_synopsis(self, parser):\n        self.add_usage(parser.usage, parser._actions,\n                       parser._mutually_exclusive_groups, prefix='')\n        usage = self._format_usage(None, parser._actions,\n                                   parser._mutually_exclusive_groups, '')\n        # replace too long list of commands with a single placeholder\n        usage = re.sub(r'{[^]]*?create,.*?}', ' COMMAND ', usage, flags=re.MULTILINE)\n        # take care of proper wrapping\n        usage = re.sub(r'\\[([-a-zA-Z0-9]*)\\s([a-zA-Z0-9{}|_]*)\\]', r'[\\1\\~\\2]', usage)\n\n        usage = usage.replace('%s ' % self._prog, '')\n        usage = '.SH SYNOPSIS\\n.nh\\n.HP\\n\\\\fB%s\\\\fR %s\\n.hy\\n' % (self._markup(self._prog),\n                                                    usage)\n        return usage\n\n    def _mk_title(self, prog):\n        name_version = \"\\\"{0} {1}\\\"\".format(prog, self._version)\n        return '.TH {0} {1} {2} {3}\\n'.format(prog, self._section,\n                                              self._today, name_version)\n\n    def _make_name(self, parser):\n        \"\"\"\n        this method is in consitent with others ... it relies on\n        distribution\n        \"\"\"\n        return '.SH NAME\\n%s \\\\- %s\\n' % (parser.prog,\n                                          parser.description)\n\n    def _mk_description(self, parser):\n        desc = parser.description\n        if not desc:\n            return ''\n        desc = desc.replace('\\n\\n', '\\n.PP\\n')\n        # sub-section headings\n        desc = re.sub(r'^\\*(.*)\\*$', r'.SS \\1', desc, flags=re.MULTILINE)\n        # italic commands\n        desc = re.sub(r'^  ([-a-z]*)$', r'.TP\\n\\\\fI\\1\\\\fR', desc, flags=re.MULTILINE)\n        # deindent body text, leave to troff viewer\n        desc = re.sub(r'^      (\\S.*)\\n', '\\\\1\\n', desc, flags=re.MULTILINE)\n        # format NOTEs as indented paragraphs\n        desc = re.sub(r'^NOTE\\n', '.TP\\nNOTE\\n', desc, flags=re.MULTILINE)\n        # deindent indented paragraphs after heading setup\n        desc = re.sub(r'^  (.*)$', '\\\\1', desc, flags=re.MULTILINE)\n\n        return '.SH DESCRIPTION\\n%s\\n' % self._markup(desc)\n\n    def _mk_footer(self, sections):\n        if not hasattr(sections, '__iter__'):\n            return ''\n\n        footer = []\n        for section, value in sections.items():\n            part = \".SH {}\\n {}\".format(section.upper(), value)\n            footer.append(part)\n\n        return '\\n'.join(footer)\n\n    def format_man_page(self, parser):\n        page = []\n        page.append(self._mk_title(self._prog))\n        page.append(self._mk_synopsis(parser))\n        page.append(self._mk_description(parser))\n        page.append(self._mk_options(parser))\n        page.append(self._mk_footer(self._ext_sections))\n\n        return ''.join(page)\n\n    def _mk_options(self, parser):\n\n        formatter = parser._get_formatter()\n\n        # positionals, optionals and user-defined groups\n        for action_group in parser._action_groups:\n            formatter.start_section(None)\n            formatter.add_text(None)\n            formatter.add_arguments(action_group._group_actions)\n            formatter.end_section()\n\n        # epilog\n        formatter.add_text(parser.epilog)\n\n        # determine help from format above\n        help = formatter.format_help()\n        # add spaces after comma delimiters for easier reformatting\n        help = re.sub(r'([a-z]),([a-z])', '\\\\1, \\\\2', help)\n        # get proper indentation for argument items\n        help = re.sub(r'^  (\\S.*)\\n', '.TP\\n\\\\1\\n', help, flags=re.MULTILINE)\n        # deindent body text, leave to troff viewer\n        help = re.sub(r'^    (\\S.*)\\n', '\\\\1\\n', help, flags=re.MULTILINE)\n        return '.SH OPTIONS\\n' + help\n\n    def _format_action_invocation(self, action):\n        if not action.option_strings:\n            metavar, = self._metavar_formatter(action, action.dest)(1)\n            return metavar\n\n        else:\n            parts = []\n\n            # if the Optional doesn't take a value, format is:\n            #    -s, --long\n            if action.nargs == 0:\n                parts.extend([self._bold(action_str) for action_str in\n                              action.option_strings])\n\n            # if the Optional takes a value, format is:\n            #    -s ARGS, --long ARGS\n            else:\n                default = self._underline(action.dest.upper())\n                args_string = self._format_args(action, default)\n                for option_string in action.option_strings:\n                    parts.append('%s %s' % (self._bold(option_string),\n                                            args_string))\n\n            return ', '.join(parts)\n\n\nclass RSTManPageFormatter(ManPageFormatter):\n    def _get_formatter(self, **kwargs):\n        return self.formatter_class(prog=self.prog, **kwargs)\n\n    def _markup(self, txt):\n        # put general tune-ups here\n        return txt\n\n    def _underline(self, string):\n        return \"*{0}*\".format(string)\n\n    def _bold(self, string):\n        return \"**{0}**\".format(string)\n\n    def _mk_synopsis(self, parser):\n        self.add_usage(parser.usage, parser._actions,\n                       parser._mutually_exclusive_groups, prefix='')\n        usage = self._format_usage(None, parser._actions,\n                                   parser._mutually_exclusive_groups, '')\n\n        usage = usage.replace('%s ' % self._prog, '')\n        usage = 'Synopsis\\n--------\\n::\\n\\n  %s %s\\n' \\\n                % (self._markup(self._prog), usage)\n        return usage\n\n    def _mk_title(self, prog):\n        title = \"{0}\".format(prog)\n        title += '\\n{0}\\n\\n'.format('=' * len(title))\n        return title\n\n    def _make_name(self, parser):\n        return ''\n\n    def _mk_description(self, parser):\n        desc = parser.description\n        if not desc:\n            return ''\n        return 'Description\\n-----------\\n%s\\n' % self._markup(desc)\n\n    def _mk_footer(self, sections):\n        if not hasattr(sections, '__iter__'):\n            return ''\n\n        footer = []\n        for section, value in sections.items():\n            part = \"\\n{0}\\n{1}\\n{2}\\n\".format(\n                section,\n                '-' * len(section),\n                value)\n            footer.append(part)\n\n        return '\\n'.join(footer)\n\n    def _mk_options(self, parser):\n\n        # this non-obvious maneuver is really necessary!\n        formatter = self.__class__(self._prog)\n\n        # positionals, optionals and user-defined groups\n        for action_group in parser._action_groups:\n            formatter.start_section(None)\n            formatter.add_text(None)\n            formatter.add_arguments(action_group._group_actions)\n            formatter.end_section()\n\n        # epilog\n        formatter.add_text(parser.epilog)\n\n        # determine help from format above\n        option_sec = formatter.format_help()\n\n        return '\\n\\nOptions\\n-------\\n{0}'.format(option_sec)\n\n    def _format_action(self, action):\n        # determine the required width and the entry label\n        action_header = self._format_action_invocation(action)\n\n        if action.help:\n            help_text = self._expand_help(action)\n            help_lines = self._split_lines(help_text, 80)\n            help = ' '.join(help_lines)\n        else:\n            help = ''\n\n        # return a single string\n        return '{0}\\n{1}\\n{2}\\n\\n'.format(\n            action_header,\n\n            '~' * len(action_header),\n            help)\n\n\ndef cmdline_example_to_rst(src, out=None, ref=None):\n    if out is None:\n        from six.moves import StringIO\n        out = StringIO()\n\n    # place header\n    out.write('.. AUTO-GENERATED FILE -- DO NOT EDIT!\\n\\n')\n    if ref:\n        # place cross-ref target\n        out.write('.. {0}:\\n\\n'.format(ref))\n\n    # parser status vars\n    inexample = False\n    incodeblock = False\n\n    for line in src:\n        if line.startswith('#% EXAMPLE START'):\n            inexample = True\n            incodeblock = False\n            continue\n        if not inexample:\n            continue\n        if line.startswith('#% EXAMPLE END'):\n            break\n        if not inexample:\n            continue\n        if line.startswith('#%'):\n            incodeblock = not incodeblock\n            if incodeblock:\n                out.write('\\n.. code-block:: sh\\n\\n')\n            continue\n        if not incodeblock and line.startswith('#'):\n            out.write(line[(min(2, len(line) - 1)):])\n            continue\n        if incodeblock:\n            out.write('  %s' % line)\n            continue\n        if not len(line.strip()):\n            continue\n        else:\n            raise RuntimeError(\"this should not happen\")\n\n    return out\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** Lines Ending with `#% SKIP` Are Not Ignored in Command Line Example Conversion

**Description:**
When converting command line examples to reStructuredText (RST), lines that end with `#% SKIP` are intended to be excluded from the output. However, currently, these lines are still being included, which leads to unwanted content in the generated documentation.

**Example Buggy Code:**
```python
demo_example = """
#!/bin/sh
datalad install http://the.world.com

datalad shameful-command  #% SKIP
#%
# The result is not comprehensible.
#%
"""
out_text = fmt.cmdline_example_to_rst(SIO(demo_example), ref='mydemo').read()
print(out_text)
```

**Expected Behavior:**
Lines ending with `#% SKIP`, such as `datalad shameful-command  #% SKIP`, should be excluded from the RST output. The generated documentation should not contain any references to these skipped commands or the accompanying comments.

**Actual Behavior:**
The line `datalad shameful-command  #% SKIP` and related comments are still present in the RST output. This results in cluttered and confusing documentation, as unintended lines are displayed.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### formatters.py
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
#
#   See COPYING file distributed along with the DataLad package for the
#   copyright and license terms.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##

import argparse
import datetime
import re


class ManPageFormatter(argparse.HelpFormatter):
    # This code was originally distributed
    # under the same License of Python
    # Copyright (c) 2014 Oz Nahum Tiram  <nahumoz@gmail.com>
    def __init__(self,
                 prog,
                 indent_increment=2,
                 max_help_position=4,
                 width=1000000,
                 section=1,
                 ext_sections=None,
                 authors=None,
                 version=None
                 ):

        super(ManPageFormatter, self).__init__(
            prog,
            indent_increment=indent_increment,
            max_help_position=max_help_position,
            width=width)

        self._prog = prog
        self._section = 1
        self._today = datetime.date.today().strftime('%Y\\-%m\\-%d')
        self._ext_sections = ext_sections
        self._version = version

    def _get_formatter(self, **kwargs):
        return self.formatter_class(prog=self.prog, **kwargs)

    def _markup(self, txt):
        return txt.replace('-', '\\-')

    def _underline(self, string):
        return "\\fI\\s-1" + string + "\\s0\\fR"

    def _bold(self, string):
        if not string.strip().startswith('\\fB'):
            string = '\\fB' + string
        if not string.strip().endswith('\\fR'):
            string = string + '\\fR'
        return string

    def _mk_synopsis(self, parser):
        self.add_usage(parser.usage, parser._actions,
                       parser._mutually_exclusive_groups, prefix='')
        usage = self._format_usage(None, parser._actions,
                                   parser._mutually_exclusive_groups, '')
        # replace too long list of commands with a single placeholder
        usage = re.sub(r'{[^]]*?create,.*?}', ' COMMAND ', usage, flags=re.MULTILINE)
        # take care of proper wrapping
        usage = re.sub(r'\[([-a-zA-Z0-9]*)\s([a-zA-Z0-9{}|_]*)\]', r'[\1\~\2]', usage)

        usage = usage.replace('%s ' % self._prog, '')
        usage = '.SH SYNOPSIS\n.nh\n.HP\n\\fB%s\\fR %s\n.hy\n' % (self._markup(self._prog),
                                                    usage)
        return usage

    def _mk_title(self, prog):
        name_version = "\"{0} {1}\"".format(prog, self._version)
        return '.TH {0} {1} {2} {3}\n'.format(prog, self._section,
                                              self._today, name_version)

    def _make_name(self, parser):
        """
        this method is in consitent with others ... it relies on
        distribution
        """
        return '.SH NAME\n%s \\- %s\n' % (parser.prog,
                                          parser.description)

    def _mk_description(self, parser):
        desc = parser.description
        if not desc:
            return ''
        desc = desc.replace('\n\n', '\n.PP\n')
        # sub-section headings
        desc = re.sub(r'^\*(.*)\*$', r'.SS \1', desc, flags=re.MULTILINE)
        # italic commands
        desc = re.sub(r'^  ([-a-z]*)$', r'.TP\n\\fI\1\\fR', desc, flags=re.MULTILINE)
        # deindent body text, leave to troff viewer
        desc = re.sub(r'^      (\S.*)\n', '\\1\n', desc, flags=re.MULTILINE)
        # format NOTEs as indented paragraphs
        desc = re.sub(r'^NOTE\n', '.TP\nNOTE\n', desc, flags=re.MULTILINE)
        # deindent indented paragraphs after heading setup
        desc = re.sub(r'^  (.*)$', '\\1', desc, flags=re.MULTILINE)

        return '.SH DESCRIPTION\n%s\n' % self._markup(desc)

    def _mk_footer(self, sections):
        if not hasattr(sections, '__iter__'):
            return ''

        footer = []
        for section, value in sections.items():
            part = ".SH {}\n {}".format(section.upper(), value)
            footer.append(part)

        return '\n'.join(footer)

    def format_man_page(self, parser):
        page = []
        page.append(self._mk_title(self._prog))
        page.append(self._mk_synopsis(parser))
        page.append(self._mk_description(parser))
        page.append(self._mk_options(parser))
        page.append(self._mk_footer(self._ext_sections))

        return ''.join(page)

    def _mk_options(self, parser):

        formatter = parser._get_formatter()

        # positionals, optionals and user-defined groups
        for action_group in parser._action_groups:
            formatter.start_section(None)
            formatter.add_text(None)
            formatter.add_arguments(action_group._group_actions)
            formatter.end_section()

        # epilog
        formatter.add_text(parser.epilog)

        # determine help from format above
        help = formatter.format_help()
        # add spaces after comma delimiters for easier reformatting
        help = re.sub(r'([a-z]),([a-z])', '\\1, \\2', help)
        # get proper indentation for argument items
        help = re.sub(r'^  (\S.*)\n', '.TP\n\\1\n', help, flags=re.MULTILINE)
        # deindent body text, leave to troff viewer
        help = re.sub(r'^    (\S.*)\n', '\\1\n', help, flags=re.MULTILINE)
        return '.SH OPTIONS\n' + help

    def _format_action_invocation(self, action):
        if not action.option_strings:
            metavar, = self._metavar_formatter(action, action.dest)(1)
            return metavar

        else:
            parts = []

            # if the Optional doesn't take a value, format is:
            #    -s, --long
            if action.nargs == 0:
                parts.extend([self._bold(action_str) for action_str in
                              action.option_strings])

            # if the Optional takes a value, format is:
            #    -s ARGS, --long ARGS
            else:
                default = self._underline(action.dest.upper())
                args_string = self._format_args(action, default)
                for option_string in action.option_strings:
                    parts.append('%s %s' % (self._bold(option_string),
                                            args_string))

            return ', '.join(parts)


class RSTManPageFormatter(ManPageFormatter):
    def _get_formatter(self, **kwargs):
        return self.formatter_class(prog=self.prog, **kwargs)

    def _markup(self, txt):
        # put general tune-ups here
        return txt

    def _underline(self, string):
        return "*{0}*".format(string)

    def _bold(self, string):
        return "**{0}**".format(string)

    def _mk_synopsis(self, parser):
        self.add_usage(parser.usage, parser._actions,
                       parser._mutually_exclusive_groups, prefix='')
        usage = self._format_usage(None, parser._actions,
                                   parser._mutually_exclusive_groups, '')

        usage = usage.replace('%s ' % self._prog, '')
        usage = 'Synopsis\n--------\n::\n\n  %s %s\n' \
                % (self._markup(self._prog), usage)
        return usage

    def _mk_title(self, prog):
        title = "{0}".format(prog)
        title += '\n{0}\n\n'.format('=' * len(title))
        return title

    def _make_name(self, parser):
        return ''

    def _mk_description(self, parser):
        desc = parser.description
        if not desc:
            return ''
        return 'Description\n-----------\n%s\n' % self._markup(desc)

    def _mk_footer(self, sections):
        if not hasattr(sections, '__iter__'):
            return ''

        footer = []
        for section, value in sections.items():
            part = "\n{0}\n{1}\n{2}\n".format(
                section,
                '-' * len(section),
                value)
            footer.append(part)

        return '\n'.join(footer)

    def _mk_options(self, parser):

        # this non-obvious maneuver is really necessary!
        formatter = self.__class__(self._prog)

        # positionals, optionals and user-defined groups
        for action_group in parser._action_groups:
            formatter.start_section(None)
            formatter.add_text(None)
            formatter.add_arguments(action_group._group_actions)
            formatter.end_section()

        # epilog
        formatter.add_text(parser.epilog)

        # determine help from format above
        option_sec = formatter.format_help()

        return '\n\nOptions\n-------\n{0}'.format(option_sec)

    def _format_action(self, action):
        # determine the required width and the entry label
        action_header = self._format_action_invocation(action)

        if action.help:
            help_text = self._expand_help(action)
            help_lines = self._split_lines(help_text, 80)
            help = ' '.join(help_lines)
        else:
            help = ''

        # return a single string
        return '{0}\n{1}\n{2}\n\n'.format(
            action_header,

            '~' * len(action_header),
            help)


def cmdline_example_to_rst(src, out=None, ref=None):
    if out is None:
        from six.moves import StringIO
        out = StringIO()

    # place header
    out.write('.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n')
    if ref:
        # place cross-ref target
        out.write('.. {0}:\n\n'.format(ref))

    # parser status vars
    inexample = False
    incodeblock = False

    for line in src:
        if line.startswith('#% EXAMPLE START'):
            inexample = True
            incodeblock = False
            continue
        if not inexample:
            continue
        if line.startswith('#% EXAMPLE END'):
            break
        if not inexample:
            continue
        if line.startswith('#%'):
            incodeblock = not incodeblock
            if incodeblock:
                out.write('\n.. code-block:: sh\n\n')
            continue
        if not incodeblock and line.startswith('#'):
            out.write(line[(min(2, len(line) - 1)):])
            continue
        if incodeblock:
            out.write('  %s' % line)
            continue
        if not len(line.strip()):
            continue
        else:
            raise RuntimeError("this should not happen")

    return out

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user