diff -pruN 0.14.2-3/CHANGES.rst 0.20.0-1/CHANGES.rst
--- 0.14.2-3/CHANGES.rst	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/CHANGES.rst	2022-06-05 17:11:40.000000000 +0000
@@ -1,6 +1,72 @@
 Changelog
 ---------
 
+0.20.0 (2022-06-05)
+^^^^^^^^^^^^^^^^^^^
+
+- Added ipv4 digit lenghts validation (#191, pull request courtesy of Norbiox)
+- Fixes error with international URLs that have more than 2 hyphens (#184, pull request courtesy of automationator)
+
+
+0.19.0 (2022-05-04)
+^^^^^^^^^^^^^^^^^^^
+
+- Dropped py34 support
+- Improve IPv6 validation (#201, pull request courtesy of SimonIT)
+
+
+0.18.2 (2020-12-18)
+^^^^^^^^^^^^^^^^^^^
+
+- Implement actual validation for old style BTC addresses including checksumming (#182, pull request courtesy of tpatja)
+- Use a regex to guesstimate validity of new segwit BTC addresses (#182, pull request courtesy of tpatja)
+
+
+0.18.1 (2020-09-03)
+^^^^^^^^^^^^^^^^^^^
+
+- Made uuid validator accept UUID objects (#174, pull request courtesy of Letsch22)
+
+
+0.18.0 (2020-08-19)
+^^^^^^^^^^^^^^^^^^^
+
+- Added bitcoin address validator (#166, pull request courtesy of daveusa31)
+
+
+0.17.1 (2020-08-03)
+^^^^^^^^^^^^^^^^^^^
+
+- Fixed python_requires using twine
+
+
+0.17.0 (2020-08-02)
+^^^^^^^^^^^^^^^^^^^
+
+- Added python_requires='>=3.4' to setup.py (#163, pull request courtesy of vphilippon)
+- Fixed URL validator ip_last_octet regex (#145, pull request courtesy of ghost)
+
+
+0.16.0 (2020-07-16)
+^^^^^^^^^^^^^^^^^^^
+
+- Added support for emojis and more IDNA URLs (#161, pull request courtesy of automationator)
+
+
+0.15.0 (2020-05-07)
+^^^^^^^^^^^^^^^^^^^
+
+- Added bank card validators (#157, pull request courtesy of TimonPeng)
+
+
+0.14.3 (2020-02-04)
+^^^^^^^^^^^^^^^^^^^
+
+- Handle None values gracefully in domain validator (#144, pull request courtesy reahaas)
+- Local part of the email address should be less or equal than 64 bytes (#147, pull request courtesy mondeja)
+- Removed py27 support
+- Removed pypy2 support
+
 
 0.14.2 (2020-01-24)
 ^^^^^^^^^^^^^^^^^^^
diff -pruN 0.14.2-3/debian/changelog 0.20.0-1/debian/changelog
--- 0.14.2-3/debian/changelog	2022-01-21 08:54:08.000000000 +0000
+++ 0.20.0-1/debian/changelog	2022-08-01 13:45:20.000000000 +0000
@@ -1,3 +1,12 @@
+validators (0.20.0-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream version 0.20.0
+  * Remove useless dependency python3-six
+  * Bump Standards-Version to 4.6.1 (no change)
+
+ -- Sophie Brun <sophie@offensive-security.com>  Mon, 01 Aug 2022 15:45:20 +0200
+
 validators (0.14.2-3) unstable; urgency=medium
 
   * Team upload.
diff -pruN 0.14.2-3/debian/control 0.20.0-1/debian/control
--- 0.14.2-3/debian/control	2022-01-21 08:54:08.000000000 +0000
+++ 0.20.0-1/debian/control	2022-08-01 13:45:20.000000000 +0000
@@ -3,8 +3,8 @@ Section: python
 Priority: optional
 Maintainer: Debian Python Team <team+python@tracker.debian.org>
 Uploaders: Harley Swick <fancycade@protonmail.com>
-Build-Depends: debhelper-compat (= 12), dh-python, python3-all, python3-setuptools, python3-pytest, python3-decorator, python3-six
-Standards-Version: 4.6.0
+Build-Depends: debhelper-compat (= 12), dh-python, python3-all, python3-setuptools, python3-pytest, python3-decorator
+Standards-Version: 4.6.1
 Rules-Requires-Root: no
 Homepage: https://github.com/kvesteri/validators
 Vcs-Browser: https://salsa.debian.org/python-team/packages/validators
diff -pruN 0.14.2-3/docs/index.rst 0.20.0-1/docs/index.rst
--- 0.14.2-3/docs/index.rst	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/docs/index.rst	2022-06-05 17:11:40.000000000 +0000
@@ -69,6 +69,17 @@ between
 .. autofunction:: between
 
 
+
+btc_address
+------
+
+.. module:: validators.btc_address
+
+.. autofunction:: btc_address
+
+
+
+
 domain
 ------
 
diff -pruN 0.14.2-3/.github/workflows/main.yml 0.20.0-1/.github/workflows/main.yml
--- 0.14.2-3/.github/workflows/main.yml	1970-01-01 00:00:00.000000000 +0000
+++ 0.20.0-1/.github/workflows/main.yml	2022-06-05 17:11:40.000000000 +0000
@@ -0,0 +1,41 @@
+name: GH
+
+on:
+  pull_request:
+    branches: '*'
+  push:
+    branches: 'master'
+    tags: '*'
+
+jobs:
+  CI:
+    runs-on: ubuntu-latest
+    strategy:
+      max-parallel: 8
+      matrix:
+        python-version: [3.5, 3.6, 3.7, 3.8, 3.9, 3.10]
+    steps:
+    - uses: actions/checkout@v2
+
+    - name: Set up Python ${{ matrix.python-version }}
+      uses: actions/setup-python@v2
+      with:
+        python-version: ${{ matrix.python-version }}
+
+    - name: Pip cache
+      uses: actions/cache@v2
+      with:
+        path: ~/.cache/pip
+        key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements/*.txt') }}
+        restore-keys: |
+          ${{ runner.os }}-pip-
+    - name: Install dependencies
+      run: pip install -e ".[test]"
+
+    - name: Lint
+      run: |
+        isort --recursive --diff validators tests && isort --recursive --check-only validators tests
+        flake8 validators tests
+
+    - name: Test
+      run: py.test --doctest-glob="*.rst" --doctest-modules --ignore=setup.py
diff -pruN 0.14.2-3/setup.py 0.20.0-1/setup.py
--- 0.14.2-3/setup.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/setup.py	2022-06-05 17:11:40.000000000 +0000
@@ -33,7 +33,6 @@ extras_require = {
 }
 
 install_requires = [
-    'six>=1.4.0',
     'decorator>=3.4.0',
 ]
 
@@ -59,10 +58,7 @@ setup(
         'License :: OSI Approved :: MIT License',
         'Operating System :: OS Independent',
         'Programming Language :: Python',
-        'Programming Language :: Python :: 2',
-        'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.4',
         'Programming Language :: Python :: 3.5',
         'Programming Language :: Python :: 3.6',
         'Programming Language :: Python :: 3.7',
@@ -70,5 +66,6 @@ setup(
         'Programming Language :: Python :: Implementation :: PyPy',
         'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
         'Topic :: Software Development :: Libraries :: Python Modules'
-    ]
+    ],
+    python_requires='>=3.4'
 )
diff -pruN 0.14.2-3/tests/i18n/test_fi.py 0.20.0-1/tests/i18n/test_fi.py
--- 0.14.2-3/tests/i18n/test_fi.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/tests/i18n/test_fi.py	2022-06-05 17:11:40.000000000 +0000
@@ -21,7 +21,7 @@ def test_returns_true_on_valid_business_
     ('1333333-8',),
     ('1231233-9',),
 ])
-def test_returns_failed_validation_on_invalid_email(value):
+def test_returns_failed_validation_on_invalid_business_id(value):
     assert isinstance(fi_business_id(value), ValidationFailure)
 
 
diff -pruN 0.14.2-3/tests/test_btc_address.py 0.20.0-1/tests/test_btc_address.py
--- 0.14.2-3/tests/test_btc_address.py	1970-01-01 00:00:00.000000000 +0000
+++ 0.20.0-1/tests/test_btc_address.py	2022-06-05 17:11:40.000000000 +0000
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+import pytest
+
+from validators import btc_address, ValidationFailure
+
+
+@pytest.mark.parametrize(
+    'value',
+    [
+        # P2PKH (Pay-to-PubkeyHash) type
+        '1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2',
+        # P2SH (Pay to script hash) type
+        '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy',
+        # Bech32/segwit type
+        'bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq',
+        'bc1qc7slrfxkknqcq2jevvvkdgvrt8080852dfjewde450xdlk4ugp7szw5tk9',
+    ],
+)
+def test_returns_true_on_valid_btc_address(value):
+    assert btc_address(value)
+
+
+@pytest.mark.parametrize(
+    'value',
+    [
+        'ff3Cwgr2g7vsi1bXDUkpEnVoRLA9w4FZfC69',
+        'b3Cgwgr2g7vsi1bXyjyDUkphEnVoRLA9w4FZfC69',
+        # incorrect header
+        '1BvBMsEYstWetqTFn5Au4m4GFg7xJaNVN2',
+        # incorrect checksum
+        '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLz',
+    ],
+)
+def test_returns_failed_validation_on_invalid_btc_address(value):
+    assert isinstance(btc_address(value), ValidationFailure)
diff -pruN 0.14.2-3/tests/test_card.py 0.20.0-1/tests/test_card.py
--- 0.14.2-3/tests/test_card.py	1970-01-01 00:00:00.000000000 +0000
+++ 0.20.0-1/tests/test_card.py	2022-06-05 17:11:40.000000000 +0000
@@ -0,0 +1,190 @@
+# -*- coding: utf-8 -*-
+import pytest
+
+from validators import (
+    amex,
+    card_number,
+    diners,
+    discover,
+    jcb,
+    mastercard,
+    unionpay,
+    ValidationFailure,
+    visa
+)
+
+visa_cards = [
+    '4242424242424242',
+    '4000002760003184'
+]
+mastercard_cards = [
+    '5555555555554444',
+    '2223003122003222'
+]
+amex_cards = [
+    '378282246310005',
+    '371449635398431'
+]
+unionpay_cards = [
+    '6200000000000005'
+]
+diners_cards = [
+    '3056930009020004',
+    '36227206271667'
+]
+jcb_cards = [
+    '3566002020360505'
+]
+discover_cards = [
+    '6011111111111117',
+    '6011000990139424'
+]
+
+
+@pytest.mark.parametrize(
+    "value",
+    visa_cards
+    + mastercard_cards
+    + amex_cards
+    + unionpay_cards
+    + diners_cards
+    + jcb_cards
+    + discover_cards,
+)
+def test_returns_true_on_valid_card_number(value):
+    assert card_number(value)
+
+
+@pytest.mark.parametrize('value', [
+    '4242424242424240',
+    '4000002760003180',
+    '400000276000318X'
+])
+def test_returns_failed_on_valid_card_number(value):
+    assert isinstance(card_number(value), ValidationFailure)
+
+
+@pytest.mark.parametrize('value', visa_cards)
+def test_returns_true_on_valid_visa(value):
+    assert visa(value)
+
+
+@pytest.mark.parametrize(
+    "value",
+    mastercard_cards
+    + amex_cards
+    + unionpay_cards
+    + diners_cards
+    + jcb_cards
+    + discover_cards,
+)
+def test_returns_failed_on_valid_visa(value):
+    assert isinstance(visa(value), ValidationFailure)
+
+
+@pytest.mark.parametrize('value', mastercard_cards)
+def test_returns_true_on_valid_mastercard(value):
+    assert mastercard(value)
+
+
+@pytest.mark.parametrize(
+    "value",
+    visa_cards
+    + amex_cards
+    + unionpay_cards
+    + diners_cards
+    + jcb_cards
+    + discover_cards,
+)
+def test_returns_failed_on_valid_mastercard(value):
+    assert isinstance(mastercard(value), ValidationFailure)
+
+
+@pytest.mark.parametrize('value', amex_cards)
+def test_returns_true_on_valid_amex(value):
+    assert amex(value)
+
+
+@pytest.mark.parametrize(
+    "value",
+    visa_cards
+    + mastercard_cards
+    + unionpay_cards
+    + diners_cards
+    + jcb_cards
+    + discover_cards,
+)
+def test_returns_failed_on_valid_amex(value):
+    assert isinstance(amex(value), ValidationFailure)
+
+
+@pytest.mark.parametrize('value', unionpay_cards)
+def test_returns_true_on_valid_unionpay(value):
+    assert unionpay(value)
+
+
+@pytest.mark.parametrize(
+    "value",
+    visa_cards
+    + mastercard_cards
+    + amex_cards
+    + diners_cards
+    + jcb_cards
+    + discover_cards,
+)
+def test_returns_failed_on_valid_unionpay(value):
+    assert isinstance(unionpay(value), ValidationFailure)
+
+
+@pytest.mark.parametrize('value', diners_cards)
+def test_returns_true_on_valid_diners(value):
+    assert diners(value)
+
+
+@pytest.mark.parametrize(
+    "value",
+    visa_cards
+    + mastercard_cards
+    + amex_cards
+    + unionpay_cards
+    + jcb_cards
+    + discover_cards,
+)
+def test_returns_failed_on_valid_diners(value):
+    assert isinstance(diners(value), ValidationFailure)
+
+
+@pytest.mark.parametrize('value', jcb_cards)
+def test_returns_true_on_valid_jcb(value):
+    assert jcb(value)
+
+
+@pytest.mark.parametrize(
+    "value",
+    visa_cards
+    + mastercard_cards
+    + amex_cards
+    + unionpay_cards
+    + diners_cards
+    + discover_cards,
+)
+def test_returns_failed_on_valid_jcb(value):
+    assert isinstance(jcb(value), ValidationFailure)
+
+
+@pytest.mark.parametrize('value', discover_cards)
+def test_returns_true_on_valid_discover(value):
+    assert discover(value)
+
+
+@pytest.mark.parametrize(
+    "value",
+    visa_cards
+    + mastercard_cards
+    + amex_cards
+    + unionpay_cards
+    + diners_cards
+    + jcb_cards,
+)
+def test_returns_failed_on_valid_discover(value):
+    assert isinstance(discover(value), ValidationFailure)
diff -pruN 0.14.2-3/tests/test_email.py 0.20.0-1/tests/test_email.py
--- 0.14.2-3/tests/test_email.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/tests/test_email.py	2022-06-05 17:11:40.000000000 +0000
@@ -34,6 +34,10 @@ def test_returns_true_on_valid_email(val
     ('example@-invalid.com',),
     ('example@inv-.alid-.com',),
     ('example@inv-.-alid.com',),
+    (
+        'john56789.john56789.john56789.john56789.john56789.john56789.john5'
+        '@example.com',
+    ),
     # Quoted-string format (CR not allowed)
     ('"\\\012"@here.com',),
 ])
diff -pruN 0.14.2-3/tests/test_ipv4.py 0.20.0-1/tests/test_ipv4.py
--- 0.14.2-3/tests/test_ipv4.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/tests/test_ipv4.py	2022-06-05 17:11:40.000000000 +0000
@@ -19,6 +19,7 @@ def test_returns_true_on_valid_ipv4_addr
     ('1278.0.0.1',),
     ('127.0.0.abc',),
     ('900.200.100.75',),
+    ('0127.0.0.1',),
 ])
 def test_returns_failed_validation_on_invalid_ipv4_address(address):
     assert isinstance(ipv4(address), ValidationFailure)
diff -pruN 0.14.2-3/tests/test_ipv6.py 0.20.0-1/tests/test_ipv6.py
--- 0.14.2-3/tests/test_ipv6.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/tests/test_ipv6.py	2022-06-05 17:11:40.000000000 +0000
@@ -5,11 +5,15 @@ from validators import ipv4, ipv6, Valid
 
 
 @pytest.mark.parametrize(('address',), [
+    ('::',),
     ('::1',),
-    ('dead:beef:0:0:0:0:42:1',),
+    ('1::',),
+    ('dead:beef:0:0:0:0000:42:1',),
     ('abcd:ef::42:1',),
     ('0:0:0:0:0:ffff:1.2.3.4',),
     ('::192.168.30.2',),
+    ('0000:0000:0000:0000:0000::',),
+    ('0:a:b:c:d:e:f::',),
 ])
 def test_returns_true_on_valid_ipv6_address(address):
     assert ipv6(address)
@@ -20,7 +24,19 @@ def test_returns_true_on_valid_ipv6_addr
     ('abc.0.0.1',),
     ('abcd:1234::123::1',),
     ('1:2:3:4:5:6:7:8:9',),
+    ('1:2:3:4:5:6:7:8::',),
+    ('1:2:3:4:5:6:7::8:9',),
     ('abcd::1ffff',),
+    ('1111:',),
+    (':8888',),
+    (':1.2.3.4',),
+    ('18:05',),
+    (':',),
+    (':1:2:',),
+    (':1:2::',),
+    ('::1:2::',),
+    ('8::1:2::9',),
+    ('02001:0000:1234:0000:0000:C1C0:ABCD:0876',),
 ])
 def test_returns_failed_validation_on_invalid_ipv6_address(address):
     assert isinstance(ipv6(address), ValidationFailure)
diff -pruN 0.14.2-3/tests/test_url.py 0.20.0-1/tests/test_url.py
--- 0.14.2-3/tests/test_url.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/tests/test_url.py	2022-06-05 17:11:40.000000000 +0000
@@ -42,12 +42,20 @@ from validators import url, ValidationFa
     u'http://مثال.إختبار',
     u'http://例子.测试',
     u'http://उदाहरण.परीक्षा',
+    u'http://www.😉.com',
+    u'http://😉.com/😁',
+    u'http://উদাহরণ.বাংলা',
+    u'http://xn--d5b6ci4b4b3a.xn--54b7fta0cc',
+    u'http://дом-м.рф/1/asdf',
+    u'http://xn----gtbybh.xn--p1ai/1/asdf',
     u'http://-.~_!$&\'()*+,;=:%40:80%2f::::::@example.com',
     u'http://1337.net',
     u'http://a.b-c.de',
     u'http://223.255.255.254',
+    u'http://10.1.1.0',
     u'http://10.1.1.1',
     u'http://10.1.1.254',
+    u'http://10.1.1.255',
     u'http://127.0.0.1:8080',
     u'http://127.0.10.150',
     u'http://localhost',
@@ -114,8 +122,6 @@ def test_returns_true_on_valid_public_ur
     'http://-a.b.co',
     'http://a.b-.co',
     'http://0.0.0.0',
-    'http://10.1.1.0',
-    'http://10.1.1.255',
     'http://224.1.1.1',
     'http://1.1.1.1.1',
     'http://123.123.123',
diff -pruN 0.14.2-3/tests/test_uuid.py 0.20.0-1/tests/test_uuid.py
--- 0.14.2-3/tests/test_uuid.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/tests/test_uuid.py	2022-06-05 17:11:40.000000000 +0000
@@ -1,4 +1,6 @@
 # -*- coding: utf-8 -*-
+from uuid import UUID
+
 import pytest
 
 from validators import uuid, ValidationFailure
@@ -12,6 +14,13 @@ def test_returns_true_on_valid_mac_addre
 
 
 @pytest.mark.parametrize(('value',), [
+    (UUID('2bc1c94f-0deb-43e9-92a1-4775189ec9f8'),),
+])
+def test_returns_true_on_valid_uuid_object(value):
+    assert uuid(value)
+
+
+@pytest.mark.parametrize(('value',), [
     ('2bc1c94f-deb-43e9-92a1-4775189ec9f8',),
     ('2bc1c94f-0deb-43e9-92a1-4775189ec9f',),
     ('gbc1c94f-0deb-43e9-92a1-4775189ec9f8',),
@@ -19,3 +28,13 @@ def test_returns_true_on_valid_mac_addre
 ])
 def test_returns_failed_validation_on_invalid_mac_address(value):
     assert isinstance(uuid(value), ValidationFailure)
+
+
+@pytest.mark.parametrize(('value',), [
+    (1,),
+    (1.0,),
+    (True,),
+    (None,),
+])
+def test_returns_failed_validation_on_invalid_types(value):
+    assert isinstance(uuid(value), ValidationFailure)
diff -pruN 0.14.2-3/tests/test_validation_failure.py 0.20.0-1/tests/test_validation_failure.py
--- 0.14.2-3/tests/test_validation_failure.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/tests/test_validation_failure.py	2022-06-05 17:11:40.000000000 +0000
@@ -1,5 +1,3 @@
-import six
-
 import validators
 
 obj_repr = (
@@ -19,7 +17,7 @@ class TestValidationFailure(object):
         assert obj_repr in repr(self.obj)
 
     def test_unicode(self):
-        assert obj_repr in six.text_type(self.obj)
+        assert obj_repr in str(self.obj)
 
     def test_arguments_as_properties(self):
         assert self.obj.value == 3
diff -pruN 0.14.2-3/.travis.yml 0.20.0-1/.travis.yml
--- 0.14.2-3/.travis.yml	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/.travis.yml	2022-06-05 17:11:40.000000000 +0000
@@ -1,14 +1,11 @@
 language: python
 matrix:
   include:
-    - python: 2.7
-    - python: 3.4
     - python: 3.5
     - python: 3.6
     - python: 3.7
       dist: xenial
       sudo: true
-    - python: pypy
     - python: pypy3
 install:
   - pip install -e ".[test]"
diff -pruN 0.14.2-3/validators/btc_address.py 0.20.0-1/validators/btc_address.py
--- 0.14.2-3/validators/btc_address.py	1970-01-01 00:00:00.000000000 +0000
+++ 0.20.0-1/validators/btc_address.py	2022-06-05 17:11:40.000000000 +0000
@@ -0,0 +1,55 @@
+import re
+from hashlib import sha256
+
+from .utils import validator
+
+segwit_pattern = re.compile(
+    r'^(bc|tc)[0-3][02-9ac-hj-np-z]{14,74}$')
+
+
+def validate_segwit_address(addr):
+    return segwit_pattern.match(addr)
+
+
+def decode_base58(addr):
+    alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
+    return sum([
+        (58 ** e) * alphabet.index(i)
+        for e, i in enumerate(addr[::-1])
+    ])
+
+
+def validate_old_btc_address(addr):
+    "Validate P2PKH and P2SH type address"
+    if not len(addr) in range(25, 35):
+        return False
+    decoded_bytes = decode_base58(addr).to_bytes(25, "big")
+    header = decoded_bytes[:-4]
+    checksum = decoded_bytes[-4:]
+    return checksum == sha256(sha256(header).digest()).digest()[:4]
+
+
+@validator
+def btc_address(value):
+    """
+    Return whether or not given value is a valid bitcoin address.
+
+    If the value is valid bitcoin address this function returns ``True``,
+    otherwise :class:`~validators.utils.ValidationFailure`.
+
+    Full validation is implemented for P2PKH and P2SH addresses.
+    For segwit addresses a regexp is used to provide a reasonable estimate
+    on whether the address is valid.
+
+    Examples::
+
+        >>> btc_address('3Cwgr2g7vsi1bXDUkpEnVoRLA9w4FZfC69')
+        True
+
+    :param value: Bitcoin address string to validate
+    """
+    if not value or not isinstance(value, str):
+        return False
+    if value[:2] in ("bc", "tb"):
+        return validate_segwit_address(value)
+    return validate_old_btc_address(value)
diff -pruN 0.14.2-3/validators/card.py 0.20.0-1/validators/card.py
--- 0.14.2-3/validators/card.py	1970-01-01 00:00:00.000000000 +0000
+++ 0.20.0-1/validators/card.py	2022-06-05 17:11:40.000000000 +0000
@@ -0,0 +1,183 @@
+import re
+
+from .utils import validator
+
+
+@validator
+def card_number(value):
+    """
+    Return whether or not given value is a valid card number.
+
+    This validator is based on Luhn algorithm.
+
+    .. luhn:
+       https://github.com/mmcloughlin/luhn
+
+    Examples::
+
+        >>> card_number('4242424242424242')
+        True
+
+        >>> card_number('4242424242424241')
+        ValidationFailure(func=card_number, args={'value': '4242424242424241'})
+
+    .. versionadded:: 0.15.0
+
+    :param value: card number string to validate
+    """
+    try:
+        digits = list(map(int, value))
+        odd_sum = sum(digits[-1::-2])
+        even_sum = sum([sum(divmod(2 * d, 10)) for d in digits[-2::-2]])
+        return (odd_sum + even_sum) % 10 == 0
+    except ValueError:
+        return False
+
+
+@validator
+def visa(value):
+    """
+    Return whether or not given value is a valid Visa card number.
+
+    Examples::
+
+        >>> visa('4242424242424242')
+        True
+
+        >>> visa('2223003122003222')
+        ValidationFailure(func=visa, args={'value': '2223003122003222'})
+
+    .. versionadded:: 0.15.0
+
+    :param value: Visa card number string to validate
+    """
+    pattern = re.compile(r'^4')
+    return card_number(value) and len(value) == 16 and pattern.match(value)
+
+
+@validator
+def mastercard(value):
+    """
+    Return whether or not given value is a valid Mastercard card number.
+
+    Examples::
+
+        >>> mastercard('5555555555554444')
+        True
+
+        >>> mastercard('4242424242424242')
+        ValidationFailure(func=mastercard, args={'value': '4242424242424242'})
+
+    .. versionadded:: 0.15.0
+
+    :param value: Mastercard card number string to validate
+    """
+    pattern = re.compile(r'^(51|52|53|54|55|22|23|24|25|26|27)')
+    return card_number(value) and len(value) == 16 and pattern.match(value)
+
+
+@validator
+def amex(value):
+    """
+    Return whether or not given value is a valid American Express card number.
+
+    Examples::
+
+        >>> amex('378282246310005')
+        True
+
+        >>> amex('4242424242424242')
+        ValidationFailure(func=amex, args={'value': '4242424242424242'})
+
+    .. versionadded:: 0.15.0
+
+    :param value: American Express card number string to validate
+    """
+    pattern = re.compile(r'^(34|37)')
+    return card_number(value) and len(value) == 15 and pattern.match(value)
+
+
+@validator
+def unionpay(value):
+    """
+    Return whether or not given value is a valid UnionPay card number.
+
+    Examples::
+
+        >>> unionpay('6200000000000005')
+        True
+
+        >>> unionpay('4242424242424242')
+        ValidationFailure(func=unionpay, args={'value': '4242424242424242'})
+
+    .. versionadded:: 0.15.0
+
+    :param value: UnionPay card number string to validate
+    """
+    pattern = re.compile(r'^62')
+    return card_number(value) and len(value) == 16 and pattern.match(value)
+
+
+@validator
+def diners(value):
+    """
+    Return whether or not given value is a valid Diners Club card number.
+
+    Examples::
+
+        >>> diners('3056930009020004')
+        True
+
+        >>> diners('4242424242424242')
+        ValidationFailure(func=diners, args={'value': '4242424242424242'})
+
+    .. versionadded:: 0.15.0
+
+    :param value: Diners Club card number string to validate
+    """
+    pattern = re.compile(r'^(30|36|38|39)')
+    return (
+        card_number(value) and len(value) in [14, 16] and pattern.match(value)
+    )
+
+
+@validator
+def jcb(value):
+    """
+    Return whether or not given value is a valid JCB card number.
+
+    Examples::
+
+        >>> jcb('3566002020360505')
+        True
+
+        >>> jcb('4242424242424242')
+        ValidationFailure(func=jcb, args={'value': '4242424242424242'})
+
+    .. versionadded:: 0.15.0
+
+    :param value: JCB card number string to validate
+    """
+    pattern = re.compile(r'^35')
+    return card_number(value) and len(value) == 16 and pattern.match(value)
+
+
+@validator
+def discover(value):
+    """
+    Return whether or not given value is a valid Discover card number.
+
+    Examples::
+
+        >>> discover('6011111111111117')
+        True
+
+        >>> discover('4242424242424242')
+        ValidationFailure(func=discover, args={'value': '4242424242424242'})
+
+    .. versionadded:: 0.15.0
+
+    :param value: Discover card number string to validate
+    """
+    pattern = re.compile(r'^(60|64|65)')
+    return card_number(value) and len(value) == 16 and pattern.match(value)
diff -pruN 0.14.2-3/validators/domain.py 0.20.0-1/validators/domain.py
--- 0.14.2-3/validators/domain.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/validators/domain.py	2022-06-05 17:11:40.000000000 +0000
@@ -1,15 +1,7 @@
 import re
 
-import six
-
 from .utils import validator
 
-if six.PY3:
-    text_type = str
-    unicode = str
-else:
-    text_type = unicode
-
 pattern = re.compile(
     r'^(?:[a-zA-Z0-9]'  # First character of the domain
     r'(?:[a-zA-Z0-9-_]{0,61}[A-Za-z0-9])?\.)'  # Sub domain + hostname
@@ -22,7 +14,7 @@ def to_unicode(obj, charset='utf-8', err
     if obj is None:
         return None
     if not isinstance(obj, bytes):
-        return text_type(obj)
+        return str(obj)
     return obj.decode(charset, errors)
 
 
@@ -58,5 +50,5 @@ def domain(value):
     """
     try:
         return pattern.match(to_unicode(value).encode('idna').decode('ascii'))
-    except UnicodeError:
+    except (UnicodeError, AttributeError):
         return False
diff -pruN 0.14.2-3/validators/email.py 0.20.0-1/validators/email.py
--- 0.14.2-3/validators/email.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/validators/email.py	2022-06-05 17:11:40.000000000 +0000
@@ -62,6 +62,9 @@ def email(value, whitelist=None):
     if not user_regex.match(user_part):
         return False
 
+    if len(user_part.encode("utf-8")) > 64:
+        return False
+
     if domain_part not in whitelist and not domain_regex.match(domain_part):
         # Try for possible IDN domain-part
         try:
diff -pruN 0.14.2-3/validators/__init__.py 0.20.0-1/validators/__init__.py
--- 0.14.2-3/validators/__init__.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/validators/__init__.py	2022-06-05 17:11:40.000000000 +0000
@@ -1,4 +1,15 @@
 from .between import between
+from .btc_address import btc_address
+from .card import (
+    amex,
+    card_number,
+    diners,
+    discover,
+    jcb,
+    mastercard,
+    unionpay,
+    visa
+)
 from .domain import domain
 from .email import email
 from .extremes import Max, Min
@@ -17,6 +28,8 @@ from .uuid import uuid
 __all__ = ('between', 'domain', 'email', 'Max', 'Min', 'md5', 'sha1', 'sha224',
            'sha256', 'sha512', 'fi_business_id', 'fi_ssn', 'iban', 'ipv4',
            'ipv4_cidr', 'ipv6', 'ipv6_cidr', 'length', 'mac_address', 'slug',
-           'truthy', 'url', 'ValidationFailure', 'validator', 'uuid')
+           'truthy', 'url', 'ValidationFailure', 'validator', 'uuid',
+           'card_number', 'visa', 'mastercard', 'amex', 'unionpay', 'diners',
+           'jcb', 'discover', 'btc_address')
 
-__version__ = '0.14.2'
+__version__ = '0.20.0'
diff -pruN 0.14.2-3/validators/ip_address.py 0.20.0-1/validators/ip_address.py
--- 0.14.2-3/validators/ip_address.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/validators/ip_address.py	2022-06-05 17:11:40.000000000 +0000
@@ -4,7 +4,7 @@ from .utils import validator
 @validator
 def ipv4(value):
     """
-    Return whether or not given value is a valid IP version 4 address.
+    Return whether a given value is a valid IP version 4 address.
 
     This validator is based on `WTForms IPAddress validator`_
 
@@ -23,8 +23,12 @@ def ipv4(value):
 
     :param value: IP address string to validate
     """
-    groups = value.split('.')
-    if len(groups) != 4 or any(not x.isdigit() for x in groups):
+    groups = value.split(".")
+    if (
+        len(groups) != 4
+        or any(not x.isdigit() for x in groups)
+        or any(len(x) > 3 for x in groups)
+    ):
         return False
     return all(0 <= int(part) < 256 for part in groups)
 
@@ -32,7 +36,7 @@ def ipv4(value):
 @validator
 def ipv4_cidr(value):
     """
-    Return whether or not given value is a valid CIDR-notated IP version 4
+    Return whether a given value is a valid CIDR-notated IP version 4
     address range.
 
     This validator is based on RFC4632 3.1.
@@ -57,7 +61,7 @@ def ipv4_cidr(value):
 @validator
 def ipv6(value):
     """
-    Return whether or not given value is a valid IP version 6 address
+    Return whether a given value is a valid IP version 6 address
     (including IPv4-mapped IPv6 addresses).
 
     This validator is based on `WTForms IPAddress validator`_.
@@ -95,10 +99,6 @@ def ipv6(value):
     else:
         ipv4_groups = []
 
-    max_groups = 6 if ipv4_groups else 8
-    if len(ipv6_groups) > max_groups:
-        return False
-
     count_blank = 0
     for part in ipv6_groups:
         if not part:
@@ -109,12 +109,24 @@ def ipv6(value):
         except ValueError:
             return False
         else:
-            if not 0 <= num <= 65536:
+            if not 0 <= num <= 65536 or len(part) > 4:
                 return False
 
-    if count_blank < 2:
+    max_groups = 6 if ipv4_groups else 8
+    part_count = len(ipv6_groups) - count_blank
+    if count_blank == 0 and part_count == max_groups:
+        # no :: -> must have size of max_groups
+        return True
+    elif count_blank == 1 and ipv6_groups[-1] and ipv6_groups[0] and part_count < max_groups:
+        # one :: inside the address or prefix or suffix : -> filter least two cases
+        return True
+    elif count_blank == 2 and part_count < max_groups and (
+            ((ipv6_groups[0] and not ipv6_groups[-1]) or (not ipv6_groups[0] and ipv6_groups[-1])) or ipv4_groups):
+        # leading or trailing :: or : at end and begin -> filter last case
+        # Check if it has ipv4 groups because they get removed from the ipv6_groups
         return True
-    elif count_blank == 2 and not ipv6_groups[0] and not ipv6_groups[1]:
+    elif count_blank == 3 and part_count == 0:
+        # :: is the address -> filter everything else
         return True
     return False
 
@@ -122,7 +134,7 @@ def ipv6(value):
 @validator
 def ipv6_cidr(value):
     """
-    Returns whether or not given value is a valid CIDR-notated IP version 6
+    Returns whether a given value is a valid CIDR-notated IP version 6
     address range.
 
     This validator is based on RFC4632 3.1.
diff -pruN 0.14.2-3/validators/truthy.py 0.20.0-1/validators/truthy.py
--- 0.14.2-3/validators/truthy.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/validators/truthy.py	2022-06-05 17:11:40.000000000 +0000
@@ -1,5 +1,3 @@
-import six
-
 from .utils import validator
 
 
@@ -37,5 +35,5 @@ def truthy(value):
     """
     return (
         value and
-        (not isinstance(value, six.string_types) or value.strip())
+        (not isinstance(value, str) or value.strip())
     )
diff -pruN 0.14.2-3/validators/url.py 0.20.0-1/validators/url.py
--- 0.14.2-3/validators/url.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/validators/url.py	2022-06-05 17:11:40.000000000 +0000
@@ -3,7 +3,7 @@ import re
 from .utils import validator
 
 ip_middle_octet = r"(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5]))"
-ip_last_octet = r"(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))"
+ip_last_octet = r"(?:\.(?:0|[1-9]\d?|1\d\d|2[0-4]\d|25[0-5]))"
 
 regex = re.compile(  # noqa: W605
     r"^"
@@ -69,16 +69,19 @@ regex = re.compile(  # noqa: W605
     r"(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
     r")\]|"
     # host name
-    u"(?:(?:[a-z\u00a1-\uffff0-9]-?)*[a-z\u00a1-\uffff0-9]+)"
+    r"(?:(?:(?:xn--[-]{0,2})|[a-z\u00a1-\uffff\U00010000-\U0010ffff0-9]-?)*"
+    r"[a-z\u00a1-\uffff\U00010000-\U0010ffff0-9]+)"
     # domain name
-    u"(?:\.(?:[a-z\u00a1-\uffff0-9]-?)*[a-z\u00a1-\uffff0-9]+)*"
+    r"(?:\.(?:(?:xn--[-]{0,2})|[a-z\u00a1-\uffff\U00010000-\U0010ffff0-9]-?)*"
+    r"[a-z\u00a1-\uffff\U00010000-\U0010ffff0-9]+)*"
     # TLD identifier
-    u"(?:\.(?:[a-z\u00a1-\uffff]{2,}))"
+    r"(?:\.(?:(?:xn--[-]{0,2}[a-z\u00a1-\uffff\U00010000-\U0010ffff0-9]{2,})|"
+    r"[a-z\u00a1-\uffff\U00010000-\U0010ffff]{2,}))"
     r")"
     # port number
     r"(?::\d{2,5})?"
     # resource path
-    u"(?:/[-a-z\u00a1-\uffff0-9._~%!$&'()*+,;=:@/]*)?"
+    r"(?:/[-a-z\u00a1-\uffff\U00010000-\U0010ffff0-9._~%!$&'()*+,;=:@/]*)?"
     # query string
     r"(?:\?\S*)?"
     # fragment
diff -pruN 0.14.2-3/validators/utils.py 0.20.0-1/validators/utils.py
--- 0.14.2-3/validators/utils.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/validators/utils.py	2022-06-05 17:11:40.000000000 +0000
@@ -2,7 +2,6 @@ import inspect
 import itertools
 from collections import OrderedDict
 
-import six
 from decorator import decorator
 
 
@@ -37,10 +36,7 @@ def func_args_as_dict(func, args, kwargs
     Return given function's positional and key value arguments as an ordered
     dictionary.
     """
-    if six.PY2:
-        _getargspec = inspect.getargspec
-    else:
-        _getargspec = inspect.getfullargspec
+    _getargspec = inspect.getfullargspec
 
     arg_names = list(
         OrderedDict.fromkeys(
@@ -51,7 +47,7 @@ def func_args_as_dict(func, args, kwargs
         )
     )
     return OrderedDict(
-        list(six.moves.zip(arg_names, args)) +
+        list(zip(arg_names, args)) +
         list(kwargs.items())
     )
 
diff -pruN 0.14.2-3/validators/uuid.py 0.20.0-1/validators/uuid.py
--- 0.14.2-3/validators/uuid.py	2020-01-24 09:58:21.000000000 +0000
+++ 0.20.0-1/validators/uuid.py	2022-06-05 17:11:40.000000000 +0000
@@ -1,4 +1,7 @@
+from __future__ import absolute_import
+
 import re
+from uuid import UUID
 
 from .utils import validator
 
@@ -28,6 +31,11 @@ def uuid(value):
 
     .. versionadded:: 0.2
 
-    :param value: UUID string to validate
+    :param value: UUID value to validate
     """
-    return pattern.match(value)
+    if isinstance(value, UUID):
+        return True
+    try:
+        return pattern.match(value)
+    except TypeError:
+        return False
