diff --git a/.travis.yml b/.travis.yml
index b23556f8cc9c71bce651c8df9f72d937fa8ac617..cccc0858164fe9902d7ee1e31ccd1a6aabc284e4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -117,11 +117,12 @@ matrix:
           os: osx
 
         # PyPy
-        # These are known to be broken.
         - python: "pypy"
+          dist: xenial
           env: LIBRARY=ffmpeg-4.0
           os: linux
         - python: "pypy3"
+          dist: xenial
           env: LIBRARY=ffmpeg-4.0
           os: linux
 
@@ -144,14 +145,11 @@ matrix:
 
     allow_failures:
 
-        - python: "pypy"
-          env: LIBRARY=ffmpeg-4.0
-          os: linux
         - python: "pypy3"
+          dist: xenial
           env: LIBRARY=ffmpeg-4.0
           os: linux
 
-
 before_install:
     - scripts/build-deps
 
diff --git a/av/codec/context.pyx b/av/codec/context.pyx
index ad812049f0a68cbaf01c214dd60cefe8c21468cb..f5c9066d406a388795d5d3ce8711add32b4f8be2 100644
--- a/av/codec/context.pyx
+++ b/av/codec/context.pyx
@@ -9,7 +9,7 @@ from av.bytesource cimport ByteSource, bytesource
 from av.codec.codec cimport Codec, wrap_codec
 from av.dictionary cimport _Dictionary
 from av.dictionary import Dictionary
-from av.enums cimport EnumType, define_enum
+from av.enums cimport define_enum
 from av.packet cimport Packet
 from av.utils cimport err_check, avdict_to_dict, avrational_to_fraction, to_avrational
 
