Skip to content

Commit

Permalink
drop support for Python 3.8 and update dependencies (python-poetry#798)
Browse files Browse the repository at this point in the history
  • Loading branch information
radoering authored Dec 4, 2024
1 parent b95ec53 commit ab1bdf3
Show file tree
Hide file tree
Showing 66 changed files with 2,128 additions and 908 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ jobs:
- MacOS
- Windows
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
include:
- os: Ubuntu
python-version: pypy-3.8
python-version: pypy-3.10
fail-fast: false
defaults:
run:
Expand Down
971 changes: 511 additions & 460 deletions poetry.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ include = [
"Bug Tracker" = "https://github.com/python-poetry/poetry/issues"

[tool.poetry.dependencies]
python = "^3.8"
python = "^3.9"

[tool.poetry.group.dev.dependencies]
pre-commit = ">=2.15.0"
Expand Down Expand Up @@ -51,7 +51,7 @@ extend-exclude = [
fix = true
line-length = 88
src = ["src"]
target-version = "py38"
target-version = "py39"

[tool.ruff.lint]
extend-select = [
Expand Down
48 changes: 27 additions & 21 deletions src/poetry/core/_vendor/fastjsonschema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,22 @@
.. code-block:: bash
$ make performance
fast_compiled valid ==> 0.0464646
fast_compiled invalid ==> 0.0030227
fast_file valid ==> 0.0461219
fast_file invalid ==> 0.0030608
fast_not_compiled valid ==> 11.4627202
fast_not_compiled invalid ==> 2.5726230
jsonschema valid ==> 7.5844927
jsonschema invalid ==> 1.9204665
jsonschema_compiled valid ==> 0.6938364
jsonschema_compiled invalid ==> 0.0359244
jsonspec valid ==> 9.0715843
jsonspec invalid ==> 2.1650488
validictory valid ==> 0.4874793
validictory invalid ==> 0.0232244
fast_compiled valid ==> 0.0993900
fast_compiled invalid ==> 0.0041089
fast_compiled_without_exc valid ==> 0.0465258
fast_compiled_without_exc invalid ==> 0.0023688
fast_file valid ==> 0.0989483
fast_file invalid ==> 0.0041104
fast_not_compiled valid ==> 11.9572681
fast_not_compiled invalid ==> 2.9512092
jsonschema valid ==> 5.2233240
jsonschema invalid ==> 1.3227916
jsonschema_compiled valid ==> 0.4447982
jsonschema_compiled invalid ==> 0.0231333
jsonspec valid ==> 4.1450569
jsonspec invalid ==> 1.0485777
validictory valid ==> 0.2730411
validictory invalid ==> 0.0183669
This library follows and implements `JSON schema draft-04, draft-06, and draft-07
<http://json-schema.org>`_. Sometimes it's not perfectly clear, so I recommend also
Expand Down Expand Up @@ -123,7 +125,7 @@
)


def validate(definition, data, handlers={}, formats={}, use_default=True, use_formats=True):
def validate(definition, data, handlers={}, formats={}, use_default=True, use_formats=True, detailed_exceptions=True):
"""
Validation function for lazy programmers or for use cases when you need
to call validation only once, so you do not have to compile it first.
Expand All @@ -139,12 +141,12 @@ def validate(definition, data, handlers={}, formats={}, use_default=True, use_fo
Preferred is to use :any:`compile` function.
"""
return compile(definition, handlers, formats, use_default, use_formats)(data)
return compile(definition, handlers, formats, use_default, use_formats, detailed_exceptions)(data)


#TODO: Change use_default to False when upgrading to version 3.
# pylint: disable=redefined-builtin,dangerous-default-value,exec-used
def compile(definition, handlers={}, formats={}, use_default=True, use_formats=True):
def compile(definition, handlers={}, formats={}, use_default=True, use_formats=True, detailed_exceptions=True):
"""
Generates validation function for validating JSON schema passed in ``definition``.
Example:
Expand Down Expand Up @@ -200,13 +202,16 @@ def compile(definition, handlers={}, formats={}, use_default=True, use_formats=T
off by passing `use_formats=False`. When disabled, custom formats are
disabled as well. (Added in 2.19.0.)
If you don't need detailed exceptions, you can turn the details off and gain
additional performance by passing `detailed_exceptions=False`.
Exception :any:`JsonSchemaDefinitionException` is raised when generating the
code fails (bad definition).
Exception :any:`JsonSchemaValueException` is raised from generated function when
validation fails (data do not follow the definition).
"""
resolver, code_generator = _factory(definition, handlers, formats, use_default, use_formats)
resolver, code_generator = _factory(definition, handlers, formats, use_default, use_formats, detailed_exceptions)
global_state = code_generator.global_state
# Do not pass local state so it can recursively call itself.
exec(code_generator.func_code, global_state)
Expand All @@ -217,7 +222,7 @@ def compile(definition, handlers={}, formats={}, use_default=True, use_formats=T


# pylint: disable=dangerous-default-value
def compile_to_code(definition, handlers={}, formats={}, use_default=True, use_formats=True):
def compile_to_code(definition, handlers={}, formats={}, use_default=True, use_formats=True, detailed_exceptions=True):
"""
Generates validation code for validating JSON schema passed in ``definition``.
Example:
Expand All @@ -240,22 +245,23 @@ def compile_to_code(definition, handlers={}, formats={}, use_default=True, use_f
Exception :any:`JsonSchemaDefinitionException` is raised when generating the
code fails (bad definition).
"""
_, code_generator = _factory(definition, handlers, formats, use_default, use_formats)
_, code_generator = _factory(definition, handlers, formats, use_default, use_formats, detailed_exceptions)
return (
'VERSION = "' + VERSION + '"\n' +
code_generator.global_state_code + '\n' +
code_generator.func_code
)


def _factory(definition, handlers, formats={}, use_default=True, use_formats=True):
def _factory(definition, handlers, formats={}, use_default=True, use_formats=True, detailed_exceptions=True):
resolver = RefResolver.from_schema(definition, handlers=handlers, store={})
code_generator = _get_code_generator_class(definition)(
definition,
resolver=resolver,
formats=formats,
use_default=use_default,
use_formats=use_formats,
detailed_exceptions=detailed_exceptions,
)
return resolver, code_generator

Expand Down
27 changes: 15 additions & 12 deletions src/poetry/core/_vendor/fastjsonschema/draft04.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ class CodeGeneratorDraft04(CodeGenerator):
# library. Some regexps are not 100% precise but good enough, fast and without dependencies.
FORMAT_REGEXS = {
'date-time': r'^\d{4}-[01]\d-[0-3]\d(t|T)[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:[+-][0-2]\d:[0-5]\d|[+-][0-2]\d[0-5]\d|z|Z)\Z',
'email': r'^[^@]+@[^@]+\.[^@]+\Z',
'email': r'^(?!.*\.\..*@)[^@.][^@]*(?<!\.)@[^@]+\.[^@]+\Z',
'hostname': r'^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9])\Z',
'ipv4': r'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\Z',
'ipv4': r'^((25[0-5]|2[0-4][0-9]|1?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\Z',
'ipv6': r'^(?:(?:[0-9A-Fa-f]{1,4}:){6}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|::(?:[0-9A-Fa-f]{1,4}:){5}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,4}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){,6}[0-9A-Fa-f]{1,4})?::)\Z',
'uri': r'^\w+:(\/?\/?)[^\s]+\Z',
}

def __init__(self, definition, resolver=None, formats={}, use_default=True, use_formats=True):
super().__init__(definition, resolver)
def __init__(self, definition, resolver=None, formats={}, use_default=True, use_formats=True, detailed_exceptions=True):
super().__init__(definition, resolver, detailed_exceptions)
self._custom_formats = formats
self._use_formats = use_formats
self._use_default = use_default
Expand Down Expand Up @@ -211,8 +211,7 @@ def generate_not(self):
elif not_definition is False:
return
elif not not_definition:
with self.l('if {}:', self._variable):
self.exc('{name} must NOT match a disallowed definition', rule='not')
self.exc('{name} must NOT match a disallowed definition', rule='not')
else:
with self.l('try:', optimize=False):
self.generate_func_code_block(not_definition, self._variable, self._variable_name)
Expand All @@ -223,15 +222,15 @@ def generate_not(self):
def generate_min_length(self):
with self.l('if isinstance({variable}, str):'):
self.create_variable_with_length()
if not isinstance(self._definition['minLength'], int):
if not isinstance(self._definition['minLength'], (int, float)):
raise JsonSchemaDefinitionException('minLength must be a number')
with self.l('if {variable}_len < {minLength}:'):
self.exc('{name} must be longer than or equal to {minLength} characters', rule='minLength')

def generate_max_length(self):
with self.l('if isinstance({variable}, str):'):
self.create_variable_with_length()
if not isinstance(self._definition['maxLength'], int):
if not isinstance(self._definition['maxLength'], (int, float)):
raise JsonSchemaDefinitionException('maxLength must be a number')
with self.l('if {variable}_len > {maxLength}:'):
self.exc('{name} must be shorter than or equal to {maxLength} characters', rule='maxLength')
Expand Down Expand Up @@ -272,6 +271,7 @@ def generate_format(self):
self._generate_format(format_, format_ + '_re_pattern', format_regex)
# Format regex is used only in meta schemas.
elif format_ == 'regex':
self._extra_imports_lines = ['import re']
with self.l('try:', optimize=False):
self.l('re.compile({variable})')
with self.l('except Exception:'):
Expand Down Expand Up @@ -321,11 +321,14 @@ def generate_multiple_of(self):
self.l('quotient = {variable} / {multipleOf}')
with self.l('if int(quotient) != quotient:'):
self.exc('{name} must be multiple of {multipleOf}', rule='multipleOf')
# For example, 1e308 / 0.123456789
with self.l('if {variable} / {multipleOf} == float("inf"):'):
self.exc('inifinity reached', rule='multipleOf')

def generate_min_items(self):
self.create_variable_is_list()
with self.l('if {variable}_is_list:'):
if not isinstance(self._definition['minItems'], int):
if not isinstance(self._definition['minItems'], (int, float)):
raise JsonSchemaDefinitionException('minItems must be a number')
self.create_variable_with_length()
with self.l('if {variable}_len < {minItems}:'):
Expand All @@ -334,7 +337,7 @@ def generate_min_items(self):
def generate_max_items(self):
self.create_variable_is_list()
with self.l('if {variable}_is_list:'):
if not isinstance(self._definition['maxItems'], int):
if not isinstance(self._definition['maxItems'], (int, float)):
raise JsonSchemaDefinitionException('maxItems must be a number')
self.create_variable_with_length()
with self.l('if {variable}_len > {maxItems}:'):
Expand Down Expand Up @@ -440,7 +443,7 @@ def generate_items(self):
def generate_min_properties(self):
self.create_variable_is_dict()
with self.l('if {variable}_is_dict:'):
if not isinstance(self._definition['minProperties'], int):
if not isinstance(self._definition['minProperties'], (int, float)):
raise JsonSchemaDefinitionException('minProperties must be a number')
self.create_variable_with_length()
with self.l('if {variable}_len < {minProperties}:'):
Expand All @@ -449,7 +452,7 @@ def generate_min_properties(self):
def generate_max_properties(self):
self.create_variable_is_dict()
with self.l('if {variable}_is_dict:'):
if not isinstance(self._definition['maxProperties'], int):
if not isinstance(self._definition['maxProperties'], (int, float)):
raise JsonSchemaDefinitionException('maxProperties must be a number')
self.create_variable_with_length()
with self.l('if {variable}_len > {maxProperties}:'):
Expand Down
4 changes: 2 additions & 2 deletions src/poetry/core/_vendor/fastjsonschema/draft06.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class CodeGeneratorDraft06(CodeGeneratorDraft04):
),
})

def __init__(self, definition, resolver=None, formats={}, use_default=True, use_formats=True):
super().__init__(definition, resolver, formats, use_default, use_formats)
def __init__(self, definition, resolver=None, formats={}, use_default=True, use_formats=True, detailed_exceptions=True):
super().__init__(definition, resolver, formats, use_default, use_formats, detailed_exceptions)
self._json_keywords_to_function.update((
('exclusiveMinimum', self.generate_exclusive_minimum),
('exclusiveMaximum', self.generate_exclusive_maximum),
Expand Down
8 changes: 4 additions & 4 deletions src/poetry/core/_vendor/fastjsonschema/draft07.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

class CodeGeneratorDraft07(CodeGeneratorDraft06):
FORMAT_REGEXS = dict(CodeGeneratorDraft06.FORMAT_REGEXS, **{
'date': r'^(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})\Z',
'date': r'^(?P<year>\d{4})-(?P<month>(0[1-9]|1[0-2]))-(?P<day>(0[1-9]|[12]\d|3[01]))\Z',
'iri': r'^\w+:(\/?\/?)[^\s]+\Z',
'iri-reference': r'^(\w+:(\/?\/?))?[^#\\\s]*(#[^\\\s]*)?\Z',
'idn-email': r'^[^@]+@[^@]+\.[^@]+\Z',
#'idn-hostname': r'',
'idn-hostname': r'^(?!-)(xn--)?[a-zA-Z0-9][a-zA-Z0-9-_]{0,61}[a-zA-Z0-9]{0,1}\.(?!-)(xn--)?([a-zA-Z0-9\-]{1,50}|[a-zA-Z0-9-]{1,30}\.[a-zA-Z]{2,})$',
'relative-json-pointer': r'^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)\Z',
#'regex': r'',
'time': (
Expand All @@ -17,8 +17,8 @@ class CodeGeneratorDraft07(CodeGeneratorDraft06):
),
})

def __init__(self, definition, resolver=None, formats={}, use_default=True, use_formats=True):
super().__init__(definition, resolver, formats, use_default, use_formats)
def __init__(self, definition, resolver=None, formats={}, use_default=True, use_formats=True, detailed_exceptions=True):
super().__init__(definition, resolver, formats, use_default, use_formats, detailed_exceptions)
# pylint: disable=duplicate-code
self._json_keywords_to_function.update((
('if', self.generate_if_then_else),
Expand Down
7 changes: 6 additions & 1 deletion src/poetry/core/_vendor/fastjsonschema/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ class CodeGenerator:

INDENT = 4 # spaces

def __init__(self, definition, resolver=None):
def __init__(self, definition, resolver=None, detailed_exceptions=True):
self._code = []
self._compile_regexps = {}
self._custom_formats = {}
self._detailed_exceptions = detailed_exceptions

# Any extra library should be here to be imported only once.
# Lines are imports to be printed in the file and objects
Expand Down Expand Up @@ -266,6 +267,10 @@ def exc(self, msg, *args, append_to_msg=None, rule=None):
"""
Short-cut for creating raising exception in the code.
"""
if not self._detailed_exceptions:
self.l('raise JsonSchemaValueException("'+msg+'")', *args)
return

arg = '"'+msg+'"'
if append_to_msg:
arg += ' + (' + append_to_msg + ')'
Expand Down
2 changes: 2 additions & 0 deletions src/poetry/core/_vendor/fastjsonschema/ref_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ def resolve_remote(uri, handlers):
result = json.loads(req.read().decode(encoding),)
except ValueError as exc:
raise JsonSchemaDefinitionException('{} failed to decode: {}'.format(uri, exc))
finally:
req.close()
return result


Expand Down
2 changes: 1 addition & 1 deletion src/poetry/core/_vendor/fastjsonschema/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = '2.20.0'
VERSION = '2.21.1'
2 changes: 1 addition & 1 deletion src/poetry/core/_vendor/lark/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from .utils import logger
from .visitors import Discard, Transformer, Transformer_NonRecursive, Visitor, v_args

__version__: str = "1.1.9"
__version__: str = "1.2.2"

__all__ = (
"GrammarError",
Expand Down
5 changes: 1 addition & 4 deletions src/poetry/core/_vendor/lark/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@
from .lexer import Lexer
from .grammar import Rule
from typing import Union, Type
if sys.version_info >= (3, 8):
from typing import Literal
else:
from typing_extensions import Literal
from typing import Literal
if sys.version_info >= (3, 10):
from typing import TypeAlias
else:
Expand Down
Loading

0 comments on commit ab1bdf3

Please sign in to comment.