aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby <[email protected]>2022-11-27 16:29:38 -0500
committerGitHub <[email protected]>2022-11-27 16:29:38 -0500
commit067d649a1a0f7d8c3de230fecc1b1542d9cacbb6 (patch)
treeb18111660ecda6741da8654e96380bce852aeaec
parent3dfdd675e661f32f7373a521ad66ab56f637e0c4 (diff)
parentb9b6b54eac925b75f3ed844f65832e5bd09e251e (diff)
downloadedify-067d649a1a0f7d8c3de230fecc1b1542d9cacbb6.tar.xz
edify-067d649a1a0f7d8c3de230fecc1b1542d9cacbb6.zip
Fix patch 0.1.1 (#20)
## Added: 1. URL Validator 2. UUID Validator 3. GUID Validator 4. SSN Validator 5. Mac Address (IEEE 802) Validator 6. Zip Code Validator 7. Password Validator Closes #7 Closes #9 Closes #10 Closes #11 Closes #12 Closes #14 Closes #15
-rw-r--r--docs/built-in/index.rst913
-rw-r--r--src/edify/library/__init__.py7
-rw-r--r--src/edify/library/guid.py15
-rw-r--r--src/edify/library/mac.py17
-rw-r--r--src/edify/library/mail.py4
-rw-r--r--src/edify/library/password.py40
-rw-r--r--src/edify/library/ssn.py17
-rw-r--r--src/edify/library/support/zip.py253
-rw-r--r--src/edify/library/url.py39
-rw-r--r--src/edify/library/uuid.py14
-rw-r--r--src/edify/library/zip.py29
-rw-r--r--tests/ssn_test.py12
-rw-r--r--tests/test_guid.py11
-rw-r--r--tests/test_mac.py12
-rw-r--r--tests/test_password.py10
-rw-r--r--tests/test_url.py63
-rw-r--r--tests/test_uuid.py13
-rw-r--r--tests/test_zip.py34
18 files changed, 1487 insertions, 16 deletions
diff --git a/docs/built-in/index.rst b/docs/built-in/index.rst
index f79571d..8887b5c 100644
--- a/docs/built-in/index.rst
+++ b/docs/built-in/index.rst
@@ -1,10 +1,20 @@
+.. |toggleStart| raw:: html
+
+ <details>
+ <summary style="font-size: 1.2rem; font-style: bold; cursor: pointer;">View Supported Locales</summary>
+
+.. |toggleEnd| raw:: html
+
+ </details>
+
+
Pre-Built Pattern API Reference
================================
Edify allows you to verify a string quickly by providing commonly used regex patterns in its extensive set of built-in patterns. To tap into a pattern, simply import the pattern function from the ``edify.library`` module. For example, to verify that a string is a valid email address, you can use the ``email`` pattern. The pattern will return either ``True`` or ``False`` depending on whether the string matches the pattern.
-email()
--------
+email(email: str)
+-----------------
The ``email`` function verifies that a string is a valid email address. The function takes a ``string`` argument which is supposed to be a valid email address. The function returns ``True`` if the string is a valid email address, and ``False`` otherwise.
@@ -25,8 +35,8 @@ Then, call the ``email`` function with a string argument.
email('[email protected]') # returns True
email('hello') # returns False
-email_rfc_5322()
------------------
+email_rfc_5322(email: str)
+--------------------------
The ``email_rfc_5322`` function verifies that a string is a valid email address according to the `RFC 5322 <https://tools.ietf.org/html/rfc5322>`_ standard which allows for the most complete validation. Usually, you should not use it because it is an overkill. In most cases apps are not able to handle all emails that this regex allows. The function takes a ``string`` argument which is supposed to be a valid email address. The function returns ``True`` if the string is a valid email address, and ``False`` otherwise.
@@ -39,8 +49,8 @@ You can use the ``email_rfc_5322`` function as follows:
email_rfc_5322('[email protected]') # returns True
email_rfc_5322('hello') # returns False
-phone()
--------
+phone(phone: str)
+-----------------
The ``phone`` function verifies that a string is a valid phone number. The function takes a ``string`` argument which is supposed to be a valid phone number. The function returns ``True`` if the string is a valid phone number, and ``False`` otherwise.
@@ -62,8 +72,8 @@ You can use the ``phone`` function as follows:
phone('+1 (615) 243-') # returns False
-ipv4()
-------
+ipv4(ip: str)
+-------------
The ``ipv4`` function verifies that a string is a valid IPv4 address. The function takes a ``string`` argument which is supposed to be a valid IPv4 address. The function returns ``True`` if the string is a valid IPv4 address, and ``False`` otherwise.
@@ -77,8 +87,8 @@ You can use the ``ipv4`` function as follows:
ipv4('128.128.128') # returns False
-ipv6()
-------
+ipv6(ip: str)
+-------------
The ``ipv6`` function verifies that a string is a valid IPv6 address. The function takes a ``string`` argument which is supposed to be a valid IPv6 address. The function returns ``True`` if the string is a valid IPv6 address, and ``False`` otherwise.
@@ -91,8 +101,8 @@ You can use the ``ipv6`` function as follows:
ipv6('2001:0db8:85a3:0000:0000:8a2e:0370:7334') # returns True
ipv6('2001:0db8:85a3:0000:0000:8a2e:0370') # returns False
-date()
-------
+date(date: str)
+---------------
The ``date`` function verifies that a string is a valid date. The function takes a ``string`` argument which is supposed to be a valid date. The function returns ``True`` if the string is a valid date, and ``False`` otherwise.
@@ -121,8 +131,8 @@ You can use the ``date`` function as follows:
date('31/12/2017') # returns True
date('31-12-2017') # returns False
-iso_date()
-----------
+iso_date(date: str)
+-------------------
The ISO 8061 is an international standard for exchanging and serializing date and time data. The ``iso_date`` function verifies that a string is a valid ISO date. The function takes a ``string`` argument which is supposed to be a valid ISO date. The function returns ``True`` if the string is a valid ISO date, and ``False`` otherwise.
@@ -134,3 +144,878 @@ You can use the ``iso_date`` function as follows:
iso_date('2021-11-04T22:32:47.142354-10:00') # returns True
iso_date('12/12/2022') # returns False
+
+url(url: str, match?: list)
+---------------------------
+
+The ``url`` function verifies that a string is a valid URL. The function takes a ``string`` argument which is supposed to be a valid URL. The function returns ``True`` if the string is a valid URL, and ``False`` otherwise.
+
+.. warning::
+
+ The ``url`` function is not a complete URL validator. It only checks that the string is in the correct format. It does not check that the URL actually exists.
+
+You can use the ``url`` function as follows:
+
+.. code-block:: python
+
+ from edify.library import url
+
+ url('https://example.com') # returns True
+ url('example.com') # returns True
+ url('example') # returns False
+
+The ``url`` function also accepts an optional ``match`` argument. The ``match`` argument is a list of strings that you can use to configure what types of URLs the function should match. The ``match`` argument can have the following values:
+
+* ``'proto'`` - matches URLs with a protocol (e.g. ``https://example.com`` or ``http://example.com``)
+* ``'no_proto'`` - matches URLs without a protocol (e.g. ``example.com``)
+
+By default, the ``url`` function matches both URLs with and without a protocol. You can use the ``match`` argument to configure the function to match only URLs with a protocol or only URLs without a protocol. For example, the following code will match only URLs without a protocol:
+
+.. code-block:: python
+
+ from edify.library import url
+
+ url('example.com', match=['no_proto']) # returns True
+ url('https://example.com', match=['no_proto']) # returns False
+
+If you supply an Invalid or empty value in the ``match`` list argument, the function will raise a ``ValueError`` exception. Similarly, if you supply another data type in the ``match`` list argument, the function will raise a ``TypeError`` exception.
+
+.. code-block:: python
+
+ from edify.library import url
+
+ url('example.com', match=['invalid']) # raises ValueError
+ url('example.com', match=['no_proto', 'invalid']) # raises ValueError
+ url('example.com', match=['no_proto', 1]) # raises TypeError
+
+uuid(uuid: str)
+---------------
+
+The ``uuid`` function verifies that a string is a valid UUID. The function takes a ``string`` argument which is supposed to be a valid UUID. The function returns ``True`` if the string is a valid UUID, and ``False`` otherwise.
+
+You can use the ``uuid`` function as follows:
+
+.. code-block:: python
+
+ from edify.library import uuid
+
+ uuid('123e4567-e89b-12d3-a456-426655440000') # returns True
+ uuid('123e4567-e') # returns False
+
+zip(zip: str, locale?: str)
+---------------------------
+
+The ``zip`` function verifies that a string is a valid ZIP code. The function takes a ``string`` argument which is supposed to be a valid ZIP code. The function returns ``True`` if the string is a valid ZIP code, and ``False`` otherwise.
+
+The ``zip`` function also accepts an optional ``locale`` argument. The ``locale`` argument is a string that you can use to configure what types of ZIP codes the function should match. You can view the ``locale`` argument values below.
+
+|toggleStart|
+
+.. list-table::
+ :header-rows: 1
+
+ * - Country
+ - Locale
+
+ * - Afghanistan
+ - AF
+
+ * - Albania
+ - AL
+
+ * - Algeria
+ - DZ
+
+ * - American Samoa
+ - AS
+
+ * - Andorra
+ - AD
+
+ * - Angola
+ - AO
+
+ * - Anguilla
+ - AI
+
+ * - Antigua and Barbuda
+ - AG
+
+ * - Argentina
+ - AR
+
+ * - Armenia
+ - AM
+
+ * - Aruba
+ - AW
+
+ * - Australia
+ - AU
+
+ * - Austria
+ - AT
+
+ * - Azerbaijan
+ - AZ
+
+ * - Bahamas
+ - BS
+
+ * - Bahrain
+ - BH
+
+ * - Bangladesh
+ - BD
+
+ * - Barbados
+ - BB
+
+ * - Belarus
+ - BY
+
+ * - Belgium
+ - BE
+
+ * - Belize
+ - BZ
+
+ * - Benin
+ - BJ
+
+ * - Bermuda
+ - BM
+
+ * - Bhutan
+ - BT
+
+ * - Bolivia
+ - BO
+
+ * - Bonaire
+ - BQ
+
+ * - Bosnia and Herzegovina
+ - BA
+
+ * - Botswana
+ - BW
+
+ * - Brazil
+ - BR
+
+ * - Brunei
+ - BN
+
+ * - Bulgaria
+ - BG
+
+ * - Burkina Faso
+ - BF
+
+ * - Burundi
+ - BI
+
+ * - Cambodia
+ - KH
+
+ * - Cameroon
+ - CM
+
+ * - Canada
+ - CA
+
+ * - Canary Islands
+ - CI
+
+ * - Cape Verde
+ - CV
+
+ * - Cayman Islands
+ - KY
+
+ * - Central African Republic
+ - CF
+
+ * - Chad
+ - TD
+
+ * - Channel Islands
+ - CI
+
+ * - Chile
+ - CL
+
+ * - China, People's Republic
+ - CN
+
+ * - Colombia
+ - CO
+
+ * - Comoros
+ - KM
+
+ * - Congo
+ - CG
+
+ * - Congo, The Democratic Republic of
+ - CD
+
+ * - Cook Islands
+ - CK
+
+ * - Costa Rica
+ - CR
+
+ * - Côte d'Ivoire
+ - CI
+
+ * - Croatia
+ - HR
+
+ * - Cuba
+ - CU
+
+ * - Curacao
+ - CW
+
+ * - Cyprus
+ - CY
+
+ * - Czech Republic
+ - CZ
+
+ * - Denmark
+ - DK
+
+ * - Djibouti
+ - DJ
+
+ * - Dominica
+ - DM
+
+ * - Dominican Republic
+ - DO
+
+ * - East Timor
+ - TL
+
+ * - Ecuador
+ - EC
+
+ * - Egypt
+ - EG
+
+ * - El Salvador
+ - SV
+
+ * - Eritrea
+ - ER
+
+ * - Estonia
+ - EE
+
+ * - Ethiopia
+ - ET
+
+ * - Falkland Islands
+ - FK
+
+ * - Faroe Islands
+ - FO
+
+ * - Fiji
+ - FJ
+
+ * - Finland
+ - FI
+
+ * - France
+ - FR
+
+ * - French Polynesia
+ - PF
+
+ * - Gabon
+ - GA
+
+ * - Gambia
+ - GM
+
+ * - Georgia
+ - GE
+
+ * - Germany
+ - DE
+
+ * - Ghana
+ - GH
+
+ * - Gibraltar
+ - GI
+
+ * - Greece
+ - GR
+
+ * - Greenland
+ - GL
+
+ * - Grenada
+ - GD
+
+ * - Guadeloupe
+ - GP
+
+ * - Guam
+ - GU
+
+ * - Guatemala
+ - GT
+
+ * - Guernsey
+ - GG
+
+ * - Guinea-Bissau
+ - GW
+
+ * - Guinea-Equatorial
+ - GQ
+
+ * - Guinea Republic
+ - GN
+
+ * - Guyana (British)
+ - GY
+
+ * - Guyana (French)
+ - GF
+
+ * - Haiti
+ - HT
+
+ * - Honduras
+ - HN
+
+ * - Hong Kong
+ - HK
+
+ * - Hungary
+ - HU
+
+ * - Iceland
+ - IS
+
+ * - India
+ - IN
+
+ * - Indonesia
+ - ID
+
+ * - Iran
+ - IR
+
+ * - Iraq
+ - IQ
+
+ * - Ireland, Republic of
+ - IE
+
+ * - Islas Malvinas
+ - FK
+
+ * - Israel
+ - IL
+
+ * - Italy
+ - IT
+
+ * - Ivory Coast
+ - CI
+
+ * - Jamaica
+ - JM
+
+ * - Japan
+ - JP
+
+ * - Jersey
+ - JE
+
+ * - Jordan
+ - JO
+
+ * - Kazakhstan
+ - KZ
+
+ * - Kenya
+ - KE
+
+ * - Kiribati
+ - KI
+
+ * - Korea, Republic of
+ - KR
+
+ * - Korea, The D.P.R of
+ - KP
+
+ * - Kosovo
+ - XK
+
+ * - Kuwait
+ - KW
+
+ * - Kyrgyzstan
+ - KG
+
+ * - Laos
+ - LA
+
+ * - Latvia
+ - LV
+
+ * - Lebanon
+ - LB
+
+ * - Lesotho
+ - LS
+
+ * - Liberia
+ - LR
+
+ * - Libya
+ - LY
+
+ * - Liechtenstein
+ - LI
+
+ * - Lithuania
+ - LT
+
+ * - Luxembourg
+ - LU
+
+ * - Macau
+ - MO
+
+ * - Macedonia, Republic of
+ - MK
+
+ * - Madagascar
+ - MG
+
+ * - Malawi
+ - MW
+
+ * - Malaysia
+ - MY
+
+ * - Maldives
+ - MV
+
+ * - Mali
+ - ML
+
+ * - Malta
+ - MT
+
+ * - Marshall Islands
+ - MH
+
+ * - Martinique
+ - MQ
+
+ * - Mauritania
+ - MR
+
+ * - Mauritius
+ - MU
+
+ * - Mayotte
+ - YT
+
+ * - Mexico
+ - MX
+
+ * - Moldova, Republic of
+ - MD
+
+ * - Monaco
+ - MC
+
+ * - Mongolia
+ - MN
+
+ * - Montenegro
+ - ME
+
+ * - Montserrat
+ - MS
+
+ * - Morocco
+ - MA
+
+ * - Mozambique
+ - MZ
+
+ * - Myanmar
+ - MM
+
+ * - Namibia
+ - NA
+
+ * - Nauru
+ - NR
+
+ * - Nepal
+ - NP
+
+ * - Netherlands
+ - NL
+
+ * - New Caledonia
+ - NC
+
+ * - New Zealand
+ - NZ
+
+ * - Nicaragua
+ - NI
+
+ * - Niger
+ - NE
+
+ * - Nigeria
+ - NG
+
+ * - Niue
+ - NU
+
+ * - Northern Mariana Islands
+ - MP
+
+ * - Norway
+ - NO
+
+ * - Oman
+ - OM
+
+ * - Pakistan
+ - PK
+
+ * - Palau
+ - PW
+
+ * - Panama
+ - PA
+
+ * - Papua New Guinea
+ - PG
+
+ * - Paraguay
+ - PY
+
+ * - Peru
+ - PE
+
+ * - Philippines
+ - PH
+
+ * - Poland
+ - PL
+
+ * - Portugal
+ - PT
+
+ * - Puerto Rico
+ - PR
+
+ * - Qatar
+ - QA
+
+ * - Réunion
+ - RE
+
+ * - Romania
+ - RO
+
+ * - Russian Federation
+ - RU
+
+ * - Rwanda
+ - RW
+
+ * - Saipan
+ - MP
+
+ * - Samoa
+ - WS
+
+ * - Sao Tome and Principe
+ - ST
+
+ * - Saudi Arabia
+ - SA
+
+ * - Senegal
+ - SN
+
+ * - Serbia
+ - RS
+
+ * - Seychelles
+ - SC
+
+ * - Sierra Leone
+ - SL
+
+ * - Singapore
+ - SG
+
+ * - Slovakia
+ - SK
+
+ * - Slovenia
+ - SI
+
+ * - Solomon Islands
+ - SB
+
+ * - Somalia
+ - SO
+
+ * - South Africa
+ - ZA
+
+ * - South Sudan
+ - SS
+
+ * - Spain
+ - ES
+
+ * - Sri Lanka
+ - LK
+
+ * - St. Barthélemy
+ - BL
+
+ * - St. Croix
+ - VI
+
+ * - St. Eustatius
+ - SE
+
+ * - St. Helena
+ - SH
+
+ * - St. John
+ - AG
+
+ * - St. Kitts and Nevis
+ - KN
+
+ * - St. Lucia
+ - LC
+
+ * - St. Maarten
+ - SX
+
+ * - St. Thomas
+ - VI
+
+ * - St. Vincent and the Grenadines
+ - VC
+
+ * - Sudan
+ - SD
+
+ * - Suriname
+ - SR
+
+ * - Swaziland
+ - SZ
+
+ * - Sweden
+ - SE
+
+ * - Switzerland
+ - CH
+
+ * - Syria
+ - SY
+
+ * - Tahiti
+ - PF
+
+ * - Taiwan
+ - TW
+
+ * - Tanzania
+ - TZ
+
+ * - Thailand
+ - TH
+
+ * - Togo
+ - TG
+
+ * - Tonga
+ - TO
+
+ * - Tortola
+ - VG
+
+ * - Trinidad and Tobago
+ - TT
+
+ * - Tunisia
+ - TN
+
+ * - Turkey
+ - TR
+
+ * - Turkmenistan
+ - TM
+
+ * - Turks and Caicos Islands
+ - TC
+
+ * - Tuvalu
+ - TV
+
+ * - Uganda
+ - UG
+
+ * - Ukraine
+ - UA
+
+ * - United Arab Emirates
+ - AE
+
+ * - United Kingdom
+ - GB
+
+ * - United States of America
+ - US
+
+ * - Uruguay
+ - UY
+
+ * - Uzbekistan
+ - UZ
+
+ * - Vanuatu
+ - VU
+
+ * - Venezuela
+ - VE
+
+ * - Vietnam
+ - VN
+
+ * - Virgin Islands (British)
+ - VG
+
+ * - Virgin Islands (US)
+ - VI
+
+ * - Yemen
+ - YE
+
+ * - Zambia
+ - ZM
+
+ * - Zimbabwe
+ - ZW
+
+|toggleEnd|
+
+By default, the ``zip`` function matches ZIP codes for "US". Here's an example of how to use the ``zip`` function to match ZIP codes:
+
+.. code-block:: python
+
+ from edify.library import zip
+
+ zip('12345') # returns True
+ zip('1234') # returns False
+ zip('12345', locale='US') # returns True
+ zip('12345-1234') # returns True
+ zip('12345-1234', locale='US') # returns True
+ zip('123456', locale='IN') # returns True
+
+If you supply an Invalid or empty value in the ``locale`` argument, the function will raise a ``ValueError`` exception. Similarly, if you supply another data type in the ``locale`` argument, the function will raise a ``TypeError`` exception.
+
+
+guid(guid: str)
+---------------
+
+The ``guid`` function validates a GUID (Globally Unique Identifier) string. The function returns ``True`` if the string is a valid GUID, and ``False`` otherwise.
+
+Here's an example of how to use the ``guid`` function:
+
+.. code-block:: python
+ from edify.library import guid
+
+ guid('6ba7b810-9dad-11d1-80b4-00c04fd430c8') # returns True
+ guid('{51d52cf1-83c9-4f02-b117-703ecb728b74}') # returns True
+ guid('{51d52cf1-83c9-4f02-b117-703ecb728-b74}') # returns False
+
+password(password: str, min_length?: int, max_length?: int, min_upper?: int, min_lower?: int, min_digit?: int, min_special?: int, special_chars?: str)
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+The ``password`` function validates a password string. The function returns ``True`` if the string is a valid password, and ``False`` otherwise.
+
+The ``password`` function takes the following arguments:
+
+ * ``password``: The password string to validate.
+ * ``min_length``: The minimum length of the password. The default value is 8.
+ * ``max_length``: The maximum length of the password. The default value is 64.
+ * ``min_upper``: The minimum number of uppercase characters in the password. The default value is 1.
+ * ``min_lower``: The minimum number of lowercase characters in the password. The default value is 1.
+ * ``min_digit``: The minimum number of digits in the password. The default value is 1.
+ * ``min_special``: The minimum number of special characters in the password. The default value is 1.
+ * ``special_chars``: The special characters to use in the password. The default value is ``!@#$%^&*()_+-=[]{}|;':\",./<>?``.
+
+Here's an example of how to use the ``password`` function:
+
+.. code-block:: python
+
+ from edify.library import password
+
+ password('password') # returns False
+ password("Password123!") # returns True
+ password("Password123!", max_length=8) # returns False
+ password("Password123!", min_upper=2) # returns False
+ password("password", min_upper=0, min_digit=0, min_special=0) # returns True
+ password("pass@#1", min_special=1, special_chars="!", min_digit=0, min_upper=0, min_length=4) # returns False
+
+ssn(ssn: str)
+-------------
+
+The ``ssn`` function validates a Social Security Number (SSN) string. The function returns ``True`` if the string is a valid SSN, and ``False`` otherwise.
+
+Here's an example of how to use the ``ssn`` function:
+
+.. code-block:: python
+
+ from edify.library import ssn
+
+ ssn('123-45-6789') # returns True
+ ssn('123-45-678') # returns False
+ ssn('123-45-67890') # returns False
+
+
+mac(mac: str)
+-------------
+
+The ``mac`` function validates a MAC address (IEEE 802) string. The function returns ``True`` if the string is a valid MAC address, and ``False`` otherwise.
+
+Here's an example of how to use the ``mac`` function:
+
+.. code-block:: python
+
+ from edify.library import mac
+
+ mac('00:00:00:00:00:00') # returns True
+ mac('00:00:00:00:00:0') # returns False
+ mac('00:00:00:00:00:000') # returns False
diff --git a/src/edify/library/__init__.py b/src/edify/library/__init__.py
index be1c093..bae5368 100644
--- a/src/edify/library/__init__.py
+++ b/src/edify/library/__init__.py
@@ -3,8 +3,15 @@
# Import everything from the library.
from .date import date
from .date import iso_date
+from .guid import guid
from .ip import ipv4
from .ip import ipv6
+from .mac import mac
from .mail import email
from .mail import email_rfc_5322
+from .password import password
from .phone import phone_number
+from .ssn import ssn
+from .url import url
+from .uuid import uuid
+from .zip import zip
diff --git a/src/edify/library/guid.py b/src/edify/library/guid.py
new file mode 100644
index 0000000..be37efd
--- /dev/null
+++ b/src/edify/library/guid.py
@@ -0,0 +1,15 @@
+import re
+
+pattern = "^(?:\\{{0,1}(?:[0-9a-fA-F]){8}-(?:[0-9a-fA-F]){4}-(?:[0-9a-fA-F]){4}-(?:[0-9a-fA-F]){4}-(?:[0-9a-fA-F]){12}\\}{0,1})$"
+
+
+def guid(guid: str) -> bool:
+ """Check if the given string is a valid GUID.
+
+ Args:
+ guid (str): The string to check.
+
+ Returns:
+ bool: True if the string is a valid GUID, False otherwise.
+ """
+ return bool(re.match(pattern, guid))
diff --git a/src/edify/library/mac.py b/src/edify/library/mac.py
new file mode 100644
index 0000000..9fba14c
--- /dev/null
+++ b/src/edify/library/mac.py
@@ -0,0 +1,17 @@
+import re
+
+mac_address_validate_pattern = "^(?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]{2})$"
+
+
+def mac(mac: str) -> bool:
+ """Validate a MAC (IEEE 802) address.
+
+ Args:
+ mac (str): The MAC address to validate.
+
+ Returns:
+ bool: True if the MAC address is valid, False otherwise.
+ """
+ if not isinstance(mac, str):
+ return False
+ return bool(re.match(mac_address_validate_pattern, mac))
diff --git a/src/edify/library/mail.py b/src/edify/library/mail.py
index 02f9484..6797bf2 100644
--- a/src/edify/library/mail.py
+++ b/src/edify/library/mail.py
@@ -1,7 +1,7 @@
import re
-pattern = r"^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$" # noqa
-rfc_5322_pattern = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])" # noqa
+pattern = r"^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$" # noqa
+rfc_5322_pattern = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])" # noqa
def email(email: str) -> bool:
diff --git a/src/edify/library/password.py b/src/edify/library/password.py
new file mode 100644
index 0000000..09e9d5f
--- /dev/null
+++ b/src/edify/library/password.py
@@ -0,0 +1,40 @@
+import re
+
+
+def password(
+ password: str,
+ min_length: int = 8,
+ max_length: int = 64,
+ min_upper: int = 1,
+ min_lower: int = 1,
+ min_digit: int = 1,
+ min_special: int = 1,
+ special_chars: str = "!@#$%^&*()_+-=[]{}|;':\",./<>?",
+) -> bool:
+ """Check if the given string is a valid password.
+
+ Args:
+ password (str): The string to check.
+ min_length (int): The minimum length of the password.
+ max_length (int): The maximum length of the password.
+ min_upper (int): The minimum number of upper case characters.
+ min_lower (int): The minimum number of lower case characters.
+ min_digit (int): The minimum number of digits.
+ min_special (int): The minimum number of special characters.
+ special_chars (str): The special characters to check for.
+
+ Returns:
+ bool: True if the string is a valid password, False otherwise.
+ """
+ if len(password) < min_length or len(password) > max_length:
+ return False
+
+ upper = re.findall("[A-Z]", password or "")
+ lower = re.findall("[a-z]", password or "")
+ digit = re.findall("[0-9]", password or "")
+ special = [c for c in password if c in special_chars]
+
+ if len(upper) < min_upper or len(lower) < min_lower or len(digit) < min_digit or len(special) < min_special:
+ return False
+
+ return True
diff --git a/src/edify/library/ssn.py b/src/edify/library/ssn.py
new file mode 100644
index 0000000..9c9dcf5
--- /dev/null
+++ b/src/edify/library/ssn.py
@@ -0,0 +1,17 @@
+import re
+
+ssn_validate_pattern = "^(?!666|000|9\\d{2})\\d{3}-(?!00)\\d{2}-(?!0{4})\\d{4}$"
+
+
+def ssn(ssn: str) -> bool:
+ """Validate a Social Security Number (SSN).
+
+ Args:
+ ssn (str): The SSN to validate.
+
+ Returns:
+ bool: True if the SSN is valid, False otherwise.
+ """
+ if not isinstance(ssn, str):
+ return False
+ return bool(re.match(ssn_validate_pattern, ssn))
diff --git a/src/edify/library/support/zip.py b/src/edify/library/support/zip.py
new file mode 100644
index 0000000..c8c37d6
--- /dev/null
+++ b/src/edify/library/support/zip.py
@@ -0,0 +1,253 @@
+# flake8: noqa
+
+ZIP_LOCALES = [
+ {"abbrev": "AF", "name": "Afghanistan", "zip": "[0-9]{4}"},
+ {"abbrev": "AL", "name": "Albania", "zip": "(120|122)[0-9]{2}"},
+ {"abbrev": "DZ", "name": "Algeria", "zip": "[0-9]{5}"},
+ {"abbrev": "AS", "name": "American Samoa", "zip": "[0-9]{5}"},
+ {"abbrev": "AD", "name": "Andorra", "zip": "[0-9]{5}"},
+ {"abbrev": "AO", "name": "Angola"},
+ {"abbrev": "AI", "name": "Anguilla", "zip": "AI-2640"},
+ {"abbrev": "AG", "name": "Antigua and Barbuda"},
+ {"abbrev": "AR", "name": "Argentina", "zip": "[A-Z]{1}[0-9]{4}[A-Z]{3}"},
+ {"abbrev": "AM", "name": "Armenia", "zip": "[0-9]{4}"},
+ {"abbrev": "AW", "name": "Aruba"},
+ {"abbrev": "AU", "name": "Australia", "zip": "[0-9]{4}"},
+ {"abbrev": "AT", "name": "Austria", "zip": "[0-9]{4}"},
+ {"abbrev": "AZ", "name": "Azerbaijan", "zip": "[0-9]{4}"},
+ {"abbrev": "BS", "name": "Bahamas"},
+ {"abbrev": "BH", "name": "Bahrain"},
+ {"abbrev": "BD", "name": "Bangladesh", "zip": "[0-9]{4}"},
+ {"abbrev": "BB", "name": "Barbados", "zip": "BB[0-9]{5}"},
+ {"abbrev": "BY", "name": "Belarus", "zip": "[0-9]{6}"},
+ {"abbrev": "BE", "name": "Belgium", "zip": "[0-9]{4}"},
+ {"abbrev": "BZ", "name": "Belize"},
+ {"abbrev": "BJ", "name": "Benin"},
+ {"abbrev": "BM", "name": "Bermuda", "zip": "[A-Z]{2}[0-9]{2}"},
+ {"abbrev": "BT", "name": "Bhutan", "zip": "[0-9]{5}"},
+ {"abbrev": "BO", "name": "Bolivia"},
+ {"abbrev": "BQ", "name": "Bonaire"},
+ {"abbrev": "BA", "name": "Bosnia and Herzegovina", "zip": "[0-9]{5}"},
+ {"abbrev": "BW", "name": "Botswana"},
+ {"abbrev": "BR", "name": "Brazil", "zip": "[0-9]{5}-[0-9]{3}"},
+ {"abbrev": "BN", "name": "Brunei", "zip": "[A-Z]{2}[0-9]{4}"},
+ {"abbrev": "BG", "name": "Bulgaria", "zip": "[0-9]{4}"},
+ {"abbrev": "BF", "name": "Burkina Faso"},
+ {"abbrev": "BI", "name": "Burundi"},
+ {"abbrev": "KH", "name": "Cambodia", "zip": "[0-9]{5}"},
+ {"abbrev": "CM", "name": "Cameroon"},
+ {"abbrev": "CA", "name": "Canada", "zip": "[A-Z][0-9][A-Z] ?[0-9][A-Z][0-9]"},
+ {"abbrev": "CI", "name": "Canary Islands", "zip": "[0-9]{5}"},
+ {"abbrev": "CV", "name": "Cape Verde", "zip": "[0-9]{4}"},
+ {"abbrev": "KY", "name": "Cayman Islands", "zip": "[A-Z]{2}[0-9]-[0-9]{4}"},
+ {"abbrev": "CF", "name": "Central African Republic"},
+ {"abbrev": "TD", "name": "Chad"},
+ {"abbrev": "CI", "name": "Channel Islands", "zip": "[A-Z]{2}[0-9]{2}"},
+ {"abbrev": "CL", "name": "Chile", "zip": "[0-9]{7}"},
+ {"abbrev": "CN", "name": "China, People's Republic", "zip": "[0-9]{6}"},
+ {"abbrev": "CO", "name": "Colombia", "zip": "[0-9]{6}"},
+ {"abbrev": "KM", "name": "Comoros"},
+ {"abbrev": "CG", "name": "Congo"},
+ {"abbrev": "CD", "name": "Congo, The Democratic Republic of"},
+ {"abbrev": "CK", "name": "Cook Islands"},
+ {"abbrev": "CR", "name": "Costa Rica", "zip": "[0-9]{5}"},
+ {"abbrev": "CI", "name": "Côte d'Ivoire"},
+ {"abbrev": "HR", "name": "Croatia", "zip": "[0-9]{5}"},
+ {"abbrev": "CU", "name": "Cuba", "zip": "[0-9]{5}"},
+ {"abbrev": "CW", "name": "Curacao"},
+ {"abbrev": "CY", "name": "Cyprus", "zip": "[0-9]{4}"},
+ {"abbrev": "CZ", "name": "Czech Republic", "zip": "[0-9]{3} [0-9]{2}"},
+ {"abbrev": "DK", "name": "Denmark", "zip": "[0-9]{5}"},
+ {"abbrev": "DJ", "name": "Djibouti"},
+ {"abbrev": "DM", "name": "Dominica"},
+ {"abbrev": "DO", "name": "Dominican Republic", "zip": "[0-9]{5}"},
+ {"abbrev": "TL", "name": "East Timor"},
+ {"abbrev": "EC", "name": "Ecuador", "zip": "[0-9]{6}"},
+ {"abbrev": "EG", "name": "Egypt", "zip": "[0-9]{5}"},
+ {"abbrev": "SV", "name": "El Salvador", "zip": "[0-9]{4}"},
+ {"abbrev": "ER", "name": "Eritrea"},
+ {"abbrev": "EE", "name": "Estonia", "zip": "[0-9]{5}"},
+ {"abbrev": "ET", "name": "Ethiopia", "zip": "[0-9]{4}"},
+ {"abbrev": "FK", "name": "Falkland Islands", "zip": "FIQQ 1ZZ"},
+ {"abbrev": "FO", "name": "Faroe Islands", "zip": "[0-9]{3}"},
+ {"abbrev": "FJ", "name": "Fiji"},
+ {"abbrev": "FI", "name": "Finland", "zip": "[0-9]{5}"},
+ {"abbrev": "FR", "name": "France", "zip": "[0-9]{5}"},
+ {"abbrev": "PF", "name": "French Polynesia", "zip": "987[0-9]{2}", "range": ["98700", "98790"]},
+ {"abbrev": "GA", "name": "Gabon"},
+ {"abbrev": "GM", "name": "Gambia"},
+ {"abbrev": "GE", "name": "Georgia"},
+ {"abbrev": "DE", "name": "Germany", "zip": "[0-9]{5}"},
+ {"abbrev": "GH", "name": "Ghana"},
+ {"abbrev": "GI", "name": "Gibraltar", "zip": "GX11 1AA"},
+ {"abbrev": "GR", "name": "Greece", "zip": "[0-9]{3} [0-9]{2}"},
+ {"abbrev": "GL", "name": "Greenland", "zip": "[0-9]{4}"},
+ {"abbrev": "GD", "name": "Grenada"},
+ {"abbrev": "GP", "name": "Guadeloupe", "zip": "971[0-9]{2}", "range": ["97100", "97190"]},
+ {"abbrev": "GU", "name": "Guam", "zip": "\\d{5}(?:[-\\s]\\d{4})?", "range": ["96910", "96932"]},
+ {"abbrev": "GT", "name": "Guatemala", "zip": "[0-9]{5}"},
+ {
+ "abbrev": "GG",
+ "name": "Guernsey",
+ "zip": "([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9][A-Za-z]?))))\\s?[0-9][A-Za-z]{2})",
+ },
+ {"abbrev": "GW", "name": "Guinea-Bissau", "zip": "[0-9]{4}"},
+ {"abbrev": "GQ", "name": "Guinea-Equatorial"},
+ {"abbrev": "GN", "name": "Guinea Republic", "zip": "[0-9]{3}"},
+ {"abbrev": "GY", "name": "Guyana (British)"},
+ {"abbrev": "GF", "name": "Guyana (French)", "zip": "973[0-9]{2}", "range": ["97300", "97390"]},
+ {"abbrev": "HT", "name": "Haiti", "zip": "[0-9]{4}"},
+ {"abbrev": "HN", "name": "Honduras", "zip": "[0-9]{5}"},
+ {"abbrev": "HK", "name": "Hong Kong"},
+ {"abbrev": "HU", "name": "Hungary", "zip": "[0-9]{4}"},
+ {"abbrev": "IS", "name": "Iceland", "zip": "[0-9]{3}"},
+ {"abbrev": "IN", "name": "India", "zip": "^(?!0{1})\d{6}$"},
+ {"abbrev": "ID", "name": "Indonesia", "zip": "[0-9]{5}"},
+ {"abbrev": "IR", "name": "Iran", "zip": "[0-9]{5}"},
+ {"abbrev": "IQ", "name": "Iraq", "zip": "[0-9]{5}"},
+ {"abbrev": "IE", "name": "Ireland, Republic of", "zip": "(?:^[AC-FHKNPRTV-Y][0-9]{2}|D6W)[ -]?[0-9AC-FHKNPRTV-Y]{4}$"},
+ {"abbrev": "FK", "name": "Islas Malvinas", "zip": "FIQQ 1ZZ"},
+ {"abbrev": "IL", "name": "Israel", "zip": "[0-9]{5}|[0-9]{7}"},
+ {"abbrev": "IT", "name": "Italy", "zip": "[0-9]{5}"},
+ {"abbrev": "CI", "name": "Ivory Coast"},
+ {"abbrev": "JM", "name": "Jamaica"},
+ {"abbrev": "JP", "name": "Japan", "zip": "[0-9]{3}-[0-9]{4}"},
+ {
+ "abbrev": "JE",
+ "name": "Jersey",
+ "zip": "([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9][A-Za-z]?))))\\s?[0-9][A-Za-z]{2})",
+ },
+ {"abbrev": "JO", "name": "Jordan", "zip": "[0-9]{5}"},
+ {"abbrev": "KZ", "name": "Kazakhstan", "zip": "[0-9]{6}"},
+ {"abbrev": "KE", "name": "Kenya", "zip": "[0-9]{5}"},
+ {"abbrev": "KI", "name": "Kiribati"},
+ {"abbrev": "KR", "name": "Korea, Republic of", "zip": "[0-9]{5}"},
+ {"abbrev": "KP", "name": "Korea, The D.P.R of"},
+ {"abbrev": "XK", "name": "Kosovo", "zip": "[0-9]{5}"},
+ {"abbrev": "KW", "name": "Kuwait", "zip": "[0-9]{5}"},
+ {"abbrev": "KG", "name": "Kyrgyzstan", "zip": "[0-9]{6}"},
+ {"abbrev": "LA", "name": "Laos", "zip": "[0-9]{5}"},
+ {"abbrev": "LV", "name": "Latvia", "zip": "LV-[0-9]{4}"},
+ {"abbrev": "LB", "name": "Lebanon", "zip": "[0-9]{4} [0-9]{4}"},
+ {"abbrev": "LS", "name": "Lesotho", "zip": "[0-9]{3}"},
+ {"abbrev": "LR", "name": "Liberia", "zip": "[0-9]{4}"},
+ {"abbrev": "LY", "name": "Libya"},
+ {"abbrev": "LI", "name": "Liechtenstein", "zip": "[0-9]{4}", "range": ["9485", "9498"]},
+ {"abbrev": "LT", "name": "Lithuania", "zip": "LT-[0-9]{5}"},
+ {"abbrev": "LU", "name": "Luxembourg", "zip": "[0-9]{4}"},
+ {"abbrev": "MO", "name": "Macau"},
+ {"abbrev": "MK", "name": "Macedonia, Republic of", "zip": "[0-9]{4}"},
+ {"abbrev": "MG", "name": "Madagascar", "zip": "[0-9]{3}"},
+ {"abbrev": "MW", "name": "Malawi"},
+ {"abbrev": "MY", "name": "Malaysia", "zip": "[0-9]{5}"},
+ {"abbrev": "MV", "name": "Maldives", "zip": "[0-9]{5}"},
+ {"abbrev": "ML", "name": "Mali"},
+ {"abbrev": "MT", "name": "Malta", "zip": "[A-Z]{3} [0-9]{4}"},
+ {"abbrev": "MH", "name": "Marshall Islands", "zip": "\\d{5}(?:[-\\s]\\d{4})?", "range": ["96960", "96970"]},
+ {"abbrev": "MQ", "name": "Martinique", "zip": "972[0-9]{2}", "range": ["97200", "97290"]},
+ {"abbrev": "MR", "name": "Mauritania"},
+ {"abbrev": "MU", "name": "Mauritius", "zip": "[0-9]{5}"},
+ {"abbrev": "YT", "name": "Mayotte", "zip": "976[0-9]{2}", "range": ["97600", "97690"]},
+ {"abbrev": "MX", "name": "Mexico", "zip": "[0-9]{5}"},
+ {"abbrev": "MD", "name": "Moldova, Republic of", "zip": "MD-?[0-9]{4}"},
+ {"abbrev": "MC", "name": "Monaco", "zip": "980[0-9]{2}"},
+ {"abbrev": "MN", "name": "Mongolia", "zip": "[0-9]{5}"},
+ {"abbrev": "ME", "name": "Montenegro", "zip": "[0-9]{5}"},
+ {"abbrev": "MS", "name": "Montserrat", "zip": "MSR [0-9]{4}", "range": ["MSR 1110", "MSR 1350"]},
+ {"abbrev": "MA", "name": "Morocco", "zip": "[0-9]{5}"},
+ {"abbrev": "MZ", "name": "Mozambique", "zip": "[0-9]{4}"},
+ {"abbrev": "MM", "name": "Myanmar", "zip": "[0-9]{5}"},
+ {"abbrev": "NA", "name": "Namibia"},
+ {"abbrev": "NR", "name": "Nauru"},
+ {"abbrev": "NP", "name": "Nepal", "zip": "[0-9]{5}"},
+ {"abbrev": "NL", "name": "Netherlands", "zip": "(?:NL-)?(\\d{4})\\s*([A-Z]{2})"},
+ {"abbrev": "NC", "name": "New Caledonia", "zip": "988[0-9]{2}", "range": ["96950", "96952"]},
+ {"abbrev": "NZ", "name": "New Zealand", "zip": "[0-9]{4}"},
+ {"abbrev": "NI", "name": "Nicaragua"},
+ {"abbrev": "NE", "name": "Niger", "zip": "[0-9]{4}"},
+ {"abbrev": "NG", "name": "Nigeria", "zip": "[0-9]{6}"},
+ {"abbrev": "NU", "name": "Niue"},
+ {"abbrev": "MP", "name": "Northern Mariana Islands", "zip": "^\\d{5}(?:[-\\s]\\d{4})?$"},
+ {"abbrev": "NO", "name": "Norway", "zip": "[0-9]{4}"},
+ {"abbrev": "OM", "name": "Oman", "zip": "[0-9]{3}"},
+ {"abbrev": "PK", "name": "Pakistan", "zip": "[0-9]{5}"},
+ {"abbrev": "PW", "name": "Palau", "zip": "\\d{5}(?:[-\\s]\\d{4})?"},
+ {"abbrev": "PA", "name": "Panama", "zip": "[0-9]{4}"},
+ {"abbrev": "PG", "name": "Papua New Guinea", "zip": "[0-9]{3}"},
+ {"abbrev": "PY", "name": "Paraguay", "zip": "[0-9]{4}"},
+ {"abbrev": "PE", "name": "Peru", "zip": "[0-9]{5}"},
+ {"abbrev": "PH", "name": "Philippines", "zip": "[0-9]{4}"},
+ {"abbrev": "PL", "name": "Poland", "zip": "[0-9]{2}-[0-9]{3}"},
+ {"abbrev": "PT", "name": "Portugal", "zip": "[0-9]{4}-[0-9]{3}"},
+ {"abbrev": "PR", "name": "Puerto Rico", "zip": "\\d{5}(?:[-\\s]\\d{4})?"},
+ {"abbrev": "QA", "name": "Qatar"},
+ {"abbrev": "RE", "name": "Réunion", "zip": "974[0-9]{2}", "range": ["97400", "97490"]},
+ {"abbrev": "RO", "name": "Romania", "zip": "[0-9]{6}"},
+ {"abbrev": "RU", "name": "Russian Federation", "zip": "[0-9]{6}"},
+ {"abbrev": "RW", "name": "Rwanda"},
+ {"abbrev": "MP", "name": "Saipan", "zip": "96950"},
+ {"abbrev": "WS", "name": "Samoa", "zip": "WS[0-9]{4}"},
+ {"abbrev": "ST", "name": "Sao Tome and Principe"},
+ {"abbrev": "SA", "name": "Saudi Arabia", "zip": "[0-9]{5}(-[0-9]{4})?"},
+ {"abbrev": "SN", "name": "Senegal", "zip": "[0-9]{5}"},
+ {"abbrev": "RS", "name": "Serbia", "zip": "[0-9]{5}"},
+ {"abbrev": "SC", "name": "Seychelles"},
+ {"abbrev": "SL", "name": "Sierra Leone"},
+ {"abbrev": "SG", "name": "Singapore", "zip": "[0-9]{6}"},
+ {"abbrev": "SK", "name": "Slovakia", "zip": "[0-9]{3} [0-9]{2}"},
+ {"abbrev": "SI", "name": "Slovenia", "zip": "[0-9]{4}"},
+ {"abbrev": "SB", "name": "Solomon Islands"},
+ {"abbrev": "SO", "name": "Somalia", "zip": "[A-Z]{2} [0-9]{5}"},
+ {"abbrev": "ZA", "name": "South Africa", "zip": "[0-9]{4}"},
+ {"abbrev": "SS", "name": "South Sudan"},
+ {"abbrev": "ES", "name": "Spain", "zip": "[0-9]{5}"},
+ {"abbrev": "LK", "name": "Sri Lanka", "zip": "[0-9]{4}"},
+ {"abbrev": "BL", "name": "St. Barthélemy", "zip": "[0-9]{5}", "range": ["97100", "97190"]},
+ {"abbrev": "VI", "name": "St. Croix", "zip": "[0-9]{5}"},
+ {"abbrev": "SE", "name": "St. Eustatius"},
+ {"abbrev": "SH", "name": "St. Helena", "zip": "STHL 1ZZ"},
+ {"abbrev": "AG", "name": "St. John", "zip": "\\d{5}(?:[-\\s]\\d{4})?"},
+ {"abbrev": "KN", "name": "St. Kitts and Nevis", "zip": "[A-Z]{2}[0-9]{4}"},
+ {"abbrev": "LC", "name": "St. Lucia", "zip": "[A-Z]{2}[0-9]{2} [0-9]{3}"},
+ {"abbrev": "SX", "name": "St. Maarten"},
+ {"abbrev": "VI", "name": "St. Thomas"},
+ {"abbrev": "VC", "name": "St. Vincent and the Grenadines", "zip": "VC[0-9]{4}"},
+ {"abbrev": "SD", "name": "Sudan", "zip": "[0-9]{5}"},
+ {"abbrev": "SR", "name": "Suriname"},
+ {"abbrev": "SZ", "name": "Swaziland", "zip": "[A-Z]{1}[0-9]{3}"},
+ {"abbrev": "SE", "name": "Sweden", "zip": "[0-9]{3} [0-9]{2}"},
+ {"abbrev": "CH", "name": "Switzerland", "zip": "[0-9]{4}"},
+ {"abbrev": "SY", "name": "Syria"},
+ {"abbrev": "PF", "name": "Tahiti", "zip": "[0-9]{5}"},
+ {"abbrev": "TW", "name": "Taiwan", "zip": "[0-9]{3}(-[0-9]{2})?"},
+ {"abbrev": "TZ", "name": "Tanzania", "zip": "[0-9]{5}"},
+ {"abbrev": "TH", "name": "Thailand", "zip": "[0-9]{5}"},
+ {"abbrev": "TG", "name": "Togo"},
+ {"abbrev": "TO", "name": "Tonga"},
+ {"abbrev": "VG", "name": "Tortola", "zip": "VG[0-9]{4}"},
+ {"abbrev": "TT", "name": "Trinidad and Tobago", "zip": "[0-9]{6}"},
+ {"abbrev": "TN", "name": "Tunisia", "zip": "[0-9]{4}"},
+ {"abbrev": "TR", "name": "Turkey", "zip": "[0-9]{5}"},
+ {"abbrev": "TM", "name": "Turkmenistan", "zip": "[0-9]{6}"},
+ {"abbrev": "TC", "name": "Turks and Caicos Islands", "zip": "TKCA 1ZZ"},
+ {"abbrev": "TV", "name": "Tuvalu"},
+ {"abbrev": "UG", "name": "Uganda"},
+ {"abbrev": "UA", "name": "Ukraine", "zip": "[0-9]{5}"},
+ {"abbrev": "AE", "name": "United Arab Emirates"},
+ {
+ "abbrev": "GB",
+ "name": "United Kingdom",
+ "zip": "([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9][A-Za-z]?))))\\s?[0-9][A-Za-z]{2})",
+ },
+ {"abbrev": "US", "name": "United States of America", "zip": "^[0-9]{5}(?:-[0-9]{4})?$"},
+ {"abbrev": "UY", "name": "Uruguay", "zip": "[0-9]{5}"},
+ {"abbrev": "UZ", "name": "Uzbekistan", "zip": "[0-9]{6}"},
+ {"abbrev": "VU", "name": "Vanuatu"},
+ {"abbrev": "VE", "name": "Venezuela", "zip": "[0-9]{4}(-[A-Z]{1})?"},
+ {"abbrev": "VN", "name": "Vietnam", "zip": "[0-9]{6}"},
+ {"abbrev": "VG", "name": "Virgin Islands (British)", "zip": "VG[0-9]{4}"},
+ {"abbrev": "VI", "name": "Virgin Islands (US)", "range": ["00801", "00851"], "zip": "\\d{5}(?:[-\\s]\\d{4})?"},
+ {"abbrev": "YE", "name": "Yemen"},
+ {"abbrev": "ZM", "name": "Zambia", "zip": "[0-9]{5}"},
+ {"abbrev": "ZW", "name": "Zimbabwe"},
+]
diff --git a/src/edify/library/url.py b/src/edify/library/url.py
new file mode 100644
index 0000000..1094155
--- /dev/null
+++ b/src/edify/library/url.py
@@ -0,0 +1,39 @@
+import re
+
+proto = "^https?:\\/\\/(?:www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_\\+.~#?&\\/=]*)$"
+no_proto = "^[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_\\+.~#?&\\/=]*)$"
+
+
+def url(url: str, match: list = ["proto", "no_proto"]) -> bool:
+ """Checks if a string is a valid URL.
+
+ Args:
+ url (str): The string to check.
+ match (list): The protocols to match against. Defaults to ["https", "http", "no_proto"].
+ Returns:
+ bool: True if the string is a valid URL, False otherwise.
+ """
+
+ # Validate match argument
+ if not isinstance(match, list):
+ raise TypeError("match argument must be a list")
+
+ if not match:
+ raise ValueError("match argument must not be empty")
+
+ # Validate protocols
+ protocols = []
+ for protocol in match:
+ if protocol == "proto":
+ protocols.append(proto)
+ elif protocol == "no_proto":
+ protocols.append(no_proto)
+ else:
+ raise ValueError("Invalid protocol: {}".format(protocol))
+
+ # Check if URL matches any of the protocols
+ for protocol in protocols:
+ if re.match(protocol, url):
+ return True
+
+ return False
diff --git a/src/edify/library/uuid.py b/src/edify/library/uuid.py
new file mode 100644
index 0000000..8c240a3
--- /dev/null
+++ b/src/edify/library/uuid.py
@@ -0,0 +1,14 @@
+import re
+
+pattern = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$"
+
+
+def uuid(uuid: str) -> bool:
+ """Checks if a string is a valid UUID.
+
+ Args:
+ uuid (str): The string to check.
+ Returns:
+ bool: True if the string is a valid UUID, False otherwise.
+ """
+ return re.match(pattern, uuid) is not None
diff --git a/src/edify/library/zip.py b/src/edify/library/zip.py
new file mode 100644
index 0000000..017f57d
--- /dev/null
+++ b/src/edify/library/zip.py
@@ -0,0 +1,29 @@
+import re
+
+from .support.zip import ZIP_LOCALES
+
+locales = [locale["abbrev"] for locale in ZIP_LOCALES]
+
+
+def zip(zip: str, locale: str = "US") -> bool:
+ """Check if a string is a valid zip code.
+
+ Args:
+ zip (str): The string to check.
+ locale (str): (optional) The locale to check against. Defaults to "US".
+ Returns:
+ bool: True if the string is a valid zip code, False otherwise.
+ """
+
+ if not isinstance(locale, str):
+ raise TypeError("locale must be a string")
+
+ if locale == "":
+ raise ValueError("locale cannot be empty")
+
+ if locale not in locales:
+ print(locales)
+ raise ValueError("locale must be one of {}".format(locales))
+
+ pattern = ZIP_LOCALES[locales.index(locale)]["zip"]
+ return re.match(pattern, zip) is not None
diff --git a/tests/ssn_test.py b/tests/ssn_test.py
new file mode 100644
index 0000000..ce2a57b
--- /dev/null
+++ b/tests/ssn_test.py
@@ -0,0 +1,12 @@
+from edify.library import ssn
+
+
+def test_ssn():
+ ssns = {
+ "000-22-3333": False,
+ "100-22-3333": True,
+ "": False,
+ 123: False,
+ }
+ for s_s_n, expected in ssns.items():
+ assert ssn(s_s_n) == expected
diff --git a/tests/test_guid.py b/tests/test_guid.py
new file mode 100644
index 0000000..b4b1a64
--- /dev/null
+++ b/tests/test_guid.py
@@ -0,0 +1,11 @@
+from edify.library import guid
+
+
+def test_valid_guids():
+ guids = {
+ "6ba7b810-9dad-11d1-80b4-00c04fd430c8": True,
+ '{51d52cf1-83c9-4f02-b117-703ecb728b74}': True,
+ '{51d52cf1-83c9-4f02-b117-703ecb728-b74}': False,
+ }
+ for guid_string, expectation in guids.items():
+ assert guid(guid_string) == expectation
diff --git a/tests/test_mac.py b/tests/test_mac.py
new file mode 100644
index 0000000..2f24b44
--- /dev/null
+++ b/tests/test_mac.py
@@ -0,0 +1,12 @@
+from edify.library import mac
+
+
+def test_mac():
+ macs = {
+ "00:00:5e:00:53:af": True,
+ "00:00:5e:00:53:af:": False,
+ 123: False,
+ }
+
+ for m_a_c, expected in macs.items():
+ assert mac(m_a_c) == expected
diff --git a/tests/test_password.py b/tests/test_password.py
new file mode 100644
index 0000000..538874b
--- /dev/null
+++ b/tests/test_password.py
@@ -0,0 +1,10 @@
+from edify.library import password
+
+
+def test_password():
+ assert password("password") is False
+ assert password("Password123!") is True
+ assert password("Password123!", max_length=8) is False
+ assert password("Password123!", min_upper=2) is False
+ assert password("password", min_upper=0, min_digit=0, min_special=0) is True
+ assert password("pass@#1", min_special=1, special_chars="!", min_digit=0, min_upper=0, min_length=4) is False
diff --git a/tests/test_url.py b/tests/test_url.py
new file mode 100644
index 0000000..74f8ed1
--- /dev/null
+++ b/tests/test_url.py
@@ -0,0 +1,63 @@
+from edify.library import url
+
+urls = [
+ "example.com",
+ "www.example.com",
+ "www.example.com/path/to/file",
+ "http://www.example.com",
+ "http://example.com",
+ "http://www.example.com/path/to/page",
+ "https://example.com",
+ "https://www.example.com/",
+ "https://www.example.com/path/to/page",
+ "//example.com",
+]
+
+
+def test_all_protocols():
+ match_list = ["proto", "no_proto"]
+ expected = [True] * 9 + [False]
+ for uri, expectation in zip(urls, expected):
+ assert url(uri, match=match_list) == expectation
+
+
+def test_proto_only():
+ match_list = ["proto"]
+ expected = [False] * 3 + [True] * 6 + [False]
+ for uri, expectation in zip(urls, expected):
+ print(uri, expectation)
+ assert url(uri, match=match_list) == expectation
+
+
+def test_no_proto_only():
+ match_list = ["no_proto"]
+ expected = [True] * 3 + [False] * 7
+ for uri, expectation in zip(urls, expected):
+ assert url(uri, match=match_list) == expectation
+
+
+def test_invalid_protocol():
+ match_list = ["invalid"]
+ for uri in urls:
+ try:
+ url(uri, match=match_list)
+ except ValueError:
+ assert True
+
+
+def test_invalid_match_type():
+ match_list = "invalid"
+ for uri in urls:
+ try:
+ url(uri, match=match_list)
+ except TypeError:
+ assert True
+
+
+def test_empty_match_list():
+ match_list = []
+ for uri in urls:
+ try:
+ url(uri, match=match_list)
+ except ValueError:
+ assert True
diff --git a/tests/test_uuid.py b/tests/test_uuid.py
new file mode 100644
index 0000000..df4e840
--- /dev/null
+++ b/tests/test_uuid.py
@@ -0,0 +1,13 @@
+from edify.library import uuid
+
+uuids = {
+ "123e4567-e89b-12d3-a456-426614174000": True,
+ "123e456-789b-12d3-426614174000": False,
+ "123e456-789b-12d3-a456-426614174000-12ad3r": False,
+ "123e456": False,
+}
+
+
+def test_valid_uuids():
+ for uuid_string, expectation in uuids.items():
+ assert uuid(uuid_string) == expectation
diff --git a/tests/test_zip.py b/tests/test_zip.py
new file mode 100644
index 0000000..999d55d
--- /dev/null
+++ b/tests/test_zip.py
@@ -0,0 +1,34 @@
+from edify.library import zip
+
+
+def test_valid_zips():
+ zips = {"12345": True, "12345-1234": True, "12345-123456": False, "1234": False}
+ for zip_string, expectation in zips.items():
+ assert zip(zip_string) == expectation
+
+
+def test_invalid_locale():
+ try:
+ zip("12345", locale="INVALID")
+ except ValueError:
+ assert True
+
+
+def test_invalid_locale_type():
+ try:
+ zip("12345", 5)
+ except TypeError:
+ assert True
+
+
+def test_empty_locale():
+ try:
+ zip("12345", "")
+ except ValueError:
+ assert True
+
+
+def test_locale_IN():
+ zips = {"123456": True, "000000": False, "012345": False, "12345": False, "1234567": False}
+ for zip_string, expectation in zips.items():
+ assert zip(zip_string, locale="IN") == expectation