@@ -41,15 +41,14 @@ cdef CodecContext wrap_codec_context(lib.AVCodecContext *c_ctx, const lib.AVCode
     return py_ctx
 
 
-cdef EnumType _ThreadType = define_enum('ThreadType', (
+ThreadType = define_enum('ThreadType', (
     ('NONE', 0),
     ('FRAME', lib.FF_THREAD_FRAME),
     ('SLICE', lib.FF_THREAD_SLICE),
     ('AUTO', lib.FF_THREAD_SLICE | lib.FF_THREAD_FRAME),
 ), is_flags=True)
-ThreadType = _ThreadType
 
-cdef EnumType _SkipType = define_enum('SkipType', (
+SkipType = define_enum('SkipType', (
     ('NONE', lib.AVDISCARD_NONE),
     ('DEFAULT', lib.AVDISCARD_DEFAULT),
     ('NONREF', lib.AVDISCARD_NONREF),
@@ -58,7 +57,6 @@ cdef EnumType _SkipType = define_enum('SkipType', (
     ('NONKEY', lib.AVDISCARD_NONKEY),
     ('ALL', lib.AVDISCARD_ALL),
 ))
-SkipType = _SkipType
 
 cdef class CodecContext(object):
 
@@ -426,17 +424,17 @@ cdef class CodecContext(object):
     property thread_type:
         """One of :class:`.ThreadType`."""
         def __get__(self):
-            return _ThreadType.get(self.ptr.thread_type, create=True)
+            return ThreadType.get(self.ptr.thread_type, create=True)
 
         def __set__(self, value):
             if lib.avcodec_is_open(self.ptr):
                 raise RuntimeError("Cannot change thread_type after codec is open.")
-            self.ptr.thread_type = _ThreadType[value].value
+            self.ptr.thread_type = ThreadType[value].value
 
     property skip_frame:
         """One of :class:`.SkipType`."""
         def __get__(self):
-            return _SkipType._get(self.ptr.skip_frame, create=True)
+            return SkipType._get(self.ptr.skip_frame, create=True)
 
         def __set__(self, value):
-            self.ptr.skip_frame = _SkipType[value].value
+            self.ptr.skip_frame = SkipType[value].value
diff --git a/av/enums.pxd b/av/enums.pxd
index d03fd37f693834332f92b5926fc371a2ca47cd0d..77e1ca75d791166dfd0ca414453e36cc675229d9 100644
--- a/av/enums.pxd
+++ b/av/enums.pxd
@@ -1,30 +1,4 @@
-
-cdef class EnumType(type):
-
-    cdef readonly str name
-    cdef readonly tuple names
-    cdef readonly tuple values
-
-    cdef readonly bint is_flags
-    cdef readonly bint allow_multi_flags
-    cdef readonly bint allow_user_create
-
-    cdef _by_name
-    cdef _by_value
-    cdef _all
-
-    cdef _init(
-        self, name, items,
-        bint is_flags,
-        bint allow_multi_flags,
-        bint allow_user_create,
-    )
-    cdef _create(self, name, value, by_value_only=*)
-    cdef _get_multi_flags(self, long value)
-    cdef _get(self, long value, bint create=*)
-
-
-cpdef EnumType define_enum(
+cpdef define_enum(
     name, items,
     bint is_flags=*,
     bint allow_multi_flags=*,
diff --git a/av/enums.pyx b/av/enums.pyx
index 0dd00454b381894b8f659cb23667ec05a0174a53..5ef75433ed8f1b9f11b04b2fc27b9733fd7204c3 100644
--- a/av/enums.pyx
+++ b/av/enums.pyx
@@ -1,3 +1,4 @@
+from collections import OrderedDict
 
 try:
     import copyreg
@@ -8,26 +9,23 @@ except ImportError:
 cdef sentinel = object()
 
 
-cdef class EnumType(type):
+class EnumType(type):
+    def __new__(cls, name, bases, attrs):
+        enum_class = type.__new__(cls, name, bases, {})
 
-    cdef _init(self, name, items, bint is_flags, bint allow_multi_flags, bint allow_user_create):
+        enum_class._by_name = {}
+        enum_class._by_value = {}
+        enum_class._all = []
 
-        self.name = name
-
-        self.names = ()
-        self.values = ()
-        self._by_name = {}
-        self._by_value = {}
-        self._all = []
+        enum_class._allow_multi_flags = False
+        enum_class._allow_user_create = False
 
-        self.is_flags = bool(is_flags)
-        self.allow_multi_flags = allow_multi_flags
-        self.allow_user_create = allow_user_create
+        for name, value in attrs.items():
+            enum_class._create(name, value)
 
-        for name, value in items:
-            self._create(name, value)
+        return enum_class
 
-    cdef _create(self, name, value, by_value_only=False):
+    def _create(self, name, value, by_value_only=False):
 
         # We only have one instance per value.
         try:
@@ -40,8 +38,6 @@ cdef class EnumType(type):
             setattr(self, name, item)
             self._all.append(item)
             self._by_name[name] = item
-            self.names += (name, )
-            self.values += (value, )
 
         return item
 
@@ -58,7 +54,7 @@ cdef class EnumType(type):
             try:
                 return self._by_value[key]
             except KeyError:
-                if not self.allow_multi_flags:
+                if not self._allow_multi_flags:
                     raise
                 try:
                     return self._get_multi_flags(key)
@@ -66,9 +62,9 @@ cdef class EnumType(type):
                     raise KeyError(key)
         if isinstance(key, self):
             return key
-        raise TypeError("Uncomparable to {}.".format(self.name), key)
+        raise TypeError("Uncomparable to {}.".format(self.__name__), key)
 
-    cdef _get(self, long value, bint create=False):
+    def _get(self, long value, bint create=False):
 
         try:
             return self._by_value[value]
@@ -78,16 +74,16 @@ cdef class EnumType(type):
         if not create:
             return
 
-        return self._create('{}_{}'.format(self.name.upper(), value), value, by_value_only=True)
+        return self._create('{}_{}'.format(self.__name__.upper(), value), value, by_value_only=True)
 
-    cdef _get_multi_flags(self, long value):
+    def _get_multi_flags(self, long value):
 
         try:
             return self._by_value[value]
         except KeyError:
             pass
 
-        if not self.allow_multi_flags:
+        if not self._allow_multi_flags:
             raise ValueError("Missing flag in {}.".format(self.__name__), value)
 
         flags = []
@@ -99,7 +95,7 @@ cdef class EnumType(type):
                 if not to_find:
                     break
         if to_find:
-            raise ValueError("Could not build combo in {}.".format(self.__name__, value))
+            raise ValueError("Could not build combo in {}.".format(self.__name__), value)
 
         name = '|'.join(f.name for f in flags)
         cdef EnumFlag combo = self._create(name, value, by_value_only=True)
@@ -112,8 +108,8 @@ cdef class EnumType(type):
             return self[key]
         except KeyError:
             if create:
-                if not self.allow_user_create:
-                    raise ValueError("Cannot create {}.".format(self.name))
+                if not self._allow_user_create:
+                    raise ValueError("Cannot create {}.".format(self.__name__))
                 return self._get(key, create=True)
             return default
 
@@ -173,7 +169,7 @@ cdef class EnumItem(object):
                 return True
 
             try:
-                other_inst = (<EnumType>self.__class__)._by_name[other]
+                other_inst = self.__class__._by_name[other]
             except KeyError:
                 raise ValueError("Name not in {}.".format(self.__class__.__name__), other)
             else:
@@ -182,7 +178,7 @@ cdef class EnumItem(object):
         if isinstance(other, int):
             if self.value == other:
                 return True
-            if other in (<EnumType>self.__class__)._by_value:
+            if other in self.__class__._by_value:
                 return False
             raise ValueError("Value not in {}.".format(self.__class__.__name__), other)
 
@@ -206,38 +202,33 @@ cdef class EnumFlag(EnumItem):
         if not isinstance(other, int):
             other = self.__class__[other].value
         value = self.value & other
-        return (<EnumType>self.__class__)._get_multi_flags(value)
+        return self.__class__._get_multi_flags(value)
 
     def __or__(self, other):
         if not isinstance(other, int):
             other = self.__class__[other].value
         value = self.value | other
-        return (<EnumType>self.__class__)._get_multi_flags(value)
+        return self.__class__._get_multi_flags(value)
 
     def __xor__(self, other):
         if not isinstance(other, int):
             other = self.__class__[other].value
         value = self.value ^ other
-        return (<EnumType>self.__class__)._get_multi_flags(value)
+        return self.__class__._get_multi_flags(value)
 
     def __invert__(self):
         # This can't result in a flag, but is helpful.
         return ~self.value
 
 
-cpdef EnumType define_enum(name, items, bint is_flags=False, bint allow_multi_flags=False, bint allow_user_create=False):
+cpdef define_enum(name, items, bint is_flags=False, bint allow_multi_flags=False, bint allow_user_create=False):
 
     if is_flags:
         base_cls = EnumFlag
     else:
         base_cls = EnumItem
 
-    cdef EnumType cls = EnumType(name, (base_cls, ), {})
-    cls._init(
-        name, items,
-        is_flags=is_flags,
-        allow_multi_flags=allow_multi_flags,
-        allow_user_create=allow_user_create,
-    )
-
+    cls = EnumType(name, (base_cls, ), OrderedDict(items))
+    cls._allow_multi_flags = allow_multi_flags
+    cls._allow_user_create = allow_user_create
     return cls
diff --git a/av/option.pyx b/av/option.pyx
index 4c74d530173a8c3771d7b238f1d12938a5934b7e..61f0ee774b5914098e982f6b538d584299b9a9f3 100644
--- a/av/option.pyx
+++ b/av/option.pyx
@@ -1,7 +1,7 @@
 cimport libav as lib
 
 from av.utils cimport flag_in_bitfield
-from av.enums cimport EnumType, define_enum
+from av.enums cimport define_enum
 
 
 cdef object _cinit_sentinel = object()
@@ -15,7 +15,7 @@ cdef Option wrap_option(tuple choices, const lib.AVOption *ptr):
     return obj
 
 
-cdef EnumType _OptionType = define_enum('OptionType', (
+OptionType = define_enum('OptionType', (
     ('FLAGS', lib.AV_OPT_TYPE_FLAGS),
     ('INT', lib.AV_OPT_TYPE_INT),
     ('INT64', lib.AV_OPT_TYPE_INT64),
@@ -36,7 +36,6 @@ cdef EnumType _OptionType = define_enum('OptionType', (
     ('CHANNEL_LAYOUT', lib.AV_OPT_TYPE_CHANNEL_LAYOUT),
     ('BOOL', lib.AV_OPT_TYPE_BOOL),
 ))
-OptionType = _OptionType
 
 cdef tuple _INT_TYPES = (
     lib.AV_OPT_TYPE_FLAGS,
@@ -49,7 +48,7 @@ cdef tuple _INT_TYPES = (
     lib.AV_OPT_TYPE_BOOL,
 )
 
-cdef EnumType _OptionFlags = define_enum('OptionFlags', (
+OptionFlags = define_enum('OptionFlags', (
     ('ENCODING_PARAM', lib.AV_OPT_FLAG_ENCODING_PARAM),
     ('DECODING_PARAM', lib.AV_OPT_FLAG_DECODING_PARAM),
     ('AUDIO_PARAM', lib.AV_OPT_FLAG_AUDIO_PARAM),
@@ -59,7 +58,6 @@ cdef EnumType _OptionFlags = define_enum('OptionFlags', (
     ('READONLY', lib.AV_OPT_FLAG_READONLY),
     ('FILTERING_PARAM', lib.AV_OPT_FLAG_FILTERING_PARAM),
 ), is_flags=True)
-OptionFlags = _OptionFlags
 
 cdef class BaseOption(object):
 
@@ -110,7 +108,7 @@ cdef class Option(BaseOption):
 
     property type:
         def __get__(self):
-            return _OptionType._get(self.ptr.type, create=True)
+            return OptionType._get(self.ptr.type, create=True)
 
     property offset:
         """
diff --git a/av/video/frame.pyx b/av/video/frame.pyx
index f5428413a9e74821e321f55a11789a81b267c222..50257e9c5bb2b8ccb43240f4660b6923b508339a 100644
--- a/av/video/frame.pyx
+++ b/av/video/frame.pyx
@@ -1,7 +1,7 @@
 from libc.stdint cimport uint8_t
 
 from av.deprecation import renamed_attr
-from av.enums cimport EnumType, define_enum
+from av.enums cimport define_enum
 from av.utils cimport err_check
 from av.video.format cimport get_video_format, VideoFormat
 from av.video.plane cimport VideoPlane
@@ -19,7 +19,7 @@ cdef VideoFrame alloc_video_frame():
     return VideoFrame.__new__(VideoFrame, _cinit_bypass_sentinel)
 
 
-cdef EnumType PictureType = define_enum('PictureType', (
+PictureType = define_enum('PictureType', (
     ('NONE', lib.AV_PICTURE_TYPE_NONE),
     ('I', lib.AV_PICTURE_TYPE_I),
     ('P', lib.AV_PICTURE_TYPE_P),
diff --git a/tests/test_enums.py b/tests/test_enums.py
index c46ff3476ea22968cb23d572a62900e41ea05a3f..f966afdfe5cacf6581418382720c6893ddc59b4a 100644
--- a/tests/test_enums.py
+++ b/tests/test_enums.py
@@ -29,6 +29,8 @@ class TestEnums(TestCase):
         self.assertEqual(foo.name, 'FOO')
         self.assertEqual(foo.value, 1)
 
+        self.assertNotIsInstance(foo, PickleableFooBar)
+
     def test_access(self):
 
         cls = self.define_foobar()