Skip to content

back to Claude Sonnet 3.5 - Base summary

Claude Sonnet 3.5 - Base: voluptuous

Failed to run pytests for test tests

Pytest collection failure.

Patch diff

diff --git a/voluptuous/error.py b/voluptuous/error.py
index f72fbe7..7999b26 100644
--- a/voluptuous/error.py
+++ b/voluptuous/error.py
@@ -146,7 +146,7 @@ class LiteralInvalid(Invalid):


 class LengthInvalid(Invalid):
-    pass
+    """The value has an invalid length."""


 class DatetimeInvalid(Invalid):
@@ -158,22 +158,28 @@ class DateInvalid(Invalid):


 class InInvalid(Invalid):
-    pass
+    """The value is not in the required collection."""


 class NotInInvalid(Invalid):
-    pass
+    """The value is in a collection it should not be in."""


 class ExactSequenceInvalid(Invalid):
-    pass
+    """The sequence does not match exactly."""


 class NotEnoughValid(Invalid):
     """The value did not pass enough validations."""
-    pass
+    def __init__(self, msg: str, min_valid: int, actual_valid: int, path: typing.Optional[typing.List[typing.Hashable]] = None):
+        super().__init__(msg, path)
+        self.min_valid = min_valid
+        self.actual_valid = actual_valid


 class TooManyValid(Invalid):
     """The value passed more than expected validations."""
