prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  cryptography.x509.Name implements __eq__ but not __hash__
  
  
  </issue>
  <code>
  [start of src/cryptography/x509/name.py]
  1 # This file is dual licensed under the terms of the Apache License, Version
  2 # 2.0, and the BSD License. See the LICENSE file in the root of this repository
  3 # for complete details.
  4 
  5 from __future__ import absolute_import, division, print_function
  6 
  7 import six
  8 
  9 from cryptography import utils
  10 from cryptography.x509.oid import ObjectIdentifier
  11 
  12 
  13 class NameAttribute(object):
  14     def __init__(self, oid, value):
  15         if not isinstance(oid, ObjectIdentifier):
  16             raise TypeError(
  17                 "oid argument must be an ObjectIdentifier instance."
  18             )
  19 
  20         if not isinstance(value, six.text_type):
  21             raise TypeError(
  22                 "value argument must be a text type."
  23             )
  24 
  25         self._oid = oid
  26         self._value = value
  27 
  28     oid = utils.read_only_property("_oid")
  29     value = utils.read_only_property("_value")
  30 
  31     def __eq__(self, other):
  32         if not isinstance(other, NameAttribute):
  33             return NotImplemented
  34 
  35         return (
  36             self.oid == other.oid and
  37             self.value == other.value
  38         )
  39 
  40     def __ne__(self, other):
  41         return not self == other
  42 
  43     def __repr__(self):
  44         return "<NameAttribute(oid={0.oid}, value={0.value!r})>".format(self)
  45 
  46 
  47 class Name(object):
  48     def __init__(self, attributes):
  49         self._attributes = attributes
  50 
  51     def get_attributes_for_oid(self, oid):
  52         return [i for i in self if i.oid == oid]
  53 
  54     def __eq__(self, other):
  55         if not isinstance(other, Name):
  56             return NotImplemented
  57 
  58         return self._attributes == other._attributes
  59 
  60     def __ne__(self, other):
  61         return not self == other
  62 
  63     def __iter__(self):
  64         return iter(self._attributes)
  65 
  66     def __len__(self):
  67         return len(self._attributes)
  68 
  69     def __repr__(self):
  70         return "<Name({0!r})>".format(self._attributes)
  71
  [end of src/cryptography/x509/name.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/cryptography/x509/name.py b/src/cryptography/x509/name.py
  --- a/src/cryptography/x509/name.py
  +++ b/src/cryptography/x509/name.py
  @@ -40,6 +40,9 @@
       def __ne__(self, other):
           return not self == other
   
  +    def __hash__(self):
  +        return hash((self.oid, self.value))
  +
       def __repr__(self):
           return "<NameAttribute(oid={0.oid}, value={0.value!r})>".format(self)
   
  @@ -60,6 +63,11 @@
       def __ne__(self, other):
           return not self == other
   
  +    def __hash__(self):
  +        # TODO: this is relatively expensive, if this looks like a bottleneck
  +        # for you, consider optimizing!
  +        return hash(tuple(self._attributes))
  +
       def __iter__(self):
           return iter(self._attributes)
  
verification_info: {"golden_diff": "diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py\n--- a/src/cryptography/x509/name.py\n+++ b/src/cryptography/x509/name.py\n@@ -40,6 +40,9 @@\n     def __ne__(self, other):\n         return not self == other\n \n+    def __hash__(self):\n+        return hash((self.oid, self.value))\n+\n     def __repr__(self):\n         return \"<NameAttribute(oid={0.oid}, value={0.value!r})>\".format(self)\n \n@@ -60,6 +63,11 @@\n     def __ne__(self, other):\n         return not self == other\n \n+    def __hash__(self):\n+        # TODO: this is relatively expensive, if this looks like a bottleneck\n+        # for you, consider optimizing!\n+        return hash(tuple(self._attributes))\n+\n     def __iter__(self):\n         return iter(self._attributes)\n", "issue": "cryptography.x509.Name implements __eq__ but not __hash__\n\n", "before_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nimport six\n\nfrom cryptography import utils\nfrom cryptography.x509.oid import ObjectIdentifier\n\n\nclass NameAttribute(object):\n    def __init__(self, oid, value):\n        if not isinstance(oid, ObjectIdentifier):\n            raise TypeError(\n                \"oid argument must be an ObjectIdentifier instance.\"\n            )\n\n        if not isinstance(value, six.text_type):\n            raise TypeError(\n                \"value argument must be a text type.\"\n            )\n\n        self._oid = oid\n        self._value = value\n\n    oid = utils.read_only_property(\"_oid\")\n    value = utils.read_only_property(\"_value\")\n\n    def __eq__(self, other):\n        if not isinstance(other, NameAttribute):\n            return NotImplemented\n\n        return (\n            self.oid == other.oid and\n            self.value == other.value\n        )\n\n    def __ne__(self, other):\n        return not self == other\n\n    def __repr__(self):\n        return \"<NameAttribute(oid={0.oid}, value={0.value!r})>\".format(self)\n\n\nclass Name(object):\n    def __init__(self, attributes):\n        self._attributes = attributes\n\n    def get_attributes_for_oid(self, oid):\n        return [i for i in self if i.oid == oid]\n\n    def __eq__(self, other):\n        if not isinstance(other, Name):\n            return NotImplemented\n\n        return self._attributes == other._attributes\n\n    def __ne__(self, other):\n        return not self == other\n\n    def __iter__(self):\n        return iter(self._attributes)\n\n    def __len__(self):\n        return len(self._attributes)\n\n    def __repr__(self):\n        return \"<Name({0!r})>\".format(self._attributes)\n", "path": "src/cryptography/x509/name.py"}]}