From 4daff9d5d246d73cbacfd6494521223e04888dfc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 24 Nov 2024 16:52:51 +0100
Subject: [PATCH 01/21] chore!: Remove testing on Python version not supported
 anymore (#87)

---
 .gitlab-ci.yml           | 56 ++++++++++++----------------------------
 README.rst               |  4 +--
 dev-requirements.txt     |  3 +--
 requirements.txt         |  5 +---
 setup.py                 | 15 ++---------
 submodules/cryptodatahub |  2 +-
 tox.ini                  |  5 ++--
 7 files changed, 25 insertions(+), 65 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b490caa..c3a0d70 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -14,48 +14,19 @@ variables:
   PYTHONPATH: "submodules/cryptodatahub"
 
 pylint:
-  image: python:3.11-slim
+  image: python:3.12-slim
   stage: earlytest
   script: tox -e pylint
 
 pep8:
+  image: python:3.12-slim
   stage: earlytest
   script: tox -e pep8
 
-python2:
-  image: python:2.7-slim
-  stage: earlytest
-  script: tox -e py27
-
 python3:
-  image: python:3.11-slim
+  image: python:3.12-slim
   stage: earlytest
-  script: tox -e py311
-
-python34:
-  image: python:3.4-slim
-  stage: fulltest
-  script: tox -e py34
-
-python35:
-  image: python:3.5-slim
-  stage: fulltest
-  script: tox -e py35
-
-python36:
-  image: python:3.6-slim
-  stage: fulltest
-  script: tox -e py36
-
-python37:
-  image: python:3.7-slim
-  stage: fulltest
-  script: tox -e py37
-
-python38:
-  image: python:3.8-slim
-  stage: fulltest
-  script: tox -e py38
+  script: tox -e py312
 
 python39:
   image: python:3.9-slim
@@ -67,15 +38,20 @@ python310:
   stage: fulltest
   script: tox -e py310
 
-pythonrc:
-  image: python:3.12-rc-slim
+python311:
+  image: python:3.11-slim
   stage: fulltest
-  script: tox -e py312
+  script: tox -e py311
+
+python313:
+  image: python:3.13-slim
+  stage: fulltest
+  script: tox -e py313
 
-pypy:
-  image: pypy:2-slim
+pythonrc:
+  image: python:3.14-rc-slim
   stage: fulltest
-  script: tox -e pypy
+  script: tox -e py314
 
 pypy3:
   image: pypy:3-slim
@@ -83,7 +59,7 @@ pypy3:
   script: tox -e pypy3
 
 coveralls:
-  image: python:3.11-slim
+  image: python:3.12-slim
   variables:
     CI_NAME: gitlab
     CI_BUILD_NUMBER: "${CI_JOB_ID}"
diff --git a/README.rst b/README.rst
index 9141435..cf3c9f8 100644
--- a/README.rst
+++ b/README.rst
@@ -31,8 +31,8 @@ Support
 Python implementation
 =====================
 
--  CPython (2.7, 3.3+)
--  PyPy (2.7, 3.5+)
+-  CPython (3.9+)
+-  PyPy (3.9+)
 
 Operating systems
 =================
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 697b294..fb4977a 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -1,4 +1,3 @@
+coverage
 tox
-pathlib2==2.3.7.post1;python_version<"3.4"
-pathlib2;python_version>="3.4"
 pyfakefs
diff --git a/requirements.txt b/requirements.txt
index 872c5c3..7103f40 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,8 +1,5 @@
 asn1crypto
-attrs>=20.3.0,<22.0.1
+attrs
 cryptodatahub==0.12.6
 python-dateutil
-py2-ipaddress;python_version<"3.4"
-typing;python_version<"3.5"
-python-dateutil
 urllib3
diff --git a/setup.py b/setup.py
index 5d78db7..53c23c1 100644
--- a/setup.py
+++ b/setup.py
@@ -47,12 +47,6 @@ def test_discover():
 
     install_requires=install_requirements,
     extras_require={
-        ":python_version < '3'": [
-            "enum34==1.1.6",
-            "pathlib2==2.3.7.post1",
-            "Mock",
-            "unittest2",
-        ],
         "test": ["coverage", ],
         "pep8": ["flake8", ],
         "pylint": ["pylint", ],
@@ -82,16 +76,11 @@ def test_discover():
         'Operating System :: MacOS',
         'Operating System :: Microsoft :: Windows',
         'Operating System :: POSIX',
-        'Programming Language :: Python :: 2.7',
-        'Programming Language :: Python :: 3.3',
-        'Programming Language :: Python :: 3.4',
-        'Programming Language :: Python :: 3.5',
-        'Programming Language :: Python :: 3.6',
-        'Programming Language :: Python :: 3.7',
-        'Programming Language :: Python :: 3.8',
         'Programming Language :: Python :: 3.9',
         'Programming Language :: Python :: 3.10',
         'Programming Language :: Python :: 3.11',
+        'Programming Language :: Python :: 3.12',
+        'Programming Language :: Python :: 3.13',
         'Programming Language :: Python :: Implementation :: CPython',
         'Programming Language :: Python :: Implementation :: PyPy',
         'Programming Language :: Python',
diff --git a/submodules/cryptodatahub b/submodules/cryptodatahub
index 3d06d56..5fe37d4 160000
--- a/submodules/cryptodatahub
+++ b/submodules/cryptodatahub
@@ -1 +1 @@
-Subproject commit 3d06d56486ad17b3b1b1d219aa61b3d7f95f215e
+Subproject commit 5fe37d499fd1653d6740ff633c2e0c6cf73c356a
diff --git a/tox.ini b/tox.ini
index 8561828..925dfea 100644
--- a/tox.ini
+++ b/tox.ini
@@ -3,8 +3,8 @@ description-file = README.rst
 
 [tox]
 envlist =
-    py{27,34,35,36,37,38,39,310,311}
-    pypy{,3}
+    py{39,310,311,312,313}
+    pypy3
     pep8
     pylint
 
@@ -21,7 +21,6 @@ commands =
 deps =
     -rrequirements.txt
     -rdev-requirements.txt
-    coverage
 
 [testenv:pep8]
 extras =

From 95a2910e6621d70d76859ed11296fdf75b939fef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 24 Nov 2024 17:05:11 +0100
Subject: [PATCH 02/21] chore!: Remove derivation from object (#87)

---
 .pylintrc                       |  2 +-
 cryptoparser/common/base.py     |  8 ++++----
 cryptoparser/common/field.py    |  2 +-
 cryptoparser/common/parse.py    |  4 ++--
 cryptoparser/ssh/key.py         |  8 ++++----
 cryptoparser/tls/grease.py      |  2 +-
 cryptoparser/tls/subprotocol.py |  2 +-
 test/common/classes.py          | 18 +++++++++---------
 8 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/.pylintrc b/.pylintrc
index 764879d..832ec4d 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -16,4 +16,4 @@ max-line-length = 120
 
 [MESSAGES CONTROL]
 
-disable = missing-docstring,too-few-public-methods,too-many-ancestors,useless-object-inheritance,duplicate-code,super-with-arguments,consider-using-f-string
+disable = missing-docstring,too-few-public-methods,too-many-ancestors,duplicate-code,super-with-arguments,consider-using-f-string
diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index 3d5cc7b..60b4214 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -49,7 +49,7 @@ def _default(
 json.JSONEncoder.default = _default
 
 
-class SerializableTextEncoder(object):
+class SerializableTextEncoder():
     def __call__(self, obj, level):
         if isinstance(obj, six.string_types):
             string_result = obj
@@ -59,7 +59,7 @@ def __call__(self, obj, level):
         return False, string_result
 
 
-class Serializable(object):  # pylint: disable=too-few-public-methods
+class Serializable():  # pylint: disable=too-few-public-methods
     _MARKDOWN_RESULT_STRING_CLASSES = (
         ipaddress.IPv4Network,
         ipaddress.IPv6Network,
@@ -371,7 +371,7 @@ def _parse(cls, parsable):
 
 
 @attr.s
-class VectorParamBase(object):  # pylint: disable=too-few-public-methods
+class VectorParamBase():  # pylint: disable=too-few-public-methods
     min_byte_num = attr.ib(validator=attr.validators.instance_of(int))
     max_byte_num = attr.ib(validator=attr.validators.instance_of(int))
     item_num_size = attr.ib(init=False, validator=attr.validators.instance_of(int))
@@ -954,7 +954,7 @@ def __str__(self):
 
 
 @attr.s
-class ListParamParsable(object):  # pylint: disable=too-few-public-methods
+class ListParamParsable():  # pylint: disable=too-few-public-methods
     item_class = attr.ib(validator=attr.validators.instance_of(type))
     fallback_class = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(type)))
     separator_class = attr.ib(attr.validators.instance_of(ParsableBase))
diff --git a/cryptoparser/common/field.py b/cryptoparser/common/field.py
index 4826002..31f856d 100644
--- a/cryptoparser/common/field.py
+++ b/cryptoparser/common/field.py
@@ -540,7 +540,7 @@ def get_canonical_name(cls):
 
 
 @attr.s
-class FieldValueComponentStringEnumParams(object):
+class FieldValueComponentStringEnumParams():
     code = attr.ib(validator=attr.validators.instance_of(six.string_types))
 
 
diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index f507b18..a3a4edd 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -21,7 +21,7 @@
 import cryptoparser.common.utils
 
 
-class ParsableBaseNoABC(object):
+class ParsableBaseNoABC():
     @classmethod
     def parse_mutable(cls, parsable):
         parsed_object, parsed_length = cls._parse(parsable)
@@ -748,7 +748,7 @@ def parse_variant(self, name, variant):
 
 
 @attr.s
-class ComposerBase(object):
+class ComposerBase():
     _composed = attr.ib(init=False, default=bytes())
 
     @property
diff --git a/cryptoparser/ssh/key.py b/cryptoparser/ssh/key.py
index 55ca367..303f146 100644
--- a/cryptoparser/ssh/key.py
+++ b/cryptoparser/ssh/key.py
@@ -47,7 +47,7 @@
 
 
 @attr.s
-class SshPublicKeyBase(object):
+class SshPublicKeyBase():
     host_key_algorithm = attr.ib(
         converter=SshHostKeyAlgorithm,
         validator=attr.validators.instance_of(SshHostKeyAlgorithm)
@@ -441,7 +441,7 @@ def get_param(cls):
 
 
 @attr.s(frozen=True)
-class SshCertExtensionParam(object):
+class SshCertExtensionParam():
     code = attr.ib(validator=attr.validators.instance_of(six.string_types))
     critical = attr.ib(validator=attr.validators.instance_of(bool))
 
@@ -724,7 +724,7 @@ def _get_variants(cls):
         raise NotImplementedError()
 
 
-class SshCertificateBase(object):
+class SshCertificateBase():
     @classmethod
     @abc.abstractmethod
     def _parse_host_key_algorithm(cls, parsable):
@@ -835,7 +835,7 @@ def compose(self):
         return composer.composed
 
 
-class SshHostCertificateBase(object):
+class SshHostCertificateBase():
     def _asdict(self):
         key_dict = OrderedDict([])
 
diff --git a/cryptoparser/tls/grease.py b/cryptoparser/tls/grease.py
index 9a7fabe..78f11c0 100644
--- a/cryptoparser/tls/grease.py
+++ b/cryptoparser/tls/grease.py
@@ -20,7 +20,7 @@ class TlsInvalidType(enum.IntEnum):
 
 
 @attr.s
-class TlsInvalidTypeParamsBase(object):
+class TlsInvalidTypeParamsBase():
     code = attr.ib(validator=attr.validators.instance_of(int))
     value_type = attr.ib(validator=attr.validators.in_(TlsInvalidType))
 
diff --git a/cryptoparser/tls/subprotocol.py b/cryptoparser/tls/subprotocol.py
index 15cf182..6371f5c 100644
--- a/cryptoparser/tls/subprotocol.py
+++ b/cryptoparser/tls/subprotocol.py
@@ -50,7 +50,7 @@ class TlsContentType(enum.IntEnum):
 
 
 @attr.s
-class SubprotocolParser(object):
+class SubprotocolParser():
     _subprotocol_type = attr.ib(validator=attr.validators.instance_of(enum.IntEnum))
 
     @classmethod
diff --git a/test/common/classes.py b/test/common/classes.py
index 286e8c6..389dd68 100644
--- a/test/common/classes.py
+++ b/test/common/classes.py
@@ -244,7 +244,7 @@ def get_param(cls):
 
 
 @attr.s
-class OpaqueEnumParams(object):
+class OpaqueEnumParams():
     code = attr.ib(validator=attr.validators.instance_of(six.string_types))
 
 
@@ -260,7 +260,7 @@ class OpaqueEnum(OpaqueEnumComposer):
     )
 
 
-class TestObject(object):
+class TestObject():
     pass
 
 
@@ -355,19 +355,19 @@ class SerializableAttributeOrder(Serializable):
     attr_a = attr.ib(default='a')
 
 
-class Class(object):
+class Class():
     def __init__(self):
         self.attr_b = 'b'
         self.attr_a = 'a'
 
 
 @attr.s
-class ClassAttr(object):
+class ClassAttr():
     attr_b = attr.ib(default='b')
     attr_a = attr.ib(default='a')
 
 
-class ClassAsDict(object):
+class ClassAsDict():
     def __init__(self):
         self.attr_a = 'a'
         self.attr_b = 'b'
@@ -380,7 +380,7 @@ def _asdict(self):
 
 
 @attr.s
-class ClassAttrAsDict(object):
+class ClassAttrAsDict():
     attr_a = attr.ib(default='a')
     attr_b = attr.ib(default='b')
 
@@ -437,7 +437,7 @@ class FlagEnum(enum.IntEnum):
 
 
 @attr.s
-class StringEnumParams(object):
+class StringEnumParams():
     code = attr.ib()
 
     def _check_code(self, code):
@@ -514,7 +514,7 @@ def get_param(cls):
 
 
 @attr.s
-class NByteEnumParam(object):
+class NByteEnumParam():
     code = attr.ib(validator=attr.validators.instance_of(int))
 
 
@@ -699,7 +699,7 @@ def get_canonical_name(cls):
 
 
 @attr.s
-class FieldValueComplexTestBase(object):  # pylint: disable=too-many-instance-attributes
+class FieldValueComplexTestBase():  # pylint: disable=too-many-instance-attributes
     time_delta = attr.ib(
         converter=FieldValueComponentTimeDeltaTest.convert,
         validator=attr.validators.instance_of(FieldValueComponentTimeDeltaTest)

From 25362d65b4217d9a7e9e90afb7082c0e2eaa4b5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 24 Nov 2024 17:11:35 +0100
Subject: [PATCH 03/21] chore!: Remove usage of six module string_types (#87)

---
 cryptoparser/common/base.py     |  6 +++---
 cryptoparser/dnsrec/record.py   | 10 +++++-----
 cryptoparser/dnsrec/txt.py      |  4 ++--
 cryptoparser/ssh/key.py         |  2 +-
 cryptoparser/ssh/subprotocol.py | 12 ++++++------
 cryptoparser/tls/extension.py   |  2 +-
 cryptoparser/tls/mysql.py       |  6 +++---
 cryptoparser/tls/openvpn.py     |  8 ++++----
 8 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index 60b4214..3e583b6 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -117,7 +117,7 @@ def _json_result(obj):
                 result = obj.name
             else:
                 result = {obj.name: obj.value}
-        elif isinstance(obj, six.string_types + six.integer_types + (float, bool, )) or obj is None:
+        elif isinstance(obj, six.string_types + (int, float, bool, )) or obj is None:
             result = obj
         elif isinstance(obj, (bytes, bytearray)):
             result = bytes_to_hex_string(obj, separator=':', lowercase=False)
@@ -223,7 +223,7 @@ def _markdown_result_list(cls, obj, level=0):
 
     @staticmethod
     def _markdown_is_directly_printable(obj):
-        return not isinstance(obj, enum.Enum) and isinstance(obj, six.string_types + six.integer_types + (float, ))
+        return not isinstance(obj, enum.Enum) and isinstance(obj, six.string_types + (int, float, ))
 
     @classmethod
     def _markdown_result(cls, obj, level=0):  # pylint: disable=too-many-branches,too-many-return-statements
@@ -1048,7 +1048,7 @@ def get_encoding(cls):
 
 @attr.s
 class NumericRangeParsableBase(ParsableBase, Serializable):
-    value = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    value = attr.ib(validator=attr.validators.instance_of(int))
 
     @value.validator
     def _validator_variant(self, _, value):
diff --git a/cryptoparser/dnsrec/record.py b/cryptoparser/dnsrec/record.py
index 449bde7..d6042d4 100644
--- a/cryptoparser/dnsrec/record.py
+++ b/cryptoparser/dnsrec/record.py
@@ -278,7 +278,7 @@ def compose(self):
 class DnsRecordDs(ParsableBase):
     HEADER_SIZE = 4
 
-    key_tag = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    key_tag = attr.ib(validator=attr.validators.instance_of(int))
     algorithm = attr.ib(validator=attr.validators.instance_of(DnsSecAlgorithm))
     digest_type = attr.ib(validator=attr.validators.instance_of(DnsSecDigestType))
     digest = attr.ib(validator=attr.validators.instance_of((bytes, bytearray)))
@@ -389,14 +389,14 @@ class DnsRecordRrsig(ParsableBase):  # pylint: disable=too-many-instance-attribu
 
     type_covered = attr.ib(validator=attr.validators.instance_of((DnsRrType, DnsRrTypePrivate)))
     algorithm = attr.ib(validator=attr.validators.instance_of(DnsSecAlgorithm))
-    labels = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    labels = attr.ib(validator=attr.validators.instance_of(int))
     original_ttl = attr.ib(
-        validator=attr.validators.instance_of(six.integer_types),
+        validator=attr.validators.instance_of(int),
         metadata={'human_readable_name': 'Original TTL'}
     )
     signature_expiration = attr.ib(validator=attr.validators.instance_of(datetime.datetime))
     signature_inception = attr.ib(validator=attr.validators.instance_of(datetime.datetime))
-    key_tag = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    key_tag = attr.ib(validator=attr.validators.instance_of(int))
     signers_name = attr.ib(
         converter=DnsNameUncompressed.convert,
         validator=attr.validators.instance_of(DnsNameUncompressed)
@@ -451,7 +451,7 @@ def compose(self):
 class DnsRecordMx(ParsableBase):
     HEADER_SIZE = 2
 
-    priority = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    priority = attr.ib(validator=attr.validators.instance_of(int))
     exchange = attr.ib(
         converter=DnsNameUncompressed.convert,
         validator=attr.validators.instance_of(DnsNameUncompressed)
diff --git a/cryptoparser/dnsrec/txt.py b/cryptoparser/dnsrec/txt.py
index 5f4fd76..4c308f9 100644
--- a/cryptoparser/dnsrec/txt.py
+++ b/cryptoparser/dnsrec/txt.py
@@ -671,11 +671,11 @@ class DnsRecordTxtValueSpfDirectiveDomainCidr(DnsRecordTxtValueSpfDirectiveBase)
     )
     ipv4_cidr_length = attr.ib(
         default=None,
-        validator=attr.validators.optional(attr.validators.instance_of(six.integer_types)),
+        validator=attr.validators.optional(attr.validators.instance_of(int)),
     )
     ipv6_cidr_length = attr.ib(
         default=None,
-        validator=attr.validators.optional(attr.validators.instance_of(six.integer_types)),
+        validator=attr.validators.optional(attr.validators.instance_of(int)),
     )
     qualifier = attr.ib(
         default=None,
diff --git a/cryptoparser/ssh/key.py b/cryptoparser/ssh/key.py
index 303f146..c75a343 100644
--- a/cryptoparser/ssh/key.py
+++ b/cryptoparser/ssh/key.py
@@ -915,7 +915,7 @@ def get_param(cls):
 @attr.s
 class SshHostCertificateV01Base(ParsableBase, SshCertificateBase):  # pylint: disable=too-many-instance-attributes
     nonce = attr.ib(validator=attr.validators.instance_of((bytes, bytearray)))
-    serial = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    serial = attr.ib(validator=attr.validators.instance_of(int))
     certificate_type = attr.ib(validator=attr.validators.instance_of(SshCertType))
     key_id = attr.ib(validator=attr.validators.instance_of(six.string_types))
     valid_principals = attr.ib(
diff --git a/cryptoparser/ssh/subprotocol.py b/cryptoparser/ssh/subprotocol.py
index 544211f..871ef31 100644
--- a/cryptoparser/ssh/subprotocol.py
+++ b/cryptoparser/ssh/subprotocol.py
@@ -260,12 +260,12 @@ class SshKeyExchangeInit(SshMessageBase):  # pylint: disable=too-many-instance-a
         converter=SshLanguageVector,
         validator=attr.validators.instance_of(SshLanguageVector), default=()
     )
-    first_kex_packet_follows = attr.ib(validator=attr.validators.instance_of(six.integer_types), default=0)
+    first_kex_packet_follows = attr.ib(validator=attr.validators.instance_of(int), default=0)
     cookie = attr.ib(
         validator=attr.validators.instance_of((bytearray, bytes)),
         default=bytearray.fromhex('{:16x}'.format(random.getrandbits(128)).zfill(32))
     )
-    reserved = attr.ib(validator=attr.validators.instance_of(six.integer_types), default=0x00000000)
+    reserved = attr.ib(validator=attr.validators.instance_of(int), default=0x00000000)
 
     @classmethod
     def _get_cipher_attributes(cls):
@@ -397,7 +397,7 @@ def compose(self):
 
 @attr.s
 class SshUnimplementedMessage(SshMessageBase):
-    sequence_number = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    sequence_number = attr.ib(validator=attr.validators.instance_of(int))
 
     @classmethod
     def get_message_code(cls):
@@ -519,9 +519,9 @@ def get_message_code(cls):
 
 @attr.s
 class SshDHGroupExchangeRequest(SshMessageBase):
-    gex_min = attr.ib(validator=attr.validators.instance_of(six.integer_types))
-    gex_number = attr.ib(validator=attr.validators.instance_of(six.integer_types))
-    gex_max = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    gex_min = attr.ib(validator=attr.validators.instance_of(int))
+    gex_number = attr.ib(validator=attr.validators.instance_of(int))
+    gex_max = attr.ib(validator=attr.validators.instance_of(int))
 
     @classmethod
     def get_message_code(cls):
diff --git a/cryptoparser/tls/extension.py b/cryptoparser/tls/extension.py
index bedbf83..3daa1c9 100644
--- a/cryptoparser/tls/extension.py
+++ b/cryptoparser/tls/extension.py
@@ -1162,7 +1162,7 @@ def compose(self):
 
 @attr.s
 class TlsExtensionPadding(TlsExtensionParsed):
-    length = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    length = attr.ib(validator=attr.validators.instance_of(int))
 
     @classmethod
     def get_extension_type(cls):
diff --git a/cryptoparser/tls/mysql.py b/cryptoparser/tls/mysql.py
index 9dfee8d..072eea3 100644
--- a/cryptoparser/tls/mysql.py
+++ b/cryptoparser/tls/mysql.py
@@ -303,7 +303,7 @@ def compose(self):
 class MySQLRecord(ParsableBase):
     HEADER_SIZE = 4
 
-    packet_number = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    packet_number = attr.ib(validator=attr.validators.instance_of(int))
     packet_bytes = attr.ib(validator=attr.validators.instance_of((bytes, bytearray)))
 
     @classmethod
@@ -336,7 +336,7 @@ def compose(self):
 class MySQLHandshakeV10(MySQLPacketBase):  # pylint: disable=too-many-instance-attributes
     protocol_version = attr.ib(validator=attr.validators.in_(MySQLVersion))
     server_version = attr.ib(validator=attr.validators.instance_of(six.string_types))
-    connection_id = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    connection_id = attr.ib(validator=attr.validators.instance_of(int))
     auth_plugin_data = attr.ib(validator=attr.validators.instance_of((bytes, bytearray)))
     capabilities = attr.ib(validator=attr.validators.deep_iterable(
         member_validator=attr.validators.instance_of(MySQLCapability),
@@ -443,7 +443,7 @@ class MySQLHandshakeSslRequest(MySQLPacketBase):
     capabilities = attr.ib(validator=attr.validators.deep_iterable(
         member_validator=attr.validators.instance_of(MySQLCapability),
     ))
-    max_packet_size = attr.ib(default=0xffff, validator=attr.validators.instance_of(six.integer_types))
+    max_packet_size = attr.ib(default=0xffff, validator=attr.validators.instance_of(int))
     character_set = attr.ib(default=None, validator=attr.validators.optional(attr.validators.in_(MySQLCharacterSet)))
 
     MINIMUM_SIZE = 5
diff --git a/cryptoparser/tls/openvpn.py b/cryptoparser/tls/openvpn.py
index b83a003..3940e82 100644
--- a/cryptoparser/tls/openvpn.py
+++ b/cryptoparser/tls/openvpn.py
@@ -45,11 +45,11 @@ def compose(self):
 class OpenVpnPacketBase(ParsableBase):
     HEADER_SIZE = 10
 
-    session_id = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    session_id = attr.ib(validator=attr.validators.instance_of(int))
     packet_id_array = attr.ib(
-        validator=attr.validators.deep_iterable(member_validator=attr.validators.instance_of(six.integer_types))
+        validator=attr.validators.deep_iterable(member_validator=attr.validators.instance_of(int))
     )
-    remote_session_id = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.integer_types)))
+    remote_session_id = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(int)))
 
     @classmethod
     @abc.abstractmethod
@@ -96,7 +96,7 @@ def _compose_header(self):
 
 @attr.s
 class OpenVpnPacketControlV1(OpenVpnPacketBase):
-    packet_id = attr.ib(validator=attr.validators.instance_of(six.integer_types))
+    packet_id = attr.ib(validator=attr.validators.instance_of(int))
     payload = attr.ib(validator=attr.validators.instance_of((bytes, bytearray)))
 
     @classmethod

From f9483159273c61214c4f4f27ebbe74ad02d5df33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 24 Nov 2024 17:17:01 +0100
Subject: [PATCH 04/21] chore!: Remove usage of six module string_types (#87)

---
 cryptoparser/common/base.py     | 14 +++++++-------
 cryptoparser/common/field.py    | 20 ++++++++++----------
 cryptoparser/common/parse.py    |  2 +-
 cryptoparser/dnsrec/record.py   |  6 +++---
 cryptoparser/dnsrec/txt.py      |  2 +-
 cryptoparser/httpx/header.py    | 18 +++++++++---------
 cryptoparser/httpx/version.py   |  4 ++--
 cryptoparser/ssh/key.py         | 14 +++++++-------
 cryptoparser/ssh/subprotocol.py |  8 ++++----
 cryptoparser/ssh/version.py     |  4 ++--
 cryptoparser/tls/extension.py   |  2 +-
 cryptoparser/tls/mysql.py       |  8 ++++----
 test/common/classes.py          |  2 +-
 13 files changed, 52 insertions(+), 52 deletions(-)

diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index 3e583b6..8f048c7 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -51,7 +51,7 @@ def _default(
 
 class SerializableTextEncoder():
     def __call__(self, obj, level):
-        if isinstance(obj, six.string_types):
+        if isinstance(obj, str):
             string_result = obj
         else:
             string_result = str(obj)
@@ -117,7 +117,7 @@ def _json_result(obj):
                 result = obj.name
             else:
                 result = {obj.name: obj.value}
-        elif isinstance(obj, six.string_types + (int, float, bool, )) or obj is None:
+        elif isinstance(obj, (str, int, float, bool, )) or obj is None:
             result = obj
         elif isinstance(obj, (bytes, bytearray)):
             result = bytes_to_hex_string(obj, separator=':', lowercase=False)
@@ -158,7 +158,7 @@ def _markdown_human_readable_names(cls, obj, dict_value):
         name_dict = {}
         fields_dict = attr.fields_dict(type(obj)) if attr.has(type(obj)) else {}
         for name in dict_value:
-            if isinstance(name, six.string_types):
+            if isinstance(name, str):
                 if name in fields_dict and 'human_readable_name' in fields_dict[name].metadata:
                     human_readable_name = fields_dict[name].metadata['human_readable_name']
                 else:
@@ -223,7 +223,7 @@ def _markdown_result_list(cls, obj, level=0):
 
     @staticmethod
     def _markdown_is_directly_printable(obj):
-        return not isinstance(obj, enum.Enum) and isinstance(obj, six.string_types + (int, float, ))
+        return not isinstance(obj, enum.Enum) and isinstance(obj, (str, int, float, ))
 
     @classmethod
     def _markdown_result(cls, obj, level=0):  # pylint: disable=too-many-branches,too-many-return-statements
@@ -406,8 +406,8 @@ def get_item_size(self, item):
 
 @attr.s
 class VectorParamString(VectorParamBase):  # pylint: disable=too-few-public-methods
-    separator = attr.ib(validator=attr.validators.instance_of(six.string_types), default=',')
-    encoding = attr.ib(validator=attr.validators.instance_of(six.string_types), default='ascii')
+    separator = attr.ib(validator=attr.validators.instance_of(str), default=',')
+    encoding = attr.ib(validator=attr.validators.instance_of(str), default='ascii')
     item_class = attr.ib(validator=attr.validators.instance_of((type, types.FunctionType)), default=str)
     fallback_class = attr.ib(
         default=None,
@@ -419,7 +419,7 @@ def get_item_size(self, item):
             return len(item.compose())
         if isinstance(item, CryptoDataEnumCodedBase):
             return item.value.get_code_size()
-        if isinstance(item, six.string_types):
+        if isinstance(item, str):
             return len(item)
 
         raise NotImplementedError(type(item))
diff --git a/cryptoparser/common/field.py b/cryptoparser/common/field.py
index 31f856d..197772d 100644
--- a/cryptoparser/common/field.py
+++ b/cryptoparser/common/field.py
@@ -92,8 +92,8 @@ def _parse_name_and_separator(cls, parsable):
 
 @attr.s
 class NameValuePair(FieldParsableBase):
-    name = attr.ib(validator=attr.validators.instance_of(six.string_types))
-    value = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.string_types)), default=None)
+    name = attr.ib(validator=attr.validators.instance_of(str))
+    value = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(str)), default=None)
     quoted = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(bool)), default=False)
 
     @classmethod
