aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2024-04-05 15:19:56 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2024-04-05 15:32:02 +0300
commitaec95948f1137dd6c659d7160160b05cfa11e0c7 (patch)
treec22e5e1d22f7954d33208806d2cdf5ac65d8ff38
parent8c029b63ffc0e0f522561452134e7f01d5db1844 (diff)
downloadydb-aec95948f1137dd6c659d7160160b05cfa11e0c7.tar.gz
Intermediate changes
-rw-r--r--contrib/python/pytest-mock/py3/.dist-info/METADATA16
-rw-r--r--contrib/python/pytest-mock/py3/pytest_mock/__init__.py8
-rw-r--r--contrib/python/pytest-mock/py3/pytest_mock/_version.py4
-rw-r--r--contrib/python/pytest-mock/py3/pytest_mock/plugin.py165
-rw-r--r--contrib/python/pytest-mock/py3/ya.make2
-rw-r--r--yt/python/yt/type_info/__init__.py2
-rw-r--r--yt/python/yt/type_info/type_base.py14
-rw-r--r--yt/python/yt/type_info/typing.py40
8 files changed, 154 insertions, 97 deletions
diff --git a/contrib/python/pytest-mock/py3/.dist-info/METADATA b/contrib/python/pytest-mock/py3/.dist-info/METADATA
index 2d35e95446..1ffa498c29 100644
--- a/contrib/python/pytest-mock/py3/.dist-info/METADATA
+++ b/contrib/python/pytest-mock/py3/.dist-info/METADATA
@@ -1,38 +1,36 @@
Metadata-Version: 2.1
Name: pytest-mock
-Version: 3.12.0
+Version: 3.14.0
Summary: Thin-wrapper around the mock package for easier use with pytest
-Home-page: https://github.com/pytest-dev/pytest-mock/
-Author: Bruno Oliveira
-Author-email: nicoddemus@gmail.com
+Author-email: Bruno Oliveira <nicoddemus@gmail.com>
License: MIT
+Project-URL: Homepage, https://github.com/pytest-dev/pytest-mock/
Project-URL: Documentation, https://pytest-mock.readthedocs.io/en/latest/
Project-URL: Changelog, https://pytest-mock.readthedocs.io/en/latest/changelog.html
Project-URL: Source, https://github.com/pytest-dev/pytest-mock/
Project-URL: Tracker, https://github.com/pytest-dev/pytest-mock/issues
-Keywords: pytest mock
-Platform: any
+Keywords: pytest,mock
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: Pytest
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
-Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.8
Description-Content-Type: text/x-rst
License-File: LICENSE
-Requires-Dist: pytest >=5.0
+Requires-Dist: pytest >=6.2.5
Provides-Extra: dev
Requires-Dist: pre-commit ; extra == 'dev'
-Requires-Dist: tox ; extra == 'dev'
Requires-Dist: pytest-asyncio ; extra == 'dev'
+Requires-Dist: tox ; extra == 'dev'
===========
pytest-mock
diff --git a/contrib/python/pytest-mock/py3/pytest_mock/__init__.py b/contrib/python/pytest-mock/py3/pytest_mock/__init__.py
index 0afa47c0c1..75fd27afde 100644
--- a/contrib/python/pytest-mock/py3/pytest_mock/__init__.py
+++ b/contrib/python/pytest-mock/py3/pytest_mock/__init__.py
@@ -1,18 +1,22 @@
+from pytest_mock.plugin import AsyncMockType
+from pytest_mock.plugin import MockerFixture
+from pytest_mock.plugin import MockType
+from pytest_mock.plugin import PytestMockWarning
from pytest_mock.plugin import class_mocker
from pytest_mock.plugin import mocker
-from pytest_mock.plugin import MockerFixture
from pytest_mock.plugin import module_mocker
from pytest_mock.plugin import package_mocker
from pytest_mock.plugin import pytest_addoption
from pytest_mock.plugin import pytest_configure
-from pytest_mock.plugin import PytestMockWarning
from pytest_mock.plugin import session_mocker
MockFixture = MockerFixture # backward-compatibility only (#204)
__all__ = [
+ "AsyncMockType",
"MockerFixture",
"MockFixture",
+ "MockType",
"PytestMockWarning",
"pytest_addoption",
"pytest_configure",
diff --git a/contrib/python/pytest-mock/py3/pytest_mock/_version.py b/contrib/python/pytest-mock/py3/pytest_mock/_version.py
index 9e1a89958d..431bd6d819 100644
--- a/contrib/python/pytest-mock/py3/pytest_mock/_version.py
+++ b/contrib/python/pytest-mock/py3/pytest_mock/_version.py
@@ -12,5 +12,5 @@ __version__: str
__version_tuple__: VERSION_TUPLE
version_tuple: VERSION_TUPLE
-__version__ = version = '3.12.0'
-__version_tuple__ = version_tuple = (3, 12, 0)
+__version__ = version = '3.14.0'
+__version_tuple__ = version_tuple = (3, 14, 0)
diff --git a/contrib/python/pytest-mock/py3/pytest_mock/plugin.py b/contrib/python/pytest-mock/py3/pytest_mock/plugin.py
index 673f98bffb..1e0a0b2025 100644
--- a/contrib/python/pytest-mock/py3/pytest_mock/plugin.py
+++ b/contrib/python/pytest-mock/py3/pytest_mock/plugin.py
@@ -2,23 +2,25 @@ import asyncio
import builtins
import functools
import inspect
-import sys
import unittest.mock
import warnings
+from dataclasses import dataclass
+from dataclasses import field
from typing import Any
from typing import Callable
-from typing import cast
from typing import Dict
from typing import Generator
from typing import Iterable
+from typing import Iterator
from typing import List
from typing import Mapping
from typing import Optional
-from typing import overload
from typing import Tuple
from typing import Type
from typing import TypeVar
from typing import Union
+from typing import cast
+from typing import overload
import pytest
@@ -27,22 +29,58 @@ from ._util import parse_ini_boolean
_T = TypeVar("_T")
-if sys.version_info >= (3, 8):
- AsyncMockType = unittest.mock.AsyncMock
- MockType = Union[
- unittest.mock.MagicMock,
- unittest.mock.AsyncMock,
- unittest.mock.NonCallableMagicMock,
- ]
-else:
- AsyncMockType = Any
- MockType = Union[unittest.mock.MagicMock, unittest.mock.NonCallableMagicMock]
+AsyncMockType = unittest.mock.AsyncMock
+MockType = Union[
+ unittest.mock.MagicMock,
+ unittest.mock.AsyncMock,
+ unittest.mock.NonCallableMagicMock,
+]
class PytestMockWarning(UserWarning):
"""Base class for all warnings emitted by pytest-mock."""
+@dataclass
+class MockCacheItem:
+ mock: MockType
+ patch: Optional[Any] = None
+
+
+@dataclass
+class MockCache:
+ """
+ Cache MagicMock and Patcher instances so we can undo them later.
+ """
+
+ cache: List[MockCacheItem] = field(default_factory=list)
+
+ def _find(self, mock: MockType) -> MockCacheItem:
+ for mock_item in self.cache:
+ if mock_item.mock is mock:
+ return mock_item
+ raise ValueError("This mock object is not registered")
+
+ def add(self, mock: MockType, **kwargs: Any) -> MockCacheItem:
+ self.cache.append(MockCacheItem(mock=mock, **kwargs))
+ return self.cache[-1]
+
+ def remove(self, mock: MockType) -> None:
+ mock_item = self._find(mock)
+ if mock_item.patch:
+ mock_item.patch.stop()
+ self.cache.remove(mock_item)
+
+ def clear(self) -> None:
+ for mock_item in reversed(self.cache):
+ if mock_item.patch is not None:
+ mock_item.patch.stop()
+ self.cache.clear()
+
+ def __iter__(self) -> Iterator[MockCacheItem]:
+ return iter(self.cache)
+
+
class MockerFixture:
"""
Fixture that provides the same interface to functions in the mock module,
@@ -50,11 +88,9 @@ class MockerFixture:
"""
def __init__(self, config: Any) -> None:
- self._patches_and_mocks: List[Tuple[Any, unittest.mock.MagicMock]] = []
+ self._mock_cache: MockCache = MockCache()
self.mock_module = mock_module = get_mock_module(config)
- self.patch = self._Patcher(
- self._patches_and_mocks, mock_module
- ) # type: MockerFixture._Patcher
+ self.patch = self._Patcher(self._mock_cache, mock_module) # type: MockerFixture._Patcher
# aliases for convenience
self.Mock = mock_module.Mock
self.MagicMock = mock_module.MagicMock
@@ -77,7 +113,7 @@ class MockerFixture:
m: MockType = self.mock_module.create_autospec(
spec, spec_set, instance, **kwargs
)
- self._patches_and_mocks.append((None, m))
+ self._mock_cache.add(m)
return m
def resetall(
@@ -95,37 +131,33 @@ class MockerFixture:
else:
supports_reset_mock_with_args = (self.Mock,)
- for p, m in self._patches_and_mocks:
+ for mock_item in self._mock_cache:
# See issue #237.
- if not hasattr(m, "reset_mock"):
+ if not hasattr(mock_item.mock, "reset_mock"):
continue
- if isinstance(m, supports_reset_mock_with_args):
- m.reset_mock(return_value=return_value, side_effect=side_effect)
+ # NOTE: The mock may be a dictionary
+ if hasattr(mock_item.mock, "spy_return_list"):
+ mock_item.mock.spy_return_list = []
+ if isinstance(mock_item.mock, supports_reset_mock_with_args):
+ mock_item.mock.reset_mock(
+ return_value=return_value, side_effect=side_effect
+ )
else:
- m.reset_mock()
+ mock_item.mock.reset_mock()
def stopall(self) -> None:
"""
Stop all patchers started by this fixture. Can be safely called multiple
times.
"""
- for p, m in reversed(self._patches_and_mocks):
- if p is not None:
- p.stop()
- self._patches_and_mocks.clear()
+ self._mock_cache.clear()
def stop(self, mock: unittest.mock.MagicMock) -> None:
"""
Stops a previous patch or spy call by passing the ``MagicMock`` object
returned by it.
"""
- for index, (p, m) in enumerate(self._patches_and_mocks):
- if mock is m:
- p.stop()
- del self._patches_and_mocks[index]
- break
- else:
- raise ValueError("This mock object is not registered")
+ self._mock_cache.remove(mock)
def spy(self, obj: object, name: str) -> MockType:
"""
@@ -137,14 +169,6 @@ class MockerFixture:
:return: Spy object.
"""
method = getattr(obj, name)
- if inspect.isclass(obj) and isinstance(
- inspect.getattr_static(obj, name), (classmethod, staticmethod)
- ):
- # Can't use autospec classmethod or staticmethod objects before 3.7
- # see: https://bugs.python.org/issue23078
- autospec = False
- else:
- autospec = inspect.ismethod(method) or inspect.isfunction(method)
def wrapper(*args, **kwargs):
spy_obj.spy_return = None
@@ -156,6 +180,7 @@ class MockerFixture:
raise
else:
spy_obj.spy_return = r
+ spy_obj.spy_return_list.append(r)
return r
async def async_wrapper(*args, **kwargs):
@@ -168,6 +193,7 @@ class MockerFixture:
raise
else:
spy_obj.spy_return = r
+ spy_obj.spy_return_list.append(r)
return r
if asyncio.iscoroutinefunction(method):
@@ -175,8 +201,11 @@ class MockerFixture:
else:
wrapped = functools.update_wrapper(wrapper, method)
+ autospec = inspect.ismethod(method) or inspect.isfunction(method)
+
spy_obj = self.patch.object(obj, name, side_effect=wrapped, autospec=autospec)
spy_obj.spy_return = None
+ spy_obj.spy_return_list = []
spy_obj.spy_exception = None
return spy_obj
@@ -214,8 +243,8 @@ class MockerFixture:
DEFAULT = object()
- def __init__(self, patches_and_mocks, mock_module):
- self.__patches_and_mocks = patches_and_mocks
+ def __init__(self, mock_cache, mock_module):
+ self.__mock_cache = mock_cache
self.mock_module = mock_module
def _start_patch(
@@ -227,22 +256,18 @@ class MockerFixture:
"""
p = mock_func(*args, **kwargs)
mocked: MockType = p.start()
- self.__patches_and_mocks.append((p, mocked))
+ self.__mock_cache.add(mock=mocked, patch=p)
if hasattr(mocked, "reset_mock"):
# check if `mocked` is actually a mock object, as depending on autospec or target
# parameters `mocked` can be anything
if hasattr(mocked, "__enter__") and warn_on_mock_enter:
- if sys.version_info >= (3, 8):
- depth = 5
- else:
- depth = 4
mocked.__enter__.side_effect = lambda: warnings.warn(
"Mocks returned by pytest-mock do not need to be used as context managers. "
"The mocker fixture automatically undoes mocking at the end of a test. "
"This warning can be ignored if it was triggered by mocking a context manager. "
"https://pytest-mock.readthedocs.io/en/latest/remarks.html#usage-as-context-manager",
PytestMockWarning,
- stacklevel=depth,
+ stacklevel=5,
)
return mocked
@@ -256,7 +281,7 @@ class MockerFixture:
spec_set: Optional[object] = None,
autospec: Optional[object] = None,
new_callable: object = None,
- **kwargs: Any
+ **kwargs: Any,
) -> MockType:
"""API to mock.patch.object"""
if new is self.DEFAULT:
@@ -272,7 +297,7 @@ class MockerFixture:
spec_set=spec_set,
autospec=autospec,
new_callable=new_callable,
- **kwargs
+ **kwargs,
)
def context_manager(
@@ -285,7 +310,7 @@ class MockerFixture:
spec_set: Optional[builtins.object] = None,
autospec: Optional[builtins.object] = None,
new_callable: builtins.object = None,
- **kwargs: Any
+ **kwargs: Any,
) -> MockType:
"""This is equivalent to mock.patch.object except that the returned mock
does not issue a warning when used as a context manager."""
@@ -302,7 +327,7 @@ class MockerFixture:
spec_set=spec_set,
autospec=autospec,
new_callable=new_callable,
- **kwargs
+ **kwargs,
)
def multiple(
@@ -313,7 +338,7 @@ class MockerFixture:
spec_set: Optional[builtins.object] = None,
autospec: Optional[builtins.object] = None,
new_callable: Optional[builtins.object] = None,
- **kwargs: Any
+ **kwargs: Any,
) -> Dict[str, MockType]:
"""API to mock.patch.multiple"""
return self._start_patch(
@@ -325,7 +350,7 @@ class MockerFixture:
spec_set=spec_set,
autospec=autospec,
new_callable=new_callable,
- **kwargs
+ **kwargs,
)
def dict(
@@ -333,7 +358,7 @@ class MockerFixture:
in_dict: Union[Mapping[Any, Any], str],
values: Union[Mapping[Any, Any], Iterable[Tuple[Any, Any]]] = (),
clear: bool = False,
- **kwargs: Any
+ **kwargs: Any,
) -> Any:
"""API to mock.patch.dict"""
return self._start_patch(
@@ -342,7 +367,7 @@ class MockerFixture:
in_dict,
values=values,
clear=clear,
- **kwargs
+ **kwargs,
)
@overload
@@ -355,9 +380,8 @@ class MockerFixture:
spec_set: Optional[builtins.object] = ...,
autospec: Optional[builtins.object] = ...,
new_callable: None = ...,
- **kwargs: Any
- ) -> MockType:
- ...
+ **kwargs: Any,
+ ) -> MockType: ...
@overload
def __call__(
@@ -369,9 +393,8 @@ class MockerFixture:
spec_set: Optional[builtins.object] = ...,
autospec: Optional[builtins.object] = ...,
new_callable: None = ...,
- **kwargs: Any
- ) -> _T:
- ...
+ **kwargs: Any,
+ ) -> _T: ...
@overload
def __call__(
@@ -383,9 +406,8 @@ class MockerFixture:
spec_set: Optional[builtins.object],
autospec: Optional[builtins.object],
new_callable: Callable[[], _T],
- **kwargs: Any
- ) -> _T:
- ...
+ **kwargs: Any,
+ ) -> _T: ...
@overload
def __call__(
@@ -398,9 +420,8 @@ class MockerFixture:
autospec: Optional[builtins.object] = ...,
*,
new_callable: Callable[[], _T],
- **kwargs: Any
- ) -> _T:
- ...
+ **kwargs: Any,
+ ) -> _T: ...
def __call__(
self,
@@ -411,7 +432,7 @@ class MockerFixture:
spec_set: Optional[builtins.object] = None,
autospec: Optional[builtins.object] = None,
new_callable: Optional[Callable[[], Any]] = None,
- **kwargs: Any
+ **kwargs: Any,
) -> Any:
"""API to mock.patch"""
if new is self.DEFAULT:
@@ -426,7 +447,7 @@ class MockerFixture:
spec_set=spec_set,
autospec=autospec,
new_callable=new_callable,
- **kwargs
+ **kwargs,
)
diff --git a/contrib/python/pytest-mock/py3/ya.make b/contrib/python/pytest-mock/py3/ya.make
index 40f864e45d..7b9bcc9b14 100644
--- a/contrib/python/pytest-mock/py3/ya.make
+++ b/contrib/python/pytest-mock/py3/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(3.12.0)
+VERSION(3.14.0)
LICENSE(MIT)
diff --git a/yt/python/yt/type_info/__init__.py b/yt/python/yt/type_info/__init__.py
index aa7268843c..33813771da 100644
--- a/yt/python/yt/type_info/__init__.py
+++ b/yt/python/yt/type_info/__init__.py
@@ -7,5 +7,5 @@ from .typing import ( # noqa
Double, String, Utf8, Yson, Json, Uuid, Date, Datetime, Timestamp,
Interval, TzDate, TzDatetime, TzTimestamp, Void, Null, Optional, List,
Tuple, Dict, Struct, Variant, Tagged, Decimal, EmptyTuple, EmptyStruct,
- serialize_yson, deserialize_yson,
+ serialize_yson, deserialize_yson, deserialize_yson_v1,
)
diff --git a/yt/python/yt/type_info/type_base.py b/yt/python/yt/type_info/type_base.py
index 57b5452e29..11b75fd2a1 100644
--- a/yt/python/yt/type_info/type_base.py
+++ b/yt/python/yt/type_info/type_base.py
@@ -82,6 +82,9 @@ class Primitive(Type):
def to_yson_type(self):
return self.yt_type_name
+ def to_yson_type_v1(self):
+ return self.yt_type_name_v1
+
class Generic(six.with_metaclass(ABCMeta)):
def __init__(self, name, yt_type_name=None):
@@ -98,7 +101,7 @@ class Generic(six.with_metaclass(ABCMeta)):
pass
-def make_primitive_type(name, yt_type_name=None):
+def make_primitive_type(name, yt_type_name=None, yt_type_name_v1=None):
assert _is_utf8(name), "Name of primitive type must be UTF-8, got {}".format(_with_type(name))
assert yt_type_name is None or _is_utf8(yt_type_name), \
"YT type name of primitive type must be UTF-8, got {}".format(_with_type(name))
@@ -106,4 +109,11 @@ def make_primitive_type(name, yt_type_name=None):
if yt_type_name is None:
yt_type_name = name.lower()
- return Primitive({"name": name, "yt_type_name": yt_type_name})
+ if yt_type_name_v1 is None:
+ yt_type_name_v1 = name.lower()
+
+ return Primitive({
+ "name": name,
+ "yt_type_name": yt_type_name,
+ "yt_type_name_v1": yt_type_name_v1,
+ })
diff --git a/yt/python/yt/type_info/typing.py b/yt/python/yt/type_info/typing.py
index 07cd5c189c..0d9abc505f 100644
--- a/yt/python/yt/type_info/typing.py
+++ b/yt/python/yt/type_info/typing.py
@@ -341,7 +341,9 @@ class _GenericDecimal(type_base.Generic):
return self.__getitem__((type_["precision"], type_["scale"],))
-Bool = type_base.make_primitive_type("Bool")
+Bool = type_base.make_primitive_type("Bool", yt_type_name_v1="boolean")
+Yson = type_base.make_primitive_type("Yson", yt_type_name_v1="any")
+
Int8 = type_base.make_primitive_type("Int8")
Uint8 = type_base.make_primitive_type("Uint8")
Int16 = type_base.make_primitive_type("Int16")
@@ -354,7 +356,6 @@ Float = type_base.make_primitive_type("Float")
Double = type_base.make_primitive_type("Double")
String = type_base.make_primitive_type("String")
Utf8 = type_base.make_primitive_type("Utf8")
-Yson = type_base.make_primitive_type("Yson")
Json = type_base.make_primitive_type("Json")
Uuid = type_base.make_primitive_type("Uuid")
Date = type_base.make_primitive_type("Date")
@@ -381,7 +382,8 @@ Decimal = _GenericDecimal("Decimal")
EmptyTuple = Tuple.__getitem__(tuple())
EmptyStruct = Struct.__getitem__(tuple())
-PRIMITIVES = {type_.yt_type_name: type_ for type_ in locals().values() if isinstance(type_, type_base.Primitive)}
+PRIMITIVES_V1 = {type_.yt_type_name_v1: type_ for type_ in locals().values() if isinstance(type_, type_base.Primitive)}
+PRIMITIVES_V3 = {type_.yt_type_name: type_ for type_ in locals().values() if isinstance(type_, type_base.Primitive)}
GENERICS = {type_.yt_type_name: type_ for type_ in locals().values() if isinstance(type_, type_base.Generic)}
@@ -396,8 +398,8 @@ def _validate_contains(dict, key):
def _parse_type(type_description):
if isinstance(type_description, six.string_types):
- _validate(type_description in PRIMITIVES, "unknown type \"{}\"".format(type_description))
- return PRIMITIVES[type_description]
+ _validate(type_description in PRIMITIVES_V3, "unknown type \"{}\"".format(type_description))
+ return PRIMITIVES_V3[type_description]
_validate(isinstance(type_description, dict),
"type must be either a string or a map, got {}".format(type_base._with_type(type_description)))
@@ -407,14 +409,23 @@ def _parse_type(type_description):
type_name = type_description["type_name"]
_validate(isinstance(type_name, six.string_types), "\"type_name\" must contain a string")
- _validate(type_name in PRIMITIVES or type_name in GENERICS, "unknown type \"{}\"".format(type_name))
+ _validate(type_name in PRIMITIVES_V3 or type_name in GENERICS, "unknown type \"{}\"".format(type_name))
- if type_name in PRIMITIVES:
- return PRIMITIVES[type_name]
+ if type_name in PRIMITIVES_V3:
+ return PRIMITIVES_V3[type_name]
return GENERICS[type_name].from_dict(type_description)
+def _parse_type_v1(type_description, required):
+ if required:
+ _validate(isinstance(type_description, six.string_types), "\"type_description\" must be a string for v1 type")
+ _validate(type_description in PRIMITIVES_V1, "unknown type \"{}\"".format(type_description))
+ return PRIMITIVES_V1[type_description]
+ else:
+ return Optional[_parse_type_v1(type_description, True)]
+
+
def _check_serialization_available():
if not _TI_SERIALIZATION_AVAILABLE:
raise ImportError("Module `yt.yson` is required to use type_info serialization. "
@@ -441,3 +452,16 @@ def deserialize_yson(yson):
return _parse_type(type_description)
except (ValueError, yt.yson.YsonError) as e:
six.raise_from(ValueError("deserialization failed: {}".format(e)), e)
+
+
+def deserialize_yson_v1(yson, required):
+ _check_serialization_available()
+
+ if type(yson) is six.text_type and six.PY3:
+ yson = yson.encode("utf-8")
+
+ try:
+ type_description = yt.yson.loads(yson)
+ return _parse_type_v1(type_description, required)
+ except (ValueError, yt.yson.YsonError) as e:
+ six.raise_from(ValueError("deserialization failed: {}".format(e)), e)