prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  We should export a `pants_contrib_requirement` in the spirit of `pants_requirement`.
  This makes plugin authors lives easier. The new macro should also support environment markers as outlined in #6358.
  
  </issue>
  <code>
  [start of src/python/pants/backend/python/register.py]
  1 # coding=utf-8
  2 # Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
  3 # Licensed under the Apache License, Version 2.0 (see LICENSE).
  4 
  5 from __future__ import absolute_import, division, print_function, unicode_literals
  6 
  7 from pants.backend.python.pants_requirement import PantsRequirement
  8 from pants.backend.python.python_artifact import PythonArtifact
  9 from pants.backend.python.python_requirement import PythonRequirement
  10 from pants.backend.python.python_requirements import PythonRequirements
  11 from pants.backend.python.targets.python_app import PythonApp
  12 from pants.backend.python.targets.python_binary import PythonBinary
  13 from pants.backend.python.targets.python_distribution import PythonDistribution
  14 from pants.backend.python.targets.python_library import PythonLibrary
  15 from pants.backend.python.targets.python_requirement_library import PythonRequirementLibrary
  16 from pants.backend.python.targets.python_tests import PythonTests
  17 from pants.backend.python.tasks.build_local_python_distributions import \
  18   BuildLocalPythonDistributions
  19 from pants.backend.python.tasks.gather_sources import GatherSources
  20 from pants.backend.python.tasks.isort_prep import IsortPrep
  21 from pants.backend.python.tasks.isort_run import IsortRun
  22 from pants.backend.python.tasks.local_python_distribution_artifact import \
  23   LocalPythonDistributionArtifact
  24 from pants.backend.python.tasks.pytest_prep import PytestPrep
  25 from pants.backend.python.tasks.pytest_run import PytestRun
  26 from pants.backend.python.tasks.python_binary_create import PythonBinaryCreate
  27 from pants.backend.python.tasks.python_bundle import PythonBundle
  28 from pants.backend.python.tasks.python_repl import PythonRepl
  29 from pants.backend.python.tasks.python_run import PythonRun
  30 from pants.backend.python.tasks.resolve_requirements import ResolveRequirements
  31 from pants.backend.python.tasks.select_interpreter import SelectInterpreter
  32 from pants.backend.python.tasks.setup_py import SetupPy
  33 from pants.build_graph.build_file_aliases import BuildFileAliases
  34 from pants.build_graph.resources import Resources
  35 from pants.goal.task_registrar import TaskRegistrar as task
  36 
  37 
  38 def build_file_aliases():
  39   return BuildFileAliases(
  40     targets={
  41       PythonApp.alias(): PythonApp,
  42       PythonBinary.alias(): PythonBinary,
  43       PythonLibrary.alias(): PythonLibrary,
  44       PythonTests.alias(): PythonTests,
  45       PythonDistribution.alias(): PythonDistribution,
  46       'python_requirement_library': PythonRequirementLibrary,
  47       Resources.alias(): Resources,
  48     },
  49     objects={
  50       'python_requirement': PythonRequirement,
  51       'python_artifact': PythonArtifact,
  52       'setup_py': PythonArtifact,
  53     },
  54     context_aware_object_factories={
  55       'python_requirements': PythonRequirements,
  56       'pants_requirement': PantsRequirement,
  57     }
  58   )
  59 
  60 
  61 def register_goals():
  62   task(name='interpreter', action=SelectInterpreter).install('pyprep')
  63   task(name='build-local-dists', action=BuildLocalPythonDistributions).install('pyprep')
  64   task(name='requirements', action=ResolveRequirements).install('pyprep')
  65   task(name='sources', action=GatherSources).install('pyprep')
  66   task(name='py', action=PythonRun).install('run')
  67   task(name='pytest-prep', action=PytestPrep).install('test')
  68   task(name='pytest', action=PytestRun).install('test')
  69   task(name='py', action=PythonRepl).install('repl')
  70   task(name='setup-py', action=SetupPy).install()
  71   task(name='py', action=PythonBinaryCreate).install('binary')
  72   task(name='py-wheels', action=LocalPythonDistributionArtifact).install('binary')
  73   task(name='isort-prep', action=IsortPrep).install('fmt')
  74   task(name='isort', action=IsortRun).install('fmt')
  75   task(name='py', action=PythonBundle).install('bundle')
  76
  [end of src/python/pants/backend/python/register.py]
  [start of src/python/pants/backend/python/pants_requirement.py]
  1 # coding=utf-8
  2 # Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
  3 # Licensed under the Apache License, Version 2.0 (see LICENSE).
  4 
  5 from __future__ import absolute_import, division, print_function, unicode_literals
  6 
  7 import os
  8 from builtins import object
  9 
  10 from pants.backend.python.python_requirement import PythonRequirement
  11 from pants.base.build_environment import pants_version
  12 
  13 
  14 class PantsRequirement(object):
  15   """Exports a `python_requirement_library` pointing at the active pants' corresponding sdist.
  16 
  17   This requirement is useful for custom plugin authors who want to build and test their plugin with
  18   pants itself.  Using the resulting target as a dependency of their plugin target ensures the
  19   dependency stays true to the surrounding repo's version of pants.
  20 
  21   NB: The requirement generated is for official pants releases on pypi; so may not be appropriate
  22   for use in a repo that tracks `pantsbuild/pants` or otherwise uses custom pants sdists.
  23 
  24   :API: public
  25   """
  26 
  27   def __init__(self, parse_context):
  28     self._parse_context = parse_context
  29 
  30   def __call__(self, name=None):
  31     """
  32     :param string name: The name to use for the target, defaults to the parent dir name.
  33     """
  34     name = name or os.path.basename(self._parse_context.rel_path)
  35 
  36     # TODO(John Sirois): Modify to constraint to >=3.5,<4 as part of
  37     # https://github.com/pantsbuild/pants/issues/6062
  38     env_marker = "python_version>='2.7' and python_version<'3'"
  39 
  40     requirement = PythonRequirement(requirement="pantsbuild.pants=={version} ; {env_marker}"
  41                                     .format(version=pants_version(), env_marker=env_marker))
  42 
  43     self._parse_context.create_object('python_requirement_library',
  44                                       name=name,
  45                                       requirements=[requirement])
  46
  [end of src/python/pants/backend/python/pants_requirement.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/src/python/pants/backend/python/pants_requirement.py b/src/python/pants/backend/python/pants_requirement.py
  --- a/src/python/pants/backend/python/pants_requirement.py
  +++ b/src/python/pants/backend/python/pants_requirement.py
  @@ -9,6 +9,9 @@
   
   from pants.backend.python.python_requirement import PythonRequirement
   from pants.base.build_environment import pants_version
  +from pants.base.exceptions import TargetDefinitionException
  +from pants.build_graph.address import Address
  +from pants.util.meta import classproperty
   
   
   class PantsRequirement(object):
  @@ -24,21 +27,37 @@
     :API: public
     """
   
  +  @classproperty
  +  def alias(self):
  +    return 'pants_requirement'
  +
     def __init__(self, parse_context):
       self._parse_context = parse_context
   
  -  def __call__(self, name=None):
  +  def __call__(self, name=None, dist=None):
       """
  -    :param string name: The name to use for the target, defaults to the parent dir name.
  +    :param string name: The name to use for the target, defaults to the dist name if specified and
  +                        otherwise the parent dir name.
  +    :param string dist: The pants dist to create a requirement for. This must be a
  +                        'pantsbuild.pants*' distribution; eg:
  +                        'pantsbuild.pants.contrib.python.checks'.
       """
  -    name = name or os.path.basename(self._parse_context.rel_path)
  +    name = name or dist or os.path.basename(self._parse_context.rel_path)
  +    dist = dist or 'pantsbuild.pants'
  +    if not (dist == 'pantsbuild.pants' or dist.startswith('pantsbuild.pants.')):
  +      target = Address(spec_path=self._parse_context.rel_path, target_name=name)
  +      raise TargetDefinitionException(target=target,
  +                                      msg='The {} target only works for pantsbuild.pants '
  +                                          'distributions, given {}'.format(self.alias, dist))
   
       # TODO(John Sirois): Modify to constraint to >=3.5,<4 as part of
       # https://github.com/pantsbuild/pants/issues/6062
       env_marker = "python_version>='2.7' and python_version<'3'"
   
  -    requirement = PythonRequirement(requirement="pantsbuild.pants=={version} ; {env_marker}"
  -                                    .format(version=pants_version(), env_marker=env_marker))
  +    requirement = PythonRequirement(requirement="{key}=={version} ; {env_marker}"
  +                                    .format(key=dist,
  +                                            version=pants_version(),
  +                                            env_marker=env_marker))
   
       self._parse_context.create_object('python_requirement_library',
                                         name=name,
  diff --git a/src/python/pants/backend/python/register.py b/src/python/pants/backend/python/register.py
  --- a/src/python/pants/backend/python/register.py
  +++ b/src/python/pants/backend/python/register.py
  @@ -53,7 +53,7 @@
       },
       context_aware_object_factories={
         'python_requirements': PythonRequirements,
  -      'pants_requirement': PantsRequirement,
  +      PantsRequirement.alias: PantsRequirement,
       }
     )
  
verification_info: {"golden_diff": "diff --git a/src/python/pants/backend/python/pants_requirement.py b/src/python/pants/backend/python/pants_requirement.py\n--- a/src/python/pants/backend/python/pants_requirement.py\n+++ b/src/python/pants/backend/python/pants_requirement.py\n@@ -9,6 +9,9 @@\n \n from pants.backend.python.python_requirement import PythonRequirement\n from pants.base.build_environment import pants_version\n+from pants.base.exceptions import TargetDefinitionException\n+from pants.build_graph.address import Address\n+from pants.util.meta import classproperty\n \n \n class PantsRequirement(object):\n@@ -24,21 +27,37 @@\n   :API: public\n   \"\"\"\n \n+  @classproperty\n+  def alias(self):\n+    return 'pants_requirement'\n+\n   def __init__(self, parse_context):\n     self._parse_context = parse_context\n \n-  def __call__(self, name=None):\n+  def __call__(self, name=None, dist=None):\n     \"\"\"\n-    :param string name: The name to use for the target, defaults to the parent dir name.\n+    :param string name: The name to use for the target, defaults to the dist name if specified and\n+                        otherwise the parent dir name.\n+    :param string dist: The pants dist to create a requirement for. This must be a\n+                        'pantsbuild.pants*' distribution; eg:\n+                        'pantsbuild.pants.contrib.python.checks'.\n     \"\"\"\n-    name = name or os.path.basename(self._parse_context.rel_path)\n+    name = name or dist or os.path.basename(self._parse_context.rel_path)\n+    dist = dist or 'pantsbuild.pants'\n+    if not (dist == 'pantsbuild.pants' or dist.startswith('pantsbuild.pants.')):\n+      target = Address(spec_path=self._parse_context.rel_path, target_name=name)\n+      raise TargetDefinitionException(target=target,\n+                                      msg='The {} target only works for pantsbuild.pants '\n+                                          'distributions, given {}'.format(self.alias, dist))\n \n     # TODO(John Sirois): Modify to constraint to >=3.5,<4 as part of\n     # https://github.com/pantsbuild/pants/issues/6062\n     env_marker = \"python_version>='2.7' and python_version<'3'\"\n \n-    requirement = PythonRequirement(requirement=\"pantsbuild.pants=={version} ; {env_marker}\"\n-                                    .format(version=pants_version(), env_marker=env_marker))\n+    requirement = PythonRequirement(requirement=\"{key}=={version} ; {env_marker}\"\n+                                    .format(key=dist,\n+                                            version=pants_version(),\n+                                            env_marker=env_marker))\n \n     self._parse_context.create_object('python_requirement_library',\n                                       name=name,\ndiff --git a/src/python/pants/backend/python/register.py b/src/python/pants/backend/python/register.py\n--- a/src/python/pants/backend/python/register.py\n+++ b/src/python/pants/backend/python/register.py\n@@ -53,7 +53,7 @@\n     },\n     context_aware_object_factories={\n       'python_requirements': PythonRequirements,\n-      'pants_requirement': PantsRequirement,\n+      PantsRequirement.alias: PantsRequirement,\n     }\n   )\n", "issue": "We should export a `pants_contrib_requirement` in the spirit of `pants_requirement`.\nThis makes plugin authors lives easier. The new macro should also support environment markers as outlined in #6358.\n", "before_files": [{"content": "# coding=utf-8\n# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nfrom pants.backend.python.pants_requirement import PantsRequirement\nfrom pants.backend.python.python_artifact import PythonArtifact\nfrom pants.backend.python.python_requirement import PythonRequirement\nfrom pants.backend.python.python_requirements import PythonRequirements\nfrom pants.backend.python.targets.python_app import PythonApp\nfrom pants.backend.python.targets.python_binary import PythonBinary\nfrom pants.backend.python.targets.python_distribution import PythonDistribution\nfrom pants.backend.python.targets.python_library import PythonLibrary\nfrom pants.backend.python.targets.python_requirement_library import PythonRequirementLibrary\nfrom pants.backend.python.targets.python_tests import PythonTests\nfrom pants.backend.python.tasks.build_local_python_distributions import \\\n  BuildLocalPythonDistributions\nfrom pants.backend.python.tasks.gather_sources import GatherSources\nfrom pants.backend.python.tasks.isort_prep import IsortPrep\nfrom pants.backend.python.tasks.isort_run import IsortRun\nfrom pants.backend.python.tasks.local_python_distribution_artifact import \\\n  LocalPythonDistributionArtifact\nfrom pants.backend.python.tasks.pytest_prep import PytestPrep\nfrom pants.backend.python.tasks.pytest_run import PytestRun\nfrom pants.backend.python.tasks.python_binary_create import PythonBinaryCreate\nfrom pants.backend.python.tasks.python_bundle import PythonBundle\nfrom pants.backend.python.tasks.python_repl import PythonRepl\nfrom pants.backend.python.tasks.python_run import PythonRun\nfrom pants.backend.python.tasks.resolve_requirements import ResolveRequirements\nfrom pants.backend.python.tasks.select_interpreter import SelectInterpreter\nfrom pants.backend.python.tasks.setup_py import SetupPy\nfrom pants.build_graph.build_file_aliases import BuildFileAliases\nfrom pants.build_graph.resources import Resources\nfrom pants.goal.task_registrar import TaskRegistrar as task\n\n\ndef build_file_aliases():\n  return BuildFileAliases(\n    targets={\n      PythonApp.alias(): PythonApp,\n      PythonBinary.alias(): PythonBinary,\n      PythonLibrary.alias(): PythonLibrary,\n      PythonTests.alias(): PythonTests,\n      PythonDistribution.alias(): PythonDistribution,\n      'python_requirement_library': PythonRequirementLibrary,\n      Resources.alias(): Resources,\n    },\n    objects={\n      'python_requirement': PythonRequirement,\n      'python_artifact': PythonArtifact,\n      'setup_py': PythonArtifact,\n    },\n    context_aware_object_factories={\n      'python_requirements': PythonRequirements,\n      'pants_requirement': PantsRequirement,\n    }\n  )\n\n\ndef register_goals():\n  task(name='interpreter', action=SelectInterpreter).install('pyprep')\n  task(name='build-local-dists', action=BuildLocalPythonDistributions).install('pyprep')\n  task(name='requirements', action=ResolveRequirements).install('pyprep')\n  task(name='sources', action=GatherSources).install('pyprep')\n  task(name='py', action=PythonRun).install('run')\n  task(name='pytest-prep', action=PytestPrep).install('test')\n  task(name='pytest', action=PytestRun).install('test')\n  task(name='py', action=PythonRepl).install('repl')\n  task(name='setup-py', action=SetupPy).install()\n  task(name='py', action=PythonBinaryCreate).install('binary')\n  task(name='py-wheels', action=LocalPythonDistributionArtifact).install('binary')\n  task(name='isort-prep', action=IsortPrep).install('fmt')\n  task(name='isort', action=IsortRun).install('fmt')\n  task(name='py', action=PythonBundle).install('bundle')\n", "path": "src/python/pants/backend/python/register.py"}, {"content": "# coding=utf-8\n# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport os\nfrom builtins import object\n\nfrom pants.backend.python.python_requirement import PythonRequirement\nfrom pants.base.build_environment import pants_version\n\n\nclass PantsRequirement(object):\n  \"\"\"Exports a `python_requirement_library` pointing at the active pants' corresponding sdist.\n\n  This requirement is useful for custom plugin authors who want to build and test their plugin with\n  pants itself.  Using the resulting target as a dependency of their plugin target ensures the\n  dependency stays true to the surrounding repo's version of pants.\n\n  NB: The requirement generated is for official pants releases on pypi; so may not be appropriate\n  for use in a repo that tracks `pantsbuild/pants` or otherwise uses custom pants sdists.\n\n  :API: public\n  \"\"\"\n\n  def __init__(self, parse_context):\n    self._parse_context = parse_context\n\n  def __call__(self, name=None):\n    \"\"\"\n    :param string name: The name to use for the target, defaults to the parent dir name.\n    \"\"\"\n    name = name or os.path.basename(self._parse_context.rel_path)\n\n    # TODO(John Sirois): Modify to constraint to >=3.5,<4 as part of\n    # https://github.com/pantsbuild/pants/issues/6062\n    env_marker = \"python_version>='2.7' and python_version<'3'\"\n\n    requirement = PythonRequirement(requirement=\"pantsbuild.pants=={version} ; {env_marker}\"\n                                    .format(version=pants_version(), env_marker=env_marker))\n\n    self._parse_context.create_object('python_requirement_library',\n                                      name=name,\n                                      requirements=[requirement])\n", "path": "src/python/pants/backend/python/pants_requirement.py"}]}