Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion check50/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ def _setup_translation():

from . import regex
from .runner import check
from .config import config
from pexpect import EOF

__all__ = ["import_checks", "data", "exists", "hash", "include", "regex",
"run", "log", "Failure", "Mismatch", "Missing", "check", "EOF"]
"run", "log", "Failure", "Mismatch", "Missing", "check", "EOF",
"config"]
12 changes: 9 additions & 3 deletions check50/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from pexpect.exceptions import EOF, TIMEOUT

from . import internal, regex
from .config import config

_log = []
internal.register.before_every(_log.clear)
Expand Down Expand Up @@ -499,7 +500,7 @@ def wrapper(*args, **kwargs):
return wrapper
return decorator

def _truncate(s, other, max_len=10):
def _truncate(s, other):
def normalize(obj):
if isinstance(obj, list):
return "\n".join(map(str, obj))
Expand All @@ -508,6 +509,11 @@ def normalize(obj):

s, other = normalize(s), normalize(other)

if not config.dynamic_truncate:
if len(s) > config.truncate_len:
s = s[:config.truncate_len] + "..."
return s

# find the index of first difference
limit = min(len(s), len(other))
i = limit
Expand All @@ -517,8 +523,8 @@ def normalize(obj):
break

# center around diff
start = max(i - (max_len // 2), 0)
end = min(start + max_len, len(s))
start = max(i - (config.truncate_len // 2), 0)
end = min(start + config.truncate_len, len(s))

snippet = s[start:end]

Expand Down
69 changes: 69 additions & 0 deletions check50/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
class Config:
"""
Configuration for `check50` behavior.

This class stores user-defined configuration options that influence
check50's output formatting.

For developers of `check50`, you can extend the `Config` class by adding new
variables to the `__init__`, which will automatically generate new "setter"
functions to modify the default values. Additionally, if the new
configuration needs to be validated before the user can modify it, add your
validation into the `_validators` dictionary.
"""

def __init__(self):
self.truncate_len = 10
self.dynamic_truncate = True

# Create boolean validators for your variables here (if needed):
# A help message is not required.
self._validators = {
"truncate_len": (lambda val: isinstance(val, int) and val >= 1,
"truncate_len must be a positive integer"),
"dynamic_truncate": (lambda val: isinstance(val, bool) or val in (0, 1),
"dynamic_truncate must be a boolean")
}

# Dynamically generates setter functions based on variable names and
# the type of the default values
self._generate_setters()

def _generate_setters(self):
def make_setter(attr):
"""Factory for making functions like `set_<attr_name>(arg)`"""

def setter(self, value):
# Get the entry in the dict of validators.
# Check to see if the value passes the validator, and if it
# didn't, display the help message, if any.
validator_entry = self._validators.get(attr)

if validator_entry:
if isinstance(validator_entry, tuple):
validator, help = validator_entry
else:
validator, help = validator_entry, None

if not validator(value):
error_msg = f"invalid value for {attr}: {value}"
if help:
error_msg += f", {help}"
raise ValueError(error_msg)

setattr(self, attr, value)
return setter

# Iterate through the names of every instantiated variable
for attribute_name in self.__dict__:
if attribute_name.startswith('_'):
continue # skip "private" attributes (denoted with a prefix `_`)
value = getattr(self, attribute_name)
if callable(value):
continue # skip functions/methods

# Create a class method with the given name and function
setattr(self.__class__, f"set_{attribute_name}", make_setter(attribute_name))


config = Config()
Loading