@@ -382,7 +382,7 @@ def _get_value_class(cls):
 
 @attr.s
 class FieldValueComponentQuotedString(FieldValueComponentKeyValueBase):
-    value = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.string_types)))
+    value = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(str)))
 
     @classmethod
     @abc.abstractmethod
@@ -541,7 +541,7 @@ def get_canonical_name(cls):
 
 @attr.s
 class FieldValueComponentStringEnumParams():
-    code = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    code = attr.ib(validator=attr.validators.instance_of(str))
 
 
 @attr.s
@@ -592,7 +592,7 @@ def _check_name(cls, name):
 
 @attr.s
 class FieldValueComponentString(FieldValueComponentKeyValueBase):
-    value = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.string_types)))
+    value = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(str)))
 
     @classmethod
     @abc.abstractmethod
@@ -809,7 +809,7 @@ class MimeTypeRegistry(enum.Enum):
 @attr.s
 class FieldValueMimeType(FieldValueComponentBase):
     type = attr.ib(
-        validator=attr.validators.instance_of(six.string_types),
+        validator=attr.validators.instance_of(str),
         default=None,
     )
     registry = attr.ib(
@@ -917,10 +917,10 @@ def _get_value_type(cls):
 
 @attr.s
 class FieldValueStringEnumParams(Serializable):
-    code = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    code = attr.ib(validator=attr.validators.instance_of(str))
     human_readable_name = attr.ib(
         default=None,
-        validator=attr.validators.optional(attr.validators.instance_of(six.string_types))
+        validator=attr.validators.optional(attr.validators.instance_of(str))
     )
 
     def _as_markdown(self, level):
@@ -933,7 +933,7 @@ def _as_markdown(self, level):
 class FieldValueString(FieldValueSingle):
     @classmethod
     def _get_value_type(cls):
-        return six.string_types
+        return str
 
     @classmethod
     def _value_from_str(cls, value):
@@ -983,7 +983,7 @@ def _get_separators(cls):
 
     @classmethod
     def _get_value_type(cls):
-        return six.string_types
+        return str
 
     @classmethod
     def _parse(cls, parsable):
diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index a3a4edd..ec5cd97 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -317,7 +317,7 @@ def _apply_item_class(  # pylint: disable=too-many-arguments,too-many-positional
             elif issubclass(item_class, ParsableBaseNoABC):
                 item, parsed_length = item_class.parse_immutable(self._parsable[item_offset:item_end])
                 item_end = item_offset + parsed_length
-            elif issubclass(item_class, six.string_types):
+            elif issubclass(item_class, str):
                 item = six.ensure_text(self._parsable[item_offset:item_end], self._encoding)
             else:
                 item = item_class(six.ensure_text(self._parsable[item_offset:item_end], self._encoding))
diff --git a/cryptoparser/dnsrec/record.py b/cryptoparser/dnsrec/record.py
index d6042d4..7d53922 100644
--- a/cryptoparser/dnsrec/record.py
+++ b/cryptoparser/dnsrec/record.py
@@ -335,7 +335,7 @@ def _get_value_length(cls):
 @attr.s
 class DnsNameUncompressed(ParsableBase, Serializable):
     labels = attr.ib(
-        validator=attr.validators.deep_iterable(member_validator=attr.validators.instance_of(six.string_types))
+        validator=attr.validators.deep_iterable(member_validator=attr.validators.instance_of(str))
     )
 
     def __str__(self):
@@ -348,7 +348,7 @@ def _as_markdown(self, level):
     def convert(cls, value):
         if isinstance(value, cls):
             return value
-        if isinstance(value, six.string_types):
+        if isinstance(value, str):
             if not value:
                 return cls([])
 
@@ -482,7 +482,7 @@ def compose(self):
 class DnsRecordTxt(ParsableBase):
     HEADER_SIZE = 1
 
-    value = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    value = attr.ib(validator=attr.validators.instance_of(str))
 
     @classmethod
     def _parse(cls, parsable):
diff --git a/cryptoparser/dnsrec/txt.py b/cryptoparser/dnsrec/txt.py
index 4c308f9..3b795f0 100644
--- a/cryptoparser/dnsrec/txt.py
+++ b/cryptoparser/dnsrec/txt.py
@@ -426,7 +426,7 @@ class SpfModifier(StringEnumParsable, enum.Enum):
 class SpfDomainSpec(FieldValueSingleBase):
     @classmethod
     def _get_value_type(cls):
-        return six.string_types
+        return str
 
     @classmethod
     def _parse(cls, parsable):
diff --git a/cryptoparser/httpx/header.py b/cryptoparser/httpx/header.py
index 3e5f78b..9c0434e 100644
--- a/cryptoparser/httpx/header.py
+++ b/cryptoparser/httpx/header.py
@@ -434,7 +434,7 @@ class ContentSecurityPolicySourceHashType(StringEnumHashParsableBase, enum.Enum)
 
 @attr.s
 class ContentSecurityPolicySourceHash(ParsableBase, Serializable):
-    hash_algorithm = attr.ib(validator=attr.validators.instance_of((Hash, six.string_types)))
+    hash_algorithm = attr.ib(validator=attr.validators.instance_of((Hash, str)))
     hash_value = attr.ib(converter=convert_base64_data(), validator=attr.validators.instance_of(Base64Data))
 
     @classmethod
@@ -509,7 +509,7 @@ def get_type(cls):
 
 @attr.s
 class ContentSecurityPolicySourceScheme(ParsableBase, Serializable):
-    value = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    value = attr.ib(validator=attr.validators.instance_of(str))
 
     @classmethod
     def _parse(cls, parsable):
@@ -540,7 +540,7 @@ def get_type(cls):
 class ContentSecurityPolicySourceHost(ParsableBase, Serializable):
     value = attr.ib(
         converter=convert_url(),
-        validator=attr.validators.instance_of(six.string_types + (urllib3.util.url.Url, ))
+        validator=attr.validators.instance_of((str, urllib3.util.url.Url, ))
     )
 
     @classmethod
@@ -1398,8 +1398,8 @@ class HttpHeaderFieldValueSetCookieParams(FieldsSemicolonSeparated):
 
 @attr.s
 class HttpHeaderFieldValueSetCookie(FieldValueBase):  # pylint: disable=too-many-instance-attributes
-    name = attr.ib(validator=attr.validators.instance_of(six.string_types))
-    value = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    name = attr.ib(validator=attr.validators.instance_of(str))
+    value = attr.ib(validator=attr.validators.instance_of(str))
     expires = attr.ib(
         converter=attr.converters.optional(HttpHeaderFieldValueComponentExpires.convert),
         validator=attr.validators.optional(attr.validators.instance_of(HttpHeaderFieldValueComponentExpires)),
@@ -1582,8 +1582,8 @@ def _get_value_type(cls):
 
 @attr.s(frozen=True)
 class HttpHeaderFieldNameParams(Serializable):
-    code = attr.ib(validator=attr.validators.instance_of(six.string_types))
-    normalized_name = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    code = attr.ib(validator=attr.validators.instance_of(str))
+    normalized_name = attr.ib(validator=attr.validators.instance_of(str))
 
     def _as_markdown(self, level):
         return self._markdown_result(self.normalized_name, level)
@@ -1995,8 +1995,8 @@ def _get_variants(cls):
 
 @attr.s
 class HttpHeaderFieldUnparsed(FieldParsableBase, Serializable):
-    name = attr.ib(validator=attr.validators.instance_of(six.string_types))
-    value = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    name = attr.ib(validator=attr.validators.instance_of(str))
+    value = attr.ib(validator=attr.validators.instance_of(str))
 
     @classmethod
     def get_separator(cls):
diff --git a/cryptoparser/httpx/version.py b/cryptoparser/httpx/version.py
index 4749426..795eebf 100644
--- a/cryptoparser/httpx/version.py
+++ b/cryptoparser/httpx/version.py
@@ -10,8 +10,8 @@
 
 @attr.s(frozen=True)
 class HttpVersionParams(Serializable):
-    code = attr.ib(validator=attr.validators.instance_of(six.string_types))
-    name = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    code = attr.ib(validator=attr.validators.instance_of(str))
+    name = attr.ib(validator=attr.validators.instance_of(str))
 
     @property
     def identifier(self):
diff --git a/cryptoparser/ssh/key.py b/cryptoparser/ssh/key.py
index c75a343..96df2be 100644
--- a/cryptoparser/ssh/key.py
+++ b/cryptoparser/ssh/key.py
@@ -366,7 +366,7 @@ def key_bytes(self):
 @attr.s(frozen=True)
 class SshCertTypeParams(Serializable):
     code = attr.ib(validator=attr.validators.instance_of(int))
-    name = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    name = attr.ib(validator=attr.validators.instance_of(str))
 
     def _as_markdown(self, level):
         return self._markdown_result(self.name, level)
@@ -412,7 +412,7 @@ def compose(self):
 
 @attr.s
 class SshString(ParsableBase):
-    value = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    value = attr.ib(validator=attr.validators.instance_of(str))
 
     @classmethod
     def _parse(cls, parsable):
@@ -442,7 +442,7 @@ def get_param(cls):
 
 @attr.s(frozen=True)
 class SshCertExtensionParam():
-    code = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    code = attr.ib(validator=attr.validators.instance_of(str))
     critical = attr.ib(validator=attr.validators.instance_of(bool))
 
 
@@ -505,7 +505,7 @@ def compose(self):
 
 @attr.s
 class SshCertExtensionUnparsed(SshCertExtensionBase):
-    extension_name = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    extension_name = attr.ib(validator=attr.validators.instance_of(str))
     extension_data = attr.ib(validator=attr.validators.instance_of((bytes, bytearray)))
 
     @classmethod
@@ -629,7 +629,7 @@ def get_extension_name(cls):
 
 @attr.s
 class SshCertExtensionForceCommand(SshCertExtensionParsed):
-    command = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    command = attr.ib(validator=attr.validators.instance_of(str))
 
     @classmethod
     def get_extension_name(cls):
@@ -751,7 +751,7 @@ def host_key_asdict(self):
 class SshHostCertificateV00Base(ParsableBase, SshCertificateBase):  # pylint: disable=too-many-instance-attributes
     certificate_type = attr.ib(validator=attr.validators.instance_of(SshCertType))
     key_id = attr.ib(
-        validator=attr.validators.instance_of(six.string_types),
+        validator=attr.validators.instance_of(str),
         metadata={'human_readable_name': 'Key ID'},
     )
     valid_principals = attr.ib(
@@ -917,7 +917,7 @@ class SshHostCertificateV01Base(ParsableBase, SshCertificateBase):  # pylint: di
     nonce = attr.ib(validator=attr.validators.instance_of((bytes, bytearray)))
     serial = attr.ib(validator=attr.validators.instance_of(int))
     certificate_type = attr.ib(validator=attr.validators.instance_of(SshCertType))
-    key_id = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    key_id = attr.ib(validator=attr.validators.instance_of(str))
     valid_principals = attr.ib(
         converter=SshCertValidPrincipals,
         validator=attr.validators.instance_of(SshCertValidPrincipals)
diff --git a/cryptoparser/ssh/subprotocol.py b/cryptoparser/ssh/subprotocol.py
index 871ef31..6cce1f6 100644
--- a/cryptoparser/ssh/subprotocol.py
+++ b/cryptoparser/ssh/subprotocol.py
@@ -84,7 +84,7 @@ def _compose_header(cls):
 class SshProtocolMessage(ParsableBase):
     protocol_version = attr.ib(validator=attr.validators.instance_of(SshProtocolVersion))
     software_version = attr.ib(validator=attr.validators.instance_of(SshSoftwareVersionBase))
-    comment = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.string_types)), default=None)
+    comment = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(str)), default=None)
 
     @comment.validator
     def comment_validator(self, _, value):  # pylint: disable=no-self-use
