From be5f91b83ade67b1841894b41abe6d5d660f207e Mon Sep 17 00:00:00 2001 From: Jan Honsbrok Date: Sun, 11 Sep 2022 14:49:51 +0200 Subject: [PATCH] chore: remove Lucidity --- cato/vendor/LICENSE.txt | 176 ---------------- cato/vendor/__init__.py | 0 cato/vendor/lucidity/__init__.py | 124 ------------ cato/vendor/lucidity/_version.py | 1 - cato/vendor/lucidity/error.py | 21 -- cato/vendor/lucidity/template.py | 331 ------------------------------- 6 files changed, 653 deletions(-) delete mode 100644 cato/vendor/LICENSE.txt delete mode 100644 cato/vendor/__init__.py delete mode 100644 cato/vendor/lucidity/__init__.py delete mode 100644 cato/vendor/lucidity/_version.py delete mode 100644 cato/vendor/lucidity/error.py delete mode 100644 cato/vendor/lucidity/template.py diff --git a/cato/vendor/LICENSE.txt b/cato/vendor/LICENSE.txt deleted file mode 100644 index d9a10c0d..00000000 --- a/cato/vendor/LICENSE.txt +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS diff --git a/cato/vendor/__init__.py b/cato/vendor/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cato/vendor/lucidity/__init__.py b/cato/vendor/lucidity/__init__.py deleted file mode 100644 index 37edb305..00000000 --- a/cato/vendor/lucidity/__init__.py +++ /dev/null @@ -1,124 +0,0 @@ -# :coding: utf-8 -# :copyright: Copyright (c) 2013 Martin Pengelly-Phillips -# :license: See LICENSE.txt. - -import os -import uuid -import imp - -from ._version import __version__ -from .template import Template, Resolver -from .error import ParseError, FormatError, NotFound - - -def discover_templates(paths=None, recursive=True): - """Search *paths* for mount points and load templates from them. - - *paths* should be a list of filesystem paths to search for mount points. - If not specified will try to use value from environment variable - :envvar:`LUCIDITY_TEMPLATE_PATH`. - - A mount point is a Python file that defines a 'register' function. The - function should return a list of instantiated - :py:class:`~lucidity.template.Template` objects. - - If *recursive* is True (the default) then all directories under a path - will also be searched. - - """ - templates = [] - - if paths is None: - paths = os.environ.get("LUCIDITY_TEMPLATE_PATH", "").split(os.pathsep) - - for path in paths: - for base, directories, filenames in os.walk(path): - for filename in filenames: - _, extension = os.path.splitext(filename) - if extension != ".py": - continue - - module_path = os.path.join(base, filename) - module_name = uuid.uuid4().hex - module = imp.load_source(module_name, module_path) - try: - registered = module.register() - except AttributeError: - pass - else: - if registered: - templates.extend(registered) - - if not recursive: - del directories[:] - - return templates - - -def parse(path, templates): - """Parse *path* against *templates*. - - *path* should be a string to parse. - - *templates* should be a list of :py:class:`~lucidity.template.Template` - instances in the order that they should be tried. - - Return ``(data, template)`` from first successful parse. - - Raise :py:class:`~lucidity.error.ParseError` if *path* is not - parseable by any of the supplied *templates*. - - """ - for template in templates: - try: - data = template.parse(path) - except ParseError: - continue - else: - return (data, template) - - raise ParseError( - "Path {0!r} did not match any of the supplied template patterns.".format(path) - ) - - -def format(data, templates): # @ReservedAssignment - """Format *data* using *templates*. - - *data* should be a dictionary of data to format into a path. - - *templates* should be a list of :py:class:`~lucidity.template.Template` - instances in the order that they should be tried. - - Return ``(path, template)`` from first successful format. - - Raise :py:class:`~lucidity.error.FormatError` if *data* is not - formattable by any of the supplied *templates*. - - - """ - for template in templates: - try: - path = template.format(data) - except FormatError: - continue - else: - return (path, template) - - raise FormatError( - "Data {0!r} was not formattable by any of the supplied templates.".format(data) - ) - - -def get_template(name, templates): - """Retrieve a template from *templates* by *name*. - - Raise :py:exc:`~lucidity.error.NotFound` if no matching template with - *name* found in *templates*. - - """ - for template in templates: - if template.name == name: - return template - - raise NotFound("{0} template not found in specified templates.".format(name)) diff --git a/cato/vendor/lucidity/_version.py b/cato/vendor/lucidity/_version.py deleted file mode 100644 index 0f228f25..00000000 --- a/cato/vendor/lucidity/_version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "1.5.1" diff --git a/cato/vendor/lucidity/error.py b/cato/vendor/lucidity/error.py deleted file mode 100644 index a0fe140f..00000000 --- a/cato/vendor/lucidity/error.py +++ /dev/null @@ -1,21 +0,0 @@ -# :coding: utf-8 -# :copyright: Copyright (c) 2013 Martin Pengelly-Phillips -# :license: See LICENSE.txt. - -"""Custom error classes.""" - - -class ParseError(Exception): - """Raise when a template is unable to parse a path.""" - - -class FormatError(Exception): - """Raise when a template is unable to format data into a path.""" - - -class NotFound(Exception): - """Raise when an item cannot be found.""" - - -class ResolveError(Exception): - """Raise when a template reference can not be resolved.""" diff --git a/cato/vendor/lucidity/template.py b/cato/vendor/lucidity/template.py deleted file mode 100644 index 2e3a2bb2..00000000 --- a/cato/vendor/lucidity/template.py +++ /dev/null @@ -1,331 +0,0 @@ -# :coding: utf-8 -# :copyright: Copyright (c) 2013 Martin Pengelly-Phillips -# :license: See LICENSE.txt. - -import abc -import sys -import re -import functools -from collections import defaultdict - -from typing import Dict - -import cato.vendor.lucidity.error - -# Type of a RegexObject for isinstance check. -from cato.vendor import lucidity - -_RegexType = type(re.compile("")) - - -class Template(object): - """A template.""" - - _STRIP_EXPRESSION_REGEX = re.compile(r"{(.+?)(:(\\}|.)+?)}") - _PLAIN_PLACEHOLDER_REGEX = re.compile(r"{(.+?)}") - _TEMPLATE_REFERENCE_REGEX = re.compile(r"{@(?P.+?)}") - - ANCHOR_START, ANCHOR_END, ANCHOR_BOTH = (1, 2, 3) - - RELAXED, STRICT = (1, 2) - - def __init__( - self, - name, - pattern, - anchor=ANCHOR_START, - default_placeholder_expression="[\w_.\-]+", # noqa: W605 - duplicate_placeholder_mode=RELAXED, - template_resolver=None, - ): - """Initialise with *name* and *pattern*. - - *anchor* determines how the pattern is anchored during a parse. A - value of :attr:`~Template.ANCHOR_START` (the default) will match the - pattern against the start of a path. :attr:`~Template.ANCHOR_END` will - match against the end of a path. To anchor at both the start and end - (a full path match) use :attr:`~Template.ANCHOR_BOTH`. Finally, - ``None`` will try to match the pattern once anywhere in the path. - - *duplicate_placeholder_mode* determines how duplicate placeholders will - be handled during parsing. :attr:`~Template.RELAXED` mode extracts the - last matching value without checking the other values. - :attr:`~Template.STRICT` mode ensures that all duplicate placeholders - extract the same value and raises :exc:`~lucidity.error.ParseError` if - they do not. - - If *template_resolver* is supplied, use it to resolve any template - references in the *pattern* during operations. It should conform to the - :class:`Resolver` interface. It can be changed at any time on the - instance to affect future operations. - - """ - super(Template, self).__init__() - self.duplicate_placeholder_mode = duplicate_placeholder_mode - self.template_resolver = template_resolver - - self._default_placeholder_expression = default_placeholder_expression - self._period_code = "_LPD_" - self._at_code = "_WXV_" - self._name = name - self._pattern = pattern - self._anchor = anchor - - # Check that supplied pattern is valid and able to be compiled. - self._construct_regular_expression(self.pattern) - - def __repr__(self): - """Return unambiguous representation of template.""" - return "{0}(name={1!r}, pattern={2!r})".format( - self.__class__.__name__, self.name, self.pattern - ) - - @property - def name(self): - """Return name of template.""" - return self._name - - @property - def pattern(self): - """Return template pattern.""" - return self._pattern - - def expanded_pattern(self): - """Return pattern with all referenced templates expanded recursively. - - Raise :exc:`lucidity.error.ResolveError` if pattern contains a reference - that cannot be resolved by currently set template_resolver. - - """ - return self._TEMPLATE_REFERENCE_REGEX.sub(self._expand_reference, self.pattern) - - def _expand_reference(self, match): - """Expand reference represented by *match*.""" - reference = match.group("reference") - - if self.template_resolver is None: - raise lucidity.error.ResolveError( - "Failed to resolve reference {0!r} as no template resolver set.".format( - reference - ) - ) - - template = self.template_resolver.get(reference) - if template is None: - raise lucidity.error.ResolveError( - "Failed to resolve reference {0!r} using template resolver.".format( - reference - ) - ) - - return template.expanded_pattern() - - def parse(self, path): - """Return dictionary of data extracted from *path* using this template. - - Raise :py:class:`~lucidity.error.ParseError` if *path* is not - parsable by this template. - - """ - # Construct regular expression for expanded pattern. - regex = self._construct_regular_expression(self.expanded_pattern()) - - # Parse. - parsed = {} - - match = regex.search(path) - if match: - data = {} - for key, value in sorted(match.groupdict().items()): - # Strip number that was added to make group name unique. - key = key[:-3] - - # If strict mode enabled for duplicate placeholders, ensure that - # all duplicate placeholders extract the same value. - if self.duplicate_placeholder_mode == self.STRICT: - if key in parsed: - if parsed[key] != value: - raise lucidity.error.ParseError( - "Different extracted values for placeholder " - "{0!r} detected. Values were {1!r} and {2!r}.".format( - key, parsed[key], value - ) - ) - else: - parsed[key] = value - - # Expand dot notation keys into nested dictionaries. - target = data - - parts = key.split(self._period_code) - for part in parts[:-1]: - target = target.setdefault(part, {}) - - target[parts[-1]] = value - - return data - - else: - raise lucidity.error.ParseError( - "Path {0!r} did not match template pattern.".format(path) - ) - - def format(self, data: Dict) -> str: - """Return a path formatted by applying *data* to this template. - - Raise :py:class:`~lucidity.error.FormatError` if *data* does not - supply enough information to fill the template fields. - - """ - - format_specification = self._construct_format_specification( - self.expanded_pattern() - ) - - return self._PLAIN_PLACEHOLDER_REGEX.sub( - functools.partial(self._format, data=data), format_specification - ) - - def _format(self, match, data): - """Return value from data for *match*.""" - placeholder = match.group(1) - parts = placeholder.split(".") - - try: - value = data - for part in parts: - value = value[part] - - except (TypeError, KeyError): - raise lucidity.error.FormatError( - "Could not format data {0!r} due to missing key {1!r}.".format( - data, placeholder - ) - ) - - else: - return value - - def keys(self): - """Return unique set of placeholders in pattern.""" - format_specification = self._construct_format_specification( - self.expanded_pattern() - ) - return set(self._PLAIN_PLACEHOLDER_REGEX.findall(format_specification)) - - def references(self): - """Return unique set of referenced templates in pattern.""" - format_specification = self._construct_format_specification(self.pattern) - return set(self._TEMPLATE_REFERENCE_REGEX.findall(format_specification)) - - def _construct_format_specification(self, pattern): - """Return format specification from *pattern*.""" - return self._STRIP_EXPRESSION_REGEX.sub("{\g<1>}", pattern) - - def _construct_regular_expression(self, pattern): - """Return a regular expression to represent *pattern*.""" - # Escape non-placeholder components. - expression = re.sub( - r"(?P{(.+?)(:(\\}|.)+?)?})|(?P.+?)", - self._escape, - pattern, - ) - - # Replace placeholders with regex pattern. - expression = re.sub( - r"{(?P.+?)(:(?P(\\}|.)+?))?}", - functools.partial(self._convert, placeholder_count=defaultdict(int)), - expression, - ) - - if self._anchor is not None: - if bool(self._anchor & self.ANCHOR_START): - expression = "^{0}".format(expression) - - if bool(self._anchor & self.ANCHOR_END): - expression = "{0}$".format(expression) - - # Compile expression. - try: - compiled = re.compile(expression) - except re.error as error: - if any( - [ - "bad group name" in str(error), - "bad character in group name" in str(error), - ] - ): - raise ValueError("Placeholder name contains invalid " "characters.") - else: - _, value, traceback = sys.exc_info() - message = "Invalid pattern: {0}".format(value) - raise ValueError(message).with_traceback(traceback) - - return compiled - - def _convert(self, match, placeholder_count): - """Return a regular expression to represent *match*. - - *placeholder_count* should be a `defaultdict(int)` that will be used to - store counts of unique placeholder names. - - """ - placeholder_name = match.group("placeholder") - - # Support at symbol (@) as referenced template indicator. Currently, - # this symbol not a valid character for a group name in the standard - # Python regex library. Rather than rewrite or monkey patch the library - # work around the restriction with a unique identifier. - placeholder_name = placeholder_name.replace("@", self._at_code) - - # Support period (.) as nested key indicator. Currently, a period is - # not a valid character for a group name in the standard Python regex - # library. Rather than rewrite or monkey patch the library work around - # the restriction with a unique identifier. - placeholder_name = placeholder_name.replace(".", self._period_code) - - # The re module does not support duplicate group names. To support - # duplicate placeholder names in templates add a unique count to the - # regular expression group name and strip it later during parse. - placeholder_count[placeholder_name] += 1 - placeholder_name += "{0:03d}".format(placeholder_count[placeholder_name]) - - expression = match.group("expression") - if expression is None: - expression = self._default_placeholder_expression - - # Un-escape potentially escaped characters in expression. - expression = expression.replace("\{", "{").replace("\}", "}") - - return r"(?P<{0}>{1})".format(placeholder_name, expression) - - def _escape(self, match): - """Escape matched 'other' group value.""" - groups = match.groupdict() - if groups["other"] is not None: - return re.escape(groups["other"]) - - return groups["placeholder"] - - -class Resolver(object): - """Template resolver interface.""" - - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def get(self, template_name, default=None): - """Return template that matches *template_name*. - - If no template matches then return *default*. - - """ - return default - - @classmethod - def __subclasshook__(cls, subclass): - """Return whether *subclass* fulfils this interface.""" - if cls is Resolver: - return callable(getattr(subclass, "get", None)) - - return NotImplemented