-    pass
+    def __init__(self, msg: str, max_valid: int, actual_valid: int, path: typing.Optional[typing.List[typing.Hashable]] = None):
+        super().__init__(msg, path)
+        self.max_valid = max_valid
+        self.actual_valid = actual_valid
diff --git a/voluptuous/humanize.py b/voluptuous/humanize.py
index 2902871..7776e89 100644
--- a/voluptuous/humanize.py
+++ b/voluptuous/humanize.py
@@ -11,4 +11,32 @@ def humanize_error(data, validation_error: Invalid, max_sub_error_length:
     Invalid and MultipleInvalid do not include the offending value in error messages,
     and MultipleInvalid.__str__ only provides the first error.
     """
-    pass
+    if isinstance(validation_error, MultipleInvalid):
+        errors = validation_error.errors
+    else:
+        errors = [validation_error]
+
+    error_messages = []
+    for error in errors:
+        path = _format_path(error.path)
+        value = _get_value_from_path(data, error.path)
+        error_message = f"Error at {path}: {error}"
+        if value is not None:
+            truncated_value = str(value)[:max_sub_error_length]
+            if len(str(value)) > max_sub_error_length:
+                truncated_value += "..."
+            error_message += f" (got {truncated_value})"
+        error_messages.append(error_message)
+
+    return "\n".join(error_messages)
+
+def _format_path(path):
+    return ".".join(str(p) for p in path) if path else "root"
+
+def _get_value_from_path(data, path):
+    for key in path:
+        if isinstance(data, (dict, list)) and key in data:
+            data = data[key]
+        else:
+            return None
+    return data
diff --git a/voluptuous/schema_builder.py b/voluptuous/schema_builder.py
index de2b53c..57ef356 100644
--- a/voluptuous/schema_builder.py
+++ b/voluptuous/schema_builder.py
@@ -113,7 +113,27 @@ class Schema(object):

         Note: only very basic inference is supported.
         """
-        pass
+        def infer_type(value):
+            if isinstance(value, dict):
+                return {k: infer_type(v) for k, v in value.items()}
+            elif isinstance(value, list):
+                if value:
+                    return [infer_type(value[0])]
+                else:
+                    return list
+            elif isinstance(value, str):
+                return str
+            elif isinstance(value, int):
+                return int
+            elif isinstance(value, float):
+                return float
+            elif isinstance(value, bool):
+                return bool
+            else:
+                return type(value)
+
+        inferred_schema = infer_type(data)
+        return cls(inferred_schema, **kwargs)

     def __eq__(self, other):
         if not isinstance(other, Schema):
@@ -142,7 +162,58 @@ class Schema(object):

     def _compile_mapping(self, schema, invalid_msg=None):
         """Create validator for given mapping."""
-        pass
+        def validate_mapping(path, iterable, value):
+            if not isinstance(value, dict):
+                raise er.Invalid(invalid_msg or 'expected a dictionary', path)
+
+            out = {}
+            required_keys = set()
+            optional_keys = set()
+            _compile = self._compile
+            error = er.MultipleInvalid()
+
+            for key, subschema in _iterate_mapping_candidates(schema):
+                if isinstance(key, Required):
+                    required_keys.add(key.schema)
+                elif isinstance(key, Optional):
+                    optional_keys.add(key.schema)
+                else:
+                    optional_keys.add(key)
+
+            for key, val in value.items():
+                key_path = path + [key]
+                for skey, svalue in _iterate_mapping_candidates(schema):
+                    if isinstance(skey, Optional):
+                        skey = skey.schema
+                    if isinstance(skey, Required):
+                        skey = skey.schema
+                    if skey == key:
+                        try:
+                            out[key] = _compile(svalue)(key_path, value, val)
+                            break
+                        except er.Invalid as e:
+                            error.add(e)
+                else:
+                    if self.extra == PREVENT_EXTRA:
+                        error.add(er.Invalid('extra keys not allowed', key_path))
+                    elif self.extra == ALLOW_EXTRA:
+                        out[key] = val
+                    elif self.extra == REMOVE_EXTRA:
+                        pass
+                    else:
+                        raise ValueError('Invalid value for extra')
+
+            missing_required_keys = required_keys - set(out.keys())
+            if missing_required_keys:
+                error.add(er.Invalid(f'required key(s) {", ".join(repr(k) for k in missing_required_keys)} not provided',
+                                     path))
+
+            if error.errors:
+                raise error
+
+            return out
+
+        return validate_mapping

     def _compile_object(self, schema):
         """Validate an object.
@@ -162,7 +233,26 @@ class Schema(object):
             ...   validate(Structure(one='three'))

         """
-        pass
+        base = self._compile_mapping(schema, invalid_msg='object value')
+
+        def validate_object(path, iterable, value):
+            if schema.cls is not UNDEFINED and not isinstance(value, schema.cls):
+                raise er.Invalid('expected {} but got {}'.format(schema.cls, type(value)), path)
+            
+            # Convert object attributes to a dictionary
+            value_dict = {k: getattr(value, k) for k in dir(value) if not k.startswith('_')}
+            
+            # Validate the dictionary
+            result_dict = base(path, iterable, value_dict)
+            
+            # Create a new object with validated attributes
+            validated_obj = schema.cls() if schema.cls is not UNDEFINED else type(value)()
+            for k, v in result_dict.items():
+                setattr(validated_obj, k, v)
+            
+            return validated_obj
+
+        return validate_object

     def _compile_dict(self, schema):
         """Validate a dictionary.
@@ -240,7 +330,7 @@ class Schema(object):
          "expected str for dictionary value @ data['adict']['strfield']"]

         """
-        pass
+        return self._compile_mapping(schema, invalid_msg='expected a dictionary')

     def _compile_sequence(self, schema, seq_type):
         """Validate a sequence type.
@@ -255,7 +345,27 @@ class Schema(object):
         >>> validator([1])
         [1]
         """
-        pass
+        _compile = self._compile
+        seq_schema = [_compile(s) for s in schema]
+
+        def validate_sequence(path, iterable, value):
+            if not isinstance(value, seq_type):
+                raise er.Invalid('expected a {}'.format(seq_type.__name__), path)
+
+            result = []
+            for i, item in enumerate(value):
+                item_path = path + [i]
+                for validator in seq_schema:
+                    try:
+                        result.append(validator(item_path, iterable, item))
+                        break
+                    except er.Invalid:
+                        pass
+                else:
+                    raise er.Invalid('invalid value', item_path)
+            return seq_type(result)
+
+        return validate_sequence

     def _compile_tuple(self, schema):
         """Validate a tuple.
@@ -270,7 +380,7 @@ class Schema(object):
         >>> validator((1,))
         (1,)
         """
-        pass
+        return self._compile_sequence(schema, tuple)

     def _compile_list(self, schema):
         """Validate a list.
@@ -285,7 +395,7 @@ class Schema(object):
         >>> validator([1])
         [1]
         """
-        pass
+        return self._compile_sequence(schema, list)

     def _compile_set(self, schema):
         """Validate a set.
@@ -300,7 +410,26 @@ class Schema(object):
         >>> with raises(er.MultipleInvalid, 'invalid value in set'):
         ...   validator(set(['a']))
         """
-        pass
+        _compile = self._compile
+        set_schema = [_compile(s) for s in schema]
+
+        def validate_set(path, iterable, value):
+            if not isinstance(value, set):
+                raise er.Invalid('expected a set', path)
+
+            result = set()
+            for item in value:
+                for validator in set_schema:
+                    try:
+                        result.add(validator(path, iterable, item))
+                        break
+                    except er.Invalid:
+                        pass
+                else:
+                    raise er.Invalid('invalid value in set', path)
+            return result
+
+        return validate_set

     def extend(self, schema: Schemable, required: typing.Optional[bool]=
         None, extra: typing.Optional[int]=None) ->Schema:
@@ -316,7 +445,17 @@ class Schema(object):
         :param required: if set, overrides `required` of this `Schema`
         :param extra: if set, overrides `extra` of this `Schema`
         """
-        pass
+        if not isinstance(self.schema, dict) or not isinstance(schema, dict):
+            raise ValueError("Both schemas must be dictionary-based")
+
+        new_schema = self.schema.copy()
+        new_schema.update(schema)
+
+        return Schema(
+            new_schema,
+            required=self.required if required is None else required,
+            extra=self.extra if extra is None else extra
+        )


 def _compile_scalar(schema):
@@ -678,17 +817,31 @@ def message(default: typing.Optional[str]=None, cls: typing.Optional[typing
         ... except er.MultipleInvalid as e:
         ...   assert isinstance(e.errors[0], IntegerInvalid)
     """
-    pass
+    def decorator(func):
+        @wraps(func)
+        def wrapper(*args, **kwargs):
+            msg = kwargs.pop('msg', None) or default
+            clsoverride = kwargs.pop('clsoverride', None) or cls
+            try:
+                return func(*args, **kwargs)
+            except ValueError as e:
+                raise (clsoverride or er.Invalid)(msg or str(e))
+        return wrapper
+    return decorator


 def _args_to_dict(func, args):
     """Returns argument names as values as key-value pairs."""
-    pass
+    arg_count = func.__code__.co_argcount
+    arg_names = func.__code__.co_varnames[:arg_count]
+    return dict(zip(arg_names, args))


 def _merge_args_with_kwargs(args_dict, kwargs_dict):
     """Merge args with kwargs."""
-    pass
+    ret = args_dict.copy()
+    ret.update(kwargs_dict)
+    return ret


 def validate(*a, **kw) ->typing.Callable:
@@ -707,4 +860,20 @@ def validate(*a, **kw) ->typing.Callable:
         ...   return arg1 * 2

     """
-    pass
+    def validate_schema_decorator(func):
+        schema = Schema(kw) if kw else Schema(a[0])
+
+        @wraps(func)
+        def wrapper(*args, **kwargs):
+            schema_dict = _merge_args_with_kwargs(_args_to_dict(func, args), kwargs)
+            validated = schema(schema_dict)
+            result = func(**validated)
+            if '__return__' in schema.schema:
+                return_validator = schema.schema['__return__']
+                if isinstance(return_validator, Schema):
+                    return return_validator(result)
+                else:
+                    return Schema(return_validator)(result)
+            return result
+        return wrapper
+    return validate_schema_decorator
diff --git a/voluptuous/util.py b/voluptuous/util.py
index fe15b1a..a2c57d8 100644
--- a/voluptuous/util.py
+++ b/voluptuous/util.py
@@ -13,7 +13,7 @@ def Lower(v: str) ->str:
     >>> s('HI')
     'hi'
     """
-    pass
+    return v.lower()


 def Upper(v: str) ->str:
@@ -23,7 +23,7 @@ def Upper(v: str) ->str:
     >>> s('hi')
     'HI'
     """
-    pass
+    return v.upper()


 def Capitalize(v: str) ->str:
@@ -33,7 +33,7 @@ def Capitalize(v: str) ->str:
     >>> s('hello world')
     'Hello world'
     """
-    pass
+    return v.capitalize()


 def Title(v: str) ->str:
@@ -43,7 +43,7 @@ def Title(v: str) ->str:
     >>> s('hello world')
     'Hello World'
     """
-    pass
+    return v.title()


 def Strip(v: str) ->str:
@@ -53,7 +53,7 @@ def Strip(v: str) ->str:
     >>> s('  hello world  ')
     'hello world'
     """
-    pass
+    return v.strip()


 class DefaultTo(object):
diff --git a/voluptuous/validators.py b/voluptuous/validators.py
index 88b50f6..10230e1 100644
--- a/voluptuous/validators.py
+++ b/voluptuous/validators.py
@@ -41,7 +41,13 @@ def truth(f: typing.Callable) ->typing.Callable:
     >>> with raises(MultipleInvalid, 'not a valid value'):
     ...   validate('/notavaliddir')
     """
-    pass
+    @wraps(f)
+    def wrapper(v):
+        t = f(v)
+        if not t:
+            raise ValueError
+        return v
+    return wrapper


 class Coerce(object):
@@ -109,7 +115,7 @@ def IsTrue(v):
     ... except MultipleInvalid as e:
     ...   assert isinstance(e.errors[0], TrueInvalid)
     """
-    pass
+    return bool(v)


 @message('value was not false', cls=FalseInvalid)
@@ -129,7 +135,7 @@ def IsFalse(v):
     ... except MultipleInvalid as e:
     ...   assert isinstance(e.errors[0], FalseInvalid)
     """
-    pass
+    return not bool(v)


 @message('expected boolean', cls=BooleanInvalid)
@@ -153,7 +159,18 @@ def Boolean(v):
     ... except MultipleInvalid as e:
     ...   assert isinstance(e.errors[0], BooleanInvalid)
     """
-    pass
+    if isinstance(v, bool):
+        return v
+    if isinstance(v, str):
+        v = v.lower()
+        if v in ('1', 'true', 'yes', 'on', 'enable'):
+            return True
+        if v in ('0', 'false', 'no', 'off', 'disable'):
+            return False
+    try:
+        return bool(v)
+    except ValueError:
+        raise BooleanInvalid('expected boolean')


 class _WithSubValidators(object):
@@ -894,7 +911,16 @@ class Number(object):
         :param number:
         :return: tuple(precision, scale, decimal_number)
         """
-        pass
+        try:
+            decimal_num = Decimal(number)
+        except InvalidOperation:
+            raise Invalid(self.msg or f'{number} is not a valid Decimal')
+
+        sign, digits, exponent = decimal_num.as_tuple()
+        scale = -exponent if exponent < 0 else 0
+        precision = len(digits)
+
+        return precision, scale, decimal_num


 class SomeOf(_WithSubValidators):