prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Improve lint messages on whitespace
  The message about the spacing for selectors isn't clear to see the problem in the number of spaces:
  
  `Selectors are suggested to take a " # []" form.`
  
  It would be clearer to have a message like: `<two spaces> # <one space> [selector]`
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `conda_smithy/lint_recipe.py`
  Content:
  ```
  1 import os
  2 import re
  3 
  4 import jinja2
  5 import ruamel.yaml
  6 
  7 
  8 EXPECTED_SECTION_ORDER = ['package', 'source', 'build', 'requirements',
  9                           'test', 'app', 'about', 'extra']
  10 
  11 REQUIREMENTS_ORDER = ['build', 'run']
  12 
  13 
  14 class NullUndefined(jinja2.Undefined):
  15     def __unicode__(self):
  16         return unicode(self._undefined_name)
  17 
  18 
  19 def get_section(parent, name, lints):
  20     section = parent.get(name, {})
  21     if not isinstance(section, dict):
  22         lints.append('The "{}" section was expected to be a dictionary, but '
  23                      'got a {}.'.format(name, type(section).__name__))
  24         section = {}
  25     return section
  26 
  27 
  28 def lintify(meta, recipe_dir=None):
  29     lints = []
  30     major_sections = list(meta.keys())
  31 
  32     # If the recipe_dir exists (no guarantee within this function) , we can
  33     # find the meta.yaml within it.
  34     meta_fname = os.path.join(recipe_dir or '', 'meta.yaml')
  35 
  36     source_section = get_section(meta, 'source', lints)
  37     build_section = get_section(meta, 'build', lints)
  38     requirements_section = get_section(meta, 'requirements', lints)
  39     about_section = get_section(meta, 'about', lints)
  40     extra_section = get_section(meta, 'extra', lints)
  41 
  42     # 1: Top level meta.yaml keys should have a specific order.
  43     section_order_sorted = sorted(major_sections,
  44                                   key=EXPECTED_SECTION_ORDER.index)
  45     if major_sections != section_order_sorted:
  46         lints.append('The top level meta keys are in an unexpected order. '
  47                      'Expecting {}.'.format(section_order_sorted))
  48 
  49     # 2: The about section should have a home, license and summary.
  50     for about_item in ['home', 'license', 'summary']:
  51         # if the section doesn't exist, or is just empty, lint it.
  52         if not about_section.get(about_item, ''):
  53             lints.append('The {} item is expected in the about section.'
  54                          ''.format(about_item))
  55 
  56     # 3: The recipe should have some maintainers.
  57     if not extra_section.get('recipe-maintainers', []):
  58         lints.append('The recipe could do with some maintainers listed in '
  59                      'the "extra/recipe-maintainers" section.')
  60 
  61     # 4: The recipe should have some tests.
  62     if 'test' not in major_sections:
  63         test_files = ['run_test.py', 'run_test.sh', 'run_test.bat',
  64                       'run_test.pl']
  65         a_test_file_exists = (recipe_dir is not None and
  66                               any(os.path.exists(os.path.join(recipe_dir,
  67                                                               test_file))
  68                                   for test_file in test_files))
  69         if not a_test_file_exists:
  70             lints.append('The recipe must have some tests.')
  71 
  72     # 5: License cannot be 'unknown.'
  73     license = about_section.get('license', '').lower()
  74     if 'unknown' == license.strip():
  75         lints.append('The recipe license cannot be unknown.')
  76 
  77     # 6: Selectors should be in a tidy form.
  78     if recipe_dir is not None and os.path.exists(meta_fname):
  79         bad_selectors = []
  80         # Good selectors look like ".*\s\s#\s[...]"
  81         good_selectors_pat = re.compile(r'(.+?)\s{2,}#\s\[(.+)\](?(2).*)$')
  82         with open(meta_fname, 'r') as fh:
  83             for selector_line in selector_lines(fh):
  84                 if not good_selectors_pat.match(selector_line):
  85                     bad_selectors.append(selector_line)
  86         if bad_selectors:
  87             lints.append('Selectors are suggested to take a '
  88                          '"  # [<selector>]" form.')
  89 
  90     # 7: The build section should have a build number.
  91     if build_section.get('number', None) is None:
  92         lints.append('The recipe must have a `build/number` section.')
  93 
  94     # 8: The build section should be before the run section in requirements.
  95     requirements_order_sorted = sorted(requirements_section,
  96                                        key=REQUIREMENTS_ORDER.index)
  97     if requirements_section.keys() != requirements_order_sorted:
  98         lints.append('The `requirements/build` section should be defined '
  99                      'before the `requirements/run` section.')
  100 
  101     # 9: Files downloaded should have a hash.
  102     if ('url' in source_section and
  103             not ({'sha1', 'sha256', 'md5'} & set(source_section.keys()))):
  104         lints.append('When defining a source/url please add a sha256, sha1 '
  105                      'or md5 checksum (sha256 preferably).')
  106 
  107     return lints
  108 
  109 
  110 def selector_lines(lines):
  111     # Using the same pattern defined in conda-build (metadata.py),
  112     # we identify selectors.
  113     sel_pat = re.compile(r'(.+?)\s*(#.*)?\[(.+)\](?(2).*)$')
  114 
  115     for line in lines:
  116         line = line.rstrip()
  117         if line.lstrip().startswith('#'):
  118             # Don't bother with comment only lines
  119             continue
  120         m = sel_pat.match(line)
  121         if m:
  122             m.group(3)
  123             yield line
  124 
  125 
  126 def main(recipe_dir):
  127     recipe_dir = os.path.abspath(recipe_dir)
  128     recipe_meta = os.path.join(recipe_dir, 'meta.yaml')
  129     if not os.path.exists(recipe_dir):
  130         raise IOError('Feedstock has no recipe/meta.yaml.')
  131 
  132     env = jinja2.Environment(undefined=NullUndefined)
  133 
  134     with open(recipe_meta, 'r') as fh:
  135         content = env.from_string(''.join(fh)).render()
  136         meta = ruamel.yaml.load(content, ruamel.yaml.RoundTripLoader)
  137     results = lintify(meta, recipe_dir)
  138     return results
  139
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/conda_smithy/lint_recipe.py b/conda_smithy/lint_recipe.py
  --- a/conda_smithy/lint_recipe.py
  +++ b/conda_smithy/lint_recipe.py
  @@ -85,7 +85,7 @@
                       bad_selectors.append(selector_line)
           if bad_selectors:
               lints.append('Selectors are suggested to take a '
  -                         '"  # [<selector>]" form.')
  +                         '"<two spaces>#<one space>[<selector>]" form.')
   
       # 7: The build section should have a build number.
       if build_section.get('number', None) is None:
  
verification_info: {"golden_diff": "diff --git a/conda_smithy/lint_recipe.py b/conda_smithy/lint_recipe.py\n--- a/conda_smithy/lint_recipe.py\n+++ b/conda_smithy/lint_recipe.py\n@@ -85,7 +85,7 @@\n                     bad_selectors.append(selector_line)\n         if bad_selectors:\n             lints.append('Selectors are suggested to take a '\n-                         '\"  # [<selector>]\" form.')\n+                         '\"<two spaces>#<one space>[<selector>]\" form.')\n \n     # 7: The build section should have a build number.\n     if build_section.get('number', None) is None:\n", "issue": "Improve lint messages on whitespace\nThe message about the spacing for selectors isn't clear to see the problem in the number of spaces:\n\n`Selectors are suggested to take a \" # []\" form.`\n\nIt would be clearer to have a message like: `<two spaces> # <one space> [selector]`\n\n", "before_files": [{"content": "import os\nimport re\n\nimport jinja2\nimport ruamel.yaml\n\n\nEXPECTED_SECTION_ORDER = ['package', 'source', 'build', 'requirements',\n                          'test', 'app', 'about', 'extra']\n\nREQUIREMENTS_ORDER = ['build', 'run']\n\n\nclass NullUndefined(jinja2.Undefined):\n    def __unicode__(self):\n        return unicode(self._undefined_name)\n\n\ndef get_section(parent, name, lints):\n    section = parent.get(name, {})\n    if not isinstance(section, dict):\n        lints.append('The \"{}\" section was expected to be a dictionary, but '\n                     'got a {}.'.format(name, type(section).__name__))\n        section = {}\n    return section\n\n\ndef lintify(meta, recipe_dir=None):\n    lints = []\n    major_sections = list(meta.keys())\n\n    # If the recipe_dir exists (no guarantee within this function) , we can\n    # find the meta.yaml within it.\n    meta_fname = os.path.join(recipe_dir or '', 'meta.yaml')\n\n    source_section = get_section(meta, 'source', lints)\n    build_section = get_section(meta, 'build', lints)\n    requirements_section = get_section(meta, 'requirements', lints)\n    about_section = get_section(meta, 'about', lints)\n    extra_section = get_section(meta, 'extra', lints)\n\n    # 1: Top level meta.yaml keys should have a specific order.\n    section_order_sorted = sorted(major_sections,\n                                  key=EXPECTED_SECTION_ORDER.index)\n    if major_sections != section_order_sorted:\n        lints.append('The top level meta keys are in an unexpected order. '\n                     'Expecting {}.'.format(section_order_sorted))\n\n    # 2: The about section should have a home, license and summary.\n    for about_item in ['home', 'license', 'summary']:\n        # if the section doesn't exist, or is just empty, lint it.\n        if not about_section.get(about_item, ''):\n            lints.append('The {} item is expected in the about section.'\n                         ''.format(about_item))\n\n    # 3: The recipe should have some maintainers.\n    if not extra_section.get('recipe-maintainers', []):\n        lints.append('The recipe could do with some maintainers listed in '\n                     'the \"extra/recipe-maintainers\" section.')\n\n    # 4: The recipe should have some tests.\n    if 'test' not in major_sections:\n        test_files = ['run_test.py', 'run_test.sh', 'run_test.bat',\n                      'run_test.pl']\n        a_test_file_exists = (recipe_dir is not None and\n                              any(os.path.exists(os.path.join(recipe_dir,\n                                                              test_file))\n                                  for test_file in test_files))\n        if not a_test_file_exists:\n            lints.append('The recipe must have some tests.')\n\n    # 5: License cannot be 'unknown.'\n    license = about_section.get('license', '').lower()\n    if 'unknown' == license.strip():\n        lints.append('The recipe license cannot be unknown.')\n\n    # 6: Selectors should be in a tidy form.\n    if recipe_dir is not None and os.path.exists(meta_fname):\n        bad_selectors = []\n        # Good selectors look like \".*\\s\\s#\\s[...]\"\n        good_selectors_pat = re.compile(r'(.+?)\\s{2,}#\\s\\[(.+)\\](?(2).*)$')\n        with open(meta_fname, 'r') as fh:\n            for selector_line in selector_lines(fh):\n                if not good_selectors_pat.match(selector_line):\n                    bad_selectors.append(selector_line)\n        if bad_selectors:\n            lints.append('Selectors are suggested to take a '\n                         '\"  # [<selector>]\" form.')\n\n    # 7: The build section should have a build number.\n    if build_section.get('number', None) is None:\n        lints.append('The recipe must have a `build/number` section.')\n\n    # 8: The build section should be before the run section in requirements.\n    requirements_order_sorted = sorted(requirements_section,\n                                       key=REQUIREMENTS_ORDER.index)\n    if requirements_section.keys() != requirements_order_sorted:\n        lints.append('The `requirements/build` section should be defined '\n                     'before the `requirements/run` section.')\n\n    # 9: Files downloaded should have a hash.\n    if ('url' in source_section and\n            not ({'sha1', 'sha256', 'md5'} & set(source_section.keys()))):\n        lints.append('When defining a source/url please add a sha256, sha1 '\n                     'or md5 checksum (sha256 preferably).')\n\n    return lints\n\n\ndef selector_lines(lines):\n    # Using the same pattern defined in conda-build (metadata.py),\n    # we identify selectors.\n    sel_pat = re.compile(r'(.+?)\\s*(#.*)?\\[(.+)\\](?(2).*)$')\n\n    for line in lines:\n        line = line.rstrip()\n        if line.lstrip().startswith('#'):\n            # Don't bother with comment only lines\n            continue\n        m = sel_pat.match(line)\n        if m:\n            m.group(3)\n            yield line\n\n\ndef main(recipe_dir):\n    recipe_dir = os.path.abspath(recipe_dir)\n    recipe_meta = os.path.join(recipe_dir, 'meta.yaml')\n    if not os.path.exists(recipe_dir):\n        raise IOError('Feedstock has no recipe/meta.yaml.')\n\n    env = jinja2.Environment(undefined=NullUndefined)\n\n    with open(recipe_meta, 'r') as fh:\n        content = env.from_string(''.join(fh)).render()\n        meta = ruamel.yaml.load(content, ruamel.yaml.RoundTripLoader)\n    results = lintify(meta, recipe_dir)\n    return results\n", "path": "conda_smithy/lint_recipe.py"}], "after_files": [{"content": "import os\nimport re\n\nimport jinja2\nimport ruamel.yaml\n\n\nEXPECTED_SECTION_ORDER = ['package', 'source', 'build', 'requirements',\n                          'test', 'app', 'about', 'extra']\n\nREQUIREMENTS_ORDER = ['build', 'run']\n\n\nclass NullUndefined(jinja2.Undefined):\n    def __unicode__(self):\n        return unicode(self._undefined_name)\n\n\ndef get_section(parent, name, lints):\n    section = parent.get(name, {})\n    if not isinstance(section, dict):\n        lints.append('The \"{}\" section was expected to be a dictionary, but '\n                     'got a {}.'.format(name, type(section).__name__))\n        section = {}\n    return section\n\n\ndef lintify(meta, recipe_dir=None):\n    lints = []\n    major_sections = list(meta.keys())\n\n    # If the recipe_dir exists (no guarantee within this function) , we can\n    # find the meta.yaml within it.\n    meta_fname = os.path.join(recipe_dir or '', 'meta.yaml')\n\n    source_section = get_section(meta, 'source', lints)\n    build_section = get_section(meta, 'build', lints)\n    requirements_section = get_section(meta, 'requirements', lints)\n    about_section = get_section(meta, 'about', lints)\n    extra_section = get_section(meta, 'extra', lints)\n\n    # 1: Top level meta.yaml keys should have a specific order.\n    section_order_sorted = sorted(major_sections,\n                                  key=EXPECTED_SECTION_ORDER.index)\n    if major_sections != section_order_sorted:\n        lints.append('The top level meta keys are in an unexpected order. '\n                     'Expecting {}.'.format(section_order_sorted))\n\n    # 2: The about section should have a home, license and summary.\n    for about_item in ['home', 'license', 'summary']:\n        # if the section doesn't exist, or is just empty, lint it.\n        if not about_section.get(about_item, ''):\n            lints.append('The {} item is expected in the about section.'\n                         ''.format(about_item))\n\n    # 3: The recipe should have some maintainers.\n    if not extra_section.get('recipe-maintainers', []):\n        lints.append('The recipe could do with some maintainers listed in '\n                     'the \"extra/recipe-maintainers\" section.')\n\n    # 4: The recipe should have some tests.\n    if 'test' not in major_sections:\n        test_files = ['run_test.py', 'run_test.sh', 'run_test.bat',\n                      'run_test.pl']\n        a_test_file_exists = (recipe_dir is not None and\n                              any(os.path.exists(os.path.join(recipe_dir,\n                                                              test_file))\n                                  for test_file in test_files))\n        if not a_test_file_exists:\n            lints.append('The recipe must have some tests.')\n\n    # 5: License cannot be 'unknown.'\n    license = about_section.get('license', '').lower()\n    if 'unknown' == license.strip():\n        lints.append('The recipe license cannot be unknown.')\n\n    # 6: Selectors should be in a tidy form.\n    if recipe_dir is not None and os.path.exists(meta_fname):\n        bad_selectors = []\n        # Good selectors look like \".*\\s\\s#\\s[...]\"\n        good_selectors_pat = re.compile(r'(.+?)\\s{2,}#\\s\\[(.+)\\](?(2).*)$')\n        with open(meta_fname, 'r') as fh:\n            for selector_line in selector_lines(fh):\n                if not good_selectors_pat.match(selector_line):\n                    bad_selectors.append(selector_line)\n        if bad_selectors:\n            lints.append('Selectors are suggested to take a '\n                         '\"<two spaces>#<one space>[<selector>]\" form.')\n\n    # 7: The build section should have a build number.\n    if build_section.get('number', None) is None:\n        lints.append('The recipe must have a `build/number` section.')\n\n    # 8: The build section should be before the run section in requirements.\n    requirements_order_sorted = sorted(requirements_section,\n                                       key=REQUIREMENTS_ORDER.index)\n    if requirements_section.keys() != requirements_order_sorted:\n        lints.append('The `requirements/build` section should be defined '\n                     'before the `requirements/run` section.')\n\n    # 9: Files downloaded should have a hash.\n    if ('url' in source_section and\n            not ({'sha1', 'sha256', 'md5'} & set(source_section.keys()))):\n        lints.append('When defining a source/url please add a sha256, sha1 '\n                     'or md5 checksum (sha256 preferably).')\n\n    return lints\n\n\ndef selector_lines(lines):\n    # Using the same pattern defined in conda-build (metadata.py),\n    # we identify selectors.\n    sel_pat = re.compile(r'(.+?)\\s*(#.*)?\\[(.+)\\](?(2).*)$')\n\n    for line in lines:\n        line = line.rstrip()\n        if line.lstrip().startswith('#'):\n            # Don't bother with comment only lines\n            continue\n        m = sel_pat.match(line)\n        if m:\n            m.group(3)\n            yield line\n\n\ndef main(recipe_dir):\n    recipe_dir = os.path.abspath(recipe_dir)\n    recipe_meta = os.path.join(recipe_dir, 'meta.yaml')\n    if not os.path.exists(recipe_dir):\n        raise IOError('Feedstock has no recipe/meta.yaml.')\n\n    env = jinja2.Environment(undefined=NullUndefined)\n\n    with open(recipe_meta, 'r') as fh:\n        content = env.from_string(''.join(fh)).render()\n        meta = ruamel.yaml.load(content, ruamel.yaml.RoundTripLoader)\n    results = lintify(meta, recipe_dir)\n    return results\n", "path": "conda_smithy/lint_recipe.py"}]}