Skip to content

Commit

Permalink
Merge branch 'master' into 'gh-pages'
Browse files Browse the repository at this point in the history
  • Loading branch information
spacegaier committed Feb 3, 2024
2 parents 1ced531 + 1fcf849 commit 6925eae
Show file tree
Hide file tree
Showing 17 changed files with 1,165 additions and 853 deletions.
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Add linters configuration, reformat whole code (#503)
c5189d2b6f9dfb3016f094561afcfb5584d143ad
3 changes: 2 additions & 1 deletion .github/ISSUE_TEMPLATE/contributions-only.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ labels: ''
assignees: ''

---

<!--
# CONTRIBUTIONS ONLY
**What does this mean?** I do not have time to fix issues myself. The only way fixes or new features will be added is by people submitting PRs.
**Current status.** Voluptuous is largely feature stable. There hasn't been a need to add new features in a while, but there are some bugs that should be fixed.
**Why?** I no longer use Voluptuous personally (in fact I no longer regularly write Python code). Rather than leave the project in a limbo of people filing issues and wondering why they're note being worked on, I believe this notice will more clearly set expectations.
-->
8 changes: 6 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ jobs:
fail-fast: false
matrix:
include:
- { python-version: "3.10", session: "flake8" }
- { python-version: "3.11", session: "black" }
- { python-version: "3.11", session: "flake8" }
- { python-version: "3.11", session: "mypy" }
- { python-version: "3.11", session: "isort" }
- { python-version: "3.12", session: "py312" }
- { python-version: "3.11", session: "py311" }
- { python-version: "3.10", session: "py310" }
- { python-version: "3.9", session: "py39" }
- { python-version: "3.8", session: "py38" }
- { python-version: "3.7", session: "py37" }

steps:
- name: Check out the repository
Expand Down
20 changes: 0 additions & 20 deletions .travis.yml

This file was deleted.

44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
# Changelog

<<<<<<< HEAD
=======
## [0.14.2]

**New**:
* [#507](https://github.com/alecthomas/voluptuous/pull/507): docs: document description field of Marker

**Fixes**:
* [#506](https://github.com/alecthomas/voluptuous/pull/506): fix: allow unsortable containers in In and NotIn validators (fixes [#451](https://github.com/alecthomas/voluptuous/issues/451)) (bug introduced in 0.12.1)
* [#488](https://github.com/alecthomas/voluptuous/pull/488): fix(typing): fix type hint for Coerce type param (bug introduced in 0.14.0)
* [#497](https://github.com/alecthomas/voluptuous/pull/497): fix(typing): allow path to be a list of strings, integers or any other hashables (bug introduced in 0.14.0)

**Changes**:
* [#499](https://github.com/alecthomas/voluptuous/pull/499): support: drop support for python 3.7
* [#501](https://github.com/alecthomas/voluptuous/pull/501): support: run tests on python 3.11
* [#502](https://github.com/alecthomas/voluptuous/pull/502): support: run tests on python 3.12
* [#495](https://github.com/alecthomas/voluptuous/pull/495): refactor: drop duplicated type checks in Schema._compile
* [#500](https://github.com/alecthomas/voluptuous/pull/500): refactor: fix few tests, use pytest.raises, extend raises helper
* [#503](https://github.com/alecthomas/voluptuous/pull/503): refactor: Add linters configuration, reformat whole code

## [0.14.1]

**Changes**:
* [#487](https://github.com/alecthomas/voluptuous/pull/487): Add pytest.ini and tox.ini to sdist
* [#494](https://github.com/alecthomas/voluptuous/pull/494): Add `python_requires` so package installers know requirement is >= 3.7

## [0.14.0]

**Fixes**:
* [#470](https://github.com/alecthomas/voluptuous/pull/470): Fix a few code comment typos
* [#472](https://github.com/alecthomas/voluptuous/pull/472): Change to SPDX conform license string


**New**:
* [#475](https://github.com/alecthomas/voluptuous/pull/475): Add typing information
* [#478](https://github.com/alecthomas/voluptuous/pull/478): Fix new type hint of schemas, for example for `Required('key')`
* [#486](https://github.com/alecthomas/voluptuous/pull/486): Fix new type hints and enable `mypy`
* [#479](https://github.com/alecthomas/voluptuous/pull/479): Allow error reporting on keys

**Changes**:
* [#476](https://github.com/alecthomas/voluptuous/pull/476): Set static PyPI project description
* [#482](https://github.com/alecthomas/voluptuous/pull/482): Remove Travis build status badge

>>>>>>> master
## [0.13.1]

**Fixes**:
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ include *.md
include COPYING
include voluptuous/tests/*.py
include voluptuous/tests/*.md
include pyproject.toml
include tox.ini
18 changes: 18 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[tool.black]
target-version = ["py38", "py39", "py310", "py311", "py312"]
skip-string-normalization = true

[tool.isort]
skip_gitignore = true
profile = "black"
multi_line_output = 5

[tool.mypy]
python_version = "3.8"

warn_unused_ignores = true

[tool.pytest.ini_options]
python_files = "tests.py"
testpaths = "voluptuous/tests"
addopts = "--doctest-glob=*.md -v"
11 changes: 11 additions & 0 deletions renovate.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
$schema: "https://docs.renovatebot.com/renovate-schema.json",
extends: [
"config:recommended",
":semanticCommits",
":semanticCommitTypeAll(chore)",
":semanticCommitScope(deps)",
"group:allNonMajor",
"schedule:earlyMondays", // Run once a week.
],
}
14 changes: 7 additions & 7 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import io
import sys

from setuptools import setup

import sys
import io
sys.path.insert(0, '.')
version = __import__('voluptuous').__version__

Expand All @@ -26,18 +27,17 @@
},
author='Alec Thomas',
author_email='[email protected]',
python_requires=">=3.8",
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
]
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
],
)
22 changes: 19 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[tox]
envlist = flake8,py37,py38,py39,py310
envlist = flake8,black,py38,py39,py310,py311,py312

[flake8]
; E501: line too long (X > 79 characters)
; W503 line break before binary operator
ignore = E501,W503
; E203, E704: black-related ignores (see https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#flake8)
extend-ignore = E203, E501, E704
exclude = .tox,.venv,build,*.egg

[testenv]
Expand All @@ -22,3 +22,19 @@ commands =
[testenv:flake8]
deps = flake8
commands = flake8 --doctests setup.py voluptuous

[testenv:mypy]
deps =
mypy
pytest
commands = mypy voluptuous

[testenv:black]
deps =
black
commands = black --check .

[testenv:isort]
deps =
isort
commands = isort --check .
11 changes: 7 additions & 4 deletions voluptuous/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# flake8: noqa

# fmt: off
from voluptuous.schema_builder import *
from voluptuous.validators import *
from voluptuous.util import *
from voluptuous.error import *
from voluptuous.validators import *

from voluptuous.error import * # isort: skip

# fmt: on

__version__ = '0.13.1'
__version__ = '0.14.2'
__author__ = 'alecthomas'
36 changes: 27 additions & 9 deletions voluptuous/error.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# fmt: off
import typing

# fmt: on


class Error(Exception):
"""Base validation exception."""
Expand All @@ -19,26 +22,39 @@ class Invalid(Error):
"""

def __init__(self, message: str, path: typing.Optional[typing.List[str]] = None, error_message: typing.Optional[str] = None, error_type: typing.Optional[str] = None) -> None:
def __init__(
self,
message: str,
path: typing.Optional[typing.List[typing.Hashable]] = None,
error_message: typing.Optional[str] = None,
error_type: typing.Optional[str] = None,
) -> None:
Error.__init__(self, message)
self.path = path or []
self.error_message = error_message or message
self._path = path or []
self._error_message = error_message or message
self.error_type = error_type

@property
def msg(self) -> str:
return self.args[0]

@property
def path(self) -> typing.List[typing.Hashable]:
return self._path

@property
def error_message(self) -> str:
return self._error_message

def __str__(self) -> str:
path = ' @ data[%s]' % ']['.join(map(repr, self.path)) \
if self.path else ''
path = ' @ data[%s]' % ']['.join(map(repr, self.path)) if self.path else ''
output = Exception.__str__(self)
if self.error_type:
output += ' for ' + self.error_type
return output + path

def prepend(self, path: typing.List[str]) -> None:
self.path = path + self.path
def prepend(self, path: typing.List[typing.Hashable]) -> None:
self._path = path + self.path


class MultipleInvalid(Invalid):
Expand All @@ -53,7 +69,7 @@ def msg(self) -> str:
return self.errors[0].msg

@property
def path(self) -> typing.List[str]:
def path(self) -> typing.List[typing.Hashable]:
return self.errors[0].path

@property
Expand All @@ -66,7 +82,7 @@ def add(self, error: Invalid) -> None:
def __str__(self) -> str:
return str(self.errors[0])

def prepend(self, path: typing.List[str]) -> None:
def prepend(self, path: typing.List[typing.Hashable]) -> None:
for error in self.errors:
error.prepend(path)

Expand Down Expand Up @@ -193,9 +209,11 @@ class ExactSequenceInvalid(Invalid):

class NotEnoughValid(Invalid):
"""The value did not pass enough validations."""

pass


class TooManyValid(Invalid):
"""The value passed more than expected validations."""

pass
38 changes: 25 additions & 13 deletions voluptuous/humanize.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# fmt: off
import typing

from voluptuous import Invalid, MultipleInvalid
from voluptuous.error import Error
from voluptuous.schema_builder import Schema
import typing

# fmt: on

MAX_VALIDATION_ERROR_ITEM_LENGTH = 500


IndexT = typing.TypeVar("IndexT")


def _nested_getitem(data: typing.Dict[IndexT, typing.Any], path: typing.List[IndexT]) -> typing.Optional[typing.Any]:
def _nested_getitem(
data: typing.Any, path: typing.List[typing.Hashable]
) -> typing.Optional[typing.Any]:
for item_index in path:
try:
data = data[item_index]
Expand All @@ -21,24 +23,34 @@ def _nested_getitem(data: typing.Dict[IndexT, typing.Any], path: typing.List[Ind
return data


def humanize_error(data, validation_error: Invalid, max_sub_error_length: int = MAX_VALIDATION_ERROR_ITEM_LENGTH) -> str:
""" Provide a more helpful + complete validation error message than that provided automatically
def humanize_error(
data,
validation_error: Invalid,
max_sub_error_length: int = MAX_VALIDATION_ERROR_ITEM_LENGTH,
) -> str:
"""Provide a more helpful + complete validation error message than that provided automatically
Invalid and MultipleInvalid do not include the offending value in error messages,
and MultipleInvalid.__str__ only provides the first error.
"""
if isinstance(validation_error, MultipleInvalid):
return '\n'.join(sorted(
humanize_error(data, sub_error, max_sub_error_length)
for sub_error in validation_error.errors
))
return '\n'.join(
sorted(
humanize_error(data, sub_error, max_sub_error_length)
for sub_error in validation_error.errors
)
)
else:
offending_item_summary = repr(_nested_getitem(data, validation_error.path))
if len(offending_item_summary) > max_sub_error_length:
offending_item_summary = offending_item_summary[:max_sub_error_length - 3] + '...'
offending_item_summary = (
offending_item_summary[: max_sub_error_length - 3] + '...'
)
return '%s. Got %s' % (validation_error, offending_item_summary)


def validate_with_humanized_errors(data, schema: Schema, max_sub_error_length: int = MAX_VALIDATION_ERROR_ITEM_LENGTH) -> typing.Any:
def validate_with_humanized_errors(
data, schema: Schema, max_sub_error_length: int = MAX_VALIDATION_ERROR_ITEM_LENGTH
) -> typing.Any:
try:
return schema(data)
except (Invalid, MultipleInvalid) as e:
Expand Down
Loading

0 comments on commit 6925eae

Please sign in to comment.