@@ -311,7 +311,7 @@ def get_message_code(cls):
     def _hassh(algorithm_vectors):
         hassh_text = ';'.join([
             ','.join([
-                algorithm if isinstance(algorithm, six.string_types) else algorithm.value.code
+                algorithm if isinstance(algorithm, str) else algorithm.value.code
                 for algorithm in algorithms
             ])
             for algorithms in algorithm_vectors
@@ -364,11 +364,11 @@ class SshDisconnectMessage(SshMessageBase):
     reason = attr.ib(validator=attr.validators.instance_of(SshReasonCode))
     description = attr.ib(
         converter=six.text_type,
-        validator=attr.validators.instance_of(six.string_types)
+        validator=attr.validators.instance_of(str)
     )
     language = attr.ib(
         default='US',
-        validator=attr.validators.instance_of(six.string_types)
+        validator=attr.validators.instance_of(str)
     )
 
     @classmethod
diff --git a/cryptoparser/ssh/version.py b/cryptoparser/ssh/version.py
index 353584d..c358f77 100644
--- a/cryptoparser/ssh/version.py
+++ b/cryptoparser/ssh/version.py
@@ -83,7 +83,7 @@ def compose(self):
 
 @attr.s
 class SshSoftwareVersionUnparsed(SshSoftwareVersionBase, Serializable):
-    raw = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    raw = attr.ib(validator=attr.validators.instance_of(str))
 
     @raw.validator
     def raw_validator(self, _, value):  # pylint: disable=no-self-use
@@ -115,7 +115,7 @@ def compose(self):
 
 @attr.s
 class SshSoftwareVersionParsedBase(SshSoftwareVersionBase):
-    version = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(six.string_types)))
+    version = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(str)))
 
     @classmethod
     @abc.abstractmethod
diff --git a/cryptoparser/tls/extension.py b/cryptoparser/tls/extension.py
index 3daa1c9..afadc9b 100644
--- a/cryptoparser/tls/extension.py
+++ b/cryptoparser/tls/extension.py
@@ -230,7 +230,7 @@ def get_param(cls):
 
 @attr.s
 class TlsExtensionServerNameClient(TlsExtensionParsed):
-    host_name = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    host_name = attr.ib(validator=attr.validators.instance_of(str))
     name_type = attr.ib(validator=attr.validators.in_(TlsServerNameType), default=TlsServerNameType.HOST_NAME)
 
     @classmethod
diff --git a/cryptoparser/tls/mysql.py b/cryptoparser/tls/mysql.py
index 072eea3..658a30a 100644
--- a/cryptoparser/tls/mysql.py
+++ b/cryptoparser/tls/mysql.py
@@ -66,8 +66,8 @@ class MySQLStatusFlag(enum.IntEnum):
 @attr.s(frozen=True)
 class MySQLCharacterSetParams(Serializable):
     code = attr.ib(validator=attr.validators.instance_of(int))
-    name = attr.ib(validator=attr.validators.instance_of(six.string_types))
-    collate_name = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    name = attr.ib(validator=attr.validators.instance_of(str))
+    collate_name = attr.ib(validator=attr.validators.instance_of(str))
 
 
 class MySQLCharacterSetFactory(OneByteEnumParsable):
@@ -335,7 +335,7 @@ def compose(self):
 @attr.s
 class MySQLHandshakeV10(MySQLPacketBase):  # pylint: disable=too-many-instance-attributes
     protocol_version = attr.ib(validator=attr.validators.in_(MySQLVersion))
-    server_version = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    server_version = attr.ib(validator=attr.validators.instance_of(str))
     connection_id = attr.ib(validator=attr.validators.instance_of(int))
     auth_plugin_data = attr.ib(validator=attr.validators.instance_of((bytes, bytearray)))
     capabilities = attr.ib(validator=attr.validators.deep_iterable(
@@ -353,7 +353,7 @@ class MySQLHandshakeV10(MySQLPacketBase):  # pylint: disable=too-many-instance-a
     )
     auth_plugin_name = attr.ib(
         default=None,
-        validator=attr.validators.optional(attr.validators.instance_of(six.string_types))
+        validator=attr.validators.optional(attr.validators.instance_of(str))
     )
 
     MINIMUM_SIZE = 33
diff --git a/test/common/classes.py b/test/common/classes.py
index 389dd68..e83a4f6 100644
--- a/test/common/classes.py
+++ b/test/common/classes.py
@@ -245,7 +245,7 @@ def get_param(cls):
 
 @attr.s
 class OpaqueEnumParams():
-    code = attr.ib(validator=attr.validators.instance_of(six.string_types))
+    code = attr.ib(validator=attr.validators.instance_of(str))
 
 
 class OpaqueEnum(OpaqueEnumComposer):

From f9f58c94925ab2e17a4a5acf810e49a1d6c41081 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sat, 30 Nov 2024 14:18:23 +0100
Subject: [PATCH 05/21] chore!: Remove usage of six module raise_from (#87)

---
 cryptoparser/common/base.py     |  4 ++--
 cryptoparser/common/field.py    |  8 +++----
 cryptoparser/common/parse.py    | 38 ++++++++++++++++-----------------
 cryptoparser/common/utils.py    |  2 +-
 cryptoparser/dnsrec/txt.py      |  4 ++--
 cryptoparser/httpx/header.py    |  4 ++--
 cryptoparser/ssh/key.py         |  2 +-
 cryptoparser/ssh/subprotocol.py |  2 +-
 cryptoparser/ssh/version.py     |  4 ++--
 cryptoparser/tls/extension.py   |  2 +-
 cryptoparser/tls/ldap.py        |  6 +++---
 cryptoparser/tls/record.py      |  4 ++--
 cryptoparser/tls/subprotocol.py |  6 +++---
 13 files changed, 42 insertions(+), 44 deletions(-)

diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index 8f048c7..c3f2fa7 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -858,7 +858,7 @@ def _parse(cls, parsable):
         try:
             code = six.ensure_text(bytes(parsable), 'ascii')
         except UnicodeDecodeError as e:
-            six.raise_from(InvalidValue(parsable, cls), e)
+            raise InvalidValue(parsable, cls) from e
 
         for enum_item in enum_items:
             if cls._code_eq(enum_item.value.code, code[:len(enum_item.value.code)]):
@@ -1015,7 +1015,7 @@ def _parse(cls, parsable):
                 if enum_item.value.code == code
             ]))
         except StopIteration as e:
-            six.raise_from(InvalidValue(code, cls), e)
+            raise InvalidValue(code, cls) from e
 
         return parsed_object, parsed_length
 
diff --git a/cryptoparser/common/field.py b/cryptoparser/common/field.py
index 197772d..5b1eea8 100644
--- a/cryptoparser/common/field.py
+++ b/cryptoparser/common/field.py
@@ -301,7 +301,7 @@ def _parse(cls, parsable):
         try:
             parser.parse_string_by_length('name', len(name), len(name))
         except NotEnoughData as e:
-            six.raise_from(InvalidType, e)
+            raise InvalidType from e
 
         cls._check_name(parser['name'])
 
@@ -568,7 +568,7 @@ def _parse_value(cls, parser):
         try:
             parser.parse_parsable('value', cls._get_value_type())
         except InvalidValue as e:
-            six.raise_from(InvalidValue(e.value.decode('ascii'), cls, 'value'), e)
+            raise InvalidValue(e.value.decode('ascii'), cls, 'value') from e
 
     def _get_value_as_simple_type(self):
         return self.value.value.code
@@ -668,7 +668,7 @@ def _parse(cls, parsable):
         try:
             raw_values = json.loads(parsable.decode('ascii'), object_pairs_hook=collections.OrderedDict)
         except ValueError as e:  # json.decoder.JSONDecodeError is derived from ValueError
-            six.raise_from(InvalidValue(six.ensure_text(parsable, 'ascii'), cls, 'value'), e)
+            raise InvalidValue(six.ensure_text(parsable, 'ascii'), cls, 'value') from e
 
         attr_fields_dict = attr.fields_dict(cls)
 
@@ -1012,7 +1012,7 @@ def _parse(cls, parsable):
         try:
             value = cls._get_value_type().parse_exact_size(parsable)
         except InvalidValue as e:
-            six.raise_from(InvalidValue(six.ensure_text(parsable, 'ascii'), cls, 'value'), e)
+            raise InvalidValue(six.ensure_text(parsable, 'ascii'), cls, 'value') from e
 
         return cls(value), len(parsable)
 
diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index ec5cd97..0b5d1ae 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -169,9 +169,9 @@ def _parse_string_by_length(
                 value = converter(value)
             self._parsed_values[name] = value
         except UnicodeError as e:
-            six.raise_from(InvalidValue(value, converter, name), e)
+            raise InvalidValue(value, converter, name) from e
         except ValueError as e:
-            six.raise_from(InvalidValue(value, converter, name), e)
+            raise InvalidValue(value, converter, name) from e
 
         return value, parsable_length
 
@@ -239,7 +239,7 @@ def _parse_numeric_array(  # pylint: disable=too-many-arguments,too-many-positio
                 try:
                     item_offset += self._check_separators(name, item_offset, separator, 1, 1)
                 except InvalidValue as e:
-                    six.raise_from(InvalidValue(self._parsable[self._parsed_length:item_offset], type(self), name), e)
+                    raise InvalidValue(self._parsable[self._parsed_length:item_offset], type(self), name) from e
 
             last_item_offset = item_offset
             floating_point_found = False
@@ -285,9 +285,7 @@ def parse_string(self, name, value):
                 name, min_length, max_length, self._encoding, str
             )
         except NotEnoughData as e:
-            six.raise_from(
-                InvalidValue(self._parsable[self._parsed_length:min_length - e.bytes_needed], type(self), name), e
-            )
+            raise InvalidValue(self._parsable[self._parsed_length:min_length - e.bytes_needed], type(self), name) from e
 
         if value != actual_value:
             raise InvalidValue(self._parsable[self._parsed_length:self._parsed_length + max_length], type(self), name)
@@ -329,7 +327,7 @@ def _apply_item_class(  # pylint: disable=too-many-arguments,too-many-positional
                 item_offset += parsed_length
                 return parsed_value
 
-            six.raise_from(InvalidValue(self._parsable[item_offset:], type(self), name), e)
+            raise InvalidValue(self._parsable[item_offset:], type(self), name) from e
 
         return item
 
@@ -472,7 +470,7 @@ def parse_date_time(self, name):
             value = self._parsable[self._parsed_length:]
             date_time = dateutil.parser.parse(six.ensure_text(value, self._encoding))
         except ValueError as e:
-            six.raise_from(InvalidValue(value, type(self), 'value'), e)
+            raise InvalidValue(value, type(self), 'value') from e
 
         self._parsed_values[name] = date_time
         self._parsed_length = len(self._parsable)
@@ -483,7 +481,7 @@ def parse_time_delta(self, name):
         try:
             time_delta = datetime.timedelta(seconds=value[0])
         except OverflowError as e:
-            six.raise_from(InvalidValue(value[0], type(self), 'value'), e)
+            raise InvalidValue(value[0], type(self), 'value') from e
 
         self._parsed_values[name] = time_delta
         self._parsed_length += parsed_length
@@ -530,7 +528,7 @@ def _parse_numeric_array(self, name, item_num, item_size, item_numeric_class):
                 try:
                     value.append(item_numeric_class(item))
                 except ValueError as e:
-                    six.raise_from(InvalidValue(item, item_numeric_class, name), e)
+                    raise InvalidValue(item, item_numeric_class, name) from e
         else:
             raise NotImplementedError()
 
@@ -622,7 +620,7 @@ def parse_bytes(self, name, size, converter=bytearray):
         try:
             self._parsed_values[name] = converter(parsed_bytes)
         except ValueError as e:
-            six.raise_from(InvalidValue(value, converter, name), e)
+            raise InvalidValue(value, converter, name) from e
         self._parsed_length += len(parsed_bytes)
 
     def parse_raw(self, name, size, converter=bytearray):
@@ -631,7 +629,7 @@ def parse_raw(self, name, size, converter=bytearray):
         try:
             self._parsed_values[name] = converter(parsed_bytes)
         except ValueError as e:
-            six.raise_from(InvalidValue(parsed_bytes, converter, name), e)
+            raise InvalidValue(parsed_bytes, converter, name) from e
 
         self._parsed_length += size
 
@@ -655,7 +653,7 @@ def parse_string_null_terminated(self, name, encoding, converter=str):
                 if value == 0
             ]))
         except StopIteration as e:
-            six.raise_from(InvalidValue(self._parsable[self._parsed_length:], str, name), e)
+            raise InvalidValue(self._parsable[self._parsed_length:], str, name) from e
 
         value, parsed_length = self._parse_string_by_length(name, length, length, encoding, converter)
         self._parsed_length += parsed_length + 1
