# Buggy code
def datatype(field_decls, superclass_name=None, **kwargs):
    """A wrapper for `namedtuple` that accounts for the type of the object in equality.

    Field declarations can be a string, which declares a field with that name and
    no type checking. Field declarations can also be a tuple `('field_name',
    field_type)`, which declares a field named `field_name` which is type-checked
    at construction. If a type is given, the value provided to the constructor for
    that field must be exactly that type (i.e. `type(x) == field_type`), and not
    e.g. a subclass.

    :param field_decls: Iterable of field declarations.
    :return: A type object which can then be subclassed.
    :raises: :class:`TypeError`
    """
    field_names = []
    fields_with_constraints = OrderedDict()
    for maybe_decl in field_decls:
        # ('field_name', type)
        if isinstance(maybe_decl, tuple):
            field_name, type_spec = maybe_decl
            if isinstance(type_spec, type):
                type_constraint = Exactly(type_spec)
            elif isinstance(type_spec, TypeConstraint):
                type_constraint = type_spec
            else:
                raise TypeError(
                    "type spec for field '{}' was not a type or TypeConstraint: was {!r} (type {!r}).".format(
                        field_name, type_spec, type(type_spec).__name__
                    )
                )
            fields_with_constraints[field_name] = type_constraint
        else:
            # interpret it as a field name without a type to check
            field_name = maybe_decl
        # namedtuple() already checks field uniqueness
        field_names.append(field_name)

    if not superclass_name:
        superclass_name = "_anonymous_namedtuple_subclass"

    namedtuple_cls = namedtuple(superclass_name, field_names, **kwargs)

    class DataType(namedtuple_cls):
        @classproperty
        def type_check_error_type(cls):
            """The exception type to use in make_type_error()."""
            return TypedDatatypeInstanceConstructionError

        @classmethod
        def make_type_error(cls, msg, *args, **kwargs):
            """A helper method to generate an exception type for type checking errors.

            This method uses `cls.type_check_error_type` to ensure that type checking errors can be caught
            with a reliable exception type. The type returned by `cls.type_check_error_type` should ensure
            that the exception messages are prefixed with enough context to be useful and *not* confusing.
            """
            return cls.type_check_error_type(cls.__name__, msg, *args, **kwargs)

        def __new__(cls, *args, **kwargs):
            # TODO: Ideally we could execute this exactly once per `cls` but it should be a
            # relatively cheap check.
            if not hasattr(cls.__eq__, "_eq_override_canary"):
                raise cls.make_type_error("Should not override __eq__.")

            try:
                this_object = super(DataType, cls).__new__(cls, *args, **kwargs)
            except TypeError as e:
                raise cls.make_type_error(
                    "error in namedtuple() base constructor: {}".format(e)
                )

            # TODO: Make this kind of exception pattern (filter for errors then display them all at once)
            # more ergonomic.
            type_failure_msgs = []
            for field_name, field_constraint in fields_with_constraints.items():
                field_value = getattr(this_object, field_name)
                try:
                    field_constraint.validate_satisfied_by(field_value)
                except TypeConstraintError as e:
                    type_failure_msgs.append(
                        "field '{}' was invalid: {}".format(field_name, e)
                    )
            if type_failure_msgs:
                raise cls.make_type_error(
                    "errors type checking constructor arguments:\n{}".format(
                        "\n".join(type_failure_msgs)
                    )
                )

            return this_object

        def __eq__(self, other):
            if self is other:
                return True

            # Compare types and fields.
            if type(self) != type(other):
                return False
            # Explicitly return super.__eq__'s value in case super returns NotImplemented
            return super(DataType, self).__eq__(other)

        # We define an attribute on the `cls` level definition of `__eq__` that will allow us to detect
        # that it has been overridden.
        __eq__._eq_override_canary = None

        def __ne__(self, other):
            return not (self == other)

        def __hash__(self):
            return super(DataType, self).__hash__()

        # NB: As datatype is not iterable, we need to override both __iter__ and all of the
        # namedtuple methods that expect self to be iterable.
        def __iter__(self):
            raise TypeError("'{}' object is not iterable".format(type(self).__name__))

        def _super_iter(self):
            return super(DataType, self).__iter__()

        def _asdict(self):
            """Return a new OrderedDict which maps field names to their values"""
            return OrderedDict(zip(self._fields, self._super_iter()))

        def _replace(_self, **kwds):
            """Return a new datatype object replacing specified fields with new values"""
            field_dict = _self._asdict()
            field_dict.update(**kwds)
            return type(_self)(**field_dict)

        copy = _replace

        # NB: it is *not* recommended to rely on the ordering of the tuple returned by this method.
        def __getnewargs__(self):
            """Return self as a plain tuple.  Used by copy and pickle."""
            return tuple(self._super_iter())

        def __repr__(self):
            args_formatted = []
            for field_name in field_names:
                field_value = getattr(self, field_name)
                args_formatted.append("{}={!r}".format(field_name, field_value))
            return "{class_name}({args_joined})".format(
                class_name=type(self).__name__, args_joined=", ".join(args_formatted)
            )

        def __str__(self):
            elements_formatted = []
            for field_name in field_names:
                constraint_for_field = fields_with_constraints.get(field_name, None)
                field_value = getattr(self, field_name)
                if not constraint_for_field:
                    elements_formatted.append(
                        # TODO: consider using the repr of arguments in this method.
                        "{field_name}={field_value}".format(
                            field_name=field_name, field_value=field_value
                        )
                    )
                else:
                    elements_formatted.append(
                        "{field_name}<{type_constraint}>={field_value}".format(
                            field_name=field_name,
                            type_constraint=constraint_for_field,
                            field_value=field_value,
                        )
                    )
            return "{class_name}({typed_tagged_elements})".format(
                class_name=type(self).__name__,
                typed_tagged_elements=", ".join(elements_formatted),
            )

    # Return a new type with the given name, inheriting from the DataType class
    # just defined, with an empty class body.
    try:  # Python3
        return type(superclass_name, (DataType,), {})
    except TypeError:  # Python2
        return type(superclass_name.encode("utf-8"), (DataType,), {})


