Fixes #85, optional skipping of the autoupdate
This commit is contained in:
parent
07512c45db
commit
91fb131abf
|
@ -1,3 +1,6 @@
|
|||
1.0.4:
|
||||
- Skipping the startup update with setting an environment variable called `PY3VE_IGNORE_UPDATER`
|
||||
|
||||
1.0.3:
|
||||
- Moving project off github
|
||||
- Static type check fixes
|
||||
|
|
|
@ -172,5 +172,7 @@ The update can be triggered manually:
|
|||
|
||||
`callback`: An optional Callable (function/method) to be called when the update is done.
|
||||
|
||||
You can completely skip the auto-update on startup by setting the environment variable `PY3VE_IGNORE_UPDATER` to any value.
|
||||
|
||||
# Read the [FAQ](https://gitea.ksol.io/karolyi/py3-validate-email/src/branch/master/FAQ.md)!
|
||||
|
||||
|
|
2
setup.py
2
setup.py
|
@ -57,7 +57,7 @@ class BuildPyCommand(build_py):
|
|||
|
||||
setup(
|
||||
name='py3-validate-email',
|
||||
version='1.0.3',
|
||||
version='1.0.4',
|
||||
packages=find_packages(exclude=['tests']),
|
||||
install_requires=['dnspython~=2.1', 'idna~=3.0', 'filelock~=3.0'],
|
||||
author='László Károlyi',
|
||||
|
|
|
@ -11,11 +11,13 @@ from validate_email.validate_email import (
|
|||
class BlacklistCheckTestCase(TestCase):
|
||||
'Testing if the included blacklist filtering works.'
|
||||
|
||||
def setUpClass():
|
||||
def setUpClass(): # type: ignore
|
||||
update_builtin_blacklist(force=False, background=False)
|
||||
|
||||
def test_blacklist_positive(self):
|
||||
'Disallows blacklist item: mailinator.com.'
|
||||
# The setting of the PY3VE_IGNORE_UPDATER variable doesn't
|
||||
# matter here as the module has already download an initial list
|
||||
with self.assertRaises(DomainBlacklistedError):
|
||||
domainlist_check(EmailAddress('pm2@mailinator.com'))
|
||||
with self.assertRaises(DomainBlacklistedError):
|
||||
|
|
|
@ -16,11 +16,11 @@ class InstallTest(TestCase):
|
|||
'Testing package installation.'
|
||||
|
||||
def test_datadir_is_in_place(self):
|
||||
'Data directory should be in the virtualenv.'
|
||||
'Data directory should be in the virtualenv *after installation*.'
|
||||
output = check_output([
|
||||
executable, '-c', (
|
||||
'import sys;sys.path.remove("");import validate_email;'
|
||||
'print(validate_email.updater.BLACKLIST_FILEPATH_INSTALLED);'
|
||||
'import sys;sys.path.remove("");import validate_email;' +
|
||||
'print(validate_email.updater.BLACKLIST_FILEPATH_INSTALLED);' +
|
||||
'print(validate_email.updater.ETAG_FILEPATH_INSTALLED, end="")'
|
||||
)]).decode('ascii')
|
||||
bl_path, etag_path = output.split('\n')
|
||||
|
|
|
@ -3,14 +3,14 @@ from re import compile as re_compile
|
|||
|
||||
HOST_REGEX = re_compile(
|
||||
# max length for domain name labels is 63 characters per RFC 1034
|
||||
r'((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+)'
|
||||
r'((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+)' +
|
||||
r'(?:[A-Z0-9-]{2,63}(?<!-))\Z', IGNORECASE)
|
||||
LITERAL_REGEX = re_compile(
|
||||
# literal form, ipv4 or ipv6 address (SMTP 4.1.3)
|
||||
r'\[([A-f0-9:\.]+)\]\Z', IGNORECASE)
|
||||
USER_REGEX = re_compile(
|
||||
# dot-atom
|
||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*\Z"
|
||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*\Z" +
|
||||
# quoted-string
|
||||
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013'
|
||||
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013' +
|
||||
r'\014\016-\177])*"\Z)', IGNORECASE)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from logging import getLogger
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from filelock import FileLock
|
||||
|
@ -6,8 +7,8 @@ from filelock import FileLock
|
|||
from .email_address import EmailAddress
|
||||
from .exceptions import DomainBlacklistedError
|
||||
from .updater import (
|
||||
BLACKLIST_FILEPATH_INSTALLED, BLACKLIST_FILEPATH_TMP, LOCK_PATH,
|
||||
update_builtin_blacklist)
|
||||
BLACKLIST_FILEPATH_INSTALLED, BLACKLIST_FILEPATH_TMP, ENV_IGNORE_UPDATER,
|
||||
LOCK_PATH, TMP_PATH, update_builtin_blacklist)
|
||||
|
||||
SetOrNone = Optional[set]
|
||||
LOGGER = getLogger(__name__)
|
||||
|
@ -17,7 +18,6 @@ class DomainListValidator(object):
|
|||
'Check the provided email against domain lists.'
|
||||
domain_whitelist = set()
|
||||
domain_blacklist = set('localhost')
|
||||
_is_builtin_bl_used: bool = False
|
||||
|
||||
def __init__(
|
||||
self, whitelist: SetOrNone = None, blacklist: SetOrNone = None):
|
||||
|
@ -26,11 +26,10 @@ class DomainListValidator(object):
|
|||
if blacklist:
|
||||
self.domain_blacklist = set(x.lower() for x in blacklist)
|
||||
else:
|
||||
self._is_builtin_bl_used = True
|
||||
self.reload_builtin_blacklist()
|
||||
|
||||
@property
|
||||
def _blacklist_path(self) -> str:
|
||||
def _blacklist_path(self) -> Path:
|
||||
'Return the path of the `blacklist.txt` that should be loaded.'
|
||||
try:
|
||||
# Zero size: file is touched to indicate the preinstalled
|
||||
|
@ -43,9 +42,8 @@ class DomainListValidator(object):
|
|||
|
||||
def reload_builtin_blacklist(self):
|
||||
'(Re)load our built-in blacklist.'
|
||||
if not self._is_builtin_bl_used:
|
||||
return
|
||||
with FileLock(lock_file=LOCK_PATH):
|
||||
TMP_PATH.mkdir(exist_ok=True)
|
||||
with FileLock(lock_file=str(LOCK_PATH)):
|
||||
bl_path = self._blacklist_path
|
||||
LOGGER.debug(msg=f'(Re)loading blacklist from {bl_path}')
|
||||
try:
|
||||
|
@ -57,7 +55,10 @@ class DomainListValidator(object):
|
|||
x.strip().lower() for x in lines if x.strip())
|
||||
|
||||
def __call__(self, email_address: EmailAddress) -> bool:
|
||||
'Do the checking here.'
|
||||
"""
|
||||
Check if the email domain is valid, raise
|
||||
`DomainBlacklistedError` if not.
|
||||
"""
|
||||
if email_address.domain in self.domain_whitelist:
|
||||
return True
|
||||
if email_address.domain in self.domain_blacklist:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from http.client import HTTPResponse
|
||||
from logging import getLogger
|
||||
from os import environ
|
||||
from pathlib import Path
|
||||
from tempfile import gettempdir, gettempprefix
|
||||
from threading import Thread
|
||||
|
@ -19,9 +20,9 @@ except ImportError:
|
|||
LOGGER = getLogger(__name__)
|
||||
TMP_PATH = Path(gettempdir()).joinpath(
|
||||
f'{gettempprefix()}-py3-validate-email-{geteuid()}')
|
||||
TMP_PATH.mkdir(exist_ok=True)
|
||||
ENV_IGNORE_UPDATER = environ.get('PY3VE_IGNORE_UPDATER')
|
||||
BLACKLIST_URL = (
|
||||
'https://raw.githubusercontent.com/disposable-email-domains/'
|
||||
'https://raw.githubusercontent.com/disposable-email-domains/' +
|
||||
'disposable-email-domains/master/disposable_email_blocklist.conf')
|
||||
LIB_PATH_DEFAULT = Path(__file__).resolve().parent.joinpath('data')
|
||||
BLACKLIST_FILEPATH_INSTALLED = LIB_PATH_DEFAULT.joinpath('blacklist.txt')
|
||||
|
@ -117,9 +118,11 @@ class BlacklistUpdater(object):
|
|||
self, force: bool = False, callback: Optional[Callable] = None):
|
||||
'Start optionally updating the blacklist.txt file.'
|
||||
# Locking to avoid multi-process update on multi-process startup
|
||||
# Import filelock locally because this module is als used by setup.py
|
||||
# Import filelock locally because this module is als used by
|
||||
# setup.py
|
||||
from filelock import FileLock
|
||||
with FileLock(lock_file=LOCK_PATH):
|
||||
TMP_PATH.mkdir(exist_ok=True)
|
||||
with FileLock(lock_file=str(LOCK_PATH)):
|
||||
self._process(force=force)
|
||||
# Always execute callback because multiple processes can have
|
||||
# different versions of blacklists (one before, one after
|
||||
|
@ -135,12 +138,15 @@ def update_builtin_blacklist(
|
|||
Update and reload the built-in blacklist. Return the `Thread` used
|
||||
to do the background update, so it can be `join()`-ed.
|
||||
"""
|
||||
if ENV_IGNORE_UPDATER:
|
||||
LOGGER.debug(msg='Skipping update of built-in blacklist.')
|
||||
return
|
||||
LOGGER.debug(msg='Starting optional update of built-in blacklist.')
|
||||
blacklist_updater = BlacklistUpdater()
|
||||
kwargs = dict(force=force, callback=callback)
|
||||
if not background:
|
||||
blacklist_updater.process(**kwargs)
|
||||
return
|
||||
bl_thread = Thread(target=blacklist_updater.process, kwargs=kwargs)
|
||||
bl_thread.start()
|
||||
return bl_thread
|
||||
updater_thread = Thread(target=blacklist_updater.process, kwargs=kwargs)
|
||||
updater_thread.start()
|
||||
return updater_thread
|
||||
|
|
Loading…
Reference in New Issue