-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
requires/types: introduce expression type (expr.py)
`expression` is a new requirement type that allows user to express a requirement in human-readable, SQL-like syntax. It has a proper grammar to allow user to write checks as easily digestable manner, which will improve the QOL for scenario writers and code reviewers. The grammar is constructed using `pyparsing` library. The current grammar supports the following constructs: - Keywords (True, False, None) - Constants (Integer, Float, String literal) - Runtime variables (Python properties) - Functions(len, not, file, systemd, read_ini, read_cert) - Arithmetic operators(sign, mul, div, add, sub, exp) - Comparison operators(<, <=, >, >=, ==, !=, in) - Logical operators(and, or, not) - Comments('#', '//', '/*...*/') Also, the following changes have been made: - Updated requirement_types.rst to document the new Expression requirement type. - Moved property resolver logic from YPropertyBase to PythonEntityResolver class. - Added `pyparsing` as a dependency. - Added unit tests for the new code, the coverage rate is 100 pct for the expr.py This patch rewrites some of the scenario checks in the new expression syntax to demonstrate the difference and provide examples. Signed-off-by: Mustafa Kemal Gilor <[email protected]>
- Loading branch information
Showing
29 changed files
with
3,020 additions
and
344 deletions.
There are no files selected for viewing
620 changes: 620 additions & 0 deletions
620
doc/source/contrib/language_ref/property_ref/requirement_types.rst
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
"""Aliasing utilities.""" | ||
|
||
from hotsos.core.log import log | ||
|
||
|
||
class AliasAlreadyInUseError(Exception): | ||
"""Raised when an alias is already in use.""" | ||
|
||
def __init__(self, name): | ||
self.message = f"Alias '{name}` already in use!" | ||
|
||
def __str__(self): | ||
return self.message | ||
|
||
|
||
class AliasForbiddenError(Exception): | ||
"""Raised when an alias is forbidden to use.""" | ||
|
||
def __init__(self, name): | ||
self.message = f"Alias '{name}` is forbidden!" | ||
|
||
def __str__(self): | ||
return self.message | ||
|
||
|
||
class AliasRegistry: | ||
""" | ||
A class that provides a registry for aliasing Python things. | ||
""" | ||
|
||
# A class-level dictionary to store registered aliases. | ||
registry = {} | ||
|
||
@staticmethod | ||
def register(name, decoratee): | ||
""" | ||
Register a function, method, or property under an alias. | ||
This method handles different types of Python objects and creates | ||
appropriate wrappers or registrations based on the object type. | ||
Args: | ||
name (str): The alias under which to register the decoratee. | ||
decoratee (callable or property): The Python object to be | ||
registered. | ||
Raises: | ||
AliasAlreadyInUseError: If the alias name is already registered. | ||
AliasForbiddenError: If the alias name starts with "hotsos." | ||
""" | ||
isprop = isinstance(decoratee, property) | ||
target = decoratee.fget if isprop else decoratee | ||
|
||
if name.startswith("hotsos."): | ||
raise AliasForbiddenError(name) | ||
|
||
if name in AliasRegistry.registry: | ||
log.debug("alias registration failed -- already in use(`%s`)", | ||
name) | ||
raise AliasAlreadyInUseError(name) | ||
|
||
import_path = f"{target.__module__}.{target.__qualname__}" | ||
log.debug("registering alias `%s` --> {%s}", name, import_path) | ||
# Register full import path. | ||
AliasRegistry.registry[name] = import_path | ||
|
||
@staticmethod | ||
def resolve(the_alias, default=None): | ||
""" | ||
Retrieve a registered alias. | ||
Args: | ||
the_alias (str): The alias to retrieve. | ||
Returns: | ||
callable: The function or wrapper associated with the alias. | ||
Raises: | ||
NoSuchAliasError: No such alias in the registry. | ||
""" | ||
|
||
if the_alias not in AliasRegistry.registry: | ||
log.debug( | ||
"alias `%s` not found in the registry, " | ||
"returning the default value", | ||
the_alias, | ||
) | ||
return default | ||
|
||
value = AliasRegistry.registry[the_alias] | ||
log.debug("alias %s resolved to %s", the_alias, value) | ||
return value | ||
|
||
|
||
def alias(argument): | ||
"""Create an alias for a property, function or a thing.""" | ||
|
||
def real_decorator(func): | ||
"""We're not wrapping the func as we don't want | ||
to do anything at runtime. We just want to alias | ||
`func` to some user-defined name and call it on-demand.""" | ||
AliasRegistry.register(argument, func) | ||
return func | ||
|
||
return real_decorator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.