# Traceback (AssertionError)
==================== FAILURES ====================
 CTypesIntegrationTest.test_ctypes_third_party_integration 

args = (<pants_test.backend.python.tasks.native.test_ctypes_integration.CTypesIntegrationTest testMethod=test_ctypes_third_party_integration>,)
kwargs = {}
variant = ToolchainVariant(value=u'gnu')

    @wraps(func)
    def wrapper(*args, **kwargs):
      for variant in ToolchainVariant.iterate_enum_variants():
>       func(*args, toolchain_variant=variant, **kwargs)

.pants.d/pyprep/sources/68db53b799a649f3f92cbd3d3e740d9a1a47be07/pants_test/backend/python/tasks/native/test_ctypes_integration.py:32: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.pants.d/pyprep/sources/68db53b799a649f3f92cbd3d3e740d9a1a47be07/pants_test/backend/python/tasks/native/test_ctypes_integration.py:195: in test_ctypes_third_party_integration
    self.assert_success(pants_run)
.pants.d/pyprep/sources/68db53b799a649f3f92cbd3d3e740d9a1a47be07/pants_test/pants_run_integration_test.py:452: in assert_success
    self.assert_result(pants_run, self.PANTS_SUCCESS_CODE, expected=True, msg=msg)
.pants.d/pyprep/sources/68db53b799a649f3f92cbd3d3e740d9a1a47be07/pants_test/pants_run_integration_test.py:473: in assert_result
    assertion(value, pants_run.returncode, error_msg)
