Merging PR_218 openai_rev package with new streamlit chat app
This commit is contained in:
35
venv/lib/python3.9/site-packages/validators/__init__.py
Normal file
35
venv/lib/python3.9/site-packages/validators/__init__.py
Normal file
@@ -0,0 +1,35 @@
|
||||
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
|
||||
from .hashes import md5, sha1, sha224, sha256, sha512
|
||||
from .i18n import fi_business_id, fi_ssn
|
||||
from .iban import iban
|
||||
from .ip_address import ipv4, ipv4_cidr, ipv6, ipv6_cidr
|
||||
from .length import length
|
||||
from .mac_address import mac_address
|
||||
from .slug import slug
|
||||
from .truthy import truthy
|
||||
from .url import url
|
||||
from .utils import ValidationFailure, validator
|
||||
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',
|
||||
'card_number', 'visa', 'mastercard', 'amex', 'unionpay', 'diners',
|
||||
'jcb', 'discover', 'btc_address')
|
||||
|
||||
__version__ = '0.20.0'
|
||||
61
venv/lib/python3.9/site-packages/validators/between.py
Normal file
61
venv/lib/python3.9/site-packages/validators/between.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from .extremes import Max, Min
|
||||
from .utils import validator
|
||||
|
||||
|
||||
@validator
|
||||
def between(value, min=None, max=None):
|
||||
"""
|
||||
Validate that a number is between minimum and/or maximum value.
|
||||
|
||||
This will work with any comparable type, such as floats, decimals and dates
|
||||
not just integers.
|
||||
|
||||
This validator is originally based on `WTForms NumberRange validator`_.
|
||||
|
||||
.. _WTForms NumberRange validator:
|
||||
https://github.com/wtforms/wtforms/blob/master/wtforms/validators.py
|
||||
|
||||
Examples::
|
||||
|
||||
>>> from datetime import datetime
|
||||
|
||||
>>> between(5, min=2)
|
||||
True
|
||||
|
||||
>>> between(13.2, min=13, max=14)
|
||||
True
|
||||
|
||||
>>> between(500, max=400)
|
||||
ValidationFailure(func=between, args=...)
|
||||
|
||||
>>> between(
|
||||
... datetime(2000, 11, 11),
|
||||
... min=datetime(1999, 11, 11)
|
||||
... )
|
||||
True
|
||||
|
||||
:param min:
|
||||
The minimum required value of the number. If not provided, minimum
|
||||
value will not be checked.
|
||||
:param max:
|
||||
The maximum value of the number. If not provided, maximum value
|
||||
will not be checked.
|
||||
|
||||
.. versionadded:: 0.2
|
||||
"""
|
||||
if min is None and max is None:
|
||||
raise AssertionError(
|
||||
'At least one of `min` or `max` must be specified.'
|
||||
)
|
||||
if min is None:
|
||||
min = Min
|
||||
if max is None:
|
||||
max = Max
|
||||
try:
|
||||
min_gt_max = min > max
|
||||
except TypeError:
|
||||
min_gt_max = max < min
|
||||
if min_gt_max:
|
||||
raise AssertionError('`min` cannot be more than `max`.')
|
||||
|
||||
return min <= value and max >= value
|
||||
55
venv/lib/python3.9/site-packages/validators/btc_address.py
Normal file
55
venv/lib/python3.9/site-packages/validators/btc_address.py
Normal file
@@ -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)
|
||||
183
venv/lib/python3.9/site-packages/validators/card.py
Normal file
183
venv/lib/python3.9/site-packages/validators/card.py
Normal file
@@ -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)
|
||||
54
venv/lib/python3.9/site-packages/validators/domain.py
Normal file
54
venv/lib/python3.9/site-packages/validators/domain.py
Normal file
@@ -0,0 +1,54 @@
|
||||
import re
|
||||
|
||||
from .utils import validator
|
||||
|
||||
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
|
||||
r'+[A-Za-z0-9][A-Za-z0-9-_]{0,61}' # First 61 characters of the gTLD
|
||||
r'[A-Za-z]$' # Last character of the gTLD
|
||||
)
|
||||
|
||||
|
||||
def to_unicode(obj, charset='utf-8', errors='strict'):
|
||||
if obj is None:
|
||||
return None
|
||||
if not isinstance(obj, bytes):
|
||||
return str(obj)
|
||||
return obj.decode(charset, errors)
|
||||
|
||||
|
||||
@validator
|
||||
def domain(value):
|
||||
"""
|
||||
Return whether or not given value is a valid domain.
|
||||
|
||||
If the value is valid domain name this function returns ``True``, otherwise
|
||||
:class:`~validators.utils.ValidationFailure`.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> domain('example.com')
|
||||
True
|
||||
|
||||
>>> domain('example.com/')
|
||||
ValidationFailure(func=domain, ...)
|
||||
|
||||
|
||||
Supports IDN domains as well::
|
||||
|
||||
>>> domain('xn----gtbspbbmkef.xn--p1ai')
|
||||
True
|
||||
|
||||
.. versionadded:: 0.9
|
||||
|
||||
.. versionchanged:: 0.10
|
||||
|
||||
Added support for internationalized domain name (IDN) validation.
|
||||
|
||||
:param value: domain string to validate
|
||||
"""
|
||||
try:
|
||||
return pattern.match(to_unicode(value).encode('idna').decode('ascii'))
|
||||
except (UnicodeError, AttributeError):
|
||||
return False
|
||||
75
venv/lib/python3.9/site-packages/validators/email.py
Normal file
75
venv/lib/python3.9/site-packages/validators/email.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import re
|
||||
|
||||
from .utils import validator
|
||||
|
||||
user_regex = re.compile(
|
||||
# dot-atom
|
||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+"
|
||||
r"(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$"
|
||||
# quoted-string
|
||||
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|'
|
||||
r"""\\[\001-\011\013\014\016-\177])*"$)""",
|
||||
re.IGNORECASE
|
||||
)
|
||||
domain_regex = re.compile(
|
||||
# domain
|
||||
r'(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+'
|
||||
r'(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?$)'
|
||||
# literal form, ipv4 address (SMTP 4.1.3)
|
||||
r'|^\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)'
|
||||
r'(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$',
|
||||
re.IGNORECASE)
|
||||
domain_whitelist = ['localhost']
|
||||
|
||||
|
||||
@validator
|
||||
def email(value, whitelist=None):
|
||||
"""
|
||||
Validate an email address.
|
||||
|
||||
This validator is based on `Django's email validator`_. Returns
|
||||
``True`` on success and :class:`~validators.utils.ValidationFailure`
|
||||
when validation fails.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> email('someone@example.com')
|
||||
True
|
||||
|
||||
>>> email('bogus@@')
|
||||
ValidationFailure(func=email, ...)
|
||||
|
||||
.. _Django's email validator:
|
||||
https://github.com/django/django/blob/master/django/core/validators.py
|
||||
|
||||
.. versionadded:: 0.1
|
||||
|
||||
:param value: value to validate
|
||||
:param whitelist: domain names to whitelist
|
||||
|
||||
:copyright: (c) Django Software Foundation and individual contributors.
|
||||
:license: BSD
|
||||
"""
|
||||
|
||||
if whitelist is None:
|
||||
whitelist = domain_whitelist
|
||||
|
||||
if not value or '@' not in value:
|
||||
return False
|
||||
|
||||
user_part, domain_part = value.rsplit('@', 1)
|
||||
|
||||
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:
|
||||
domain_part = domain_part.encode('idna').decode('ascii')
|
||||
return domain_regex.match(domain_part)
|
||||
except UnicodeError:
|
||||
return False
|
||||
return True
|
||||
61
venv/lib/python3.9/site-packages/validators/extremes.py
Normal file
61
venv/lib/python3.9/site-packages/validators/extremes.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from functools import total_ordering
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Min(object):
|
||||
"""
|
||||
An object that is less than any other object (except itself).
|
||||
|
||||
Inspired by https://pypi.python.org/pypi/Extremes
|
||||
|
||||
Examples::
|
||||
|
||||
>>> import sys
|
||||
|
||||
>>> Min < -sys.maxint
|
||||
True
|
||||
|
||||
>>> Min < None
|
||||
True
|
||||
|
||||
>>> Min < ''
|
||||
True
|
||||
|
||||
.. versionadded:: 0.2
|
||||
"""
|
||||
def __lt__(self, other):
|
||||
if other is Min:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Max(object):
|
||||
"""
|
||||
An object that is greater than any other object (except itself).
|
||||
|
||||
Inspired by https://pypi.python.org/pypi/Extremes
|
||||
|
||||
Examples::
|
||||
|
||||
>>> import sys
|
||||
|
||||
>>> Max > Min
|
||||
True
|
||||
|
||||
>>> Max > sys.maxint
|
||||
True
|
||||
|
||||
>>> Max > 99999999999999999
|
||||
True
|
||||
|
||||
.. versionadded:: 0.2
|
||||
"""
|
||||
def __gt__(self, other):
|
||||
if other is Max:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
Min = Min()
|
||||
Max = Max()
|
||||
121
venv/lib/python3.9/site-packages/validators/hashes.py
Normal file
121
venv/lib/python3.9/site-packages/validators/hashes.py
Normal file
@@ -0,0 +1,121 @@
|
||||
import re
|
||||
|
||||
from .utils import validator
|
||||
|
||||
md5_regex = re.compile(
|
||||
r"^[0-9a-f]{32}$",
|
||||
re.IGNORECASE
|
||||
)
|
||||
sha1_regex = re.compile(
|
||||
r"^[0-9a-f]{40}$",
|
||||
re.IGNORECASE
|
||||
)
|
||||
sha224_regex = re.compile(
|
||||
r"^[0-9a-f]{56}$",
|
||||
re.IGNORECASE
|
||||
)
|
||||
sha256_regex = re.compile(
|
||||
r"^[0-9a-f]{64}$",
|
||||
re.IGNORECASE
|
||||
)
|
||||
sha512_regex = re.compile(
|
||||
r"^[0-9a-f]{128}$",
|
||||
re.IGNORECASE
|
||||
)
|
||||
|
||||
|
||||
@validator
|
||||
def md5(value):
|
||||
"""
|
||||
Return whether or not given value is a valid MD5 hash.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> md5('d41d8cd98f00b204e9800998ecf8427e')
|
||||
True
|
||||
|
||||
>>> md5('900zz11')
|
||||
ValidationFailure(func=md5, args={'value': '900zz11'})
|
||||
|
||||
:param value: MD5 string to validate
|
||||
"""
|
||||
return md5_regex.match(value)
|
||||
|
||||
|
||||
@validator
|
||||
def sha1(value):
|
||||
"""
|
||||
Return whether or not given value is a valid SHA1 hash.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> sha1('da39a3ee5e6b4b0d3255bfef95601890afd80709')
|
||||
True
|
||||
|
||||
>>> sha1('900zz11')
|
||||
ValidationFailure(func=sha1, args={'value': '900zz11'})
|
||||
|
||||
:param value: SHA1 string to validate
|
||||
"""
|
||||
return sha1_regex.match(value)
|
||||
|
||||
|
||||
@validator
|
||||
def sha224(value):
|
||||
"""
|
||||
Return whether or not given value is a valid SHA224 hash.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> sha224('d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f')
|
||||
True
|
||||
|
||||
>>> sha224('900zz11')
|
||||
ValidationFailure(func=sha224, args={'value': '900zz11'})
|
||||
|
||||
:param value: SHA224 string to validate
|
||||
"""
|
||||
return sha224_regex.match(value)
|
||||
|
||||
|
||||
@validator
|
||||
def sha256(value):
|
||||
"""
|
||||
Return whether or not given value is a valid SHA256 hash.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> sha256(
|
||||
... 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b'
|
||||
... '855'
|
||||
... )
|
||||
True
|
||||
|
||||
>>> sha256('900zz11')
|
||||
ValidationFailure(func=sha256, args={'value': '900zz11'})
|
||||
|
||||
:param value: SHA256 string to validate
|
||||
"""
|
||||
return sha256_regex.match(value)
|
||||
|
||||
|
||||
@validator
|
||||
def sha512(value):
|
||||
"""
|
||||
Return whether or not given value is a valid SHA512 hash.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> sha512(
|
||||
... 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce'
|
||||
... '9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af9'
|
||||
... '27da3e'
|
||||
... )
|
||||
True
|
||||
|
||||
>>> sha512('900zz11')
|
||||
ValidationFailure(func=sha512, args={'value': '900zz11'})
|
||||
|
||||
:param value: SHA512 string to validate
|
||||
"""
|
||||
return sha512_regex.match(value)
|
||||
@@ -0,0 +1,4 @@
|
||||
# TODO: remove, let the user import it if they really want it
|
||||
from .fi import fi_business_id, fi_ssn # noqa
|
||||
|
||||
__all__ = ('fi_business_id', 'fi_ssn')
|
||||
200
venv/lib/python3.9/site-packages/validators/i18n/es.py
Normal file
200
venv/lib/python3.9/site-packages/validators/i18n/es.py
Normal file
@@ -0,0 +1,200 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from validators.utils import validator
|
||||
|
||||
__all__ = ('es_cif', 'es_nif', 'es_nie', 'es_doi',)
|
||||
|
||||
|
||||
def nif_nie_validation(doi, number_by_letter, special_cases):
|
||||
"""
|
||||
Validate if the doi is a NIF or a NIE.
|
||||
:param doi: DOI to validate.
|
||||
:return: boolean if it's valid.
|
||||
"""
|
||||
doi = doi.upper()
|
||||
if doi in special_cases:
|
||||
return False
|
||||
|
||||
table = 'TRWAGMYFPDXBNJZSQVHLCKE'
|
||||
|
||||
if len(doi) != 9:
|
||||
return False
|
||||
|
||||
control = doi[8]
|
||||
|
||||
# If it is not a DNI, convert the first letter to the corresponding
|
||||
# digit
|
||||
numbers = number_by_letter.get(doi[0], doi[0]) + doi[1:8]
|
||||
|
||||
return numbers.isdigit() and control == table[int(numbers) % 23]
|
||||
|
||||
|
||||
@validator
|
||||
def es_cif(doi):
|
||||
"""
|
||||
Validate a Spanish CIF.
|
||||
|
||||
Each company in Spain prior to 2008 had a distinct CIF and has been
|
||||
discontinued. For more information see `wikipedia.org/cif`_.
|
||||
|
||||
The new replacement is to use NIF for absolutely everything. The issue is
|
||||
that there are "types" of NIFs now: company, person[citizen vs recident]
|
||||
all distinguished by the first character of the DOI. For this reason we
|
||||
will continue to call CIF NIFs that are used for companies.
|
||||
|
||||
This validator is based on `generadordni.es`_.
|
||||
|
||||
.. _generadordni.es:
|
||||
https://generadordni.es/
|
||||
|
||||
.. _wikipedia.org/cif:
|
||||
https://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
|
||||
|
||||
Examples::
|
||||
|
||||
>>> es_cif('B25162520')
|
||||
True
|
||||
|
||||
>>> es_cif('B25162529')
|
||||
ValidationFailure(func=es_cif, args=...)
|
||||
|
||||
.. versionadded:: 0.13.0
|
||||
|
||||
:param doi: DOI to validate
|
||||
"""
|
||||
doi = doi.upper()
|
||||
|
||||
if len(doi) != 9:
|
||||
return False
|
||||
|
||||
table = 'JABCDEFGHI'
|
||||
first_chr = doi[0]
|
||||
doi_body = doi[1:8]
|
||||
control = doi[8]
|
||||
|
||||
if not doi_body.isdigit():
|
||||
return False
|
||||
|
||||
odd_result = 0
|
||||
even_result = 0
|
||||
for index, char in enumerate(doi_body):
|
||||
if index % 2 == 0:
|
||||
# Multiply each each odd position doi digit by 2 and sum it all
|
||||
# together
|
||||
odd_result += sum(map(int, str(int(char) * 2)))
|
||||
else:
|
||||
even_result += int(char)
|
||||
|
||||
res = (10 - (even_result + odd_result) % 10) % 10
|
||||
|
||||
if first_chr in 'ABEH': # Number type
|
||||
return str(res) == control
|
||||
elif first_chr in 'PSQW': # Letter type
|
||||
return table[res] == control
|
||||
elif first_chr not in 'CDFGJNRUV':
|
||||
return False
|
||||
|
||||
return control == str(res) or control == table[res]
|
||||
|
||||
|
||||
@validator
|
||||
def es_nif(doi):
|
||||
"""
|
||||
Validate a Spanish NIF.
|
||||
|
||||
Each entity, be it person or company in Spain has a distinct NIF. Since
|
||||
we've designated CIF to be a company NIF, this NIF is only for person.
|
||||
For more information see `wikipedia.org/nif`_.
|
||||
|
||||
This validator is based on `generadordni.es`_.
|
||||
|
||||
.. _generadordni.es:
|
||||
https://generadordni.es/
|
||||
|
||||
.. _wikipedia.org/nif:
|
||||
https://es.wikipedia.org/wiki/N%C3%BAmero_de_identificaci%C3%B3n_fiscal
|
||||
|
||||
Examples::
|
||||
|
||||
>>> es_nif('26643189N')
|
||||
True
|
||||
|
||||
>>> es_nif('26643189X')
|
||||
ValidationFailure(func=es_nif, args=...)
|
||||
|
||||
.. versionadded:: 0.13.0
|
||||
|
||||
:param doi: DOI to validate
|
||||
"""
|
||||
number_by_letter = {'L': '0', 'M': '0', 'K': '0'}
|
||||
special_cases = ['X0000000T', '00000000T', '00000001R']
|
||||
return nif_nie_validation(doi, number_by_letter, special_cases)
|
||||
|
||||
|
||||
@validator
|
||||
def es_nie(doi):
|
||||
"""
|
||||
Validate a Spanish NIE.
|
||||
|
||||
The NIE is a tax identification number in Spain, known in Spanish as the
|
||||
NIE, or more formally the Número de identidad de extranjero. For more
|
||||
information see `wikipedia.org/nie`_.
|
||||
|
||||
This validator is based on `generadordni.es`_.
|
||||
|
||||
.. _generadordni.es:
|
||||
https://generadordni.es/
|
||||
|
||||
.. _wikipedia.org/nie:
|
||||
https://es.wikipedia.org/wiki/N%C3%BAmero_de_identidad_de_extranjero
|
||||
|
||||
Examples::
|
||||
|
||||
>>> es_nie('X0095892M')
|
||||
True
|
||||
|
||||
>>> es_nie('X0095892X')
|
||||
ValidationFailure(func=es_nie, args=...)
|
||||
|
||||
.. versionadded:: 0.13.0
|
||||
|
||||
:param doi: DOI to validate
|
||||
"""
|
||||
number_by_letter = {'X': '0', 'Y': '1', 'Z': '2'}
|
||||
special_cases = ['X0000000T']
|
||||
|
||||
# NIE must must start with X Y or Z
|
||||
if not doi or doi[0] not in number_by_letter.keys():
|
||||
return False
|
||||
|
||||
return nif_nie_validation(doi, number_by_letter, special_cases)
|
||||
|
||||
|
||||
@validator
|
||||
def es_doi(doi):
|
||||
"""
|
||||
Validate a Spanish DOI.
|
||||
|
||||
A DOI in spain is all NIF / CIF / NIE / DNI -- a digital ID. For more
|
||||
information see `wikipedia.org/doi`_.
|
||||
|
||||
This validator is based on `generadordni.es`_.
|
||||
|
||||
.. _generadordni.es:
|
||||
https://generadordni.es/
|
||||
|
||||
.. _wikipedia.org/doi:
|
||||
https://es.wikipedia.org/wiki/Identificador_de_objeto_digital
|
||||
|
||||
Examples::
|
||||
|
||||
>>> es_doi('X0095892M')
|
||||
True
|
||||
|
||||
>>> es_doi('X0095892X')
|
||||
ValidationFailure(func=es_doi, args=...)
|
||||
|
||||
.. versionadded:: 0.13.0
|
||||
|
||||
:param doi: DOI to validate
|
||||
"""
|
||||
return es_nie(doi) or es_nif(doi) or es_cif(doi)
|
||||
94
venv/lib/python3.9/site-packages/validators/i18n/fi.py
Normal file
94
venv/lib/python3.9/site-packages/validators/i18n/fi.py
Normal file
@@ -0,0 +1,94 @@
|
||||
import re
|
||||
|
||||
from validators.utils import validator
|
||||
|
||||
business_id_pattern = re.compile(r'^[0-9]{7}-[0-9]$')
|
||||
ssn_checkmarks = '0123456789ABCDEFHJKLMNPRSTUVWXY'
|
||||
ssn_pattern = re.compile(
|
||||
r"""^
|
||||
(?P<date>(0[1-9]|[1-2]\d|3[01])
|
||||
(0[1-9]|1[012])
|
||||
(\d{{2}}))
|
||||
[A+-]
|
||||
(?P<serial>(\d{{3}}))
|
||||
(?P<checksum>[{checkmarks}])$""".format(checkmarks=ssn_checkmarks),
|
||||
re.VERBOSE
|
||||
)
|
||||
|
||||
|
||||
@validator
|
||||
def fi_business_id(business_id):
|
||||
"""
|
||||
Validate a Finnish Business ID.
|
||||
|
||||
Each company in Finland has a distinct business id. For more
|
||||
information see `Finnish Trade Register`_
|
||||
|
||||
.. _Finnish Trade Register:
|
||||
http://en.wikipedia.org/wiki/Finnish_Trade_Register
|
||||
|
||||
Examples::
|
||||
|
||||
>>> fi_business_id('0112038-9') # Fast Monkeys Ltd
|
||||
True
|
||||
|
||||
>>> fi_business_id('1234567-8') # Bogus ID
|
||||
ValidationFailure(func=fi_business_id, ...)
|
||||
|
||||
.. versionadded:: 0.4
|
||||
.. versionchanged:: 0.5
|
||||
Method renamed from ``finnish_business_id`` to ``fi_business_id``
|
||||
|
||||
:param business_id: business_id to validate
|
||||
"""
|
||||
if not business_id or not re.match(business_id_pattern, business_id):
|
||||
return False
|
||||
factors = [7, 9, 10, 5, 8, 4, 2]
|
||||
numbers = map(int, business_id[:7])
|
||||
checksum = int(business_id[8])
|
||||
sum_ = sum(f * n for f, n in zip(factors, numbers))
|
||||
modulo = sum_ % 11
|
||||
return (11 - modulo == checksum) or (modulo == 0 and checksum == 0)
|
||||
|
||||
|
||||
@validator
|
||||
def fi_ssn(ssn, allow_temporal_ssn=True):
|
||||
"""
|
||||
Validate a Finnish Social Security Number.
|
||||
|
||||
This validator is based on `django-localflavor-fi`_.
|
||||
|
||||
.. _django-localflavor-fi:
|
||||
https://github.com/django/django-localflavor-fi/
|
||||
|
||||
Examples::
|
||||
|
||||
>>> fi_ssn('010101-0101')
|
||||
True
|
||||
|
||||
>>> fi_ssn('101010-0102')
|
||||
ValidationFailure(func=fi_ssn, args=...)
|
||||
|
||||
.. versionadded:: 0.5
|
||||
|
||||
:param ssn: Social Security Number to validate
|
||||
:param allow_temporal_ssn:
|
||||
Whether to accept temporal SSN numbers. Temporal SSN numbers are the
|
||||
ones where the serial is in the range [900-999]. By default temporal
|
||||
SSN numbers are valid.
|
||||
|
||||
"""
|
||||
if not ssn:
|
||||
return False
|
||||
|
||||
result = re.match(ssn_pattern, ssn)
|
||||
if not result:
|
||||
return False
|
||||
gd = result.groupdict()
|
||||
checksum = int(gd['date'] + gd['serial'])
|
||||
return (
|
||||
int(gd['serial']) >= 2 and
|
||||
(allow_temporal_ssn or int(gd['serial']) <= 899) and
|
||||
ssn_checkmarks[checksum % len(ssn_checkmarks)] ==
|
||||
gd['checksum']
|
||||
)
|
||||
52
venv/lib/python3.9/site-packages/validators/iban.py
Normal file
52
venv/lib/python3.9/site-packages/validators/iban.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import re
|
||||
|
||||
from .utils import validator
|
||||
|
||||
regex = (
|
||||
r'^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$'
|
||||
)
|
||||
pattern = re.compile(regex)
|
||||
|
||||
|
||||
def char_value(char):
|
||||
"""A=10, B=11, ..., Z=35
|
||||
"""
|
||||
if char.isdigit():
|
||||
return int(char)
|
||||
else:
|
||||
return 10 + ord(char) - ord('A')
|
||||
|
||||
|
||||
def modcheck(value):
|
||||
"""Check if the value string passes the mod97-test.
|
||||
"""
|
||||
# move country code and check numbers to end
|
||||
rearranged = value[4:] + value[:4]
|
||||
# convert letters to numbers
|
||||
converted = [char_value(char) for char in rearranged]
|
||||
# interpret as integer
|
||||
integerized = int(''.join([str(i) for i in converted]))
|
||||
return (integerized % 97 == 1)
|
||||
|
||||
|
||||
@validator
|
||||
def iban(value):
|
||||
"""
|
||||
Return whether or not given value is a valid IBAN code.
|
||||
|
||||
If the value is a valid IBAN this function returns ``True``, otherwise
|
||||
:class:`~validators.utils.ValidationFailure`.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> iban('DE29100500001061045672')
|
||||
True
|
||||
|
||||
>>> iban('123456')
|
||||
ValidationFailure(func=iban, ...)
|
||||
|
||||
.. versionadded:: 0.8
|
||||
|
||||
:param value: IBAN string to validate
|
||||
"""
|
||||
return pattern.match(value) and modcheck(value)
|
||||
156
venv/lib/python3.9/site-packages/validators/ip_address.py
Normal file
156
venv/lib/python3.9/site-packages/validators/ip_address.py
Normal file
@@ -0,0 +1,156 @@
|
||||
from .utils import validator
|
||||
|
||||
|
||||
@validator
|
||||
def ipv4(value):
|
||||
"""
|
||||
Return whether a given value is a valid IP version 4 address.
|
||||
|
||||
This validator is based on `WTForms IPAddress validator`_
|
||||
|
||||
.. _WTForms IPAddress validator:
|
||||
https://github.com/wtforms/wtforms/blob/master/wtforms/validators.py
|
||||
|
||||
Examples::
|
||||
|
||||
>>> ipv4('123.0.0.7')
|
||||
True
|
||||
|
||||
>>> ipv4('900.80.70.11')
|
||||
ValidationFailure(func=ipv4, args={'value': '900.80.70.11'})
|
||||
|
||||
.. versionadded:: 0.2
|
||||
|
||||
:param value: IP address string to validate
|
||||
"""
|
||||
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)
|
||||
|
||||
|
||||
@validator
|
||||
def ipv4_cidr(value):
|
||||
"""
|
||||
Return whether a given value is a valid CIDR-notated IP version 4
|
||||
address range.
|
||||
|
||||
This validator is based on RFC4632 3.1.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> ipv4_cidr('1.1.1.1/8')
|
||||
True
|
||||
|
||||
>>> ipv4_cidr('1.1.1.1')
|
||||
ValidationFailure(func=ipv4_cidr, args={'value': '1.1.1.1'})
|
||||
"""
|
||||
try:
|
||||
prefix, suffix = value.split('/', 2)
|
||||
except ValueError:
|
||||
return False
|
||||
if not ipv4(prefix) or not suffix.isdigit():
|
||||
return False
|
||||
return 0 <= int(suffix) <= 32
|
||||
|
||||
|
||||
@validator
|
||||
def ipv6(value):
|
||||
"""
|
||||
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`_.
|
||||
|
||||
.. _WTForms IPAddress validator:
|
||||
https://github.com/wtforms/wtforms/blob/master/wtforms/validators.py
|
||||
|
||||
Examples::
|
||||
|
||||
>>> ipv6('abcd:ef::42:1')
|
||||
True
|
||||
|
||||
>>> ipv6('::ffff:192.0.2.128')
|
||||
True
|
||||
|
||||
>>> ipv6('::192.0.2.128')
|
||||
True
|
||||
|
||||
>>> ipv6('abc.0.0.1')
|
||||
ValidationFailure(func=ipv6, args={'value': 'abc.0.0.1'})
|
||||
|
||||
.. versionadded:: 0.2
|
||||
|
||||
:param value: IP address string to validate
|
||||
"""
|
||||
ipv6_groups = value.split(':')
|
||||
if len(ipv6_groups) == 1:
|
||||
return False
|
||||
ipv4_groups = ipv6_groups[-1].split('.')
|
||||
|
||||
if len(ipv4_groups) > 1:
|
||||
if not ipv4(ipv6_groups[-1]):
|
||||
return False
|
||||
ipv6_groups = ipv6_groups[:-1]
|
||||
else:
|
||||
ipv4_groups = []
|
||||
|
||||
count_blank = 0
|
||||
for part in ipv6_groups:
|
||||
if not part:
|
||||
count_blank += 1
|
||||
continue
|
||||
try:
|
||||
num = int(part, 16)
|
||||
except ValueError:
|
||||
return False
|
||||
else:
|
||||
if not 0 <= num <= 65536 or len(part) > 4:
|
||||
return False
|
||||
|
||||
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 == 3 and part_count == 0:
|
||||
# :: is the address -> filter everything else
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@validator
|
||||
def ipv6_cidr(value):
|
||||
"""
|
||||
Returns whether a given value is a valid CIDR-notated IP version 6
|
||||
address range.
|
||||
|
||||
This validator is based on RFC4632 3.1.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> ipv6_cidr('::1/128')
|
||||
True
|
||||
|
||||
>>> ipv6_cidr('::1')
|
||||
ValidationFailure(func=ipv6_cidr, args={'value': '::1'})
|
||||
"""
|
||||
try:
|
||||
prefix, suffix = value.split('/', 2)
|
||||
except ValueError:
|
||||
return False
|
||||
if not ipv6(prefix) or not suffix.isdigit():
|
||||
return False
|
||||
return 0 <= int(suffix) <= 128
|
||||
37
venv/lib/python3.9/site-packages/validators/length.py
Normal file
37
venv/lib/python3.9/site-packages/validators/length.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from .between import between
|
||||
from .utils import validator
|
||||
|
||||
|
||||
@validator
|
||||
def length(value, min=None, max=None):
|
||||
"""
|
||||
Return whether or not the length of given string is within a specified
|
||||
range.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> length('something', min=2)
|
||||
True
|
||||
|
||||
>>> length('something', min=9, max=9)
|
||||
True
|
||||
|
||||
>>> length('something', max=5)
|
||||
ValidationFailure(func=length, ...)
|
||||
|
||||
:param value:
|
||||
The string to validate.
|
||||
:param min:
|
||||
The minimum required length of the string. If not provided, minimum
|
||||
length will not be checked.
|
||||
:param max:
|
||||
The maximum length of the string. If not provided, maximum length
|
||||
will not be checked.
|
||||
|
||||
.. versionadded:: 0.2
|
||||
"""
|
||||
if (min is not None and min < 0) or (max is not None and max < 0):
|
||||
raise AssertionError(
|
||||
'`min` and `max` need to be greater than zero.'
|
||||
)
|
||||
return between(len(value), min=min, max=max)
|
||||
33
venv/lib/python3.9/site-packages/validators/mac_address.py
Normal file
33
venv/lib/python3.9/site-packages/validators/mac_address.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import re
|
||||
|
||||
from .utils import validator
|
||||
|
||||
pattern = re.compile(r'^(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$')
|
||||
|
||||
|
||||
@validator
|
||||
def mac_address(value):
|
||||
"""
|
||||
Return whether or not given value is a valid MAC address.
|
||||
|
||||
If the value is valid MAC address this function returns ``True``,
|
||||
otherwise :class:`~validators.utils.ValidationFailure`.
|
||||
|
||||
This validator is based on `WTForms MacAddress validator`_.
|
||||
|
||||
.. _WTForms MacAddress validator:
|
||||
https://github.com/wtforms/wtforms/blob/master/wtforms/validators.py
|
||||
|
||||
Examples::
|
||||
|
||||
>>> mac_address('01:23:45:67:ab:CD')
|
||||
True
|
||||
|
||||
>>> mac_address('00:00:00:00:00')
|
||||
ValidationFailure(func=mac_address, args={'value': '00:00:00:00:00'})
|
||||
|
||||
.. versionadded:: 0.2
|
||||
|
||||
:param value: Mac address string to validate
|
||||
"""
|
||||
return pattern.match(value)
|
||||
28
venv/lib/python3.9/site-packages/validators/slug.py
Normal file
28
venv/lib/python3.9/site-packages/validators/slug.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import re
|
||||
|
||||
from .utils import validator
|
||||
|
||||
slug_regex = re.compile(r'^[-a-zA-Z0-9_]+$')
|
||||
|
||||
|
||||
@validator
|
||||
def slug(value):
|
||||
"""
|
||||
Validate whether or not given value is valid slug.
|
||||
|
||||
Valid slug can contain only alphanumeric characters, hyphens and
|
||||
underscores.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> slug('my.slug')
|
||||
ValidationFailure(func=slug, args={'value': 'my.slug'})
|
||||
|
||||
>>> slug('my-slug-2134')
|
||||
True
|
||||
|
||||
.. versionadded:: 0.6
|
||||
|
||||
:param value: value to validate
|
||||
"""
|
||||
return slug_regex.match(value)
|
||||
39
venv/lib/python3.9/site-packages/validators/truthy.py
Normal file
39
venv/lib/python3.9/site-packages/validators/truthy.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from .utils import validator
|
||||
|
||||
|
||||
@validator
|
||||
def truthy(value):
|
||||
"""
|
||||
Validate that given value is not a falsey value.
|
||||
|
||||
This validator is based on `WTForms DataRequired validator`_.
|
||||
|
||||
.. _WTForms DataRequired validator:
|
||||
https://github.com/wtforms/wtforms/blob/master/wtforms/validators.py
|
||||
|
||||
Examples::
|
||||
|
||||
>>> truthy(1)
|
||||
True
|
||||
|
||||
>>> truthy('someone')
|
||||
True
|
||||
|
||||
>>> truthy(0)
|
||||
ValidationFailure(func=truthy, args={'value': 0})
|
||||
|
||||
>>> truthy(' ')
|
||||
ValidationFailure(func=truthy, args={'value': ' '})
|
||||
|
||||
>>> truthy(False)
|
||||
ValidationFailure(func=truthy, args={'value': False})
|
||||
|
||||
>>> truthy(None)
|
||||
ValidationFailure(func=truthy, args={'value': None})
|
||||
|
||||
.. versionadded:: 0.2
|
||||
"""
|
||||
return (
|
||||
value and
|
||||
(not isinstance(value, str) or value.strip())
|
||||
)
|
||||
154
venv/lib/python3.9/site-packages/validators/url.py
Normal file
154
venv/lib/python3.9/site-packages/validators/url.py
Normal file
@@ -0,0 +1,154 @@
|
||||
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"(?:\.(?:0|[1-9]\d?|1\d\d|2[0-4]\d|25[0-5]))"
|
||||
|
||||
regex = re.compile( # noqa: W605
|
||||
r"^"
|
||||
# protocol identifier
|
||||
r"(?:(?:https?|ftp)://)"
|
||||
# user:pass authentication
|
||||
r"(?:[-a-z\u00a1-\uffff0-9._~%!$&'()*+,;=:]+"
|
||||
r"(?::[-a-z0-9._~%!$&'()*+,;=:]*)?@)?"
|
||||
r"(?:"
|
||||
r"(?P<private_ip>"
|
||||
# IP address exclusion
|
||||
# private & local networks
|
||||
r"(?:(?:10|127)" + ip_middle_octet + r"{2}" + ip_last_octet + r")|"
|
||||
r"(?:(?:169\.254|192\.168)" + ip_middle_octet + ip_last_octet + r")|"
|
||||
r"(?:172\.(?:1[6-9]|2\d|3[0-1])" + ip_middle_octet + ip_last_octet + r"))"
|
||||
r"|"
|
||||
# private & local hosts
|
||||
r"(?P<private_host>"
|
||||
r"(?:localhost))"
|
||||
r"|"
|
||||
# IP address dotted notation octets
|
||||
# excludes loopback network 0.0.0.0
|
||||
# excludes reserved space >= 224.0.0.0
|
||||
# excludes network & broadcast addresses
|
||||
# (first & last IP address of each class)
|
||||
r"(?P<public_ip>"
|
||||
r"(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])"
|
||||
r"" + ip_middle_octet + r"{2}"
|
||||
r"" + ip_last_octet + r")"
|
||||
r"|"
|
||||
# IPv6 RegEx from https://stackoverflow.com/a/17871737
|
||||
r"\[("
|
||||
# 1:2:3:4:5:6:7:8
|
||||
r"([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|"
|
||||
# 1:: 1:2:3:4:5:6:7::
|
||||
r"([0-9a-fA-F]{1,4}:){1,7}:|"
|
||||
# 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8
|
||||
r"([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|"
|
||||
# 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8
|
||||
r"([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|"
|
||||
# 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8
|
||||
r"([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|"
|
||||
# 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8
|
||||
r"([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|"
|
||||
# 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8
|
||||
r"([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|"
|
||||
# 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8
|
||||
r"[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|"
|
||||
# ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::
|
||||
r":((:[0-9a-fA-F]{1,4}){1,7}|:)|"
|
||||
# fe80::7:8%eth0 fe80::7:8%1
|
||||
# (link-local IPv6 addresses with zone index)
|
||||
r"fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|"
|
||||
r"::(ffff(:0{1,4}){0,1}:){0,1}"
|
||||
r"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}"
|
||||
# ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255
|
||||
# (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
|
||||
r"(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|"
|
||||
r"([0-9a-fA-F]{1,4}:){1,4}:"
|
||||
r"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}"
|
||||
# 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33
|
||||
# (IPv4-Embedded IPv6 Address)
|
||||
r"(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
|
||||
r")\]|"
|
||||
# host name
|
||||
r"(?:(?:(?:xn--[-]{0,2})|[a-z\u00a1-\uffff\U00010000-\U0010ffff0-9]-?)*"
|
||||
r"[a-z\u00a1-\uffff\U00010000-\U0010ffff0-9]+)"
|
||||
# domain name
|
||||
r"(?:\.(?:(?:xn--[-]{0,2})|[a-z\u00a1-\uffff\U00010000-\U0010ffff0-9]-?)*"
|
||||
r"[a-z\u00a1-\uffff\U00010000-\U0010ffff0-9]+)*"
|
||||
# TLD identifier
|
||||
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
|
||||
r"(?:/[-a-z\u00a1-\uffff\U00010000-\U0010ffff0-9._~%!$&'()*+,;=:@/]*)?"
|
||||
# query string
|
||||
r"(?:\?\S*)?"
|
||||
# fragment
|
||||
r"(?:#\S*)?"
|
||||
r"$",
|
||||
re.UNICODE | re.IGNORECASE
|
||||
)
|
||||
|
||||
pattern = re.compile(regex)
|
||||
|
||||
|
||||
@validator
|
||||
def url(value, public=False):
|
||||
"""
|
||||
Return whether or not given value is a valid URL.
|
||||
|
||||
If the value is valid URL this function returns ``True``, otherwise
|
||||
:class:`~validators.utils.ValidationFailure`.
|
||||
|
||||
This validator is based on the wonderful `URL validator of dperini`_.
|
||||
|
||||
.. _URL validator of dperini:
|
||||
https://gist.github.com/dperini/729294
|
||||
|
||||
Examples::
|
||||
|
||||
>>> url('http://foobar.dk')
|
||||
True
|
||||
|
||||
>>> url('ftp://foobar.dk')
|
||||
True
|
||||
|
||||
>>> url('http://10.0.0.1')
|
||||
True
|
||||
|
||||
>>> url('http://foobar.d')
|
||||
ValidationFailure(func=url, ...)
|
||||
|
||||
>>> url('http://10.0.0.1', public=True)
|
||||
ValidationFailure(func=url, ...)
|
||||
|
||||
.. versionadded:: 0.2
|
||||
|
||||
.. versionchanged:: 0.10.2
|
||||
|
||||
Added support for various exotic URLs and fixed various false
|
||||
positives.
|
||||
|
||||
.. versionchanged:: 0.10.3
|
||||
|
||||
Added ``public`` parameter.
|
||||
|
||||
.. versionchanged:: 0.11.0
|
||||
|
||||
Made the regular expression this function uses case insensitive.
|
||||
|
||||
.. versionchanged:: 0.11.3
|
||||
|
||||
Added support for URLs containing localhost
|
||||
|
||||
:param value: URL address string to validate
|
||||
:param public: (default=False) Set True to only allow a public IP address
|
||||
"""
|
||||
result = pattern.match(value)
|
||||
if not public:
|
||||
return result
|
||||
|
||||
return result and not any(
|
||||
(result.groupdict().get(key) for key in ('private_ip', 'private_host'))
|
||||
)
|
||||
85
venv/lib/python3.9/site-packages/validators/utils.py
Normal file
85
venv/lib/python3.9/site-packages/validators/utils.py
Normal file
@@ -0,0 +1,85 @@
|
||||
import inspect
|
||||
import itertools
|
||||
from collections import OrderedDict
|
||||
|
||||
from decorator import decorator
|
||||
|
||||
|
||||
class ValidationFailure(Exception):
|
||||
def __init__(self, func, args):
|
||||
self.func = func
|
||||
self.__dict__.update(args)
|
||||
|
||||
def __repr__(self):
|
||||
return u'ValidationFailure(func={func}, args={args})'.format(
|
||||
func=self.func.__name__,
|
||||
args=dict(
|
||||
[(k, v) for (k, v) in self.__dict__.items() if k != 'func']
|
||||
)
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return repr(self)
|
||||
|
||||
def __unicode__(self):
|
||||
return repr(self)
|
||||
|
||||
def __bool__(self):
|
||||
return False
|
||||
|
||||
def __nonzero__(self):
|
||||
return False
|
||||
|
||||
|
||||
def func_args_as_dict(func, args, kwargs):
|
||||
"""
|
||||
Return given function's positional and key value arguments as an ordered
|
||||
dictionary.
|
||||
"""
|
||||
_getargspec = inspect.getfullargspec
|
||||
|
||||
arg_names = list(
|
||||
OrderedDict.fromkeys(
|
||||
itertools.chain(
|
||||
_getargspec(func)[0],
|
||||
kwargs.keys()
|
||||
)
|
||||
)
|
||||
)
|
||||
return OrderedDict(
|
||||
list(zip(arg_names, args)) +
|
||||
list(kwargs.items())
|
||||
)
|
||||
|
||||
|
||||
def validator(func, *args, **kwargs):
|
||||
"""
|
||||
A decorator that makes given function validator.
|
||||
|
||||
Whenever the given function is called and returns ``False`` value
|
||||
this decorator returns :class:`ValidationFailure` object.
|
||||
|
||||
Example::
|
||||
|
||||
>>> @validator
|
||||
... def even(value):
|
||||
... return not (value % 2)
|
||||
|
||||
>>> even(4)
|
||||
True
|
||||
|
||||
>>> even(5)
|
||||
ValidationFailure(func=even, args={'value': 5})
|
||||
|
||||
:param func: function to decorate
|
||||
:param args: positional function arguments
|
||||
:param kwargs: key value function arguments
|
||||
"""
|
||||
def wrapper(func, *args, **kwargs):
|
||||
value = func(*args, **kwargs)
|
||||
if not value:
|
||||
return ValidationFailure(
|
||||
func, func_args_as_dict(func, args, kwargs)
|
||||
)
|
||||
return True
|
||||
return decorator(wrapper, func)
|
||||
41
venv/lib/python3.9/site-packages/validators/uuid.py
Normal file
41
venv/lib/python3.9/site-packages/validators/uuid.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import re
|
||||
from uuid import UUID
|
||||
|
||||
from .utils import validator
|
||||
|
||||
pattern = re.compile(r'^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$')
|
||||
|
||||
|
||||
@validator
|
||||
def uuid(value):
|
||||
"""
|
||||
Return whether or not given value is a valid UUID.
|
||||
|
||||
If the value is valid UUID this function returns ``True``, otherwise
|
||||
:class:`~validators.utils.ValidationFailure`.
|
||||
|
||||
This validator is based on `WTForms UUID validator`_.
|
||||
|
||||
.. _WTForms UUID validator:
|
||||
https://github.com/wtforms/wtforms/blob/master/wtforms/validators.py
|
||||
|
||||
Examples::
|
||||
|
||||
>>> uuid('2bc1c94f-0deb-43e9-92a1-4775189ec9f8')
|
||||
True
|
||||
|
||||
>>> uuid('2bc1c94f 0deb-43e9-92a1-4775189ec9f8')
|
||||
ValidationFailure(func=uuid, ...)
|
||||
|
||||
.. versionadded:: 0.2
|
||||
|
||||
:param value: UUID value to validate
|
||||
"""
|
||||
if isinstance(value, UUID):
|
||||
return True
|
||||
try:
|
||||
return pattern.match(value)
|
||||
except TypeError:
|
||||
return False
|
||||
Reference in New Issue
Block a user