@@ -692,7 +690,7 @@ def parse_parsable_array(self, name, items_size, item_class, fallback_class=None
         except NotEnoughData as e:
             raise e
         except ValueError as e:
-            six.raise_from(InvalidValue(e.args[0], item_class, name), e)
+            raise InvalidValue(e.args[0], item_class, name) from e
 
         self._parsed_values[name] = items
         self._parsed_length += items_size
@@ -704,7 +702,7 @@ def parse_parsable_derived_array(self, name, items_size, item_base_class, fallba
         except NotEnoughData as e:
             raise e
         except ValueError as e:
-            six.raise_from(InvalidValue(e.args[0], item_base_class, name), e)
+            raise InvalidValue(e.args[0], item_base_class, name) from e
 
         self._parsed_values[name] = items
         self._parsed_length += items_size
@@ -720,7 +718,7 @@ def parse_parsable_list(self, name, item_class, fallback_class=None, separator_c
                 self.unparsed_length, [separator_class, item_class], fallback_class
             )
         except ValueError as e:
-            six.raise_from(InvalidValue(e.args[0], item_class, name), e)
+            raise InvalidValue(e.args[0], item_class, name) from e
 
         if not items:
             raise NotEnoughData(2)
@@ -770,7 +768,7 @@ def _compose_string_array(self, values, encoding, separator):
                 else:
                     composed_str += six.ensure_binary(six.text_type(value), encoding)
             except UnicodeError as e:
-                six.raise_from(InvalidValue(value, type(self)), e)
+                raise InvalidValue(value, type(self)) from e
 
             composed_str += separator
 
@@ -874,7 +872,7 @@ def _compose_numeric_array(self, values, item_size):
                 else:
                     composed_bytes += packed_bytes
             except struct.error as e:
-                six.raise_from(InvalidValue(value, int), e)
+                raise InvalidValue(value, int) from e
 
         self._composed += composed_bytes
 
@@ -972,7 +970,7 @@ def compose_string(self, value, encoding, item_size):
         try:
             value = six.ensure_binary(value, encoding)
         except UnicodeError as e:
-            six.raise_from(InvalidValue(value, type(self)), e)
+            raise InvalidValue(value, type(self)) from e
 
         self.compose_bytes(value, item_size)
 
@@ -980,7 +978,7 @@ def compose_string_null_terminated(self, value, encoding):
         try:
             value = value.encode(encoding)
         except UnicodeError as e:
-            six.raise_from(InvalidValue(value, type(self)), e)
+            raise InvalidValue(value, type(self)) from e
 
         self.compose_raw(value)
         self.compose_raw(b'\x00')
diff --git a/cryptoparser/common/utils.py b/cryptoparser/common/utils.py
index 3135614..d57ee29 100644
--- a/cryptoparser/common/utils.py
+++ b/cryptoparser/common/utils.py
@@ -39,6 +39,6 @@ def bytes_from_hex_string(hex_string, separator=''):
     try:
         binary_data = binascii.a2b_hex(hex_string)
     except (TypeError, ValueError) as e:
-        six.raise_from(ValueError(*e.args), e)
+        raise ValueError(*e.args) from e
 
     return binary_data
diff --git a/cryptoparser/dnsrec/txt.py b/cryptoparser/dnsrec/txt.py
index 3b795f0..defa3c0 100644
--- a/cryptoparser/dnsrec/txt.py
+++ b/cryptoparser/dnsrec/txt.py
@@ -494,7 +494,7 @@ def _parse_qualifier_and_mechanism_name(cls, parsable):
         try:
             parser.parse_string('mechanism', mechanism.value.code)
         except InvalidValue as e:
-            six.raise_from(InvalidType, e)
+            raise InvalidType from e
 
         return parser
 
@@ -879,7 +879,7 @@ def _parse(cls, parsable):
         try:
             parser.parse_parsable('version', DnsRecordTxtValueSpfVersion)
         except InvalidValue as e:
-            six.raise_from(InvalidType, e)
+            raise InvalidType from e
 
         terms = []
         while parser.unparsed_length:
diff --git a/cryptoparser/httpx/header.py b/cryptoparser/httpx/header.py
index 9c0434e..7acf9ec 100644
--- a/cryptoparser/httpx/header.py
+++ b/cryptoparser/httpx/header.py
@@ -448,7 +448,7 @@ def _parse(cls, parsable):
         try:
             parser.parse_parsable('hash_algorithm', cls._get_hash_algorithm_enum_type())
         except InvalidValue as e:
-            six.raise_from(InvalidType(), e)
+            raise InvalidType() from e
 
         parser.parse_string_until_separator_or_end('hash_value', ' ')
 
@@ -483,7 +483,7 @@ def _parse(cls, parsable):
         try:
             parser.parse_string('prefix', cls._PREFIX)
         except InvalidValue as e:
-            six.raise_from(InvalidType(), e)
+            raise InvalidType() from e
 
         del parser['prefix']
 
diff --git a/cryptoparser/ssh/key.py b/cryptoparser/ssh/key.py
index 96df2be..bab4f9b 100644
--- a/cryptoparser/ssh/key.py
+++ b/cryptoparser/ssh/key.py
@@ -1107,7 +1107,7 @@ def _parse(cls, parsable):
         try:
             parser.parse_raw('public_key', public_key_length, PublicKeyX509.from_der)
         except (NotEnoughData, InvalidValue) as e:
-            six.raise_from(InvalidValue(parser.unparsed, cls, 'public_key'), e)
+            raise InvalidValue(parser.unparsed, cls, 'public_key') from e
 
         public_key = parser['public_key']
         if host_key_algorithm is None:
diff --git a/cryptoparser/ssh/subprotocol.py b/cryptoparser/ssh/subprotocol.py
index 6cce1f6..a4fa95c 100644
--- a/cryptoparser/ssh/subprotocol.py
+++ b/cryptoparser/ssh/subprotocol.py
@@ -94,7 +94,7 @@ def comment_validator(self, _, value):  # pylint: disable=no-self-use
             try:
                 six.ensure_binary(value, 'ascii')
             except UnicodeEncodeError as e:
-                six.raise_from(InvalidValue(value, SshProtocolMessage, 'comment'), e)
+                raise InvalidValue(value, SshProtocolMessage, 'comment') from e
 
     @classmethod
     def _parse(cls, parsable):
diff --git a/cryptoparser/ssh/version.py b/cryptoparser/ssh/version.py
index c358f77..a7e87d5 100644
--- a/cryptoparser/ssh/version.py
+++ b/cryptoparser/ssh/version.py
@@ -45,7 +45,7 @@ def _parse(cls, parsable):
             parser.parse_separator('.')
             parser.parse_numeric('minor')
         except InvalidValue as e:
-            six.raise_from(InvalidValue(parsable, SshProtocolVersion), e)
+            raise InvalidValue(parsable, SshProtocolVersion) from e
 
         return SshProtocolVersion(parser['major'], parser['minor']), parser.parsed_length
 
@@ -92,7 +92,7 @@ def raw_validator(self, _, value):  # pylint: disable=no-self-use
         try:
             six.ensure_binary(value, 'ascii')
         except UnicodeEncodeError as e:
-            six.raise_from(InvalidValue(value, SshSoftwareVersionUnparsed, 'raw'), e)
+            raise InvalidValue(value, SshSoftwareVersionUnparsed, 'raw') from e
 
     def _as_markdown(self, level):
         return self._markdown_result(self.raw, level)
diff --git a/cryptoparser/tls/extension.py b/cryptoparser/tls/extension.py
index afadc9b..00f9a62 100644
--- a/cryptoparser/tls/extension.py
+++ b/cryptoparser/tls/extension.py
@@ -72,7 +72,7 @@ def get_item_by_type(self, extension_type):
                 if extension.extension_type == extension_type
             )
         except StopIteration as e:
-            six.raise_from(KeyError, e)
+            raise KeyError from e
 
         return item
 
diff --git a/cryptoparser/tls/ldap.py b/cryptoparser/tls/ldap.py
index 0919f00..6e7c46f 100644
--- a/cryptoparser/tls/ldap.py
+++ b/cryptoparser/tls/ldap.py
@@ -159,9 +159,9 @@ def _parse_asn1(cls, parsable):
             if match:
                 bytes_requested = int(match.group(1))
                 bytes_available = int(match.group(2))
-                six.raise_from(NotEnoughData(bytes_requested - bytes_available), e)
-            else:
-                six.raise_from(InvalidValue(parsable, cls), e)
+                raise NotEnoughData(bytes_requested - bytes_available) from e
+
+            raise InvalidValue(parsable, cls) from e
 
         return message
 
diff --git a/cryptoparser/tls/record.py b/cryptoparser/tls/record.py
index 780bc15..35940c3 100644
--- a/cryptoparser/tls/record.py
+++ b/cryptoparser/tls/record.py
@@ -37,7 +37,7 @@ def parse_header(cls, parsable):
         try:
             parser.parse_numeric('content_type', 1, TlsContentType)
         except InvalidValue as e:
-            six.raise_from(InvalidValue(e.value, TlsContentType), e)
+            raise InvalidValue(e.value, TlsContentType) from e
         parser.parse_parsable('protocol_version', TlsProtocolVersion)
         parser.parse_numeric('fragment_length', 2)
 
@@ -90,7 +90,7 @@ def _parse(cls, parsable):
         try:
             parser.parse_numeric('message_type', 1, SslMessageType)
         except InvalidValue as e:
-            six.raise_from(InvalidValue(e.value, SslMessageType), e)
+            raise InvalidValue(e.value, SslMessageType) from e
 
         parser.parse_variant('message', SslSubprotocolMessageParser(parser['message_type']))
         parser.parse_raw('padding', padding_length)
diff --git a/cryptoparser/tls/subprotocol.py b/cryptoparser/tls/subprotocol.py
index 6371f5c..77a0482 100644
--- a/cryptoparser/tls/subprotocol.py
+++ b/cryptoparser/tls/subprotocol.py
@@ -153,14 +153,14 @@ def _validator_level(self, attribute, value):  # pylint: disable=unused-argument
         try:
             self.level = TlsAlertLevel(value)
         except ValueError as e:
-            six.raise_from(InvalidValue(value, TlsAlertLevel, 'level'), e)
+            raise InvalidValue(value, TlsAlertLevel, 'level') from e
 
     @description.validator
     def _validator_description(self, attribute, value):  # pylint: disable=unused-argument
         try:
             self.description = TlsAlertDescription(value)
         except ValueError as e:
-            six.raise_from(InvalidValue(value, TlsAlertDescription), e)
+            raise InvalidValue(value, TlsAlertDescription) from e
 
 
 class TlsChangeCipherSpecType(enum.IntEnum):
@@ -255,7 +255,7 @@ def _parse_handshake_header(cls, parsable):
         try:
             parser.parse_bytes('payload', 3)
         except NotEnoughData as e:
-            six.raise_from(NotEnoughData(e.bytes_needed), e)
+            raise NotEnoughData(e.bytes_needed) from e
 
         return parser
 

From 0433a1ade786f034af411fcddba3ddd8ef3442f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sat, 30 Nov 2024 14:42:52 +0100
Subject: [PATCH 06/21] chore!: Remove usage of six module assertRaisesRegex
 (#87)

---
 test/common/test_algorithm.py       |  2 +-
 test/common/test_exception.py       | 18 ++++++++----------
 test/ssh/test_version.py            |  6 +++---
 test/tls/test_alert.py              |  4 ++--
 test/tls/test_change_cipher_spec.py |  2 +-
 test/tls/test_handshake.py          |  4 ++--
 test/tls/test_record.py             |  6 +++---
 test/tls/test_version.py            |  4 ++--
 8 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/test/common/test_algorithm.py b/test/common/test_algorithm.py
index 564df3d..cb45e72 100644
--- a/test/common/test_algorithm.py
+++ b/test/common/test_algorithm.py
@@ -10,7 +10,7 @@
 
 class TestAlgortihmOIDBase(unittest.TestCase):
     def test_error_not_found(self):
-        with six.assertRaisesRegex(self, InvalidValue, '\'1.2.3.4.5.6.7.8\' is not a valid Authentication oid value'):
+        with self.assertRaisesRegex(InvalidValue, '\'1.2.3.4.5.6.7.8\' is not a valid Authentication oid value'):
             Authentication.from_oid('1.2.3.4.5.6.7.8')
 
     def test_from_oid(self):
diff --git a/test/common/test_exception.py b/test/common/test_exception.py
index 7659021..d9c8d9e 100644
--- a/test/common/test_exception.py
+++ b/test/common/test_exception.py
@@ -11,29 +11,27 @@
 
 class TestException(unittest.TestCase):
     def test_str(self):
-        with six.assertRaisesRegex(
-                self, NotEnoughData, 'not enough data received from target; missing_byte_count="10"'
+        with self.assertRaisesRegex(
+                NotEnoughData, 'not enough data received from target; missing_byte_count="10"'
         ) as context_manager:
             raise NotEnoughData(10)
         self.assertEqual(context_manager.exception.bytes_needed, 10)
 
-        with six.assertRaisesRegex(
-                self, TooMuchData, 'too much data received from target; rest_byte_count="10"'
+        with self.assertRaisesRegex(
+                TooMuchData, 'too much data received from target; rest_byte_count="10"'
         ) as context_manager:
             raise TooMuchData(10)
         self.assertEqual(context_manager.exception.bytes_needed, 10)
 
-        with six.assertRaisesRegex(
-                self, InvalidValue, '0xa is not a valid str member name value'
+        with self.assertRaisesRegex(
+                InvalidValue, '0xa is not a valid str member name value'
         ) as context_manager:
             raise InvalidValue(10, str, 'member name')
         self.assertEqual(context_manager.exception.value, 10)
 
-        with six.assertRaisesRegex(
-                self, InvalidValue, '0xa is not a valid str'
-        ) as context_manager:
+        with self.assertRaisesRegex(InvalidValue, '0xa is not a valid str') as context_manager:
             raise InvalidValue(10, str)
         self.assertEqual(context_manager.exception.value, 10)
 
-        with six.assertRaisesRegex(self, InvalidType, 'invalid type value received from target') as context_manager:
+        with self.assertRaisesRegex(InvalidType, 'invalid type value received from target') as context_manager:
             raise InvalidType(10)
diff --git a/test/ssh/test_version.py b/test/ssh/test_version.py
index 5c21838..9ff1835 100644
--- a/test/ssh/test_version.py
+++ b/test/ssh/test_version.py
@@ -28,17 +28,17 @@ class TestSshVersion(unittest.TestCase):
     def test_error(self):
         parsable = b'3.0'
         expected_error_message = '3 is not a valid SshVersion'
-        with six.assertRaisesRegex(self, ValueError, expected_error_message):
+        with self.assertRaisesRegex(ValueError, expected_error_message):
             # pylint: disable=expression-not-assigned
             SshProtocolVersion.parse_exact_size(parsable)
 
         expected_error_message = '\'.0\' is not a valid SshProtocolVersion'
-        with six.assertRaisesRegex(self, InvalidValue, expected_error_message):
+        with self.assertRaisesRegex(InvalidValue, expected_error_message):
             # pylint: disable=expression-not-assigned
             SshProtocolVersion.parse_exact_size(b'.0')
 
         expected_error_message = '\'2.\' is not a valid SshProtocolVersion'
-        with six.assertRaisesRegex(self, InvalidValue, expected_error_message):
+        with self.assertRaisesRegex(InvalidValue, expected_error_message):
             # pylint: disable=expression-not-assigned
             SshProtocolVersion.parse_exact_size(b'2.')
 
diff --git a/test/tls/test_alert.py b/test/tls/test_alert.py
index feda418..d6bae46 100644
--- a/test/tls/test_alert.py
+++ b/test/tls/test_alert.py
@@ -13,11 +13,11 @@
 
 class TestAlert(unittest.TestCase):
     def test_error(self):
-        with six.assertRaisesRegex(self, InvalidValue, '0xff is not a valid TlsAlertLevel'):
+        with self.assertRaisesRegex(InvalidValue, '0xff is not a valid TlsAlertLevel'):
             # pylint: disable=expression-not-assigned
             TlsAlertMessage.parse_exact_size(b'\xff\x00')
 
-        with six.assertRaisesRegex(self, InvalidValue, '0xff is not a valid TlsAlertDescription'):
+        with self.assertRaisesRegex(InvalidValue, '0xff is not a valid TlsAlertDescription'):
             # pylint: disable=expression-not-assigned
             TlsAlertMessage.parse_exact_size(b'\x01\xff')
 
diff --git a/test/tls/test_change_cipher_spec.py b/test/tls/test_change_cipher_spec.py
index 61df568..03d8656 100644
--- a/test/tls/test_change_cipher_spec.py
+++ b/test/tls/test_change_cipher_spec.py
@@ -15,7 +15,7 @@
 
 class TestRecord(unittest.TestCase):
     def test_error(self):
-        with six.assertRaisesRegex(self, InvalidValue, '0xff is not a valid TlsChangeCipherSpecType'):
+        with self.assertRaisesRegex(InvalidValue, '0xff is not a valid TlsChangeCipherSpecType'):
             # pylint: disable=expression-not-assigned
             TlsChangeCipherSpecMessage.parse_exact_size(b'\xff')
 
diff --git a/test/tls/test_handshake.py b/test/tls/test_handshake.py
index 214622c..1782b29 100644
--- a/test/tls/test_handshake.py
+++ b/test/tls/test_handshake.py
@@ -117,7 +117,7 @@ def test_error(self):
         ])
         invalid_tls_message_bytes = b''.join(invalid_tls_message_dict.values())
 
-        with six.assertRaisesRegex(self, InvalidValue, 'is not a valid TlsHandshakeMessageVariant'):
+        with self.assertRaisesRegex(InvalidValue, 'is not a valid TlsHandshakeMessageVariant'):
             TlsHandshakeMessageVariant.parse_exact_size(invalid_tls_message_bytes)
 
     def test_compose(self):
@@ -701,7 +701,7 @@ def test_error(self):
             error_regex = '\'\\\\x00\' is not a valid TlsHandshakeServerHelloDone payload value'
         else:
             error_regex = 'b\'\\\\x00\' is not a valid TlsHandshakeServerHelloDone payload value'
-        with six.assertRaisesRegex(self, InvalidValue, error_regex):
+        with self.assertRaisesRegex(InvalidValue, error_regex):
             # pylint: disable=expression-not-assigned
             TlsHandshakeServerHelloDone.parse_exact_size(b'\x0e\x00\x00\x01\x00')
 
diff --git a/test/tls/test_record.py b/test/tls/test_record.py
index 5e5ee6e..e6505ef 100644
--- a/test/tls/test_record.py
+++ b/test/tls/test_record.py
@@ -18,7 +18,7 @@
 class TestTlsSubprotocolMessageBase(unittest.TestCase):
     def test_error(self):
         error_message = 'Can\'t instantiate abstract class TlsSubprotocolMessageBase'
-        with six.assertRaisesRegex(self, BaseException, error_message) as context_manager:
+        with self.assertRaisesRegex(BaseException, error_message) as context_manager:
             TlsSubprotocolMessageBase()  # pylint: disable=abstract-class-instantiated
         self.assertTrue(isinstance(context_manager.exception, (TypeError, AssertionError)))
 
@@ -48,7 +48,7 @@ def test_error(self):
             TlsRecord.parse_exact_size(b'')
         self.assertEqual(context_manager.exception.bytes_needed, TlsRecord.HEADER_SIZE)
 
-        with six.assertRaisesRegex(self, InvalidValue, '0xff is not a valid TlsContentType'):
+        with self.assertRaisesRegex(InvalidValue, '0xff is not a valid TlsContentType'):
             TlsRecord.parse_exact_size(
                 b'\xff' +      # type = INVALID
                 b'\x03\x03' +  # version = TLS 1.2
@@ -111,7 +111,7 @@ def setUp(self):
         )
 
     def test_error(self):
-        with six.assertRaisesRegex(self, InvalidValue, '0xff is not a valid SslMessageType'):
+        with self.assertRaisesRegex(InvalidValue, '0xff is not a valid SslMessageType'):
             SslRecord.parse_exact_size(
                 b'\x80\x00' +  # length = 0
                 b'\xff' +      # type = INVALID
diff --git a/test/tls/test_version.py b/test/tls/test_version.py
index 00db865..c0a3a19 100644
--- a/test/tls/test_version.py
+++ b/test/tls/test_version.py
@@ -16,12 +16,12 @@ class TestTlsProtocolVersion(unittest.TestCase):
     def test_parse(self):
         parsable = b'\x03\xff'
         expected_error_message = ' is not a valid TlsVersionFactory'
-        with six.assertRaisesRegex(self, InvalidValue, expected_error_message):
+        with self.assertRaisesRegex(InvalidValue, expected_error_message):
             # pylint: disable=expression-not-assigned
             TlsProtocolVersion.parse_exact_size(parsable)
 
         expected_error_message = ' is not a valid TlsVersionFactory'
-        with six.assertRaisesRegex(self, InvalidValue, expected_error_message):
+        with self.assertRaisesRegex(InvalidValue, expected_error_message):
             # pylint: disable=expression-not-assigned
             TlsProtocolVersion.parse_exact_size(b'\x8f\x00')
 

From 5433121a064bdc0314e6c45419511acb736b048f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sat, 30 Nov 2024 21:58:57 +0100
Subject: [PATCH 07/21] chore!: Remove usage of six module
 ensure_text/str/binary (#87)

---
 cryptoparser/common/base.py     | 11 ++++-------
 cryptoparser/common/field.py    |  6 +++---
 cryptoparser/common/parse.py    | 32 ++++++++++++++++----------------
 cryptoparser/httpx/header.py    |  4 ++--
 cryptoparser/ssh/key.py         |  6 +++---
 cryptoparser/ssh/subprotocol.py |  6 +++---
 cryptoparser/ssh/version.py     |  2 +-
 cryptoparser/tls/extension.py   |  6 ++----
 test/common/classes.py          | 12 +++---------
 test/common/test_base.py        |  8 ++++----
 test/common/test_field.py       |  2 +-
 test/common/test_parse.py       | 16 ++++++++--------
 test/ssh/test_record.py         | 10 +++++-----
 test/ssh/test_subprotocol.py    |  6 +++---
 test/ssh/test_version.py        |  8 ++++----
 test/tls/test_extension.py      |  2 +-
 16 files changed, 63 insertions(+), 74 deletions(-)

diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index c3f2fa7..4dd949b 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -856,7 +856,7 @@ def _parse(cls, parsable):
         enum_items.sort(key=lambda color: len(color.value.code), reverse=True)
 
         try:
-            code = six.ensure_text(bytes(parsable), 'ascii')
+            code = bytes(parsable).decode('ascii')
         except UnicodeDecodeError as e:
             raise InvalidValue(parsable, cls) from e
 
@@ -867,7 +867,7 @@ def _parse(cls, parsable):
         raise InvalidValue(parsable, cls, 'code')
 
     def compose(self):
-        return six.ensure_binary(self._asdict(), 'ascii')
+        return self._asdict().encode('ascii')
 
     def _asdict(self):
         return getattr(self, 'value').code
@@ -1003,10 +1003,7 @@ class OpaqueEnumParsable(Vector):
     @classmethod
     def _parse(cls, parsable):
         opaque, parsed_length = super(OpaqueEnumParsable, cls)._parse(parsable)
-        code = six.ensure_text(
-            b''.join([six.int2byte(opaque_item) for opaque_item in opaque]),
-            cls.get_encoding()
-        )
+        code = b''.join([six.int2byte(opaque_item) for opaque_item in opaque]).decode(cls.get_encoding())
 
         try:
             parsed_object = next(iter([
@@ -1035,7 +1032,7 @@ def __repr__(self):
 
     def compose(self):
         composer = ComposerBinary()
-        value = six.ensure_binary(self.value.code, self.get_encoding())  # pylint: disable=no-member
+        value = self.value.code.encode(self.get_encoding())  # pylint: disable=no-member
 
         composer.compose_bytes(value, 1)
 
diff --git a/cryptoparser/common/field.py b/cryptoparser/common/field.py
index 5b1eea8..38dcb77 100644
--- a/cryptoparser/common/field.py
+++ b/cryptoparser/common/field.py
@@ -668,7 +668,7 @@ def _parse(cls, parsable):
         try:
             raw_values = json.loads(parsable.decode('ascii'), object_pairs_hook=collections.OrderedDict)
         except ValueError as e:  # json.decoder.JSONDecodeError is derived from ValueError
-            raise InvalidValue(six.ensure_text(parsable, 'ascii'), cls, 'value') from e
+            raise InvalidValue(parsable.decode('ascii'), cls, 'value') from e
 
         attr_fields_dict = attr.fields_dict(cls)
 
@@ -720,7 +720,7 @@ def _parse_basic_params(cls, attr_to_component_name_dict, attr_fields_dict, comp
                     parsable = component
                 else:
                     parsable = '='.join([attr_to_component_name_dict[name].get_canonical_name(), parsable])
-                params[name] = attr_to_component_name_dict[name].parse_exact_size(six.ensure_binary(parsable, 'ascii'))
+                params[name] = attr_to_component_name_dict[name].parse_exact_size(parsable.encode('ascii'))
             else:
                 params[name] = attribute.default
 
@@ -1012,7 +1012,7 @@ def _parse(cls, parsable):
         try:
             value = cls._get_value_type().parse_exact_size(parsable)
         except InvalidValue as e:
-            raise InvalidValue(six.ensure_text(parsable, 'ascii'), cls, 'value') from e
+            raise InvalidValue(parsable.decode('ascii'), cls, 'value') from e
 
         return cls(value), len(parsable)
 
diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index 0b5d1ae..68f3b5d 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -164,7 +164,7 @@ def _parse_string_by_length(
 
         value = self._parsable[self._parsed_length:self._parsed_length + parsable_length]
         try:
-            value = six.ensure_text(value, encoding)
+            value = value.decode(encoding)
             if converter != str:
                 value = converter(value)
             self._parsed_values[name] = value
@@ -189,7 +189,7 @@ def _check_separators(  # pylint: disable=too-many-arguments,too-many-positional
             min_count,
             max_count
     ):
-        separators = six.ensure_binary(separators, self._encoding)
+        separators = separators.encode(self._encoding)
 
         count = 0
         actual_offset = count_offset
@@ -309,16 +309,16 @@ def _apply_item_class(  # pylint: disable=too-many-arguments,too-many-positional
             may_end):
         try:
             if not isinstance(item_class, type):
-                item = item_class(six.ensure_text(self._parsable[item_offset:item_end], self._encoding))
+                item = item_class(self._parsable[item_offset:item_end].decode(self._encoding))
             elif issubclass(item_class, CryptoDataEnumCodedBase):
-                item = item_class.from_code(six.ensure_text(self._parsable[item_offset:item_end], self._encoding))
+                item = item_class.from_code(self._parsable[item_offset:item_end].decode(self._encoding))
             elif issubclass(item_class, ParsableBaseNoABC):
                 item, parsed_length = item_class.parse_immutable(self._parsable[item_offset:item_end])
                 item_end = item_offset + parsed_length
             elif issubclass(item_class, str):
-                item = six.ensure_text(self._parsable[item_offset:item_end], self._encoding)
+                item = self._parsable[item_offset:item_end].decode(self._encoding)
             else:
-                item = item_class(six.ensure_text(self._parsable[item_offset:item_end], self._encoding))
+                item = item_class(self._parsable[item_offset:item_end].decode(self._encoding))
         except (InvalidValue, ValueError, UnicodeError) as e:
             if fallback_class is not None:
                 parsed_value, parsed_length = self._parse_string_until_separator(
@@ -342,7 +342,7 @@ def _parse_string_until_separator(  # pylint: disable=too-many-arguments,too-man
             separator_spaces=''
     ):
         item_end = None
-        byte_separators = [six.ensure_binary(separator, self._encoding) for separator in separators]
+        byte_separators = [separator.encode(self._encoding) for separator in separators]
 
         for separator_end in range(item_offset, len(self._parsable) + 1):
             for separator in byte_separators:
@@ -358,7 +358,7 @@ def _parse_string_until_separator(  # pylint: disable=too-many-arguments,too-man
             item_end = len(self._parsable)
 
         separator_space_count = 0
-        byte_separator_spaces = six.ensure_binary(separator_spaces, self._encoding)
+        byte_separator_spaces = separator_spaces.encode(self._encoding)
         while (item_end > item_offset and
                 self._parsable[
                     item_end - separator_space_count - 1:
@@ -468,7 +468,7 @@ def parse_string_array(
     def parse_date_time(self, name):
         try:
             value = self._parsable[self._parsed_length:]
-            date_time = dateutil.parser.parse(six.ensure_text(value, self._encoding))
+            date_time = dateutil.parser.parse(value.decode(self._encoding))
         except ValueError as e:
             raise InvalidValue(value, type(self), 'value') from e
 
@@ -758,7 +758,7 @@ def composed_length(self):
         return len(self._composed)
 
     def _compose_string_array(self, values, encoding, separator):
-        separator = bytearray(six.ensure_binary(separator, encoding))
+        separator = bytearray(separator.encode(encoding))
         composed_str = bytearray()
 
         for value in values:
@@ -766,7 +766,7 @@ def _compose_string_array(self, values, encoding, separator):
                 if isinstance(value, ParsableBaseNoABC):
                     composed_str += value.compose()
                 else:
-                    composed_str += six.ensure_binary(six.text_type(value), encoding)
+                    composed_str += six.text_type(value).encode(encoding)
             except UnicodeError as e:
                 raise InvalidValue(value, type(self)) from e
 
@@ -786,7 +786,7 @@ def _compose_numeric_array(self, values, separator):
         for value in values:
             composed_str += '{:d}{}'.format(value, separator)
 
-        self._composed += six.ensure_binary(composed_str[:len(composed_str) - len(separator)], self._encoding)
+        self._composed += composed_str[:len(composed_str) - len(separator)].encode(self._encoding)
 
     def compose_numeric(self, value):
         self._compose_numeric_array([value, ], separator='')
@@ -811,16 +811,16 @@ def compose_parsable(self, value):
         self._composed += self._compose_parsable(value)
 
     def compose_parsable_array(self, values, separator=',', fallback_class=None):
-        separator = six.ensure_binary(separator, self._encoding)
+        separator = separator.encode(self._encoding)
 
         composed_items = []
         for item in values:
             if isinstance(item, (ComposerBase, ParsableBase, ParsableBaseNoABC)):
                 composed_item = self._compose_parsable(item)
             elif isinstance(item, CryptoDataEnumBase):
-                composed_item = six.ensure_binary(item.value.code, self._encoding)
+                composed_item = item.value.code.encode(self._encoding)
             elif fallback_class is not None and isinstance(item, fallback_class):
-                composed_item = six.ensure_binary(item, self._encoding)
+                composed_item = item.encode(self._encoding)
             else:
                 raise InvalidType()
 
@@ -968,7 +968,7 @@ def compose_raw(self, value):
 
     def compose_string(self, value, encoding, item_size):
         try:
-            value = six.ensure_binary(value, encoding)
+            value = value.encode(encoding)
         except UnicodeError as e:
             raise InvalidValue(value, type(self)) from e
 
diff --git a/cryptoparser/httpx/header.py b/cryptoparser/httpx/header.py
index 7acf9ec..930297e 100644
--- a/cryptoparser/httpx/header.py
+++ b/cryptoparser/httpx/header.py
@@ -1747,14 +1747,14 @@ def _parse(cls, parsable):
         parser.parse_separator(' ', min_length=0, max_length=None)
         parser.parse_string_until_separator('value', ['\r\n', ])
 
-        value = cls._get_value_class().parse_exact_size(six.ensure_binary(parser['value'], 'ascii'))
+        value = cls._get_value_class().parse_exact_size(parser['value'].encode('ascii'))
 
         return cls(value), parser.parsed_length
 
     def compose(self):
         return self._compose_name_and_value(
             self.get_header_field_name().value.normalized_name,
-            six.ensure_text(bytes(self.value.compose()), 'ascii')
+            bytes(self.value.compose()).decode('ascii')
         )
 
     def _asdict(self):
diff --git a/cryptoparser/ssh/key.py b/cryptoparser/ssh/key.py
index bab4f9b..9c11077 100644
--- a/cryptoparser/ssh/key.py
+++ b/cryptoparser/ssh/key.py
@@ -72,9 +72,9 @@ def _fingerprint(cls, hash_type, key_bytes, prefix):
         digest = hash_bytes(hash_type, key_bytes)
 
         if hash_type == Hash.MD5:
-            fingerprint = ':'.join(textwrap.wrap(six.ensure_text(binascii.hexlify(digest), 'ascii'), 2))
+            fingerprint = ':'.join(textwrap.wrap(binascii.hexlify(digest).decode('ascii'), 2))
         else:
-            fingerprint = six.ensure_text(base64.b64encode(digest), 'ascii')
+            fingerprint = base64.b64encode(digest).decode('ascii')
 
         return ':'.join((prefix, fingerprint))
 
@@ -87,7 +87,7 @@ def fingerprints(self):
         ])
 
     def host_key_asdict(self):
-        known_hosts = six.ensure_text(base64.b64encode(self.key_bytes), 'ascii')
+        known_hosts = base64.b64encode(self.key_bytes).decode('ascii')
 
         public_key_dict = (
             [('key_type', self.host_key_algorithm.value.key_type.value)] +
diff --git a/cryptoparser/ssh/subprotocol.py b/cryptoparser/ssh/subprotocol.py
index a4fa95c..bf0a93c 100644
--- a/cryptoparser/ssh/subprotocol.py
+++ b/cryptoparser/ssh/subprotocol.py
@@ -92,7 +92,7 @@ def comment_validator(self, _, value):  # pylint: disable=no-self-use
             if '\r' in value or '\n' in value:
                 raise InvalidValue(value, SshProtocolMessage, 'comment')
             try:
-                six.ensure_binary(value, 'ascii')
+                value.encode('ascii')
             except UnicodeEncodeError as e:
                 raise InvalidValue(value, SshProtocolMessage, 'comment') from e
 
@@ -114,7 +114,7 @@ def _parse(cls, parsable):
         if software_version_and_comment[-1][-1] == '\r':
             software_version_and_comment[-1] = software_version_and_comment[-1][:-1]
 
-        software_version_parser = ParserText(six.ensure_binary(software_version_and_comment[0], 'ascii'))
+        software_version_parser = ParserText(software_version_and_comment[0].encode('ascii'))
         try:
             software_version_parser.parse_parsable('value', SshSoftwareVersionParsedVariant)
         except InvalidValue:
@@ -318,7 +318,7 @@ def _hassh(algorithm_vectors):
         ])
 
         message = hashlib.md5()
-        message.update(six.ensure_binary(hassh_text, 'ascii'))
+        message.update(hassh_text.encode('ascii'))
 
         return bytes_to_hex_string(message.digest(), lowercase=True)
 
diff --git a/cryptoparser/ssh/version.py b/cryptoparser/ssh/version.py
index a7e87d5..59c43b0 100644
--- a/cryptoparser/ssh/version.py
+++ b/cryptoparser/ssh/version.py
@@ -90,7 +90,7 @@ def raw_validator(self, _, value):  # pylint: disable=no-self-use
         if '\r' in value or '\n' in value or ' ' in value:
             raise InvalidValue(value, SshSoftwareVersionUnparsed, 'raw')
         try:
-            six.ensure_binary(value, 'ascii')
+            value.encode('ascii')
         except UnicodeEncodeError as e:
             raise InvalidValue(value, SshSoftwareVersionUnparsed, 'raw') from e
 
diff --git a/cryptoparser/tls/extension.py b/cryptoparser/tls/extension.py
index 00f9a62..832f35b 100644
--- a/cryptoparser/tls/extension.py
+++ b/cryptoparser/tls/extension.py
@@ -245,14 +245,12 @@ def _parse(cls, parsable):
         parser.parse_numeric('server_name_type', 1, TlsServerNameType)
         parser.parse_parsable('server_name', TlsServerName)
 
-        return cls(
-            six.ensure_text(bytes(bytearray(parser['server_name'])), 'idna')
-        ), parser.parsed_length
+        return cls(bytearray(parser['server_name']).decode('idna')), parser.parsed_length
 
     def compose(self):
         composer = ComposerBinary()
 
-        idna_encoded_host_name = six.ensure_binary(self.host_name, 'idna')
+        idna_encoded_host_name = self.host_name.encode('idna')
 
         composer.compose_numeric(3 + len(idna_encoded_host_name), 2)
         composer.compose_numeric(self.name_type, 1)
diff --git a/test/common/classes.py b/test/common/classes.py
index e83a4f6..403228d 100644
--- a/test/common/classes.py
+++ b/test/common/classes.py
@@ -249,15 +249,9 @@ class OpaqueEnumParams():
 
 
 class OpaqueEnum(OpaqueEnumComposer):
-    ALPHA = OpaqueEnumParams(
-        code=six.ensure_text('άλφα')
-    )
-    BETA = OpaqueEnumParams(
-        code=six.ensure_text('βήτα')
-    )
-    GAMMA = OpaqueEnumParams(
-        code=six.ensure_text('γάμμα')
-    )
+    ALPHA = OpaqueEnumParams(code='άλφα')
+    BETA = OpaqueEnumParams(code='βήτα')
+    GAMMA = OpaqueEnumParams(code='γάμμα')
 
 
 class TestObject():
diff --git a/test/common/test_base.py b/test/common/test_base.py
index 7d839d4..ab7fbf5 100644
--- a/test/common/test_base.py
+++ b/test/common/test_base.py
@@ -485,18 +485,18 @@ def test_compose(self):
 class TestOpaqueEnum(unittest.TestCase):
     def test_error(self):
         with self.assertRaises(InvalidValue) as context_manager:
-            OpaqueEnumFactory.parse_exact_size(b'\x0a' + six.ensure_binary('δέλτα', 'utf-8'))
-        self.assertEqual(context_manager.exception.value, six.ensure_text('δέλτα'))
+            OpaqueEnumFactory.parse_exact_size(b'\x0a' + 'δέλτα'.encode('utf-8'))
+        self.assertEqual(context_manager.exception.value, 'δέλτα')
 
     def test_parse(self):
         self.assertEqual(
             OpaqueEnum.ALPHA,
-            OpaqueEnumFactory.parse_exact_size(b'\x08' + six.ensure_binary(six.ensure_text('άλφα'), 'utf-8'))
+            OpaqueEnumFactory.parse_exact_size(b'\x08' + 'άλφα'.encode('utf-8'))
         )
 
     def test_compose(self):
         self.assertEqual(
-            b'\x0a' + six.ensure_binary(six.ensure_text('γάμμα'), 'utf-8'),
+            b'\x0a' + 'γάμμα'.encode('utf-8'),
             OpaqueEnum.GAMMA.compose()  # pylint: disable=no-member
         )
 
diff --git a/test/common/test_field.py b/test/common/test_field.py
index 427bb5d..f5be94c 100644
--- a/test/common/test_field.py
+++ b/test/common/test_field.py
@@ -307,7 +307,7 @@ def test_error(self):
 
         with self.assertRaises(InvalidValue) as context_manager:
             FieldValueComponentTimeDeltaTest.parse_exact_size(
-                b'testTimeDelta=' + six.ensure_binary(str(2 ** 48), 'ascii')
+                b'testTimeDelta=' + str(2 ** 48).encode('ascii')
             )
         self.assertEqual(context_manager.exception.value, 2 ** 48)
 
diff --git a/test/common/test_parse.py b/test/common/test_parse.py
index 7322522..5dce24d 100644
--- a/test/common/test_parse.py
+++ b/test/common/test_parse.py
@@ -35,11 +35,11 @@
 
 
 class TestParsableBase(unittest.TestCase):
-    _ALPHA_BETA_GAMMA = six.ensure_text('αβγ')
-    _ALPHA_BETA_GAMMA_BYTES = six.ensure_binary(six.ensure_text('αβγ'), 'utf-8')
+    _ALPHA_BETA_GAMMA = 'αβγ'
+    _ALPHA_BETA_GAMMA_BYTES = 'αβγ'.encode('utf-8')
     _ALPHA_BETA_GAMMA_LEN_BYTES = six.int2byte(len(_ALPHA_BETA_GAMMA_BYTES))
 
-    _ALPHA_BETA_GAMMA_HASHMARK_BYTES = six.ensure_binary(six.ensure_text('αβγ#'), 'utf-8')
+    _ALPHA_BETA_GAMMA_HASHMARK_BYTES = 'αβγ#'.encode('utf-8')
 
 
 class TestParsable(TestParsableBase):
@@ -534,7 +534,7 @@ def test_parse_string_until_separator(self):
 
         parser = ParserText(self._ALPHA_BETA_GAMMA_HASHMARK_BYTES, 'utf-8')
         parser.parse_string_until_separator('alphabet', '#')
-        self.assertEqual(parser['alphabet'], six.ensure_text('αβγ'))
+        self.assertEqual(parser['alphabet'], 'αβγ')
         self.assertEqual(parser.unparsed_length, 1)
 
         parser = ParserText(b'ab')
@@ -787,7 +787,7 @@ def test_parse_time_delta(self):
         self.assertEqual(parser['timedelta'], datetime.timedelta(1))
         self.assertEqual(parser.unparsed_length, 0)
 
-        timedelta_value = six.ensure_binary(str(int(datetime.timedelta.max.total_seconds())), 'ascii')
+        timedelta_value = str(int(datetime.timedelta.max.total_seconds())).encode('ascii')
         parser = ParserText(timedelta_value)
         with self.assertRaises(InvalidValue) as context_manager:
             parser.parse_time_delta('timedelta')
@@ -1134,7 +1134,7 @@ def test_compose_string(self):
         composer = ComposerText('utf-8')
         for index, char in enumerate(self._ALPHA_BETA_GAMMA):
             composer.compose_string(char)
-            expected_composed = six.ensure_binary(self._ALPHA_BETA_GAMMA[0:index + 1], 'utf-8')
+            expected_composed = self._ALPHA_BETA_GAMMA[0:index + 1].encode('utf-8')
             self.assertEqual(composer.composed, expected_composed)
             self.assertEqual(composer.composed_length, (index + 1) * 2)
 
@@ -1152,7 +1152,7 @@ def test_compose_string_array(self):
 
         composer = ComposerText('utf-8')
         composer.compose_string_array(list(self._ALPHA_BETA_GAMMA), '')
-        self.assertEqual(composer.composed, six.ensure_binary(self._ALPHA_BETA_GAMMA, 'utf-8'))
+        self.assertEqual(composer.composed, self._ALPHA_BETA_GAMMA.encode('utf-8'))
         self.assertEqual(composer.composed_length, len(self._ALPHA_BETA_GAMMA) * 2)
 
         composer = ComposerText()
@@ -1176,7 +1176,7 @@ def test_compose_separator(self):
         composer = ComposerText('utf-8')
 
         composer.compose_separator(self._ALPHA_BETA_GAMMA)
-        self.assertEqual(composer.composed, six.ensure_binary(self._ALPHA_BETA_GAMMA, 'utf-8'))
+        self.assertEqual(composer.composed, self._ALPHA_BETA_GAMMA.encode('utf-8'))
 
     def test_compose_date_time(self):
         composer = ComposerText()
diff --git a/test/ssh/test_record.py b/test/ssh/test_record.py
index 3fe6e54..88b0b14 100644
--- a/test/ssh/test_record.py
+++ b/test/ssh/test_record.py
@@ -15,7 +15,7 @@ class TestRecord(unittest.TestCase):
     def setUp(self):
         self.test_packet = SshDisconnectMessage(
             SshReasonCode.PROTOCOL_ERROR,
-            six.text_type(six.ensure_text('αβγ')),
+            six.text_type('αβγ'),
             six.text_type('en-US')
         )
         self.test_record = SshRecordInit(self.test_packet)
@@ -25,7 +25,7 @@ def setUp(self):
             b'\x01' +                                             # message code = DISCONNECT
             b'\x00\x00\x00\x02' +                                 # reason = PROTOCOL_ERROR
             b'\x00\x00\x00\x06' +                                 # description length = 6
-            six.ensure_binary(six.ensure_text('αβγ'), 'utf-8') +  # description
+            'αβγ'.encode('utf-8') +                               # description
             b'\x00\x00\x00\x05' +                                 # language length = 5
             b'en-US' +                                            # language
             b'\x00\x00\x00\x00\x00\x00\x00\x00' +                 # padding
@@ -47,17 +47,17 @@ def test_error(self):
     def test_parse(self):
         record = SshRecordInit.parse_exact_size(self.test_record_bytes)
         self.assertEqual(record.packet.reason, SshReasonCode.PROTOCOL_ERROR)
-        self.assertEqual(record.packet.description, six.ensure_text('αβγ'))
+        self.assertEqual(record.packet.description, 'αβγ')
         self.assertEqual(record.packet.language, 'en-US')
 
         record = SshRecordKexDH.parse_exact_size(self.test_record_bytes)
         self.assertEqual(record.packet.reason, SshReasonCode.PROTOCOL_ERROR)
-        self.assertEqual(record.packet.description, six.ensure_text('αβγ'))
+        self.assertEqual(record.packet.description, 'αβγ')
         self.assertEqual(record.packet.language, 'en-US')
 
         record = SshRecordKexDHGroup.parse_exact_size(self.test_record_bytes)
         self.assertEqual(record.packet.reason, SshReasonCode.PROTOCOL_ERROR)
-        self.assertEqual(record.packet.description, six.ensure_text('αβγ'))
+        self.assertEqual(record.packet.description, 'αβγ')
         self.assertEqual(record.packet.language, 'en-US')
 
     def test_compose(self):
diff --git a/test/ssh/test_subprotocol.py b/test/ssh/test_subprotocol.py
index 5f90520..95299ae 100644
--- a/test/ssh/test_subprotocol.py
+++ b/test/ssh/test_subprotocol.py
@@ -82,19 +82,19 @@ def test_comment(self):
             SshProtocolMessage(
                 SshProtocolVersion(SshVersion.SSH2, 2),
                 SshSoftwareVersionUnparsed('software_version'),
-                comment=six.ensure_text('αβγ'),
+                comment='αβγ',
             )
         with self.assertRaises(InvalidValue):
             SshProtocolMessage(
                 SshProtocolVersion(SshVersion.SSH2, 2),
                 SshSoftwareVersionUnparsed('software_version'),
-                comment=six.ensure_text('comment\r'),
+                comment='comment\r',
             )
         with self.assertRaises(InvalidValue):
             SshProtocolMessage(
                 SshProtocolVersion(SshVersion.SSH2, 2),
                 SshSoftwareVersionUnparsed('software_version'),
-                comment=six.ensure_text('comment\n'),
+                comment='comment\n',
             )
 
     def test_compose(self):
diff --git a/test/ssh/test_version.py b/test/ssh/test_version.py
index 9ff1835..4ca23ed 100644
--- a/test/ssh/test_version.py
+++ b/test/ssh/test_version.py
@@ -185,10 +185,10 @@ def test_compose(self):
 
     def test_error_raw(self):
         with self.assertRaises(InvalidValue):
-            SshSoftwareVersionUnparsed(six.ensure_text('αβγ'))
+            SshSoftwareVersionUnparsed('αβγ')
         with self.assertRaises(InvalidValue):
-            SshSoftwareVersionUnparsed(six.ensure_text('software_version '))
+            SshSoftwareVersionUnparsed('software_version ')
         with self.assertRaises(InvalidValue):
-            SshSoftwareVersionUnparsed(six.ensure_text('software_version\r'))
+            SshSoftwareVersionUnparsed('software_version\r')
         with self.assertRaises(InvalidValue):
-            SshSoftwareVersionUnparsed(six.ensure_text('software_version\n'))
+            SshSoftwareVersionUnparsed('software_version\n')
diff --git a/test/tls/test_extension.py b/test/tls/test_extension.py
index bd942ee..ed21140 100644
--- a/test/tls/test_extension.py
+++ b/test/tls/test_extension.py
@@ -170,7 +170,7 @@ def test_parse(self):
         extension_hostname_internationalized = TlsExtensionServerNameClient.parse_exact_size(
             extension_hostname_internationalized_bytes
         )
-        self.assertEqual(extension_hostname_internationalized.host_name, six.ensure_text('ísland.icom.museum'))
+        self.assertEqual(extension_hostname_internationalized.host_name, 'ísland.icom.museum')
         self.assertEqual(extension_hostname_internationalized.compose(), extension_hostname_internationalized_bytes)
 
 

From 5505bfd4470f4d7e136810bb46bd950570f444f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sat, 30 Nov 2024 22:09:11 +0100
Subject: [PATCH 08/21] chore!: Remove usage of six module u (#87)

---
 cryptoparser/dnsrec/record.py | 2 +-
 test/common/classes.py        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/cryptoparser/dnsrec/record.py b/cryptoparser/dnsrec/record.py
index 7d53922..fa413f9 100644
--- a/cryptoparser/dnsrec/record.py
+++ b/cryptoparser/dnsrec/record.py
@@ -339,7 +339,7 @@ class DnsNameUncompressed(ParsableBase, Serializable):
     )
 
     def __str__(self):
-        return six.u('.').join(self.labels)
+        return '.'.join(self.labels)
 
     def _as_markdown(self, level):
         return self._markdown_result(str(self), level)
diff --git a/test/common/classes.py b/test/common/classes.py
index 403228d..19f4641 100644
--- a/test/common/classes.py
+++ b/test/common/classes.py
@@ -263,7 +263,7 @@ def __init__(self):
         self.int_value = 1
         self.float_value = 1.0
         self.bool_value = False
-        self.str_value = six.u('string')
+        self.str_value = 'string'
         self.bytearray_value = bytearray(b'\x00\x01\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f')
         self.none_value = None
 

From e949df0c810f8cd3fa979b822b181bb149e5a9c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sat, 30 Nov 2024 22:11:54 +0100
Subject: [PATCH 09/21] chore!: Remove usage of six module iterbytes (#87)

---
 cryptoparser/common/base.py  | 2 +-
 cryptoparser/common/parse.py | 2 +-
 cryptoparser/common/utils.py | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index 4dd949b..ac38efa 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -464,7 +464,7 @@ class ArrayBase(ParsableBase, MutableSequence, Serializable):
 
     def __attrs_post_init__(self):
         if isinstance(self._items, six.binary_type):
-            items = six.iterbytes(bytes(self._items))
+            items = bytes(self._items)
         else:
             items = self._items
 
diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index 68f3b5d..d15ba0e 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -649,7 +649,7 @@ def parse_string_null_terminated(self, name, encoding, converter=str):
         try:
             length = next(iter([
                 i
-                for i, value in enumerate(six.iterbytes(self._parsable[self._parsed_length:]))
+                for i, value in enumerate(self._parsable[self._parsed_length:])
                 if value == 0
             ]))
         except StopIteration as e:
diff --git a/cryptoparser/common/utils.py b/cryptoparser/common/utils.py
index d57ee29..5dd8d5d 100644
--- a/cryptoparser/common/utils.py
+++ b/cryptoparser/common/utils.py
@@ -29,7 +29,7 @@ def bytes_to_hex_string(byte_array, separator='', lowercase=False):
     else:
         format_str = '{:02X}'
 
-    return separator.join([format_str.format(x) for x in six.iterbytes(bytes(byte_array))])
+    return separator.join([format_str.format(x) for x in bytes(byte_array)])
 
 
 def bytes_from_hex_string(hex_string, separator=''):

From 28cdb69c356f5aabeac9906c9be6e6f3e24f75e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 1 Dec 2024 19:03:32 +0100
Subject: [PATCH 10/21] chore!: Remove usage of six module int2byte (#87)

---
 cryptoparser/common/base.py   | 2 +-
 cryptoparser/common/parse.py  | 2 +-
 cryptoparser/tls/extension.py | 2 +-
 test/common/test_parse.py     | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index ac38efa..0f5671e 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -1003,7 +1003,7 @@ class OpaqueEnumParsable(Vector):
     @classmethod
     def _parse(cls, parsable):
         opaque, parsed_length = super(OpaqueEnumParsable, cls)._parse(parsable)
-        code = b''.join([six.int2byte(opaque_item) for opaque_item in opaque]).decode(cls.get_encoding())
+        code = b''.join([bytes((opaque_item,)) for opaque_item in opaque]).decode(cls.get_encoding())
 
         try:
             parsed_object = next(iter([
diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index d15ba0e..8672687 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -562,7 +562,7 @@ def parse_numeric_flags(self, name, size, flags_class, shift_left=0):
 
     def _parse_mpint(self, mpint_length, mpint_offset, negative):
         if mpint_length % 4:
-            pad_byte = six.int2byte(0xff) if negative else six.int2byte(0x00)
+            pad_byte = bytes((0xff,)) if negative else bytes((0x00,))
             pad_bytes = (4 - (mpint_length % 4)) * pad_byte
         else:
             pad_bytes = b''
diff --git a/cryptoparser/tls/extension.py b/cryptoparser/tls/extension.py
index 832f35b..28e815e 100644
--- a/cryptoparser/tls/extension.py
+++ b/cryptoparser/tls/extension.py
@@ -1173,7 +1173,7 @@ def _parse(cls, parsable):
         parser.parse_raw('padding', parser['extension_length'])
         try:
             non_zero_int = next(byte for byte in parser['padding'] if byte != 0)
-            raise InvalidValue(six.int2byte(non_zero_int), cls)
+            raise InvalidValue(bytes((non_zero_int,)), cls)
         except StopIteration:
             pass
 
diff --git a/test/common/test_parse.py b/test/common/test_parse.py
index 5dce24d..46fd98f 100644
--- a/test/common/test_parse.py
+++ b/test/common/test_parse.py
@@ -37,7 +37,7 @@
 class TestParsableBase(unittest.TestCase):
     _ALPHA_BETA_GAMMA = 'αβγ'
     _ALPHA_BETA_GAMMA_BYTES = 'αβγ'.encode('utf-8')
-    _ALPHA_BETA_GAMMA_LEN_BYTES = six.int2byte(len(_ALPHA_BETA_GAMMA_BYTES))
+    _ALPHA_BETA_GAMMA_LEN_BYTES = bytes((len(_ALPHA_BETA_GAMMA_BYTES),))
 
     _ALPHA_BETA_GAMMA_HASHMARK_BYTES = 'αβγ#'.encode('utf-8')
 

From 11cddc608e0139ad4b448e809f715388439db0ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 1 Dec 2024 19:07:55 +0100
Subject: [PATCH 11/21] chore!: Remove usage of six module text_type (#87)

---
 cryptoparser/common/parse.py    | 2 +-
 cryptoparser/ssh/subprotocol.py | 2 +-
 test/ssh/test_record.py         | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index 8672687..532a291 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -766,7 +766,7 @@ def _compose_string_array(self, values, encoding, separator):
                 if isinstance(value, ParsableBaseNoABC):
                     composed_str += value.compose()
                 else:
-                    composed_str += six.text_type(value).encode(encoding)
+                    composed_str += str(value).encode(encoding)
             except UnicodeError as e:
                 raise InvalidValue(value, type(self)) from e
 
diff --git a/cryptoparser/ssh/subprotocol.py b/cryptoparser/ssh/subprotocol.py
index bf0a93c..7c747fe 100644
--- a/cryptoparser/ssh/subprotocol.py
+++ b/cryptoparser/ssh/subprotocol.py
@@ -363,7 +363,7 @@ class SshReasonCode(enum.IntEnum):
 class SshDisconnectMessage(SshMessageBase):
     reason = attr.ib(validator=attr.validators.instance_of(SshReasonCode))
     description = attr.ib(
-        converter=six.text_type,
+        converter=str,
         validator=attr.validators.instance_of(str)
     )
     language = attr.ib(
diff --git a/test/ssh/test_record.py b/test/ssh/test_record.py
index 88b0b14..d8f1723 100644
--- a/test/ssh/test_record.py
+++ b/test/ssh/test_record.py
@@ -15,8 +15,8 @@ class TestRecord(unittest.TestCase):
     def setUp(self):
         self.test_packet = SshDisconnectMessage(
             SshReasonCode.PROTOCOL_ERROR,
-            six.text_type('αβγ'),
-            six.text_type('en-US')
+            'αβγ',
+            'en-US'
         )
         self.test_record = SshRecordInit(self.test_packet)
         self.test_record_bytes = bytes(

From 38e3b8de05d78613a03561915bd5e270513e8dff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 1 Dec 2024 19:11:45 +0100
Subject: [PATCH 12/21] chore!: Remove usage of six module binary_type (#87)

---
 cryptoparser/common/base.py | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index 0f5671e..73df603 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -463,10 +463,7 @@ class ArrayBase(ParsableBase, MutableSequence, Serializable):
     param = attr.ib(init=False, default=None)
 
     def __attrs_post_init__(self):
-        if isinstance(self._items, six.binary_type):
-            items = bytes(self._items)
-        else:
-            items = self._items
+        items = self._items
 
         self.param = self.get_param()
         self._items = []

From 51fbed78e56eb9f351a97310059a18973a02d938 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 1 Dec 2024 19:21:20 +0100
Subject: [PATCH 13/21] chore!: Remove usage of six module indexbytes (#87)

---
 cryptoparser/common/parse.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index 532a291..ad3343b 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -225,7 +225,7 @@ def _parse_numeric_array(  # pylint: disable=too-many-arguments,too-many-positio
 
             if (is_floating and
                     not floating_point_found and item_offset < len(self._parsable) and
-                    six.indexbytes(self._parsable, item_offset) == ord('.')):
+                    self._parsable[item_offset] == ord('.')):
                 item_offset += 1
                 floating_point_found = True
                 continue
@@ -593,7 +593,7 @@ def parse_ssh_mpint(self, name):
         mpint_length, parsed_length = self._parse_numeric_array(name, 1, 4, int)
         mpint_length = mpint_length[0]
 
-        negative = (mpint_length and (six.indexbytes(self._parsable, self._parsed_length + 4) >= 0x80))
+        negative = (mpint_length and self._parsable[self._parsed_length + 4] >= 0x80)
 
         value = self._parse_mpint(mpint_length, 4, negative)
 

From b9c7a58bae927e5b723c1f54399d85a1877c9ff8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 1 Dec 2024 19:25:24 +0100
Subject: [PATCH 14/21] chore!: Remove usage of six module add_metaclass (#87)

---
 cryptoparser/common/base.py  | 3 +--
 cryptoparser/common/parse.py | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index 73df603..5f8470c 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -882,8 +882,7 @@ def _code_eq(cls, item_code, parsed_code):
         return item_code.lower() == parsed_code.lower()
 
 
-@six.add_metaclass(abc.ABCMeta)
-class ProtocolVersionBase(Serializable, ParsableBase):
+class ProtocolVersionBase(Serializable, ParsableBase, metaclass=abc.ABCMeta):
     @classmethod
     @abc.abstractmethod
     def _parse(cls, parsable):
diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index ad3343b..61e2c47 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -51,8 +51,7 @@ def compose(self):
         raise NotImplementedError()
 
 
-@six.add_metaclass(abc.ABCMeta)
-class ParsableBase(ParsableBaseNoABC):
+class ParsableBase(ParsableBaseNoABC, metaclass=abc.ABCMeta):
     @classmethod
     @abc.abstractmethod
     def _parse(cls, parsable):

From 6cf87dd3ea98e728cc045e3db17dc14021567aec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 1 Dec 2024 19:39:55 +0100
Subject: [PATCH 15/21] chore!: Remove usage of six module indexbytes (#87)

---
 test/tls/test_handshake.py | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/test/tls/test_handshake.py b/test/tls/test_handshake.py
index 1782b29..4a3dedc 100644
--- a/test/tls/test_handshake.py
+++ b/test/tls/test_handshake.py
@@ -697,10 +697,7 @@ def setUp(self):
         self.server_hello_done = TlsHandshakeServerHelloDone()
 
     def test_error(self):
-        if six.PY2:
-            error_regex = '\'\\\\x00\' is not a valid TlsHandshakeServerHelloDone payload value'
-        else:
-            error_regex = 'b\'\\\\x00\' is not a valid TlsHandshakeServerHelloDone payload value'
+        error_regex = 'b\'\\\\x00\' is not a valid TlsHandshakeServerHelloDone payload value'
         with self.assertRaisesRegex(InvalidValue, error_regex):
             # pylint: disable=expression-not-assigned
             TlsHandshakeServerHelloDone.parse_exact_size(b'\x0e\x00\x00\x01\x00')

From f0c06efd63b8605d853d9435ecb6b66cf79ca750 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 1 Dec 2024 19:54:37 +0100
Subject: [PATCH 16/21] chore!: Remove import of six modules (#87)

---
 cryptoparser/common/base.py         | 1 -
 cryptoparser/common/field.py        | 1 -
 cryptoparser/common/parse.py        | 2 --
 cryptoparser/common/utils.py        | 2 --
 cryptoparser/dnsrec/record.py       | 1 -
 cryptoparser/dnsrec/txt.py          | 1 -
 cryptoparser/httpx/header.py        | 1 -
 cryptoparser/httpx/version.py       | 1 -
 cryptoparser/ssh/key.py             | 1 -
 cryptoparser/ssh/subprotocol.py     | 1 -
 cryptoparser/ssh/version.py         | 1 -
 cryptoparser/tls/extension.py       | 1 -
 cryptoparser/tls/ldap.py            | 1 -
 cryptoparser/tls/mysql.py           | 1 -
 cryptoparser/tls/openvpn.py         | 1 -
 cryptoparser/tls/record.py          | 1 -
 cryptoparser/tls/subprotocol.py     | 1 -
 test/common/classes.py              | 1 -
 test/common/test_algorithm.py       | 1 -
 test/common/test_base.py            | 1 -
 test/common/test_exception.py       | 1 -
 test/common/test_field.py           | 1 -
 test/common/test_parse.py           | 1 -
 test/ssh/test_record.py             | 1 -
 test/ssh/test_subprotocol.py        | 1 -
 test/ssh/test_version.py            | 1 -
 test/tls/test_alert.py              | 1 -
 test/tls/test_change_cipher_spec.py | 1 -
 test/tls/test_extension.py          | 1 -
 test/tls/test_handshake.py          | 1 -
 test/tls/test_record.py             | 1 -
 test/tls/test_version.py            | 1 -
 32 files changed, 34 deletions(-)

diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index 5f8470c..194ebd5 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -18,7 +18,6 @@
 from collections import OrderedDict
 
 import attr
-import six
 import urllib3
 
 from cryptodatahub.common.exception import InvalidValue
diff --git a/cryptoparser/common/field.py b/cryptoparser/common/field.py
index 38dcb77..f14d359 100644
--- a/cryptoparser/common/field.py
+++ b/cryptoparser/common/field.py
@@ -8,7 +8,6 @@
 import json
 
 import attr
-import six
 import urllib3
 
 from cryptodatahub.common.exception import InvalidValue
diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index 61e2c47..7fcff07 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -7,8 +7,6 @@
 import time
 
 import attr
-import six
-from six.moves import collections_abc
 
 import dateutil
 import dateutil.parser
diff --git a/cryptoparser/common/utils.py b/cryptoparser/common/utils.py
index 5dd8d5d..47dd592 100644
--- a/cryptoparser/common/utils.py
+++ b/cryptoparser/common/utils.py
@@ -3,8 +3,6 @@
 import binascii
 import inspect
 
-import six
-
 
 def get_leaf_classes(base_class):
 
diff --git a/cryptoparser/dnsrec/record.py b/cryptoparser/dnsrec/record.py
index fa413f9..5e3856c 100644
--- a/cryptoparser/dnsrec/record.py
+++ b/cryptoparser/dnsrec/record.py
@@ -6,7 +6,6 @@
 import enum
 
 import attr
-import six
 
 from cryptodatahub.common.algorithm import Authentication, NamedGroup, Signature
 from cryptodatahub.common.exception import InvalidValue
diff --git a/cryptoparser/dnsrec/txt.py b/cryptoparser/dnsrec/txt.py
index defa3c0..bd0befa 100644
--- a/cryptoparser/dnsrec/txt.py
+++ b/cryptoparser/dnsrec/txt.py
@@ -7,7 +7,6 @@
 import ipaddress
 
 import attr
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 from cryptodatahub.common.types import convert_url, convert_value_to_object
diff --git a/cryptoparser/httpx/header.py b/cryptoparser/httpx/header.py
index 930297e..cd5176c 100644
--- a/cryptoparser/httpx/header.py
+++ b/cryptoparser/httpx/header.py
@@ -7,7 +7,6 @@
 import itertools
 import enum
 
-import six
 
 import attr
 import urllib3
diff --git a/cryptoparser/httpx/version.py b/cryptoparser/httpx/version.py
index 795eebf..276a629 100644
--- a/cryptoparser/httpx/version.py
+++ b/cryptoparser/httpx/version.py
@@ -3,7 +3,6 @@
 import enum
 
 import attr
-import six
 
 from cryptoparser.common.base import Serializable
 
diff --git a/cryptoparser/ssh/key.py b/cryptoparser/ssh/key.py
index 9c11077..abae721 100644
--- a/cryptoparser/ssh/key.py
+++ b/cryptoparser/ssh/key.py
@@ -14,7 +14,6 @@
 
 import ipaddress
 import attr
-import six
 
 
 from cryptodatahub.common.algorithm import Authentication, Hash, NamedGroup
diff --git a/cryptoparser/ssh/subprotocol.py b/cryptoparser/ssh/subprotocol.py
index 7c747fe..8caac16 100644
--- a/cryptoparser/ssh/subprotocol.py
+++ b/cryptoparser/ssh/subprotocol.py
@@ -7,7 +7,6 @@
 import random
 
 import attr
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 from cryptodatahub.ssh.algorithm import (
diff --git a/cryptoparser/ssh/version.py b/cryptoparser/ssh/version.py
index 59c43b0..66066be 100644
--- a/cryptoparser/ssh/version.py
+++ b/cryptoparser/ssh/version.py
@@ -4,7 +4,6 @@
 import abc
 import collections
 import enum
-import six
 
 import attr
 
diff --git a/cryptoparser/tls/extension.py b/cryptoparser/tls/extension.py
index 28e815e..a1581af 100644
--- a/cryptoparser/tls/extension.py
+++ b/cryptoparser/tls/extension.py
@@ -4,7 +4,6 @@
 import abc
 import collections
 import enum
-import six
 import attr
 
 from cryptodatahub.common.exception import InvalidValue
diff --git a/cryptoparser/tls/ldap.py b/cryptoparser/tls/ldap.py
index 6e7c46f..c02d4a8 100644
--- a/cryptoparser/tls/ldap.py
+++ b/cryptoparser/tls/ldap.py
@@ -3,7 +3,6 @@
 import abc
 import enum
 import re
-import six
 
 import attr
 
diff --git a/cryptoparser/tls/mysql.py b/cryptoparser/tls/mysql.py
index 658a30a..e99e1ab 100644
--- a/cryptoparser/tls/mysql.py
+++ b/cryptoparser/tls/mysql.py
@@ -2,7 +2,6 @@
 
 import abc
 import enum
-import six
 
 import attr
 
diff --git a/cryptoparser/tls/openvpn.py b/cryptoparser/tls/openvpn.py
index 3940e82..6fa9ad2 100644
--- a/cryptoparser/tls/openvpn.py
+++ b/cryptoparser/tls/openvpn.py
@@ -4,7 +4,6 @@
 import abc
 import collections
 import enum
-import six
 
 import attr
 
diff --git a/cryptoparser/tls/record.py b/cryptoparser/tls/record.py
index 35940c3..162e2ff 100644
--- a/cryptoparser/tls/record.py
+++ b/cryptoparser/tls/record.py
@@ -2,7 +2,6 @@
 
 import attr
 
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 
diff --git a/cryptoparser/tls/subprotocol.py b/cryptoparser/tls/subprotocol.py
index 77a0482..3571354 100644
--- a/cryptoparser/tls/subprotocol.py
+++ b/cryptoparser/tls/subprotocol.py
@@ -9,7 +9,6 @@
 import random
 import attr
 
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 from cryptodatahub.tls.algorithm import SslCipherKind, TlsCipherSuite, TlsCipherSuiteExtension, TlsCompressionMethod
diff --git a/test/common/classes.py b/test/common/classes.py
index 19f4641..3312c1a 100644
--- a/test/common/classes.py
+++ b/test/common/classes.py
@@ -7,7 +7,6 @@
 import enum
 import json
 import attr
-import six
 
 try:
     import pathlib
diff --git a/test/common/test_algorithm.py b/test/common/test_algorithm.py
index cb45e72..e536e54 100644
--- a/test/common/test_algorithm.py
+++ b/test/common/test_algorithm.py
@@ -2,7 +2,6 @@
 
 import unittest
 
-import six
 
 from cryptodatahub.common.algorithm import Authentication, MAC, Signature
 from cryptodatahub.common.exception import InvalidValue
diff --git a/test/common/test_base.py b/test/common/test_base.py
index ab7fbf5..040e6b5 100644
--- a/test/common/test_base.py
+++ b/test/common/test_base.py
@@ -3,7 +3,6 @@
 import json
 import unittest
 
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 
diff --git a/test/common/test_exception.py b/test/common/test_exception.py
index d9c8d9e..1c846d4 100644
--- a/test/common/test_exception.py
+++ b/test/common/test_exception.py
@@ -2,7 +2,6 @@
 
 import unittest
 
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 
diff --git a/test/common/test_field.py b/test/common/test_field.py
index f5be94c..daff978 100644
--- a/test/common/test_field.py
+++ b/test/common/test_field.py
@@ -9,7 +9,6 @@
 
 import attr
 import dateutil
-import six
 import urllib3
 
 from cryptodatahub.common.exception import InvalidValue
diff --git a/test/common/test_parse.py b/test/common/test_parse.py
index 46fd98f..53a57d3 100644
--- a/test/common/test_parse.py
+++ b/test/common/test_parse.py
@@ -4,7 +4,6 @@
 import datetime
 import unittest
 
-import six
 import dateutil.tz
 
 import asn1crypto.x509
diff --git a/test/ssh/test_record.py b/test/ssh/test_record.py
index d8f1723..1d7c53c 100644
--- a/test/ssh/test_record.py
+++ b/test/ssh/test_record.py
@@ -3,7 +3,6 @@
 
 import unittest
 
-import six
 
 from cryptoparser.common.exception import NotEnoughData
 
diff --git a/test/ssh/test_subprotocol.py b/test/ssh/test_subprotocol.py
index 95299ae..276ec36 100644
--- a/test/ssh/test_subprotocol.py
+++ b/test/ssh/test_subprotocol.py
@@ -4,7 +4,6 @@
 import collections
 import unittest
 
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 from cryptodatahub.common.key import PublicKey, PublicKeyParamsRsa
diff --git a/test/ssh/test_version.py b/test/ssh/test_version.py
index 4ca23ed..67e7184 100644
--- a/test/ssh/test_version.py
+++ b/test/ssh/test_version.py
@@ -4,7 +4,6 @@
 import collections
 import unittest
 
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 from cryptodatahub.common.grade import Grade
diff --git a/test/tls/test_alert.py b/test/tls/test_alert.py
index d6bae46..1948230 100644
--- a/test/tls/test_alert.py
+++ b/test/tls/test_alert.py
@@ -2,7 +2,6 @@
 
 import unittest
 
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 
diff --git a/test/tls/test_change_cipher_spec.py b/test/tls/test_change_cipher_spec.py
index 03d8656..c3b2f60 100644
--- a/test/tls/test_change_cipher_spec.py
+++ b/test/tls/test_change_cipher_spec.py
@@ -2,7 +2,6 @@
 
 import unittest
 
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 
diff --git a/test/tls/test_extension.py b/test/tls/test_extension.py
index ed21140..f883df2 100644
--- a/test/tls/test_extension.py
+++ b/test/tls/test_extension.py
@@ -5,7 +5,6 @@
 import unittest
 
 import dateutil
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 from cryptodatahub.common.types import Base64Data
diff --git a/test/tls/test_handshake.py b/test/tls/test_handshake.py
index 4a3dedc..4bb8fa7 100644
--- a/test/tls/test_handshake.py
+++ b/test/tls/test_handshake.py
@@ -5,7 +5,6 @@
 import collections
 import copy
 import datetime
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 from cryptodatahub.tls.algorithm import (
diff --git a/test/tls/test_record.py b/test/tls/test_record.py
index e6505ef..e5c60fb 100644
--- a/test/tls/test_record.py
+++ b/test/tls/test_record.py
@@ -2,7 +2,6 @@
 
 import unittest
 
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 from cryptoparser.common.exception import NotEnoughData
diff --git a/test/tls/test_version.py b/test/tls/test_version.py
index c0a3a19..4cf5fa5 100644
--- a/test/tls/test_version.py
+++ b/test/tls/test_version.py
@@ -2,7 +2,6 @@
 
 import unittest
 
-import six
 
 from cryptodatahub.common.exception import InvalidValue
 from cryptodatahub.common.grade import Grade

From 53e43caa7632738faddf6a41d1b6cda278589136 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 1 Dec 2024 19:56:23 +0100
Subject: [PATCH 17/21] chore!: Remove import of six modules (#87)

---
 cryptoparser/common/parse.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index 7fcff07..0880ede 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 
 import abc
+import collections.abc
 import datetime
 import enum
 import struct
@@ -90,7 +91,7 @@ class ByteOrder(enum.Enum):
 
 
 @attr.s
-class ParserBase(collections_abc.Mapping):
+class ParserBase(collections.abc.Mapping):
     _parsable = attr.ib(converter=bytes, validator=attr.validators.instance_of((bytes, bytearray)))
     _parsed_length = attr.ib(init=False, default=0)
     _parsed_values = attr.ib(init=False, default=None)

From 340267968bfb4056e13549228c55ed2aed5d2941 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Tue, 3 Dec 2024 18:59:43 +0100
Subject: [PATCH 18/21] chore!: Remove unnecessary error hadling during
 unittest2 import (#87)

---
 test/common/test_parse.py | 6 +-----
 test/tls/test_grease.py   | 5 +----
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/test/common/test_parse.py b/test/common/test_parse.py
index 53a57d3..a414461 100644
--- a/test/common/test_parse.py
+++ b/test/common/test_parse.py
@@ -3,16 +3,12 @@
 
 import datetime
 import unittest
+from unittest import mock
 
 import dateutil.tz
 
 import asn1crypto.x509
 
-try:
-    from unittest import mock
-except ImportError:
-    import mock
-
 from cryptodatahub.common.exception import InvalidValue
 from cryptoparser.common.exception import NotEnoughData, TooMuchData, InvalidType
 from cryptoparser.common.parse import ParserBinary, ParserText, ParsableBase, ComposerBinary, ComposerText, ByteOrder
diff --git a/test/tls/test_grease.py b/test/tls/test_grease.py
index 47a8c57..cdc54d6 100644
--- a/test/tls/test_grease.py
+++ b/test/tls/test_grease.py
@@ -1,10 +1,7 @@
 # -*- coding: utf-8 -*-
 
 import unittest
-try:
-    from unittest import mock
-except ImportError:
-    import mock
+from unittest import mock
 
 from cryptoparser.tls.grease import (
     TlsInvalidType,

From ad5ad4ea49b1b2f6262f8756d93fa514b2927216 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Tue, 3 Dec 2024 19:15:03 +0100
Subject: [PATCH 19/21] chore!: Remove unnecessary error hadling during
 pathlib2 import (#87)

---
 docs/conf.py           | 6 +-----
 test/common/classes.py | 7 ++-----
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/docs/conf.py b/docs/conf.py
index 8911906..6ba6cff 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -4,14 +4,10 @@
 
 import datetime
 import os
+import pathlib
 import sys
 import urllib
 
-try:
-    import pathlib
-except ImportError:  # pragma: no cover
-    import pathlib2 as pathlib  # pragma: no cover
-
 sys.path.insert(0, os.path.abspath('..'))
 from cryptoparser.__setup__ import (  # noqa: E402, pylint: disable=wrong-import-position
     __author__,
diff --git a/test/common/classes.py b/test/common/classes.py
index 3312c1a..b90c1af 100644
--- a/test/common/classes.py
+++ b/test/common/classes.py
@@ -6,12 +6,9 @@
 import collections
 import enum
 import json
-import attr
+import pathlib
 
-try:
-    import pathlib
-except ImportError:  # pragma: no cover
-    import pathlib2 as pathlib  # pragma: no cover
+import attr
 
 import pyfakefs.fake_filesystem_unittest
 

From f86f6c2b0b79e0a66358159e3873380a01141ea4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 22 Dec 2024 13:34:04 +0100
Subject: [PATCH 20/21] chore!: Remove parameters of super function calls (#87)

---
 .pylintrc                       |  2 +-
 cryptoparser/common/base.py     |  2 +-
 cryptoparser/common/field.py    |  2 +-
 cryptoparser/common/parse.py    |  4 ++--
 cryptoparser/common/x509.py     |  2 +-
 cryptoparser/dnsrec/record.py   |  2 +-
 cryptoparser/httpx/header.py    |  2 +-
 cryptoparser/ssh/key.py         |  2 +-
 cryptoparser/ssh/subprotocol.py |  2 +-
 cryptoparser/tls/extension.py   |  2 +-
 cryptoparser/tls/openvpn.py     |  6 +++---
 cryptoparser/tls/subprotocol.py |  6 +++---
 test/common/classes.py          |  2 +-
 test/ssh/test_key.py            | 16 ++++++++--------
 14 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/.pylintrc b/.pylintrc
index 832ec4d..72db8e2 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -16,4 +16,4 @@ max-line-length = 120
 
 [MESSAGES CONTROL]
 
-disable = missing-docstring,too-few-public-methods,too-many-ancestors,duplicate-code,super-with-arguments,consider-using-f-string
+disable = missing-docstring,too-few-public-methods,too-many-ancestors,duplicate-code,consider-using-f-string
diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index 194ebd5..cf0fc19 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -397,7 +397,7 @@ def get_item_size(self, item):
 @attr.s(init=False)
 class OpaqueParam(VectorParamNumeric):  # pylint: disable=too-few-public-methods
     def __init__(self, min_byte_num, max_byte_num):
-        super(OpaqueParam, self).__init__(min_byte_num, max_byte_num, 1)
+        super().__init__(min_byte_num, max_byte_num, 1)
 
     def get_item_size(self, item):
         return 1
diff --git a/cryptoparser/common/field.py b/cryptoparser/common/field.py
index f14d359..2d0c90d 100644
--- a/cryptoparser/common/field.py
+++ b/cryptoparser/common/field.py
@@ -366,7 +366,7 @@ def _get_value_class(cls):
 class FieldValueComponentParsableOptional(FieldValueComponentParsableBase):
     def __attrs_post_init__(self):
         if self.value is not None:
-            super(FieldValueComponentParsableOptional, self).__attrs_post_init__()
+            super().__attrs_post_init__()
 
     @classmethod
     @abc.abstractmethod
diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index 0880ede..a1de0f8 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -176,7 +176,7 @@ def _parse_string_by_length(
 
 class ParserText(ParserBase):
     def __init__(self, parsable, encoding='ascii'):
-        super(ParserText, self).__init__(parsable)
+        super().__init__(parsable)
         self._encoding = encoding
 
     def _check_separators(  # pylint: disable=too-many-arguments,too-many-positional-arguments
@@ -775,7 +775,7 @@ def _compose_string_array(self, values, encoding, separator):
 
 class ComposerText(ComposerBase):
     def __init__(self, encoding='ascii'):
-        super(ComposerText, self).__init__()
+        super().__init__()
         self._encoding = encoding
 
     def _compose_numeric_array(self, values, separator):
diff --git a/cryptoparser/common/x509.py b/cryptoparser/common/x509.py
index 7bb50f5..8041d2b 100644
--- a/cryptoparser/common/x509.py
+++ b/cryptoparser/common/x509.py
@@ -116,7 +116,7 @@ def signed_certificate_timestamps(self):
         return SignedCertificateTimestampList([])
 
     def _asdict(self):
-        dict_value = super(PublicKeyX509, self)._asdict()
+        dict_value = super()._asdict()
 
         return collections.OrderedDict(list(dict_value.items()) + [
             ('signed_certificate_timestamps', self.signed_certificate_timestamps),
diff --git a/cryptoparser/dnsrec/record.py b/cryptoparser/dnsrec/record.py
index 5e3856c..32e9918 100644
--- a/cryptoparser/dnsrec/record.py
+++ b/cryptoparser/dnsrec/record.py
@@ -86,7 +86,7 @@ def key_tag(self):
         return key_tag & 0xffff
 
     def _asdict(self):
-        dict_value = super(DnsRecordDnskey, self)._asdict()
+        dict_value = super()._asdict()
         return collections.OrderedDict([('key_tag', self.key_tag)] + list(dict_value.items()))
 
     @classmethod
diff --git a/cryptoparser/httpx/header.py b/cryptoparser/httpx/header.py
index cd5176c..9a4c2f3 100644
--- a/cryptoparser/httpx/header.py
+++ b/cryptoparser/httpx/header.py
@@ -836,7 +836,7 @@ def _get_source_parser(cls):
         return ContentSecurityPolicyFrameAncestorsSource
 
     def _value_validator(self, value):
-        super(ContentSecurityPolicyDirectiveFrameAncestors, self)._value_validator(value)
+        super()._value_validator(value)
 
         has_invalid_source_type = any(map(
             lambda source: (
diff --git a/cryptoparser/ssh/key.py b/cryptoparser/ssh/key.py
index abae721..b49d1fb 100644
--- a/cryptoparser/ssh/key.py
+++ b/cryptoparser/ssh/key.py
@@ -572,7 +572,7 @@ def _parse_header(cls, parsable):
         return header_parser
 
     def _compose_header(self):
-        header_composer = super(SshCertExtensionNoData, self)._compose_header()
+        header_composer = super()._compose_header()
 
         header_composer.compose_numeric(0, 4)
 
diff --git a/cryptoparser/ssh/subprotocol.py b/cryptoparser/ssh/subprotocol.py
index 8caac16..d5a6bc2 100644
--- a/cryptoparser/ssh/subprotocol.py
+++ b/cryptoparser/ssh/subprotocol.py
@@ -199,7 +199,7 @@ def get_item_class(cls):
 
 class VectorParamSshLanguage(VectorParamString):
     def __init__(self):
-        super(VectorParamSshLanguage, self).__init__(
+        super().__init__(
             min_byte_num=0,
             max_byte_num=2 ** 32 - 1,
             separator=',',
diff --git a/cryptoparser/tls/extension.py b/cryptoparser/tls/extension.py
index a1581af..b01f841 100644
--- a/cryptoparser/tls/extension.py
+++ b/cryptoparser/tls/extension.py
@@ -684,7 +684,7 @@ def get_param(cls):
 
 class TlsExtensionCertificateStatusRequestClient(TlsExtensionParsed):
     def __init__(self, responder_id_list=(), extensions=()):
-        super(TlsExtensionCertificateStatusRequestClient, self).__init__()
+        super().__init__()
 
         self.responder_id_list = TlsCertificateStatusRequestResponderIdList(responder_id_list)
         self.request_extensions = TlsCertificateStatusRequestExtensions(extensions)
diff --git a/cryptoparser/tls/openvpn.py b/cryptoparser/tls/openvpn.py
index 6fa9ad2..cc2606b 100644
--- a/cryptoparser/tls/openvpn.py
+++ b/cryptoparser/tls/openvpn.py
@@ -130,7 +130,7 @@ def _parse(cls, parsable):
 @attr.s(init=False)
 class OpenVpnPacketAckV1(OpenVpnPacketBase):
     def __init__(self, session_id, remote_session_id, packet_id_array):
-        super(OpenVpnPacketAckV1, self).__init__(session_id, packet_id_array, remote_session_id)
+        super().__init__(session_id, packet_id_array, remote_session_id)
 
     @classmethod
     def get_op_code(cls):
@@ -149,7 +149,7 @@ def _parse(cls, parsable):
 @attr.s(init=False)
 class OpenVpnPacketHardResetClientV2(OpenVpnPacketBase):
     def __init__(self, session_id, packet_id):
-        super(OpenVpnPacketHardResetClientV2, self).__init__(session_id, packet_id_array=[], remote_session_id=None)
+        super().__init__(session_id, packet_id_array=[], remote_session_id=None)
 
         self.packet_id = packet_id
 
@@ -181,7 +181,7 @@ def compose(self):
 @attr.s(init=False)
 class OpenVpnPacketHardResetServerV2(OpenVpnPacketBase):
     def __init__(self, session_id, remote_session_id, packet_id_array, packet_id):
-        super(OpenVpnPacketHardResetServerV2, self).__init__(session_id, packet_id_array, remote_session_id)
+        super().__init__(session_id, packet_id_array, remote_session_id)
 
         self.packet_id = packet_id
 
diff --git a/cryptoparser/tls/subprotocol.py b/cryptoparser/tls/subprotocol.py
index 3571354..c0f3676 100644
--- a/cryptoparser/tls/subprotocol.py
+++ b/cryptoparser/tls/subprotocol.py
@@ -279,7 +279,7 @@ def _parse(cls, parsable):
         return cls(vector), parsed_length - vector_param.item_num_size
 
     def compose(self):
-        return super(TlsHandshakeHelloRandomBytes, self).compose()[self.get_param().item_num_size:]
+        return super().compose()[self.get_param().item_num_size:]
 
     @classmethod
     def get_param(cls):
@@ -334,7 +334,7 @@ def _parse_hello_header(cls, parsable):
     def _compose_header(self, payload_length):
         composer = ComposerBinary()
 
-        handshake_header_bytes = super(TlsHandshakeHello, self)._compose_header(
+        handshake_header_bytes = super()._compose_header(
             payload_length + composer.composed_length
         )
 
@@ -668,7 +668,7 @@ def compose(self):
 
 class TlsHandshakeCertificateStatus(TlsHandshakeMessage):
     def __init__(self, status_type, status):
-        super(TlsHandshakeCertificateStatus, self).__init__()
+        super().__init__()
 
         self.status_type = status_type
         self.status = status
diff --git a/test/common/classes.py b/test/common/classes.py
index b90c1af..f762d8f 100644
--- a/test/common/classes.py
+++ b/test/common/classes.py
@@ -754,7 +754,7 @@ class FieldValueMultipleExtendableTest(FieldValueMultipleTest):
 
 class SerializableUpperCaseEncoder(SerializableTextEncoder):
     def __call__(self, obj, level):
-        _, string_result = super(SerializableUpperCaseEncoder, self).__call__(obj, level)
+        _, string_result = super().__call__(obj, level)
 
         return False, string_result.upper()
 
diff --git a/test/ssh/test_key.py b/test/ssh/test_key.py
index 9e52681..87a6d66 100644
--- a/test/ssh/test_key.py
+++ b/test/ssh/test_key.py
@@ -438,7 +438,7 @@ def setUp(self):
 
 class TestHostCertificateV00DSS(TestHostCertificateDSSBase):
     def setUp(self):
-        super(TestHostCertificateV00DSS, self).setUp()
+        super().setUp()
         self.host_cert_bytes = bytes(
             b'\x00\x00\x00\x1c' +
             b'ssh-dss-cert-v00@openssh.com' +
@@ -575,7 +575,7 @@ def test_asdict(self):
 
 class TestHostCertificateV01DSS(TestHostCertificateDSSBase):
     def setUp(self):
-        super(TestHostCertificateV01DSS, self).setUp()
+        super().setUp()
         self.host_cert_bytes = bytes(
             b'\x00\x00\x00\x1c' +
             b'ssh-dss-cert-v01@openssh.com' +
@@ -738,7 +738,7 @@ def setUp(self):
 
 class TestHostCertificateV00RSA(TestHostCertificateRSABase):
     def setUp(self):
-        super(TestHostCertificateV00RSA, self).setUp()
+        super().setUp()
         self.host_cert_bytes = bytes(
             b'\x00\x00\x00\x1c' +
             b'ssh-rsa-cert-v00@openssh.com' +
@@ -853,7 +853,7 @@ def test_asdict(self):
 
 class TestHostCertificateV01RSA(TestHostCertificateRSABase):
     def setUp(self):
-        super(TestHostCertificateV01RSA, self).setUp()
+        super().setUp()
         self.host_cert_bytes = bytes(
             b'\x00\x00\x00\x1c' +
             b'ssh-rsa-cert-v01@openssh.com' +
@@ -998,7 +998,7 @@ def setUp(self):
 
 class TestHostCertificateV01ECDSA(TestHostCertificateECDSABase):
     def setUp(self):
-        super(TestHostCertificateV01ECDSA, self).setUp()
+        super().setUp()
         self.point_x_bytes = b'\x80' + (256 // 8 - 1) * b'\x00'
         self.point_y_bytes = b'\x40' + (256 // 8 - 1) * b'\x00'
         self.host_cert_bytes = bytes(
@@ -1151,7 +1151,7 @@ def setUp(self):
 
 class TestHostCertificateV01EDDSA(TestHostCertificateEDDSABase):
     def setUp(self):
-        super(TestHostCertificateV01EDDSA, self).setUp()
+        super().setUp()
         self.host_cert_bytes = bytes(
             b'\x00\x00\x00\x20' +
             b'ssh-ed25519-cert-v01@openssh.com' +
@@ -1270,7 +1270,7 @@ def test_asdict(self):
 
 class TestX509CertificateChain(TestClasses.TestKeyBase):
     def setUp(self):
-        super(TestX509CertificateChain, self).setUp()
+        super().setUp()
 
         x509_certificate = self._get_public_key_x509('snakeoil_cert.pem')
         self.x509_certificate_bytes = x509_certificate.der
@@ -1316,7 +1316,7 @@ def test_compose(self):
 
 class TestX509Certificate(TestClasses.TestKeyBase):
     def setUp(self):
-        super(TestX509Certificate, self).setUp()
+        super().setUp()
 
         self.x509v3_sign_rsa_header = bytes(
             b'\x00\x00\x00\x14' +  # host_key_algorithm

From feac42f90af613e4fa64ef476ca75d4740c0bcb3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szil=C3=A1rd=20Pfeiffer?= <coroner@pfeifferszilard.hu>
Date: Sun, 22 Dec 2024 14:08:32 +0100
Subject: [PATCH 21/21] chore!: Use f-string whenever possible (#87)

---
 .pylintrc                        |  2 +-
 cryptoparser/common/base.py      | 20 ++++++++------------
 cryptoparser/common/exception.py |  4 ++--
 cryptoparser/common/field.py     |  4 ++--
 cryptoparser/common/parse.py     |  2 +-
 cryptoparser/ssh/subprotocol.py  |  2 +-
 cryptoparser/ssh/version.py      |  4 ++--
 cryptoparser/tls/subprotocol.py  |  4 ++--
 cryptoparser/tls/version.py      |  6 +++---
 docs/conf.py                     |  2 +-
 test/common/classes.py           |  2 +-
 11 files changed, 24 insertions(+), 28 deletions(-)

diff --git a/.pylintrc b/.pylintrc
index 72db8e2..e477af8 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -16,4 +16,4 @@ max-line-length = 120
 
 [MESSAGES CONTROL]
 
-disable = missing-docstring,too-few-public-methods,too-many-ancestors,duplicate-code,consider-using-f-string
+disable = missing-docstring,too-few-public-methods,too-many-ancestors,duplicate-code
diff --git a/cryptoparser/common/base.py b/cryptoparser/common/base.py
index cf0fc19..cd2e5bc 100644
--- a/cryptoparser/common/base.py
+++ b/cryptoparser/common/base.py
@@ -188,12 +188,12 @@ def _markdown_result_complex(cls, obj, level=0):
         result = ''
         name_dict = cls._markdown_human_readable_names(obj, dict_value)
         for name, value in dict_value.items():
-            result += '{indent}* {name}'.format(indent=indent, name=name_dict[name])
+            result += f'{indent}* {name_dict[name]}'
             multiline, markdnow_result = cls._markdown_result(value, level + 1)
             if multiline:
-                result += ':\n{result}'.format(result=markdnow_result)
+                result += f':\n{markdnow_result}'
             else:
-                result += ': {result}\n'.format(result=markdnow_result)
+                result += f': {markdnow_result}\n'
 
         if not result:
             return False, '-'
@@ -210,13 +210,9 @@ def _markdown_result_list(cls, obj, level=0):
         result = ''
         for index, item in enumerate(obj):
             multiline, markdnow_result = cls._markdown_result(item, level + 1)
-            result += '{indent}{index}.{separator}{value}{newline}'.format(
-                indent=indent,
-                index=index + 1,
-                separator='\n' if multiline else ' ',
-                value=markdnow_result,
-                newline='' if multiline else '\n',
-            )
+            separator = '\n' if multiline else ' '
+            newline = '' if multiline else '\n'
+            result += f'{indent}{index + 1}.{separator}{markdnow_result}{newline}'
 
         return True, result
 
@@ -942,10 +938,10 @@ def compose(self):
 
     @property
     def identifier(self):
-        return '{}_{}'.format(self.major, self.minor)
+        return f'{self.major}_{self.minor}'
 
     def __str__(self):
-        return '{}.{}'.format(self.major, self.minor)
+        return f'{self.major}.{self.minor}'
 
 
 @attr.s
diff --git a/cryptoparser/common/exception.py b/cryptoparser/common/exception.py
index bc62dad..d285457 100644
--- a/cryptoparser/common/exception.py
+++ b/cryptoparser/common/exception.py
@@ -11,13 +11,13 @@ class InvalidDataLength(Exception):
 @attr.s
 class NotEnoughData(InvalidDataLength):
     def __str__(self):
-        return 'not enough data received from target; missing_byte_count="{}"'.format(self.bytes_needed)
+        return f'not enough data received from target; missing_byte_count="{self.bytes_needed}"'
 
 
 @attr.s
 class TooMuchData(InvalidDataLength):
     def __str__(self):
-        return 'too much data received from target; rest_byte_count="{}"'.format(self.bytes_needed)
+        return f'too much data received from target; rest_byte_count="{self.bytes_needed}"'
 
 
 class InvalidType(Exception):
diff --git a/cryptoparser/common/field.py b/cryptoparser/common/field.py
index 2d0c90d..fbe2a27 100644
--- a/cryptoparser/common/field.py
+++ b/cryptoparser/common/field.py
@@ -389,7 +389,7 @@ def get_canonical_name(cls):
         raise NotImplementedError()
 
     def _get_value_as_str(self):
-        return '"{}"'.format(self.value)
+        return f'"{self.value}"'
 
     def _get_value_as_simple_type(self):
         return self.value
@@ -817,7 +817,7 @@ class FieldValueMimeType(FieldValueComponentBase):
     )
 
     def __str__(self):
-        return '{}/{}'.format(self.registry.value, self.type)
+        return f'{self.registry.value}/{self.type}'
 
     @property
     def value(self):
diff --git a/cryptoparser/common/parse.py b/cryptoparser/common/parse.py
index a1de0f8..fc85432 100644
--- a/cryptoparser/common/parse.py
+++ b/cryptoparser/common/parse.py
@@ -782,7 +782,7 @@ def _compose_numeric_array(self, values, separator):
         composed_str = str()
 
         for value in values:
-            composed_str += '{:d}{}'.format(value, separator)
+            composed_str += f'{value:d}{separator}'
 
         self._composed += composed_str[:len(composed_str) - len(separator)].encode(self._encoding)
 
diff --git a/cryptoparser/ssh/subprotocol.py b/cryptoparser/ssh/subprotocol.py
index d5a6bc2..74e452f 100644
--- a/cryptoparser/ssh/subprotocol.py
+++ b/cryptoparser/ssh/subprotocol.py
@@ -262,7 +262,7 @@ class SshKeyExchangeInit(SshMessageBase):  # pylint: disable=too-many-instance-a
     first_kex_packet_follows = attr.ib(validator=attr.validators.instance_of(int), default=0)
     cookie = attr.ib(
         validator=attr.validators.instance_of((bytearray, bytes)),
-        default=bytearray.fromhex('{:16x}'.format(random.getrandbits(128)).zfill(32))
+        default=bytearray.fromhex(f'{random.getrandbits(128):16x}'.zfill(32))
     )
     reserved = attr.ib(validator=attr.validators.instance_of(int), default=0x00000000)
 
diff --git a/cryptoparser/ssh/version.py b/cryptoparser/ssh/version.py
index 66066be..3cacdb0 100644
--- a/cryptoparser/ssh/version.py
+++ b/cryptoparser/ssh/version.py
@@ -33,7 +33,7 @@ def grade(self):
         return Grade.SECURE
 
     def __str__(self):
-        return 'SSH {}.{}'.format(self.major, self.minor)
+        return f'SSH {self.major}.{self.minor}'
 
     @classmethod
     def _parse(cls, parsable):
@@ -59,7 +59,7 @@ def compose(self):
 
     @property
     def identifier(self):
-        return 'ssh{}'.format(self.major)
+        return f'ssh{self.major}'
 
     @property
     def supported_versions(self):
diff --git a/cryptoparser/tls/subprotocol.py b/cryptoparser/tls/subprotocol.py
index c0f3676..c681bda 100644
--- a/cryptoparser/tls/subprotocol.py
+++ b/cryptoparser/tls/subprotocol.py
@@ -298,7 +298,7 @@ def _default_time(self):  # pylint: disable=no-self-use
     @random.default
     def _default_random(self):  # pylint: disable=no-self-use
         return TlsHandshakeHelloRandomBytes(
-            bytearray.fromhex('{:28x}'.format(random.getrandbits(224)).zfill(56))
+            bytearray.fromhex(f'{random.getrandbits(224):28x}'.zfill(56))
         )
 
     @classmethod
@@ -1003,7 +1003,7 @@ def _default_session_id(self):  # pylint: disable=no-self-use
 
     @challenge.default
     def _default_challenge(self):  # pylint: disable=no-self-use
-        return bytes(bytearray.fromhex('{:16x}'.format(random.getrandbits(128)).zfill(32)))
+        return bytes(bytearray.fromhex(f'{random.getrandbits(128):16x}'.zfill(32)))
 
     @classmethod
     def get_message_type(cls):
diff --git a/cryptoparser/tls/version.py b/cryptoparser/tls/version.py
index 6ece89d..c6b5931 100644
--- a/cryptoparser/tls/version.py
+++ b/cryptoparser/tls/version.py
@@ -89,15 +89,15 @@ def identifier(self):
 
     def __str__(self):
         if self.is_draft:
-            return 'TLS 1.3 Draft {}'.format(self.minor)
+            return f'TLS 1.3 Draft {self.minor}'
         if self.is_google_experimental:
-            return 'TLS 1.3 Google Experiment {}'.format(self.minor)
+            return f'TLS 1.3 Google Experiment {self.minor}'
         if self.version == TlsVersion.SSL3:
             return 'SSL 3.0'
         if self.version == TlsVersion.SSL2:
             return 'SSL 2.0'
 
-        return 'TLS 1.{}'.format(self.minor - 1)
+        return f'TLS 1.{self.minor - 1}'
 
     def _as_markdown(self, level):
         return self._markdown_result(str(self), level)
diff --git a/docs/conf.py b/docs/conf.py
index 6ba6cff..7f1cdfd 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -45,7 +45,7 @@
     ]
     for lang in ('en',):
         for tag in ('latest', 'stable'):
-            _robots_txt_lines.append('Sitemap: {}{}/{}/sitemap.xml'.format(_baseurl, lang, tag))
+            _robots_txt_lines.append(f'Sitemap: {_baseurl}{lang}/{tag}/sitemap.xml')
 
     _html_extra_dir_name = 'readthedocs'
     _html_extra_path = pathlib.Path(_html_extra_dir_name)
diff --git a/test/common/classes.py b/test/common/classes.py
index f762d8f..6adaa42 100644
--- a/test/common/classes.py
+++ b/test/common/classes.py
@@ -92,7 +92,7 @@ def compose(self):
         return composer.composed_bytes
 
     def __repr__(self):
-        return '{0:#0{1}x}'.format(self.value, self.get_byte_size() * 2 + 2)
+        return f'0x{self.value:>0{self.get_byte_size() * 2}x}'
 
     def __eq__(self, other):
         return self.get_byte_size() == other.get_byte_size() and self.value == other.value