E   AssertionError: /Users/travis/build/pantsbuild/pants/pants --no-pantsrc --pants-workdir=/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d --kill-nailguns --print-exception-stacktrace=True --pants-config-files=/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/pants.ini -q run testprojects/src/python/python_distribution/ctypes_with_third_party:bin_with_third_party
E   returncode: 1
E   stdout:
E   	
E   	FAILURE: /usr/bin/python /Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/run/py/CPython-2.7.10/a8a8db2fdd4fae99b02f6010a93d6f6dc4f9f3dc ... exited non-zero (1)
E   	
E   stderr:
E   	Traceback (most recent call last):
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/run/py/CPython-2.7.10/a8a8db2fdd4fae99b02f6010a93d6f6dc4f9f3dc/.bootstrap/_pex/pex.py", line 349, in execute
E   	    exit_code = self._wrap_coverage(self._wrap_profiling, self._execute)
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/run/py/CPython-2.7.10/a8a8db2fdd4fae99b02f6010a93d6f6dc4f9f3dc/.bootstrap/_pex/pex.py", line 281, in _wrap_coverage
E   	    return runner(*args)
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/run/py/CPython-2.7.10/a8a8db2fdd4fae99b02f6010a93d6f6dc4f9f3dc/.bootstrap/_pex/pex.py", line 312, in _wrap_profiling
E   	    return runner(*args)
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/run/py/CPython-2.7.10/a8a8db2fdd4fae99b02f6010a93d6f6dc4f9f3dc/.bootstrap/_pex/pex.py", line 394, in _execute
E   	    return self.execute_entry(self._pex_info.entry_point)
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/run/py/CPython-2.7.10/a8a8db2fdd4fae99b02f6010a93d6f6dc4f9f3dc/.bootstrap/_pex/pex.py", line 506, in execute_entry
E   	    return runner(entry_point)
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/run/py/CPython-2.7.10/a8a8db2fdd4fae99b02f6010a93d6f6dc4f9f3dc/.bootstrap/_pex/pex.py", line 513, in execute_module
E   	    runpy.run_module(module_name, run_name='__main__')
E   	  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 180, in run_module
E   	    fname, loader, pkg_name)
E   	  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
E   	    exec code in run_globals
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/pyprep/sources/46bc27ffbe03ecfe648c4d677289275aa6a6a93c-DefaultFingerprintStrategy_1b8903baa709/python_distribution/ctypes_with_third_party/main.py", line 7, in <module>
E   	    from ctypes_python_pkg.ctypes_wrapper import f
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/pyprep/requirements/CPython-2.7.10/dbfa0d2bb6877c576abca571691b6e7c8432a15a-DefaultFingerprintStrategy_25eb7243d755/.deps/ctypes_third_party_test-0.0.1+20865c6b4968b7f61c37fdc3ed80306ee2ca4a3e.defaultfingerprintstrategy.174c3658bd6c.8f03fa43ba4e-py2-none-macosx_10_13_x86_64.whl/ctypes_python_pkg/ctypes_wrapper.py", line 20, in <module>
E   	    asdf_cpp_lib = ctypes.CDLL(asdf_cpp_lib_path)
E   	  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 365, in __init__
E   	    self._handle = _dlopen(self._name, mode)
E   	OSError: dlopen(/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/pyprep/requirements/CPython-2.7.10/dbfa0d2bb6877c576abca571691b6e7c8432a15a-DefaultFingerprintStrategy_25eb7243d755/.deps/ctypes_third_party_test-0.0.1+20865c6b4968b7f61c37fdc3ed80306ee2ca4a3e.defaultfingerprintstrategy.174c3658bd6c.8f03fa43ba4e-py2-none-macosx_10_13_x86_64.whl/libasdf-cpp_ctypes-with-third-party.so, 6): Library not loaded: /Users/stuhood/src/pantsbuild-binaries/build-support/bin/gcc/mac/10.13/7.3.0/gcc-7.3.0-osx/gcc-install/lib/libstdc++.6.dylib
E   	  Referenced from: /Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp1ZloAV.pants.d/pyprep/requirements/CPython-2.7.10/dbfa0d2bb6877c576abca571691b6e7c8432a15a-DefaultFingerprintStrategy_25eb7243d755/.deps/ctypes_third_party_test-0.0.1+20865c6b4968b7f61c37fdc3ed80306ee2ca4a3e.defaultfingerprintstrategy.174c3658bd6c.8f03fa43ba4e-py2-none-macosx_10_13_x86_64.whl/libasdf-cpp_ctypes-with-third-party.so
E   	  Reason: image not found
E   	
E   	FAILURE
-------------- Captured stdout call --------------
logs/exceptions.4006.log +++ 
logs/exceptions.4006.log --- 
logs/exceptions.log +++ 
logs/exceptions.log --- 
 CTypesIntegrationTest.test_native_compiler_option_sets_integration 

args = (<pants_test.backend.python.tasks.native.test_ctypes_integration.CTypesIntegrationTest testMethod=test_native_compiler_option_sets_integration>,)
kwargs = {}
variant = ToolchainVariant(value=u'gnu')

    @wraps(func)
    def wrapper(*args, **kwargs):
      for variant in ToolchainVariant.iterate_enum_variants():
>       func(*args, toolchain_variant=variant, **kwargs)

.pants.d/pyprep/sources/68db53b799a649f3f92cbd3d3e740d9a1a47be07/pants_test/backend/python/tasks/native/test_ctypes_integration.py:32: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.pants.d/pyprep/sources/68db53b799a649f3f92cbd3d3e740d9a1a47be07/pants_test/backend/python/tasks/native/test_ctypes_integration.py:246: in test_native_compiler_option_sets_integration
    self.assert_success(pants_run)
