reactpy 2.0.0b3__py3-none-any.whl → 2.0.0b5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- reactpy/__init__.py +2 -5
- reactpy/_console/rewrite_props.py +2 -2
- reactpy/_option.py +2 -1
- reactpy/config.py +2 -2
- reactpy/core/_life_cycle_hook.py +8 -9
- reactpy/core/_thread_local.py +2 -1
- reactpy/core/component.py +4 -38
- reactpy/core/events.py +61 -48
- reactpy/core/hooks.py +26 -30
- reactpy/core/layout.py +175 -188
- reactpy/core/serve.py +9 -28
- reactpy/core/vdom.py +6 -7
- reactpy/executors/asgi/__init__.py +9 -4
- reactpy/executors/asgi/middleware.py +1 -2
- reactpy/executors/asgi/pyscript.py +3 -7
- reactpy/executors/asgi/standalone.py +4 -6
- reactpy/executors/asgi/types.py +2 -2
- reactpy/pyscript/components.py +3 -3
- reactpy/pyscript/utils.py +50 -53
- reactpy/static/index.js +2 -2
- reactpy/static/index.js.map +6 -6
- reactpy/testing/backend.py +2 -1
- reactpy/testing/common.py +3 -5
- reactpy/types.py +116 -47
- reactpy/utils.py +7 -7
- reactpy/web/module.py +87 -6
- reactpy/widgets.py +4 -26
- {reactpy-2.0.0b3.dist-info → reactpy-2.0.0b5.dist-info}/METADATA +4 -7
- {reactpy-2.0.0b3.dist-info → reactpy-2.0.0b5.dist-info}/RECORD +32 -32
- {reactpy-2.0.0b3.dist-info → reactpy-2.0.0b5.dist-info}/WHEEL +0 -0
- {reactpy-2.0.0b3.dist-info → reactpy-2.0.0b5.dist-info}/entry_points.txt +0 -0
- {reactpy-2.0.0b3.dist-info → reactpy-2.0.0b5.dist-info}/licenses/LICENSE +0 -0
reactpy/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@ from reactpy import config, logging, types, web, widgets
|
|
|
2
2
|
from reactpy._html import html
|
|
3
3
|
from reactpy.core import hooks
|
|
4
4
|
from reactpy.core.component import component
|
|
5
|
-
from reactpy.core.events import
|
|
5
|
+
from reactpy.core.events import event
|
|
6
6
|
from reactpy.core.hooks import (
|
|
7
7
|
create_context,
|
|
8
8
|
use_async_effect,
|
|
@@ -18,17 +18,14 @@ from reactpy.core.hooks import (
|
|
|
18
18
|
use_scope,
|
|
19
19
|
use_state,
|
|
20
20
|
)
|
|
21
|
-
from reactpy.core.layout import Layout
|
|
22
21
|
from reactpy.core.vdom import Vdom
|
|
23
22
|
from reactpy.pyscript.components import pyscript_component
|
|
24
23
|
from reactpy.utils import Ref, reactpy_to_string, string_to_reactpy
|
|
25
24
|
|
|
26
25
|
__author__ = "The Reactive Python Team"
|
|
27
|
-
__version__ = "2.0.
|
|
26
|
+
__version__ = "2.0.0b5"
|
|
28
27
|
|
|
29
28
|
__all__ = [
|
|
30
|
-
"Event",
|
|
31
|
-
"Layout",
|
|
32
29
|
"Ref",
|
|
33
30
|
"Vdom",
|
|
34
31
|
"component",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import ast
|
|
4
|
+
from collections.abc import Callable
|
|
4
5
|
from copy import copy
|
|
5
6
|
from keyword import kwlist
|
|
6
7
|
from pathlib import Path
|
|
7
|
-
from typing import Callable
|
|
8
8
|
|
|
9
9
|
import click
|
|
10
10
|
|
|
@@ -102,7 +102,7 @@ def _rewrite_props(
|
|
|
102
102
|
keys: list[ast.expr | None] = []
|
|
103
103
|
values: list[ast.expr] = []
|
|
104
104
|
# Iterate over the keys and values in the dictionary
|
|
105
|
-
for k, v in zip(props_node.keys, props_node.values):
|
|
105
|
+
for k, v in zip(props_node.keys, props_node.values, strict=False):
|
|
106
106
|
if isinstance(k, ast.Constant) and isinstance(k.value, str):
|
|
107
107
|
# Construct the new key and value
|
|
108
108
|
k_value, new_v = constructor(k.value, v)
|
reactpy/_option.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
from collections.abc import Callable
|
|
4
5
|
from logging import getLogger
|
|
5
|
-
from typing import Any,
|
|
6
|
+
from typing import Any, Generic, TypeVar, cast
|
|
6
7
|
|
|
7
8
|
from reactpy._warnings import warn
|
|
8
9
|
|
reactpy/config.py
CHANGED
|
@@ -85,11 +85,11 @@ REACTPY_TESTS_DEFAULT_TIMEOUT = Option(
|
|
|
85
85
|
|
|
86
86
|
REACTPY_ASYNC_RENDERING = Option(
|
|
87
87
|
"REACTPY_ASYNC_RENDERING",
|
|
88
|
-
default=
|
|
88
|
+
default=True,
|
|
89
89
|
mutable=True,
|
|
90
90
|
validator=boolean,
|
|
91
91
|
)
|
|
92
|
-
"""Whether to render components asynchronously.
|
|
92
|
+
"""Whether to render components asynchronously."""
|
|
93
93
|
|
|
94
94
|
REACTPY_RECONNECT_INTERVAL = Option(
|
|
95
95
|
"REACTPY_RECONNECT_INTERVAL",
|
reactpy/core/_life_cycle_hook.py
CHANGED
|
@@ -3,13 +3,14 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
import sys
|
|
5
5
|
from asyncio import Event, Task, create_task, gather
|
|
6
|
+
from collections.abc import Callable
|
|
6
7
|
from contextvars import ContextVar, Token
|
|
7
|
-
from typing import Any,
|
|
8
|
+
from typing import Any, Protocol, TypeVar
|
|
8
9
|
|
|
9
10
|
from anyio import Semaphore
|
|
10
11
|
|
|
11
12
|
from reactpy.core._thread_local import ThreadLocal
|
|
12
|
-
from reactpy.types import
|
|
13
|
+
from reactpy.types import Component, Context, ContextProvider
|
|
13
14
|
from reactpy.utils import Singleton
|
|
14
15
|
|
|
15
16
|
T = TypeVar("T")
|
|
@@ -145,13 +146,13 @@ class LifeCycleHook:
|
|
|
145
146
|
"component",
|
|
146
147
|
)
|
|
147
148
|
|
|
148
|
-
component:
|
|
149
|
+
component: Component
|
|
149
150
|
|
|
150
151
|
def __init__(
|
|
151
152
|
self,
|
|
152
153
|
schedule_render: Callable[[], None],
|
|
153
154
|
) -> None:
|
|
154
|
-
self._context_providers: dict[Context[Any],
|
|
155
|
+
self._context_providers: dict[Context[Any], ContextProvider[Any]] = {}
|
|
155
156
|
self._schedule_render_callback = schedule_render
|
|
156
157
|
self._scheduled_render = False
|
|
157
158
|
self._rendered_atleast_once = False
|
|
@@ -200,7 +201,7 @@ class LifeCycleHook:
|
|
|
200
201
|
"""
|
|
201
202
|
self._effect_funcs.append(effect_func)
|
|
202
203
|
|
|
203
|
-
def set_context_provider(self, provider:
|
|
204
|
+
def set_context_provider(self, provider: ContextProvider[Any]) -> None:
|
|
204
205
|
"""Set a context provider for this hook
|
|
205
206
|
|
|
206
207
|
The context provider will be used to provide state to any child components
|
|
@@ -208,9 +209,7 @@ class LifeCycleHook:
|
|
|
208
209
|
"""
|
|
209
210
|
self._context_providers[provider.type] = provider
|
|
210
211
|
|
|
211
|
-
def get_context_provider(
|
|
212
|
-
self, context: Context[T]
|
|
213
|
-
) -> ContextProviderType[T] | None:
|
|
212
|
+
def get_context_provider(self, context: Context[T]) -> ContextProvider[T] | None:
|
|
214
213
|
"""Get a context provider for this hook of the given type
|
|
215
214
|
|
|
216
215
|
The context provider will have been set by a parent component. If no provider
|
|
@@ -218,7 +217,7 @@ class LifeCycleHook:
|
|
|
218
217
|
"""
|
|
219
218
|
return self._context_providers.get(context)
|
|
220
219
|
|
|
221
|
-
async def affect_component_will_render(self, component:
|
|
220
|
+
async def affect_component_will_render(self, component: Component) -> None:
|
|
222
221
|
"""The component is about to render"""
|
|
223
222
|
await self._render_access.acquire()
|
|
224
223
|
self._scheduled_render = False
|
reactpy/core/_thread_local.py
CHANGED
reactpy/core/component.py
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
|
+
from collections.abc import Callable
|
|
4
5
|
from functools import wraps
|
|
5
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
6
7
|
|
|
7
|
-
from reactpy.types import
|
|
8
|
+
from reactpy.types import Component, VdomDict
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def component(
|
|
11
|
-
function: Callable[...,
|
|
12
|
+
function: Callable[..., Component | VdomDict | str | None],
|
|
12
13
|
) -> Callable[..., Component]:
|
|
13
14
|
"""A decorator for defining a new component.
|
|
14
15
|
|
|
@@ -29,38 +30,3 @@ def component(
|
|
|
29
30
|
return Component(function, key, args, kwargs, sig)
|
|
30
31
|
|
|
31
32
|
return constructor
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class Component:
|
|
35
|
-
"""An object for rending component models."""
|
|
36
|
-
|
|
37
|
-
__slots__ = "__weakref__", "_args", "_func", "_kwargs", "_sig", "key", "type"
|
|
38
|
-
|
|
39
|
-
def __init__(
|
|
40
|
-
self,
|
|
41
|
-
function: Callable[..., ComponentType | VdomDict | str | None],
|
|
42
|
-
key: Any | None,
|
|
43
|
-
args: tuple[Any, ...],
|
|
44
|
-
kwargs: dict[str, Any],
|
|
45
|
-
sig: inspect.Signature,
|
|
46
|
-
) -> None:
|
|
47
|
-
self.key = key
|
|
48
|
-
self.type = function
|
|
49
|
-
self._args = args
|
|
50
|
-
self._kwargs = kwargs
|
|
51
|
-
self._sig = sig
|
|
52
|
-
|
|
53
|
-
def render(self) -> ComponentType | VdomDict | str | None:
|
|
54
|
-
return self.type(*self._args, **self._kwargs)
|
|
55
|
-
|
|
56
|
-
def __repr__(self) -> str:
|
|
57
|
-
try:
|
|
58
|
-
args = self._sig.bind(*self._args, **self._kwargs).arguments
|
|
59
|
-
except TypeError:
|
|
60
|
-
return f"{self.type.__name__}(...)"
|
|
61
|
-
else:
|
|
62
|
-
items = ", ".join(f"{k}={v!r}" for k, v in args.items())
|
|
63
|
-
if items:
|
|
64
|
-
return f"{self.type.__name__}({id(self):02x}, {items})"
|
|
65
|
-
else:
|
|
66
|
-
return f"{self.type.__name__}({id(self):02x})"
|
reactpy/core/events.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import asyncio
|
|
4
3
|
import dis
|
|
5
|
-
|
|
6
|
-
from
|
|
4
|
+
import inspect
|
|
5
|
+
from collections.abc import Callable, Sequence
|
|
6
|
+
from functools import lru_cache
|
|
7
|
+
from types import CodeType
|
|
8
|
+
from typing import Any, Literal, cast, overload
|
|
7
9
|
|
|
8
10
|
from anyio import create_task_group
|
|
9
11
|
|
|
10
|
-
from reactpy.types import
|
|
12
|
+
from reactpy.types import BaseEventHandler, EventHandlerFunc
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
@overload
|
|
@@ -73,19 +75,7 @@ def event(
|
|
|
73
75
|
return setup(function) if function is not None else setup
|
|
74
76
|
|
|
75
77
|
|
|
76
|
-
class
|
|
77
|
-
def __getattr__(self, name: str) -> Any:
|
|
78
|
-
value = self.get(name)
|
|
79
|
-
return Event(value) if isinstance(value, dict) else value
|
|
80
|
-
|
|
81
|
-
def preventDefault(self) -> None:
|
|
82
|
-
"""Prevent the default action of the event."""
|
|
83
|
-
|
|
84
|
-
def stopPropagation(self) -> None:
|
|
85
|
-
"""Stop the event from propagating."""
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
class EventHandler:
|
|
78
|
+
class EventHandler(BaseEventHandler):
|
|
89
79
|
"""Turn a function or coroutine into an event handler
|
|
90
80
|
|
|
91
81
|
Parameters:
|
|
@@ -99,14 +89,6 @@ class EventHandler:
|
|
|
99
89
|
A unique identifier for this event handler (auto-generated by default)
|
|
100
90
|
"""
|
|
101
91
|
|
|
102
|
-
__slots__ = (
|
|
103
|
-
"__weakref__",
|
|
104
|
-
"function",
|
|
105
|
-
"prevent_default",
|
|
106
|
-
"stop_propagation",
|
|
107
|
-
"target",
|
|
108
|
-
)
|
|
109
|
-
|
|
110
92
|
def __init__(
|
|
111
93
|
self,
|
|
112
94
|
function: EventHandlerFunc,
|
|
@@ -125,26 +107,14 @@ class EventHandler:
|
|
|
125
107
|
while hasattr(func_to_inspect, "__wrapped__"):
|
|
126
108
|
func_to_inspect = func_to_inspect.__wrapped__
|
|
127
109
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
last_was_event = False
|
|
132
|
-
|
|
133
|
-
for instr in dis.get_instructions(func_to_inspect):
|
|
134
|
-
if instr.opname == "LOAD_FAST" and instr.argval == event_arg_name:
|
|
135
|
-
last_was_event = True
|
|
136
|
-
continue
|
|
137
|
-
|
|
138
|
-
if last_was_event and instr.opname in (
|
|
139
|
-
"LOAD_METHOD",
|
|
140
|
-
"LOAD_ATTR",
|
|
141
|
-
):
|
|
142
|
-
if instr.argval == "preventDefault":
|
|
143
|
-
self.prevent_default = True
|
|
144
|
-
elif instr.argval == "stopPropagation":
|
|
145
|
-
self.stop_propagation = True
|
|
110
|
+
found_prevent_default, found_stop_propagation = _inspect_event_handler_code(
|
|
111
|
+
func_to_inspect.__code__
|
|
112
|
+
)
|
|
146
113
|
|
|
147
|
-
|
|
114
|
+
if found_prevent_default:
|
|
115
|
+
self.prevent_default = True
|
|
116
|
+
if found_stop_propagation:
|
|
117
|
+
self.stop_propagation = True
|
|
148
118
|
|
|
149
119
|
__hash__ = None # type: ignore
|
|
150
120
|
|
|
@@ -180,7 +150,7 @@ def to_event_handler_function(
|
|
|
180
150
|
Whether to pass the event parameters a positional args or as a list.
|
|
181
151
|
"""
|
|
182
152
|
if positional_args:
|
|
183
|
-
if
|
|
153
|
+
if inspect.iscoroutinefunction(function):
|
|
184
154
|
|
|
185
155
|
async def wrapper(data: Sequence[Any]) -> None:
|
|
186
156
|
await function(*data)
|
|
@@ -194,7 +164,7 @@ def to_event_handler_function(
|
|
|
194
164
|
|
|
195
165
|
cast(Any, wrapper).__wrapped__ = function
|
|
196
166
|
return wrapper
|
|
197
|
-
elif not
|
|
167
|
+
elif not inspect.iscoroutinefunction(function):
|
|
198
168
|
|
|
199
169
|
async def wrapper(data: Sequence[Any]) -> None:
|
|
200
170
|
function(data)
|
|
@@ -206,8 +176,8 @@ def to_event_handler_function(
|
|
|
206
176
|
|
|
207
177
|
|
|
208
178
|
def merge_event_handlers(
|
|
209
|
-
event_handlers: Sequence[
|
|
210
|
-
) ->
|
|
179
|
+
event_handlers: Sequence[BaseEventHandler],
|
|
180
|
+
) -> BaseEventHandler:
|
|
211
181
|
"""Merge multiple event handlers into one
|
|
212
182
|
|
|
213
183
|
Raises a ValueError if any handlers have conflicting
|
|
@@ -259,3 +229,46 @@ def merge_event_handler_funcs(
|
|
|
259
229
|
group.start_soon(func, data)
|
|
260
230
|
|
|
261
231
|
return await_all_event_handlers
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
@lru_cache(maxsize=4096)
|
|
235
|
+
def _inspect_event_handler_code(code: CodeType) -> tuple[bool, bool]:
|
|
236
|
+
prevent_default = False
|
|
237
|
+
stop_propagation = False
|
|
238
|
+
|
|
239
|
+
if code.co_argcount > 0:
|
|
240
|
+
names = code.co_names
|
|
241
|
+
check_prevent_default = "preventDefault" in names
|
|
242
|
+
check_stop_propagation = "stopPropagation" in names
|
|
243
|
+
|
|
244
|
+
if not (check_prevent_default or check_stop_propagation):
|
|
245
|
+
return False, False
|
|
246
|
+
|
|
247
|
+
event_arg_name = code.co_varnames[0]
|
|
248
|
+
last_was_event = False
|
|
249
|
+
|
|
250
|
+
for instr in dis.get_instructions(code):
|
|
251
|
+
if (
|
|
252
|
+
instr.opname in ("LOAD_FAST", "LOAD_FAST_BORROW")
|
|
253
|
+
and instr.argval == event_arg_name
|
|
254
|
+
):
|
|
255
|
+
last_was_event = True
|
|
256
|
+
continue
|
|
257
|
+
|
|
258
|
+
if last_was_event and instr.opname in (
|
|
259
|
+
"LOAD_METHOD",
|
|
260
|
+
"LOAD_ATTR",
|
|
261
|
+
):
|
|
262
|
+
if check_prevent_default and instr.argval == "preventDefault":
|
|
263
|
+
prevent_default = True
|
|
264
|
+
check_prevent_default = False
|
|
265
|
+
elif check_stop_propagation and instr.argval == "stopPropagation":
|
|
266
|
+
stop_propagation = True
|
|
267
|
+
check_stop_propagation = False
|
|
268
|
+
|
|
269
|
+
if not (check_prevent_default or check_stop_propagation):
|
|
270
|
+
break
|
|
271
|
+
|
|
272
|
+
last_was_event = False
|
|
273
|
+
|
|
274
|
+
return prevent_default, stop_propagation
|
reactpy/core/hooks.py
CHANGED
|
@@ -2,31 +2,30 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import contextlib
|
|
5
|
-
|
|
5
|
+
import inspect
|
|
6
|
+
from collections.abc import Callable, Coroutine, Sequence
|
|
6
7
|
from logging import getLogger
|
|
7
8
|
from types import FunctionType
|
|
8
9
|
from typing import (
|
|
9
10
|
TYPE_CHECKING,
|
|
10
11
|
Any,
|
|
11
|
-
Callable,
|
|
12
12
|
Generic,
|
|
13
13
|
Protocol,
|
|
14
|
+
TypeAlias,
|
|
14
15
|
TypeVar,
|
|
15
16
|
cast,
|
|
16
17
|
overload,
|
|
17
18
|
)
|
|
18
19
|
|
|
19
|
-
from typing_extensions import TypeAlias
|
|
20
|
-
|
|
21
20
|
from reactpy.config import REACTPY_DEBUG
|
|
22
21
|
from reactpy.core._life_cycle_hook import HOOK_STACK
|
|
23
22
|
from reactpy.types import (
|
|
24
23
|
Connection,
|
|
25
24
|
Context,
|
|
25
|
+
ContextProvider,
|
|
26
26
|
Key,
|
|
27
27
|
Location,
|
|
28
28
|
State,
|
|
29
|
-
VdomDict,
|
|
30
29
|
)
|
|
31
30
|
from reactpy.utils import Ref
|
|
32
31
|
|
|
@@ -146,12 +145,19 @@ def use_effect(
|
|
|
146
145
|
Returns:
|
|
147
146
|
If not function is provided, a decorator. Otherwise ``None``.
|
|
148
147
|
"""
|
|
148
|
+
|
|
149
149
|
hook = HOOK_STACK.current_hook()
|
|
150
150
|
dependencies = _try_to_infer_closure_values(function, dependencies)
|
|
151
151
|
memoize = use_memo(dependencies=dependencies)
|
|
152
152
|
cleanup_func: Ref[_EffectCleanFunc | None] = use_ref(None)
|
|
153
153
|
|
|
154
154
|
def decorator(func: _SyncEffectFunc) -> None:
|
|
155
|
+
if inspect.iscoroutinefunction(func):
|
|
156
|
+
raise TypeError(
|
|
157
|
+
"`use_effect` does not support async functions. "
|
|
158
|
+
"Use `use_async_effect` instead."
|
|
159
|
+
)
|
|
160
|
+
|
|
155
161
|
async def effect(stop: asyncio.Event) -> None:
|
|
156
162
|
# Since the effect is asynchronous, we need to make sure we
|
|
157
163
|
# always clean up the previous effect's resources
|
|
@@ -297,8 +303,8 @@ def create_context(default_value: _Type) -> Context[_Type]:
|
|
|
297
303
|
*children: Any,
|
|
298
304
|
value: _Type = default_value,
|
|
299
305
|
key: Key | None = None,
|
|
300
|
-
) ->
|
|
301
|
-
return
|
|
306
|
+
) -> ContextProvider[_Type]:
|
|
307
|
+
return ContextProvider(
|
|
302
308
|
*children,
|
|
303
309
|
value=value,
|
|
304
310
|
key=key,
|
|
@@ -354,27 +360,6 @@ def use_location() -> Location:
|
|
|
354
360
|
return use_connection().location
|
|
355
361
|
|
|
356
362
|
|
|
357
|
-
class _ContextProvider(Generic[_Type]):
|
|
358
|
-
def __init__(
|
|
359
|
-
self,
|
|
360
|
-
*children: Any,
|
|
361
|
-
value: _Type,
|
|
362
|
-
key: Key | None,
|
|
363
|
-
type: Context[_Type],
|
|
364
|
-
) -> None:
|
|
365
|
-
self.children = children
|
|
366
|
-
self.key = key
|
|
367
|
-
self.type = type
|
|
368
|
-
self.value = value
|
|
369
|
-
|
|
370
|
-
def render(self) -> VdomDict:
|
|
371
|
-
HOOK_STACK.current_hook().set_context_provider(self)
|
|
372
|
-
return VdomDict(tagName="", children=self.children)
|
|
373
|
-
|
|
374
|
-
def __repr__(self) -> str:
|
|
375
|
-
return f"ContextProvider({self.type})"
|
|
376
|
-
|
|
377
|
-
|
|
378
363
|
_ActionType = TypeVar("_ActionType")
|
|
379
364
|
|
|
380
365
|
|
|
@@ -509,7 +494,7 @@ def use_memo(
|
|
|
509
494
|
# if deps are same length check identity for each item
|
|
510
495
|
or not all(
|
|
511
496
|
strictly_equal(current, new)
|
|
512
|
-
for current, new in zip(memo.deps, dependencies)
|
|
497
|
+
for current, new in zip(memo.deps, dependencies, strict=False)
|
|
513
498
|
)
|
|
514
499
|
):
|
|
515
500
|
memo.deps = dependencies
|
|
@@ -611,7 +596,18 @@ def strictly_equal(x: Any, y: Any) -> bool:
|
|
|
611
596
|
getattr(x.__code__, attr) == getattr(y.__code__, attr)
|
|
612
597
|
for attr in dir(x.__code__)
|
|
613
598
|
if attr.startswith("co_")
|
|
614
|
-
and attr
|
|
599
|
+
and attr
|
|
600
|
+
not in {
|
|
601
|
+
"co_positions",
|
|
602
|
+
"co_linetable",
|
|
603
|
+
"co_lines",
|
|
604
|
+
"co_lnotab",
|
|
605
|
+
"co_branches",
|
|
606
|
+
"co_firstlineno",
|
|
607
|
+
"co_end_lineno",
|
|
608
|
+
"co_col_offset",
|
|
609
|
+
"co_end_col_offset",
|
|
610
|
+
}
|
|
615
611
|
)
|
|
616
612
|
|
|
617
613
|
# Check via the `==` operator if possible
|