From e516059c716537259c601c022cc3bad44025385e Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Thu, 8 Jul 2021 20:08:22 -0700 Subject: Rename simple_acl -> acl --- acl.py | 202 +++++++++++++++++++++++++++++++++++++++++++ dateparse/dateparse_utils.py | 24 ++--- simple_acl.py | 202 ------------------------------------------- tests/acl_test.py | 49 +++++++++++ tests/simple_acl_test.py | 49 ----------- 5 files changed, 264 insertions(+), 262 deletions(-) create mode 100644 acl.py delete mode 100644 simple_acl.py create mode 100755 tests/acl_test.py delete mode 100755 tests/simple_acl_test.py diff --git a/acl.py b/acl.py new file mode 100644 index 0000000..5040304 --- /dev/null +++ b/acl.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python3 + +from abc import ABC, abstractmethod +import fnmatch +import logging +import re +from typing import Any, Callable, List, Optional, Set + + +logger = logging.getLogger(__name__) + + +ACL_ORDER_ALLOW_DENY = 1 +ACL_ORDER_DENY_ALLOW = 2 + + +class SimpleACL(ABC): + """A simple Access Control List interface.""" + + def __init__( + self, + *, + order_to_check_allow_deny: int, + default_answer: bool + ): + if order_to_check_allow_deny not in ( + ACL_ORDER_ALLOW_DENY, ACL_ORDER_DENY_ALLOW + ): + raise Exception( + 'order_to_check_allow_deny must be ACL_ORDER_ALLOW_DENY or ' + + 'ACL_ORDER_DENY_ALLOW') + self.order_to_check_allow_deny = order_to_check_allow_deny + self.default_answer = default_answer + + def __call__(self, x: Any) -> bool: + """Returns True if x is allowed, False otherwise.""" + logger.debug(f'SimpleACL checking {x}') + if self.order_to_check_allow_deny == ACL_ORDER_ALLOW_DENY: + logger.debug('Checking allowed first...') + if self.check_allowed(x): + logger.debug(f'{x} was allowed explicitly.') + return True + logger.debug('Checking denied next...') + if self.check_denied(x): + logger.debug(f'{x} was denied explicitly.') + return False + elif self.order_to_check_allow_deny == ACL_ORDER_DENY_ALLOW: + logger.debug('Checking denied first...') + if self.check_denied(x): + logger.debug(f'{x} was denied explicitly.') + return False + if self.check_allowed(x): + logger.debug(f'{x} was allowed explicitly.') + return True + + logger.debug( + f'{x} was not explicitly allowed or denied; ' + + f'using default answer ({self.default_answer})' + ) + return self.default_answer + + @abstractmethod + def check_allowed(self, x: Any) -> bool: + """Return True if x is explicitly allowed, False otherwise.""" + pass + + @abstractmethod + def check_denied(self, x: Any) -> bool: + """Return True if x is explicitly denied, False otherwise.""" + pass + + +class SetBasedACL(SimpleACL): + """An ACL that allows or denies based on membership in a set.""" + def __init__(self, + *, + allow_set: Optional[Set[Any]] = None, + deny_set: Optional[Set[Any]] = None, + order_to_check_allow_deny: int, + default_answer: bool) -> None: + super().__init__( + order_to_check_allow_deny=order_to_check_allow_deny, + default_answer=default_answer + ) + self.allow_set = allow_set + self.deny_set = deny_set + + def check_allowed(self, x: Any) -> bool: + if self.allow_set is None: + return False + return x in self.allow_set + + def check_denied(self, x: Any) -> bool: + if self.deny_set is None: + return False + return x in self.deny_set + + +class PredicateListBasedACL(SimpleACL): + """An ACL that allows or denies by applying predicates.""" + def __init__(self, + *, + allow_predicate_list: List[Callable[[Any], bool]] = None, + deny_predicate_list: List[Callable[[Any], bool]] = None, + order_to_check_allow_deny: int, + default_answer: bool) -> None: + super().__init__( + order_to_check_allow_deny=order_to_check_allow_deny, + default_answer=default_answer + ) + self.allow_predicate_list = allow_predicate_list + self.deny_predicate_list = deny_predicate_list + + def check_allowed(self, x: Any) -> bool: + if self.allow_predicate_list is None: + return False + return any(predicate(x) for predicate in self.allow_predicate_list) + + def check_denied(self, x: Any) -> bool: + if self.deny_predicate_list is None: + return False + return any(predicate(x) for predicate in self.deny_predicate_list) + + +class StringWildcardBasedACL(PredicateListBasedACL): + """An ACL that allows or denies based on string glob (*, ?) patterns.""" + def __init__(self, + *, + allowed_patterns: Optional[List[str]] = None, + denied_patterns: Optional[List[str]] = None, + order_to_check_allow_deny: int, + default_answer: bool) -> None: + allow_predicates = [] + if allowed_patterns is not None: + for pattern in allowed_patterns: + allow_predicates.append( + lambda x, pattern=pattern: fnmatch.fnmatch(x, pattern) + ) + deny_predicates = None + if denied_patterns is not None: + deny_predicates = [] + for pattern in denied_patterns: + deny_predicates.append( + lambda x, pattern=pattern: fnmatch.fnmatch(x, pattern) + ) + + super().__init__( + allow_predicate_list=allow_predicates, + deny_predicate_list=deny_predicates, + order_to_check_allow_deny=order_to_check_allow_deny, + default_answer=default_answer, + ) + + +class StringREBasedACL(PredicateListBasedACL): + """An ACL that allows or denies by applying regexps.""" + def __init__(self, + *, + allowed_regexs: Optional[List[re.Pattern]] = None, + denied_regexs: Optional[List[re.Pattern]] = None, + order_to_check_allow_deny: int, + default_answer: bool) -> None: + allow_predicates = None + if allowed_regexs is not None: + allow_predicates = [] + for pattern in allowed_regexs: + allow_predicates.append( + lambda x, pattern=pattern: pattern.match(x) is not None + ) + deny_predicates = None + if denied_regexs is not None: + deny_predicates = [] + for pattern in denied_regexs: + deny_predicates.append( + lambda x, pattern=pattern: pattern.match(x) is not None + ) + super().__init__( + allow_predicate_list=allow_predicates, + deny_predicate_list=deny_predicates, + order_to_check_allow_deny=order_to_check_allow_deny, + default_answer=default_answer, + ) + + +class AnyCompoundACL(object): + """An ACL that allows if any of its subacls allow.""" + def __init__(self, subacls: List[SimpleACL]): + assert subacls is not None + self.subacls = subacls + + def __call__(self, x: Any): + return any(acl(x) for acl in self.subacls) + + +class AllCompoundACL(object): + """An ACL that allows if all of its subacls allow.""" + def __init__(self, subacls: List[SimpleACL]): + assert subacls is not None + self.subacls = subacls + + def __call__(self, x: Any): + return all(acl(x) for acl in self.subacls) diff --git a/dateparse/dateparse_utils.py b/dateparse/dateparse_utils.py index fc5408f..00e7b9d 100755 --- a/dateparse/dateparse_utils.py +++ b/dateparse/dateparse_utils.py @@ -13,13 +13,13 @@ import dateutil.easter import dateutil.tz import pytz +import acl import bootstrap import datetime_utils import decorator_utils from dateparse.dateparse_utilsLexer import dateparse_utilsLexer # type: ignore from dateparse.dateparse_utilsListener import dateparse_utilsListener # type: ignore from dateparse.dateparse_utilsParser import dateparse_utilsParser # type: ignore -import simple_acl as acl logger = logging.getLogger(__name__) @@ -78,16 +78,18 @@ class RaisingErrorListener(antlr4.DiagnosticErrorListener): pass -@decorator_utils.decorate_matching_methods_with(debug_parse, - acl=acl.StringWildcardBasedACL( - allowed_patterns=[ - 'enter*', - 'exit*', - ], - denied_patterns=None, - order_to_check_allow_deny=acl.ACL_ORDER_DENY_ALLOW, - default_answer=False - )) +@decorator_utils.decorate_matching_methods_with( + debug_parse, + acl=acl.StringWildcardBasedACL( + allowed_patterns=[ + 'enter*', + 'exit*', + ], + denied_patterns=None, + order_to_check_allow_deny=acl.ACL_ORDER_DENY_ALLOW, + default_answer=False + ) +) class DateParser(dateparse_utilsListener): PARSE_TYPE_SINGLE_DATE_EXPR = 1 PARSE_TYPE_BASE_AND_OFFSET_EXPR = 2 diff --git a/simple_acl.py b/simple_acl.py deleted file mode 100644 index 5040304..0000000 --- a/simple_acl.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env python3 - -from abc import ABC, abstractmethod -import fnmatch -import logging -import re -from typing import Any, Callable, List, Optional, Set - - -logger = logging.getLogger(__name__) - - -ACL_ORDER_ALLOW_DENY = 1 -ACL_ORDER_DENY_ALLOW = 2 - - -class SimpleACL(ABC): - """A simple Access Control List interface.""" - - def __init__( - self, - *, - order_to_check_allow_deny: int, - default_answer: bool - ): - if order_to_check_allow_deny not in ( - ACL_ORDER_ALLOW_DENY, ACL_ORDER_DENY_ALLOW - ): - raise Exception( - 'order_to_check_allow_deny must be ACL_ORDER_ALLOW_DENY or ' + - 'ACL_ORDER_DENY_ALLOW') - self.order_to_check_allow_deny = order_to_check_allow_deny - self.default_answer = default_answer - - def __call__(self, x: Any) -> bool: - """Returns True if x is allowed, False otherwise.""" - logger.debug(f'SimpleACL checking {x}') - if self.order_to_check_allow_deny == ACL_ORDER_ALLOW_DENY: - logger.debug('Checking allowed first...') - if self.check_allowed(x): - logger.debug(f'{x} was allowed explicitly.') - return True - logger.debug('Checking denied next...') - if self.check_denied(x): - logger.debug(f'{x} was denied explicitly.') - return False - elif self.order_to_check_allow_deny == ACL_ORDER_DENY_ALLOW: - logger.debug('Checking denied first...') - if self.check_denied(x): - logger.debug(f'{x} was denied explicitly.') - return False - if self.check_allowed(x): - logger.debug(f'{x} was allowed explicitly.') - return True - - logger.debug( - f'{x} was not explicitly allowed or denied; ' + - f'using default answer ({self.default_answer})' - ) - return self.default_answer - - @abstractmethod - def check_allowed(self, x: Any) -> bool: - """Return True if x is explicitly allowed, False otherwise.""" - pass - - @abstractmethod - def check_denied(self, x: Any) -> bool: - """Return True if x is explicitly denied, False otherwise.""" - pass - - -class SetBasedACL(SimpleACL): - """An ACL that allows or denies based on membership in a set.""" - def __init__(self, - *, - allow_set: Optional[Set[Any]] = None, - deny_set: Optional[Set[Any]] = None, - order_to_check_allow_deny: int, - default_answer: bool) -> None: - super().__init__( - order_to_check_allow_deny=order_to_check_allow_deny, - default_answer=default_answer - ) - self.allow_set = allow_set - self.deny_set = deny_set - - def check_allowed(self, x: Any) -> bool: - if self.allow_set is None: - return False - return x in self.allow_set - - def check_denied(self, x: Any) -> bool: - if self.deny_set is None: - return False - return x in self.deny_set - - -class PredicateListBasedACL(SimpleACL): - """An ACL that allows or denies by applying predicates.""" - def __init__(self, - *, - allow_predicate_list: List[Callable[[Any], bool]] = None, - deny_predicate_list: List[Callable[[Any], bool]] = None, - order_to_check_allow_deny: int, - default_answer: bool) -> None: - super().__init__( - order_to_check_allow_deny=order_to_check_allow_deny, - default_answer=default_answer - ) - self.allow_predicate_list = allow_predicate_list - self.deny_predicate_list = deny_predicate_list - - def check_allowed(self, x: Any) -> bool: - if self.allow_predicate_list is None: - return False - return any(predicate(x) for predicate in self.allow_predicate_list) - - def check_denied(self, x: Any) -> bool: - if self.deny_predicate_list is None: - return False - return any(predicate(x) for predicate in self.deny_predicate_list) - - -class StringWildcardBasedACL(PredicateListBasedACL): - """An ACL that allows or denies based on string glob (*, ?) patterns.""" - def __init__(self, - *, - allowed_patterns: Optional[List[str]] = None, - denied_patterns: Optional[List[str]] = None, - order_to_check_allow_deny: int, - default_answer: bool) -> None: - allow_predicates = [] - if allowed_patterns is not None: - for pattern in allowed_patterns: - allow_predicates.append( - lambda x, pattern=pattern: fnmatch.fnmatch(x, pattern) - ) - deny_predicates = None - if denied_patterns is not None: - deny_predicates = [] - for pattern in denied_patterns: - deny_predicates.append( - lambda x, pattern=pattern: fnmatch.fnmatch(x, pattern) - ) - - super().__init__( - allow_predicate_list=allow_predicates, - deny_predicate_list=deny_predicates, - order_to_check_allow_deny=order_to_check_allow_deny, - default_answer=default_answer, - ) - - -class StringREBasedACL(PredicateListBasedACL): - """An ACL that allows or denies by applying regexps.""" - def __init__(self, - *, - allowed_regexs: Optional[List[re.Pattern]] = None, - denied_regexs: Optional[List[re.Pattern]] = None, - order_to_check_allow_deny: int, - default_answer: bool) -> None: - allow_predicates = None - if allowed_regexs is not None: - allow_predicates = [] - for pattern in allowed_regexs: - allow_predicates.append( - lambda x, pattern=pattern: pattern.match(x) is not None - ) - deny_predicates = None - if denied_regexs is not None: - deny_predicates = [] - for pattern in denied_regexs: - deny_predicates.append( - lambda x, pattern=pattern: pattern.match(x) is not None - ) - super().__init__( - allow_predicate_list=allow_predicates, - deny_predicate_list=deny_predicates, - order_to_check_allow_deny=order_to_check_allow_deny, - default_answer=default_answer, - ) - - -class AnyCompoundACL(object): - """An ACL that allows if any of its subacls allow.""" - def __init__(self, subacls: List[SimpleACL]): - assert subacls is not None - self.subacls = subacls - - def __call__(self, x: Any): - return any(acl(x) for acl in self.subacls) - - -class AllCompoundACL(object): - """An ACL that allows if all of its subacls allow.""" - def __init__(self, subacls: List[SimpleACL]): - assert subacls is not None - self.subacls = subacls - - def __call__(self, x: Any): - return all(acl(x) for acl in self.subacls) diff --git a/tests/acl_test.py b/tests/acl_test.py new file mode 100755 index 0000000..810aedf --- /dev/null +++ b/tests/acl_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +import re +import unittest + +import acl +import bootstrap + + +class TestSimpleACL(unittest.TestCase): + + def test_set_based_acl(self): + even = acl.SetBasedACL( + allow_set = set([2, 4, 6, 8, 10]), + deny_set = set([1, 3, 5, 7, 9]), + order_to_check_allow_deny = acl.ACL_ORDER_ALLOW_DENY, + default_answer = False + ) + self.assertTrue(even(2)) + self.assertFalse(even(3)) + self.assertFalse(even(-4)) + + def test_wildcard_based_acl(self): + a_or_b = acl.StringWildcardBasedACL( + allowed_patterns = ['a*', 'b*'], + order_to_check_allow_deny = acl.ACL_ORDER_ALLOW_DENY, + default_answer = False + ) + self.assertTrue(a_or_b('aardvark')) + self.assertTrue(a_or_b('bubblegum')) + self.assertFalse(a_or_b('charlie')) + + def test_re_based_acl(self): + weird = acl.StringREBasedACL( + denied_regexs = [ + re.compile('^a.*a$'), + re.compile('^b.*b$') + ], + order_to_check_allow_deny = acl.ACL_ORDER_ALLOW_DENY, + default_answer = True + ) + self.assertTrue(weird('aardvark')) + self.assertFalse(weird('anaconda')) + self.assertFalse(weird('beelzebub')) + + +if __name__ == '__main__': + unittest.main = bootstrap.initialize(unittest.main) + unittest.main() diff --git a/tests/simple_acl_test.py b/tests/simple_acl_test.py deleted file mode 100755 index 6c9b24c..0000000 --- a/tests/simple_acl_test.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python3 - -import re -import unittest - -import bootstrap -import simple_acl as acl - - -class TestSimpleACL(unittest.TestCase): - - def test_set_based_acl(self): - even = acl.SetBasedACL( - allow_set = set([2, 4, 6, 8, 10]), - deny_set = set([1, 3, 5, 7, 9]), - order_to_check_allow_deny = acl.ACL_ORDER_ALLOW_DENY, - default_answer = False - ) - self.assertTrue(even(2)) - self.assertFalse(even(3)) - self.assertFalse(even(-4)) - - def test_wildcard_based_acl(self): - a_or_b = acl.StringWildcardBasedACL( - allowed_patterns = ['a*', 'b*'], - order_to_check_allow_deny = acl.ACL_ORDER_ALLOW_DENY, - default_answer = False - ) - self.assertTrue(a_or_b('aardvark')) - self.assertTrue(a_or_b('bubblegum')) - self.assertFalse(a_or_b('charlie')) - - def test_re_based_acl(self): - weird = acl.StringREBasedACL( - denied_regexs = [ - re.compile('^a.*a$'), - re.compile('^b.*b$') - ], - order_to_check_allow_deny = acl.ACL_ORDER_ALLOW_DENY, - default_answer = True - ) - self.assertTrue(weird('aardvark')) - self.assertFalse(weird('anaconda')) - self.assertFalse(weird('beelzebub')) - - -if __name__ == '__main__': - unittest.main = bootstrap.initialize(unittest.main) - unittest.main() -- cgit v1.3