.pants.d/pyprep/sources/68db53b799a649f3f92cbd3d3e740d9a1a47be07/pants_test/pants_run_integration_test.py:452: in assert_success
    self.assert_result(pants_run, self.PANTS_SUCCESS_CODE, expected=True, msg=msg)
.pants.d/pyprep/sources/68db53b799a649f3f92cbd3d3e740d9a1a47be07/pants_test/pants_run_integration_test.py:473: in assert_result
    assertion(value, pants_run.returncode, error_msg)
E   AssertionError: /Users/travis/build/pantsbuild/pants/pants --no-pantsrc --pants-workdir=/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d --kill-nailguns --print-exception-stacktrace=True --pants-config-files=/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/pants.ini run testprojects/src/python/python_distribution/ctypes_with_extra_compiler_flags:bin
E   returncode: 1
E   stdout:
E   	
E   	16:40:21 00:00 [main]
E   	               (To run a reporting server: ./pants server)
E   	16:40:22 00:01   [setup]
E   	16:40:22 00:01     [parse]
E   	               Executing tasks in goals: bootstrap -> imports -> unpack-jars -> unpack-wheels -> deferred-sources -> native-compile -> link -> jvm-platform-validate -> gen -> pyprep -> resolve -> resources -> compile -> binary -> run
E   	16:40:23 00:02   [bootstrap]
E   	16:40:23 00:02     [substitute-aliased-targets]
E   	16:40:23 00:02     [jar-dependency-management]
E   	16:40:23 00:02     [bootstrap-jvm-tools]
E   	16:40:23 00:02     [provide-tools-jar]
E   	16:40:24 00:03   [imports]
E   	16:40:24 00:03     [ivy-imports]
E   	16:40:24 00:03   [unpack-jars]
E   	16:40:24 00:03     [unpack-jars]
E   	16:40:24 00:03   [unpack-wheels]
E   	16:40:24 00:03     [unpack-wheels]
E   	16:40:24 00:03   [deferred-sources]
E   	16:40:24 00:03     [deferred-sources]
E   	16:40:24 00:03   [native-compile]
E   	16:40:24 00:03     [conan-prep]
E   	16:40:24 00:03       [create-conan-pex]
E   	16:40:32 00:11     [conan-fetch]
E   	16:40:32 00:11     [c-for-ctypes]
E   	16:40:32 00:11     [cpp-for-ctypes]
E   	                   Invalidated 1 target.
E   	                   selected compiler exe name: 'g++'
E   	16:40:32 00:11       [cpp-compile]
E   	                     
E   	16:40:33 00:12   [link]
E   	16:40:33 00:12     [shared-libraries]
E   	                   Invalidated 1 target.
E   	                   selected linker exe name: 'g++'
E   	16:40:33 00:12       [link-shared-libraries]
E   	16:40:33 00:12   [jvm-platform-validate]
E   	16:40:33 00:12     [jvm-platform-validate]
E   	16:40:33 00:12   [gen]
E   	16:40:33 00:12     [antlr-java]
E   	16:40:33 00:12     [antlr-py]
E   	16:40:33 00:12     [jaxb]
E   	16:40:33 00:12     [protoc]
E   	16:40:33 00:12     [ragel]
E   	16:40:33 00:12     [thrift-java]
E   	16:40:33 00:12     [thrift-py]
E   	16:40:33 00:12     [grpcio-prep]
E   	16:40:33 00:12     [grpcio-run]
E   	16:40:33 00:12     [wire]
E   	16:40:33 00:12     [avro-java]
E   	16:40:33 00:12     [go-thrift]
E   	16:40:33 00:12     [go-protobuf]
E   	16:40:33 00:12     [jax-ws]
E   	16:40:33 00:12     [scrooge]
E   	16:40:33 00:12     [thrifty]
E   	16:40:33 00:12   [pyprep]
E   	16:40:33 00:12     [interpreter]
E   	16:40:33 00:12     [build-local-dists]
E   	                   Invalidated 1 target.
E   	16:40:35 00:14       [setup.py]
E   	16:40:35 00:14     [requirements]
E   	                   Invalidated 1 target.
E   	16:40:36 00:15     [sources]
E   	                   Invalidated 1 target.
E   	16:40:36 00:15   [resolve]
E   	16:40:36 00:15     [ivy]
E   	16:40:36 00:15     [coursier]
E   	16:40:36 00:15     [go]
E   	16:40:36 00:15     [scala-js-compile]
E   	16:40:36 00:15     [scala-js-link]
E   	16:40:37 00:16     [node]
E   	16:40:37 00:16   [resources]
E   	16:40:37 00:16     [prepare]
E   	16:40:37 00:16     [services]
E   	16:40:37 00:16   [compile]
E   	16:40:37 00:16     [node]
E   	16:40:37 00:16     [compile-jvm-prep-command]
E   	16:40:37 00:16       [jvm_prep_command]
E   	16:40:37 00:16     [compile-prep-command]
E   	16:40:37 00:16     [compile]
E   	16:40:37 00:16     [rsc]
E   	16:40:37 00:16     [zinc]
E   	16:40:37 00:16     [javac]
E   	16:40:37 00:16     [cpp]
E   	16:40:37 00:16     [errorprone]
E   	16:40:37 00:16     [findbugs]
E   	16:40:37 00:16     [go]
E   	16:40:37 00:16   [binary]
E   	16:40:37 00:16     [binary-jvm-prep-command]
E   	16:40:37 00:16       [jvm_prep_command]
E   	16:40:37 00:16     [binary-prep-command]
E   	16:40:37 00:16     [py]
E   	                   Invalidated 1 target.
E   	                   created pex dist/bin.pex
E   	16:40:38 00:17     [py-wheels]
E   	                   created wheel dist/ctypes_test-0.0.1+74173b5ce60ddd85088b1fed70c8b071f2679604.defaultfingerprintstrategy.12652e89be0f.8f03fa43ba4e-py2-none-macosx_10_13_x86_64.whl
E   	16:40:38 00:17     [jvm]
E   	16:40:38 00:17     [dup]
E   	16:40:38 00:17     [cpplib]
E   	16:40:38 00:17       [cpp-library]
E   	16:40:38 00:17     [cpp]
E   	16:40:38 00:17       [cpp-binary]
E   	16:40:38 00:17     [go]
E   	16:40:38 00:17   [run]
E   	16:40:38 00:17     [py]
E   	                   Invalidated 3 targets.
E   	16:40:39 00:18       [run]
E   	
E   	FAILURE: /usr/bin/python /Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/run/py/CPython-2.7.10/3784d4150334a9a89ddceb31bdb13969e94f73b2 ... exited non-zero (1)
E   	
E   	
E   	               Waiting for background workers to finish.
E   	16:40:39 00:18   [complete]
E   	               FAILURE
E   stderr:
E   	Traceback (most recent call last):
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/run/py/CPython-2.7.10/3784d4150334a9a89ddceb31bdb13969e94f73b2/.bootstrap/_pex/pex.py", line 349, in execute
E   	    exit_code = self._wrap_coverage(self._wrap_profiling, self._execute)
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/run/py/CPython-2.7.10/3784d4150334a9a89ddceb31bdb13969e94f73b2/.bootstrap/_pex/pex.py", line 281, in _wrap_coverage
E   	    return runner(*args)
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/run/py/CPython-2.7.10/3784d4150334a9a89ddceb31bdb13969e94f73b2/.bootstrap/_pex/pex.py", line 312, in _wrap_profiling
E   	    return runner(*args)
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/run/py/CPython-2.7.10/3784d4150334a9a89ddceb31bdb13969e94f73b2/.bootstrap/_pex/pex.py", line 394, in _execute
E   	    return self.execute_entry(self._pex_info.entry_point)
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/run/py/CPython-2.7.10/3784d4150334a9a89ddceb31bdb13969e94f73b2/.bootstrap/_pex/pex.py", line 506, in execute_entry
E   	    return runner(entry_point)
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/run/py/CPython-2.7.10/3784d4150334a9a89ddceb31bdb13969e94f73b2/.bootstrap/_pex/pex.py", line 513, in execute_module
E   	    runpy.run_module(module_name, run_name='__main__')
E   	  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 180, in run_module
E   	    fname, loader, pkg_name)
E   	  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
E   	    exec code in run_globals
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/pyprep/sources/be29db057705cafb8edc0e69942013e74ccffbe3-DefaultFingerprintStrategy_1b8903baa709/python_distribution/ctypes_with_extra_compiler_flags/main.py", line 7, in <module>
E   	    from ctypes_python_pkg.ctypes_wrapper import f
E   	  File "/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/pyprep/requirements/CPython-2.7.10/2122a483545750a790ffdd2c65a8039affd3f167-DefaultFingerprintStrategy_25eb7243d755/.deps/ctypes_test-0.0.1+74173b5ce60ddd85088b1fed70c8b071f2679604.defaultfingerprintstrategy.12652e89be0f.8f03fa43ba4e-py2-none-macosx_10_13_x86_64.whl/ctypes_python_pkg/ctypes_wrapper.py", line 20, in <module>
E   	    asdf_cpp_lib = ctypes.CDLL(asdf_cpp_lib_path)
E   	  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 365, in __init__
E   	    self._handle = _dlopen(self._name, mode)
E   	OSError: dlopen(/Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/pyprep/requirements/CPython-2.7.10/2122a483545750a790ffdd2c65a8039affd3f167-DefaultFingerprintStrategy_25eb7243d755/.deps/ctypes_test-0.0.1+74173b5ce60ddd85088b1fed70c8b071f2679604.defaultfingerprintstrategy.12652e89be0f.8f03fa43ba4e-py2-none-macosx_10_13_x86_64.whl/libasdf-cpp_ctypes-with-extra-compiler-flags.so, 6): Library not loaded: /Users/stuhood/src/pantsbuild-binaries/build-support/bin/gcc/mac/10.13/7.3.0/gcc-7.3.0-osx/gcc-install/lib/libstdc++.6.dylib
E   	  Referenced from: /Users/travis/build/pantsbuild/pants/.pants.d/tmp/tmp8qW7hO.pants.d/pyprep/requirements/CPython-2.7.10/2122a483545750a790ffdd2c65a8039affd3f167-DefaultFingerprintStrategy_25eb7243d755/.deps/ctypes_test-0.0.1+74173b5ce60ddd85088b1fed70c8b071f2679604.defaultfingerprintstrategy.12652e89be0f.8f03fa43ba4e-py2-none-macosx_10_13_x86_64.whl/libasdf-cpp_ctypes-with-extra-compiler-flags.so
E   	  Reason: image not found
-------------- Captured stdout call --------------
logs/exceptions.4063.log +++ 
logs/exceptions.4063.log --- 
logs/exceptions.log +++ 
logs/exceptions.log --- 
====== 2 failed, 3 passed in 199.95 seconds ======

# Fixed code
def datatype(field_decls, superclass_name=None, **kwargs):
    """A wrapper for `namedtuple` that accounts for the type of the object in equality.

    Field declarations can be a string, which declares a field with that name and
    no type checking. Field declarations can also be a tuple `('field_name',
    field_type)`, which declares a field named `field_name` which is type-checked
    at construction. If a type is given, the value provided to the constructor for
    that field must be exactly that type (i.e. `type(x) == field_type`), and not
    e.g. a subclass.

    :param field_decls: Iterable of field declarations.
    :return: A type object which can then be subclassed.
    :raises: :class:`TypeError`
    """
    field_names = []
    fields_with_constraints = OrderedDict()
    for maybe_decl in field_decls:
        # ('field_name', type)
        if isinstance(maybe_decl, tuple):
            field_name, type_spec = maybe_decl
            if isinstance(type_spec, type):
                type_constraint = Exactly(type_spec)
            elif isinstance(type_spec, TypeConstraint):
                type_constraint = type_spec
            else:
                raise TypeError(
                    "type spec for field '{}' was not a type or TypeConstraint: was {!r} (type {!r}).".format(
                        field_name, type_spec, type(type_spec).__name__
                    )
                )
            fields_with_constraints[field_name] = type_constraint
        else:
            # interpret it as a field name without a type to check
            field_name = maybe_decl
        # namedtuple() already checks field uniqueness
        field_names.append(field_name)

    if not superclass_name:
        superclass_name = "_anonymous_namedtuple_subclass"

    namedtuple_cls = namedtuple(superclass_name, field_names, **kwargs)

    class DataType(namedtuple_cls):
        @classproperty
        def type_check_error_type(cls):
            """The exception type to use in make_type_error()."""
            return TypedDatatypeInstanceConstructionError

        @classmethod
        def make_type_error(cls, msg, *args, **kwargs):
            """A helper method to generate an exception type for type checking errors.

            This method uses `cls.type_check_error_type` to ensure that type checking errors can be caught
            with a reliable exception type. The type returned by `cls.type_check_error_type` should ensure
            that the exception messages are prefixed with enough context to be useful and *not* confusing.
            """
            return cls.type_check_error_type(cls.__name__, msg, *args, **kwargs)

        def __new__(cls, *args, **kwargs):
            # TODO: Ideally we could execute this exactly once per `cls` but it should be a
            # relatively cheap check.
            if not hasattr(cls.__eq__, "_eq_override_canary"):
                raise cls.make_type_error("Should not override __eq__.")

            try:
                this_object = super(DataType, cls).__new__(cls, *args, **kwargs)
            except TypeError as e:
                raise cls.make_type_error(
                    "error in namedtuple() base constructor: {}".format(e)
                )

            # TODO: Make this kind of exception pattern (filter for errors then display them all at once)
            # more ergonomic.
            type_failure_msgs = []
            for field_name, field_constraint in fields_with_constraints.items():
                field_value = getattr(this_object, field_name)
                try:
                    field_constraint.validate_satisfied_by(field_value)
                except TypeConstraintError as e:
                    type_failure_msgs.append(
                        "field '{}' was invalid: {}".format(field_name, e)
                    )
            if type_failure_msgs:
                raise cls.make_type_error(
                    "errors type checking constructor arguments:\n{}".format(
                        "\n".join(type_failure_msgs)
                    )
                )

            return this_object

        def __eq__(self, other):
            if self is other:
                return True

            # Compare types and fields.
            if type(self) != type(other):
                return False
            # Explicitly return super.__eq__'s value in case super returns NotImplemented
            return super(DataType, self).__eq__(other)

        # We define an attribute on the `cls` level definition of `__eq__` that will allow us to detect
        # that it has been overridden.
        __eq__._eq_override_canary = None

        def __ne__(self, other):
            return not (self == other)

        # NB: in Python 3, whenever __eq__ is overridden, __hash__() must also be
        # explicitly implemented, otherwise Python will raise "unhashable type". See
        # https://docs.python.org/3/reference/datamodel.html#object.__hash__.
        def __hash__(self):
            return super(DataType, self).__hash__()

        # NB: As datatype is not iterable, we need to override both __iter__ and all of the
        # namedtuple methods that expect self to be iterable.
        def __iter__(self):
            raise self.make_type_error("datatype object is not iterable")

        def _super_iter(self):
            return super(DataType, self).__iter__()

        def _asdict(self):
            """Return a new OrderedDict which maps field names to their values"""
            return OrderedDict(zip(self._fields, self._super_iter()))

        def _replace(_self, **kwds):
            """Return a new datatype object replacing specified fields with new values"""
            field_dict = _self._asdict()
            field_dict.update(**kwds)
            return type(_self)(**field_dict)

        copy = _replace

        # NB: it is *not* recommended to rely on the ordering of the tuple returned by this method.
        def __getnewargs__(self):
            """Return self as a plain tuple.  Used by copy and pickle."""
            return tuple(self._super_iter())

        def __repr__(self):
            args_formatted = []
            for field_name in field_names:
                field_value = getattr(self, field_name)
                args_formatted.append("{}={!r}".format(field_name, field_value))
            return "{class_name}({args_joined})".format(
                class_name=type(self).__name__, args_joined=", ".join(args_formatted)
            )

        def __str__(self):
            elements_formatted = []
            for field_name in field_names:
                constraint_for_field = fields_with_constraints.get(field_name, None)
                field_value = getattr(self, field_name)
                if not constraint_for_field:
                    elements_formatted.append(
                        # TODO: consider using the repr of arguments in this method.
                        "{field_name}={field_value}".format(
                            field_name=field_name, field_value=field_value
                        )
                    )
                else:
                    elements_formatted.append(
                        "{field_name}<{type_constraint}>={field_value}".format(
                            field_name=field_name,
                            type_constraint=constraint_for_field,
                            field_value=field_value,
                        )
                    )
            return "{class_name}({typed_tagged_elements})".format(
                class_name=type(self).__name__,
                typed_tagged_elements=", ".join(elements_formatted),
            )

    # Return a new type with the given name, inheriting from the DataType class
    # just defined, with an empty class body.
    try:  # Python3
        return type(superclass_name, (DataType,), {})
    except TypeError:  # Python2
        return type(superclass_name.encode("utf-8"), (DataType,), {})