From 16bce9735a9238cafda1e97c89f80fe9f57b382f Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 12 Jun 2022 16:22:01 +0300 Subject: [PATCH 1/2] gh-91162: Support splitting of unpacked arbitrary-length tuple over TypeVar and TypeVarTuple parameters (alt) (GH-93412) For example: A[T, *Ts][*tuple[int, ...]] -> A[int, *tuple[int, ...]] A[*Ts, T][*tuple[int, ...]] -> A[*tuple[int, ...], int] (cherry picked from commit 3473817106c23eca7341c931453da0341c367e1d) Co-authored-by: Serhiy Storchaka --- Include/internal/pycore_global_strings.h | 1 + Include/internal/pycore_runtime_init.h | 1 + Lib/test/test_typing.py | 17 +-- Lib/typing.py | 110 ++++++++---------- ...2-06-01-11-24-13.gh-issue-91162.NxvU_u.rst | 5 + Objects/genericaliasobject.c | 99 +++++++--------- 6 files changed, 106 insertions(+), 127 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-06-01-11-24-13.gh-issue-91162.NxvU_u.rst diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index cfa8ae99d1b6d9..ca970627cb2e17 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -202,6 +202,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(__truediv__) STRUCT_FOR_ID(__trunc__) STRUCT_FOR_ID(__typing_is_unpacked_typevartuple__) + STRUCT_FOR_ID(__typing_prepare_subst__) STRUCT_FOR_ID(__typing_subst__) STRUCT_FOR_ID(__typing_unpacked_tuple_args__) STRUCT_FOR_ID(__warningregistry__) diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index 57cacb97bcf1a8..13eae1e4c88d8f 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -825,6 +825,7 @@ extern "C" { INIT_ID(__truediv__), \ INIT_ID(__trunc__), \ INIT_ID(__typing_is_unpacked_typevartuple__), \ + INIT_ID(__typing_prepare_subst__), \ INIT_ID(__typing_subst__), \ INIT_ID(__typing_unpacked_tuple_args__), \ INIT_ID(__warningregistry__), \ diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index d6cd3d9bdd6a48..dfbe2d9d34c8ff 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -753,14 +753,11 @@ class C(Generic[*Ts]): pass ('generic[*Ts]', '[*tuple_type[int]]', 'generic[int]'), ('generic[*Ts]', '[*tuple_type[*Ts]]', 'generic[*Ts]'), ('generic[*Ts]', '[*tuple_type[int, str]]', 'generic[int, str]'), + ('generic[*Ts]', '[str, *tuple_type[int, ...], bool]', 'generic[str, *tuple_type[int, ...], bool]'), ('generic[*Ts]', '[tuple_type[int, ...]]', 'generic[tuple_type[int, ...]]'), ('generic[*Ts]', '[tuple_type[int, ...], tuple_type[str, ...]]', 'generic[tuple_type[int, ...], tuple_type[str, ...]]'), ('generic[*Ts]', '[*tuple_type[int, ...]]', 'generic[*tuple_type[int, ...]]'), - - # Technically, multiple unpackings are forbidden by PEP 646, but we - # choose to be less restrictive at runtime, to allow folks room - # to experiment. So all three of these should be valid. - ('generic[*Ts]', '[*tuple_type[int, ...], *tuple_type[str, ...]]', 'generic[*tuple_type[int, ...], *tuple_type[str, ...]]'), + ('generic[*Ts]', '[*tuple_type[int, ...], *tuple_type[str, ...]]', 'TypeError'), ('generic[*Ts]', '[*Ts]', 'generic[*Ts]'), ('generic[*Ts]', '[T, *Ts]', 'generic[T, *Ts]'), @@ -772,8 +769,6 @@ class C(Generic[*Ts]): pass ('generic[list[T], *Ts]', '[int, str]', 'generic[list[int], str]'), ('generic[list[T], *Ts]', '[int, str, bool]', 'generic[list[int], str, bool]'), - ('generic[T, *Ts]', '[*tuple[int, ...]]', 'TypeError'), # Should be generic[int, *tuple[int, ...]] - ('generic[*Ts, T]', '[int]', 'generic[int]'), ('generic[*Ts, T]', '[int, str]', 'generic[int, str]'), ('generic[*Ts, T]', '[int, str, bool]', 'generic[int, str, bool]'), @@ -781,6 +776,14 @@ class C(Generic[*Ts]): pass ('generic[*Ts, list[T]]', '[int, str]', 'generic[int, list[str]]'), ('generic[*Ts, list[T]]', '[int, str, bool]', 'generic[int, str, list[bool]]'), + ('generic[T, *Ts]', '[*tuple_type[int, ...]]', 'generic[int, *tuple_type[int, ...]]'), + ('generic[*Ts, T]', '[*tuple_type[int, ...]]', 'generic[*tuple_type[int, ...], int]'), + ('generic[T1, *Ts, T2]', '[*tuple_type[int, ...]]', 'generic[int, *tuple_type[int, ...], int]'), + ('generic[T, str, *Ts]', '[*tuple_type[int, ...]]', 'generic[int, str, *tuple_type[int, ...]]'), + ('generic[*Ts, str, T]', '[*tuple_type[int, ...]]', 'generic[*tuple_type[int, ...], str, int]'), + ('generic[list[T], *Ts]', '[*tuple_type[int, ...]]', 'generic[list[int], *tuple_type[int, ...]]'), + ('generic[*Ts, list[T]]', '[*tuple_type[int, ...]]', 'generic[*tuple_type[int, ...], list[int]]'), + ('generic[T, *tuple_type[int, ...]]', '[str]', 'generic[str, *tuple_type[int, ...]]'), ('generic[T1, T2, *tuple_type[int, ...]]', '[str, bool]', 'generic[str, bool, *tuple_type[int, ...]]'), ('generic[T1, *tuple_type[int, ...], T2]', '[str, bool]', 'generic[str, *tuple_type[int, ...], bool]'), diff --git a/Lib/typing.py b/Lib/typing.py index 40ab516f7c8ff7..25cae7ffb8d788 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1065,6 +1065,42 @@ def __repr__(self): def __typing_subst__(self, arg): raise TypeError("Substitution of bare TypeVarTuple is not supported") + def __typing_prepare_subst__(self, alias, args): + params = alias.__parameters__ + typevartuple_index = params.index(self) + for param in enumerate(params[typevartuple_index + 1:]): + if isinstance(param, TypeVarTuple): + raise TypeError(f"More than one TypeVarTuple parameter in {alias}") + + alen = len(args) + plen = len(params) + left = typevartuple_index + right = plen - typevartuple_index - 1 + var_tuple_index = None + fillarg = None + for k, arg in enumerate(args): + if not (isinstance(arg, type) and not isinstance(arg, GenericAlias)): + subargs = getattr(arg, '__typing_unpacked_tuple_args__', None) + if subargs and len(subargs) == 2 and subargs[-1] is ...: + if var_tuple_index is not None: + raise TypeError("More than one unpacked arbitrary-length tuple argument") + var_tuple_index = k + fillarg = subargs[0] + if var_tuple_index is not None: + left = min(left, var_tuple_index) + right = min(right, alen - var_tuple_index - 1) + elif left + right > alen: + raise TypeError(f"Too few arguments for {alias};" + f" actual {alen}, expected at least {plen-1}") + + return ( + *args[:left], + *([fillarg]*(typevartuple_index - left)), + tuple(args[left: alen - right]), + *([fillarg]*(plen - right - left - typevartuple_index - 1)), + *args[alen - right:], + ) + class ParamSpecArgs(_Final, _Immutable, _root=True): """The args for a ParamSpec object. @@ -1184,6 +1220,8 @@ def __typing_subst__(self, arg): f"ParamSpec, or Concatenate. Got {arg}") return arg + def __typing_prepare_subst__(self, alias, args): + return _prepare_paramspec_params(alias, args) def _is_dunder(attr): return attr.startswith('__') and attr.endswith('__') @@ -1255,44 +1293,6 @@ def __dir__(self): + [attr for attr in dir(self.__origin__) if not _is_dunder(attr)])) -def _is_unpacked_tuple(x: Any) -> bool: - # Is `x` something like `*tuple[int]` or `*tuple[int, ...]`? - if not isinstance(x, _UnpackGenericAlias): - return False - # Alright, `x` is `Unpack[something]`. - - # `x` will always have `__args__`, because Unpack[] and Unpack[()] - # aren't legal. - unpacked_type = x.__args__[0] - - return getattr(unpacked_type, '__origin__', None) is tuple - - -def _is_unpacked_arbitrary_length_tuple(x: Any) -> bool: - if not _is_unpacked_tuple(x): - return False - unpacked_tuple = x.__args__[0] - - if not hasattr(unpacked_tuple, '__args__'): - # It's `Unpack[tuple]`. We can't make any assumptions about the length - # of the tuple, so it's effectively an arbitrary-length tuple. - return True - - tuple_args = unpacked_tuple.__args__ - if not tuple_args: - # It's `Unpack[tuple[()]]`. - return False - - last_arg = tuple_args[-1] - if last_arg is Ellipsis: - # It's `Unpack[tuple[something, ...]]`, which is arbitrary-length. - return True - - # If the arguments didn't end with an ellipsis, then it's not an - # arbitrary-length tuple. - return False - - # Special typing constructs Union, Optional, Generic, Callable and Tuple # use three special attributes for internal bookkeeping of generic types: # * __parameters__ is a tuple of unique free type parameters of a generic @@ -1385,10 +1385,6 @@ def __getitem__(self, args): args = (args,) args = tuple(_type_convert(p) for p in args) args = _unpack_args(args) - if (self._paramspec_tvars - and any(isinstance(t, ParamSpec) for t in self.__parameters__)): - args = _prepare_paramspec_params(self, args) - new_args = self._determine_new_args(args) r = self.copy_with(new_args) return r @@ -1410,30 +1406,16 @@ def _determine_new_args(self, args): params = self.__parameters__ # In the example above, this would be {T3: str} - new_arg_by_param = {} - typevartuple_index = None - for i, param in enumerate(params): - if isinstance(param, TypeVarTuple): - if typevartuple_index is not None: - raise TypeError(f"More than one TypeVarTuple parameter in {self}") - typevartuple_index = i - + for param in params: + prepare = getattr(param, '__typing_prepare_subst__', None) + if prepare is not None: + args = prepare(self, args) alen = len(args) plen = len(params) - if typevartuple_index is not None: - i = typevartuple_index - j = alen - (plen - i - 1) - if j < i: - raise TypeError(f"Too few arguments for {self};" - f" actual {alen}, expected at least {plen-1}") - new_arg_by_param.update(zip(params[:i], args[:i])) - new_arg_by_param[params[i]] = tuple(args[i: j]) - new_arg_by_param.update(zip(params[i + 1:], args[j:])) - else: - if alen != plen: - raise TypeError(f"Too {'many' if alen > plen else 'few'} arguments for {self};" - f" actual {alen}, expected {plen}") - new_arg_by_param.update(zip(params, args)) + if alen != plen: + raise TypeError(f"Too {'many' if alen > plen else 'few'} arguments for {self};" + f" actual {alen}, expected {plen}") + new_arg_by_param = dict(zip(params, args)) new_args = [] for old_arg in self.__args__: diff --git a/Misc/NEWS.d/next/Library/2022-06-01-11-24-13.gh-issue-91162.NxvU_u.rst b/Misc/NEWS.d/next/Library/2022-06-01-11-24-13.gh-issue-91162.NxvU_u.rst new file mode 100644 index 00000000000000..09fa47c0d23840 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-06-01-11-24-13.gh-issue-91162.NxvU_u.rst @@ -0,0 +1,5 @@ +Support splitting of unpacked arbitrary-length tuple over ``TypeVar`` and +``TypeVarTuple`` parameters. For example: + +* ``A[T, *Ts][*tuple[int, ...]]`` -> ``A[int, *tuple[int, ...]]`` +* ``A[*Ts, T][*tuple[int, ...]]`` -> ``A[*tuple[int, ...], int]`` diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 59420816496f09..0a0d0cc4c15b68 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -269,7 +269,7 @@ _Py_make_parameters(PyObject *args) a non-empty tuple, return a new reference to obj. */ static PyObject * subs_tvars(PyObject *obj, PyObject *params, - PyObject **argitems, Py_ssize_t nargs, Py_ssize_t varparam) + PyObject **argitems, Py_ssize_t nargs) { PyObject *subparams; if (_PyObject_LookupAttr(obj, &_Py_ID(__parameters__), &subparams) < 0) { @@ -283,28 +283,28 @@ subs_tvars(PyObject *obj, PyObject *params, Py_DECREF(subparams); return NULL; } - for (Py_ssize_t i = 0, j = 0; i < nsubargs; ++i) { + Py_ssize_t j = 0; + for (Py_ssize_t i = 0; i < nsubargs; ++i) { PyObject *arg = PyTuple_GET_ITEM(subparams, i); Py_ssize_t iparam = tuple_index(params, nparams, arg); - if (iparam == varparam) { - j = tuple_extend(&subargs, j, - argitems + iparam, nargs - nparams + 1); - if (j < 0) { - return NULL; - } - } - else { - if (iparam >= 0) { - if (iparam > varparam) { - iparam += nargs - nparams; + if (iparam >= 0) { + PyObject *param = PyTuple_GET_ITEM(params, iparam); + arg = argitems[iparam]; + if (Py_TYPE(param)->tp_iter && PyTuple_Check(arg)) { // TypeVarTuple + j = tuple_extend(&subargs, j, + &PyTuple_GET_ITEM(arg, 0), + PyTuple_GET_SIZE(arg)); + if (j < 0) { + return NULL; } - arg = argitems[iparam]; + continue; } - Py_INCREF(arg); - PyTuple_SET_ITEM(subargs, j, arg); - j++; } + Py_INCREF(arg); + PyTuple_SET_ITEM(subargs, j, arg); + j++; } + assert(j == PyTuple_GET_SIZE(subargs)); obj = PyObject_GetItem(obj, subargs); @@ -409,39 +409,37 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje self); } item = _unpack_args(item); - int is_tuple = PyTuple_Check(item); - Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1; - PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item; - Py_ssize_t varparam = nparams; for (Py_ssize_t i = 0; i < nparams; i++) { PyObject *param = PyTuple_GET_ITEM(parameters, i); - if (Py_TYPE(param)->tp_iter) { // TypeVarTuple - if (varparam < nparams) { - Py_DECREF(item); - return PyErr_Format(PyExc_TypeError, - "More than one TypeVarTuple parameter in %S", - self); - } - varparam = i; - } - } - if (varparam < nparams) { - if (nitems < nparams - 1) { + PyObject *prepare, *tmp; + if (_PyObject_LookupAttr(param, &_Py_ID(__typing_prepare_subst__), &prepare) < 0) { Py_DECREF(item); - return PyErr_Format(PyExc_TypeError, - "Too few arguments for %R", - self); + return NULL; } - } - else { - if (nitems != nparams) { - Py_DECREF(item); - return PyErr_Format(PyExc_TypeError, - "Too %s arguments for %R; actual %zd, expected %zd", - nitems > nparams ? "many" : "few", - self, nitems, nparams); + if (prepare && prepare != Py_None) { + if (PyTuple_Check(item)) { + tmp = PyObject_CallFunction(prepare, "OO", self, item); + } + else { + tmp = PyObject_CallFunction(prepare, "O(O)", self, item); + } + Py_DECREF(prepare); + Py_SETREF(item, tmp); + if (item == NULL) { + return NULL; + } } } + int is_tuple = PyTuple_Check(item); + Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1; + PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item; + if (nitems != nparams) { + Py_DECREF(item); + return PyErr_Format(PyExc_TypeError, + "Too %s arguments for %R; actual %zd, expected %zd", + nitems > nparams ? "many" : "few", + self, nitems, nparams); + } /* Replace all type variables (specified by parameters) with corresponding values specified by argitems. t = list[T]; t[int] -> newargs = [int] @@ -471,22 +469,11 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje if (subst) { Py_ssize_t iparam = tuple_index(parameters, nparams, arg); assert(iparam >= 0); - if (iparam == varparam) { - Py_DECREF(subst); - Py_DECREF(newargs); - Py_DECREF(item); - PyErr_SetString(PyExc_TypeError, - "Substitution of bare TypeVarTuple is not supported"); - return NULL; - } - if (iparam > varparam) { - iparam += nitems - nparams; - } arg = PyObject_CallOneArg(subst, argitems[iparam]); Py_DECREF(subst); } else { - arg = subs_tvars(arg, parameters, argitems, nitems, varparam); + arg = subs_tvars(arg, parameters, argitems, nitems); } if (arg == NULL) { Py_DECREF(newargs); From a5faeacf8011c8ac5156ac940ea208d761cb32d9 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Sun, 12 Jun 2022 18:44:36 +0100 Subject: [PATCH 2/2] Regenerate ABI file --- Doc/data/python3.11.abi | 4348 ++++++++++++++++++++------------------- 1 file changed, 2182 insertions(+), 2166 deletions(-) diff --git a/Doc/data/python3.11.abi b/Doc/data/python3.11.abi index c5a1fdaea6fffc..ebbc75f05ff232 100644 --- a/Doc/data/python3.11.abi +++ b/Doc/data/python3.11.abi @@ -1637,7 +1637,7 @@ - + @@ -1658,7 +1658,7 @@ - + @@ -1672,7 +1672,7 @@ - + @@ -1698,7 +1698,7 @@ - + @@ -1993,7 +1993,7 @@ - + @@ -2051,7 +2051,7 @@ - + @@ -2267,7 +2267,7 @@ - + @@ -2485,7 +2485,7 @@ - + @@ -2872,12 +2872,12 @@ - + - + @@ -2890,10 +2890,10 @@ - + - + @@ -2949,18 +2949,18 @@ - + - + - - + + - - + + @@ -3172,7 +3172,7 @@ - + @@ -3624,463 +3624,466 @@ - + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + @@ -4088,12 +4091,12 @@ - + - - + + @@ -4101,12 +4104,12 @@ - + - - + + @@ -4114,12 +4117,12 @@ - + - - + + @@ -4127,12 +4130,12 @@ - + - - + + @@ -4140,12 +4143,12 @@ - + - - + + @@ -4153,12 +4156,12 @@ - + - - + + @@ -4166,12 +4169,12 @@ - + - - + + @@ -4179,12 +4182,12 @@ - + - - + + @@ -4192,12 +4195,12 @@ - + - - + + @@ -4205,12 +4208,12 @@ - + - - + + @@ -4218,12 +4221,12 @@ - + - - + + @@ -4231,12 +4234,12 @@ - + - - + + @@ -4244,80 +4247,93 @@ - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + + + + + + + + + + + + + + - + - + - + - + - + @@ -4331,36 +4347,36 @@ - + - - + + - + - + - + - - - + + + - + - + - + @@ -4374,10 +4390,10 @@ - + - + @@ -4388,7 +4404,7 @@ - + @@ -4397,17 +4413,17 @@ - + - + - + - + @@ -4425,16 +4441,16 @@ - + - + - + - + @@ -4452,7 +4468,7 @@ - + @@ -4464,12 +4480,12 @@ - + - - + + @@ -4481,11 +4497,11 @@ - + - + @@ -4544,16 +4560,16 @@ - + - + - + - + @@ -4628,7 +4644,7 @@ - + @@ -4676,24 +4692,24 @@ - + - + - - - - - - - + + + + + + + - + @@ -4712,7 +4728,7 @@ - + @@ -4721,7 +4737,7 @@ - + @@ -4732,18 +4748,18 @@ - - - + + + - + - + - + @@ -4754,10 +4770,10 @@ - + - + @@ -4769,8 +4785,8 @@ - - + + @@ -4783,21 +4799,21 @@ - + - + - + - - - - + + + + @@ -4811,36 +4827,36 @@ - - + + - + - + - + - - + + - - + + - + - + @@ -4851,28 +4867,28 @@ - - + + - - + + - + - + - + @@ -4883,13 +4899,13 @@ - + - + - + @@ -4912,80 +4928,80 @@ - + - + - - - + + + - + - - - - + + + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - + - + - + - + @@ -4994,14 +5010,14 @@ - - - + + + - + @@ -5010,21 +5026,21 @@ - + - - - - + + + + - + @@ -5033,7 +5049,7 @@ - + @@ -5059,8 +5075,8 @@ - - + + @@ -5773,10 +5789,10 @@ - + - + @@ -5788,8 +5804,8 @@ - - + + @@ -5803,44 +5819,44 @@ - + - + - - - - - - - - + + + + + + + + - + - - + + - + - + - + - + @@ -5917,9 +5933,9 @@ - - - + + + @@ -5930,27 +5946,27 @@ - + - + - + - + - - - - - + + + + + - + @@ -5959,16 +5975,16 @@ - + - - - - - - + + + + + + @@ -6006,10 +6022,10 @@ - + - + @@ -6018,31 +6034,31 @@ - + - + - + - + - + - + - + - + @@ -6054,34 +6070,34 @@ - + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - - - + + + + - - + + @@ -6128,9 +6144,9 @@ - + - + @@ -6149,22 +6165,22 @@ - - - + + + - + - + - + @@ -6226,7 +6242,7 @@ - + @@ -6261,16 +6277,16 @@ - - - + + + - + - + @@ -6687,10 +6703,10 @@ - - + + - + @@ -6700,27 +6716,27 @@ - - + + - + - + - - + + - + @@ -6730,23 +6746,23 @@ - + - + - + - + - + @@ -6801,8 +6817,8 @@ - - + + @@ -6810,31 +6826,31 @@ - - + + - + - + - + - + - + - + @@ -6843,37 +6859,37 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -6904,7 +6920,7 @@ - + @@ -6914,7 +6930,7 @@ - + @@ -6934,51 +6950,51 @@ - + - - + + - - + + - + - + - + - + - + - + - + @@ -7031,10 +7047,10 @@ - + - + @@ -7058,7 +7074,7 @@ - + @@ -7073,7 +7089,7 @@ - + @@ -7087,10 +7103,10 @@ - + - + @@ -7103,7 +7119,7 @@ - + @@ -7114,7 +7130,7 @@ - + @@ -7122,11 +7138,11 @@ - - + + - + @@ -7145,7 +7161,7 @@ - + @@ -7159,7 +7175,7 @@ - + @@ -7311,7 +7327,7 @@ - + @@ -7323,10 +7339,10 @@ - + - + @@ -7345,7 +7361,7 @@ - + @@ -7364,11 +7380,11 @@ - + - + @@ -7384,7 +7400,7 @@ - + @@ -7426,14 +7442,14 @@ - + - + @@ -7445,27 +7461,27 @@ - + - + - + - - - - + + + + - + - + - + @@ -7473,7 +7489,7 @@ - + @@ -7493,7 +7509,7 @@ - + @@ -7514,9 +7530,9 @@ - + - + @@ -7566,83 +7582,83 @@ - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - + @@ -7664,7 +7680,7 @@ - + @@ -7675,7 +7691,7 @@ - + @@ -7687,12 +7703,12 @@ - - - + + + - + @@ -7716,18 +7732,18 @@ - + - + - + @@ -7956,15 +7972,15 @@ - + - + - + @@ -7972,15 +7988,15 @@ - + - + - + @@ -7998,12 +8014,12 @@ - + - + - + @@ -8015,16 +8031,16 @@ - + - + - + - + @@ -8036,10 +8052,10 @@ - + - + @@ -8089,30 +8105,30 @@ - - - - - - + + + + + + - + - + - + - + @@ -8130,7 +8146,7 @@ - + @@ -8152,7 +8168,7 @@ - + @@ -8193,127 +8209,127 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + @@ -8385,7 +8401,7 @@ - + @@ -8400,7 +8416,7 @@ - + @@ -8414,7 +8430,7 @@ - + @@ -8431,7 +8447,7 @@ - + @@ -8479,17 +8495,17 @@ - + - + - + - + @@ -8516,13 +8532,13 @@ - + - + - + - + @@ -8537,19 +8553,19 @@ - + - + - + @@ -8557,10 +8573,10 @@ - + - + @@ -8572,7 +8588,7 @@ - + @@ -8581,18 +8597,18 @@ - + - - - + + + - + @@ -8630,7 +8646,7 @@ - + @@ -8661,19 +8677,19 @@ - + - - + + - - + + - + @@ -8713,11 +8729,11 @@ - + - + @@ -8737,15 +8753,15 @@ - + - + - + @@ -8779,7 +8795,7 @@ - + @@ -8790,7 +8806,7 @@ - + @@ -8801,7 +8817,7 @@ - + @@ -8816,7 +8832,7 @@ - + @@ -8881,13 +8897,13 @@ - + - + @@ -8931,7 +8947,7 @@ - + @@ -8976,11 +8992,11 @@ - + - + @@ -9001,12 +9017,12 @@ - + - + @@ -9022,7 +9038,7 @@ - + @@ -9032,7 +9048,7 @@ - + @@ -9066,7 +9082,7 @@ - + @@ -9085,9 +9101,9 @@ - + - + @@ -9102,7 +9118,7 @@ - + @@ -9114,12 +9130,12 @@ - + - + @@ -9128,9 +9144,9 @@ - - - + + + @@ -9138,13 +9154,13 @@ - - - - + + + + - + @@ -9178,22 +9194,22 @@ - + - + - + - + @@ -9206,27 +9222,27 @@ - + - + - + - + - + - + @@ -9296,7 +9312,7 @@ - + @@ -9381,7 +9397,7 @@ - + @@ -9398,13 +9414,13 @@ - + - + @@ -9480,7 +9496,7 @@ - + @@ -9492,21 +9508,21 @@ - + - + - + - + @@ -9535,10 +9551,10 @@ - - + + - + @@ -9547,19 +9563,19 @@ - + - + - + - + @@ -9594,10 +9610,10 @@ - - + + - + @@ -9636,66 +9652,66 @@ - + - + - + - - - - + + + + - + - + - + - - + + - + - + - + - + - - - - - + + + + + - - + + - - + + @@ -9704,7 +9720,7 @@ - + @@ -9714,52 +9730,52 @@ - + - + - + - + - - + + - + - + - + - + - + - + @@ -9767,19 +9783,19 @@ - + - + - + @@ -9797,7 +9813,7 @@ - + @@ -9832,7 +9848,7 @@ - + @@ -9887,9 +9903,9 @@ - + - + @@ -9897,13 +9913,13 @@ - + - + @@ -9911,32 +9927,32 @@ - - - - + + + + - + - + - + - + - + @@ -9956,11 +9972,11 @@ - + - + @@ -10003,7 +10019,7 @@ - + @@ -10017,7 +10033,7 @@ - + @@ -10027,7 +10043,7 @@ - + @@ -10051,7 +10067,7 @@ - + @@ -10065,10 +10081,10 @@ - + - + @@ -10076,22 +10092,22 @@ - - - - + + + + - + - + - + @@ -10110,7 +10126,7 @@ - + @@ -10160,14 +10176,14 @@ - + - + - - + + @@ -10199,55 +10215,55 @@ - + - + - + - + - + - + - - + + - - + + - + - + - + @@ -10332,7 +10348,7 @@ - + @@ -10364,14 +10380,14 @@ - + - + @@ -10395,7 +10411,7 @@ - + @@ -10416,9 +10432,9 @@ - + - + @@ -10426,7 +10442,7 @@ - + @@ -10530,7 +10546,7 @@ - + @@ -10547,7 +10563,7 @@ - + @@ -10555,7 +10571,7 @@ - + @@ -10572,7 +10588,7 @@ - + @@ -10580,7 +10596,7 @@ - + @@ -10592,29 +10608,29 @@ - + - - - - + + + + - + - + - - - - + + + + @@ -10656,13 +10672,13 @@ - + - + @@ -10672,22 +10688,22 @@ - - - + + + - + - + - + - + @@ -10816,19 +10832,19 @@ - + - + - + - + @@ -10838,7 +10854,7 @@ - + @@ -10852,7 +10868,7 @@ - + @@ -10865,12 +10881,12 @@ - + - + @@ -10901,7 +10917,7 @@ - + @@ -10911,116 +10927,116 @@ - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + @@ -11042,7 +11058,7 @@ - + @@ -11056,27 +11072,27 @@ - + - + - - + + - + - + - + @@ -11129,22 +11145,22 @@ - + - + - + - + @@ -11174,7 +11190,7 @@ - + @@ -11182,10 +11198,10 @@ - - + + - + @@ -11195,7 +11211,7 @@ - + @@ -11206,14 +11222,14 @@ - + - + @@ -11245,7 +11261,7 @@ - + @@ -11335,7 +11351,7 @@ - + @@ -11375,21 +11391,21 @@ - - + + - + - + - + @@ -11414,13 +11430,13 @@ - + - + @@ -11471,7 +11487,7 @@ - + @@ -11592,16 +11608,16 @@ - + - + - - - - + + + + @@ -11620,60 +11636,60 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -11688,7 +11704,7 @@ - + @@ -11718,144 +11734,144 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -11870,12 +11886,12 @@ - + - + - + @@ -11890,7 +11906,7 @@ - + @@ -11920,143 +11936,143 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - - - + + + - + - + - + - + - + - + - + @@ -12072,172 +12088,172 @@ - - + + - + - + - + - - + + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + @@ -12252,277 +12268,277 @@ - - + + - + - - - + + + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + @@ -12537,7 +12553,7 @@ - + @@ -12548,161 +12564,161 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - - + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -12717,65 +12733,65 @@ - + - + - + - + - + - + - + - - + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + @@ -12790,116 +12806,116 @@ - - + + - + - - - + + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - - + + + - + - + - + - + - + - + - - - - - + + + + + - + - + - - + + - + @@ -12947,7 +12963,7 @@ - + @@ -13027,7 +13043,7 @@ - + @@ -13246,14 +13262,14 @@ - + - + - + @@ -13293,12 +13309,12 @@ - + - + @@ -13319,17 +13335,17 @@ - + - - + + - + @@ -13342,7 +13358,7 @@ - + @@ -13356,22 +13372,22 @@ - - + + - - + + - + @@ -13379,21 +13395,21 @@ - + - + - + @@ -13401,23 +13417,23 @@ - - + + - - + + - + @@ -13425,7 +13441,7 @@ - + @@ -13439,13 +13455,13 @@ - + - + @@ -13487,29 +13503,29 @@ - + - + - + - - - + + + - + @@ -13518,8 +13534,8 @@ - - + + @@ -13527,48 +13543,48 @@ - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - + - + @@ -13577,78 +13593,78 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + - + - - + + - + - + - - - + + + - + - - - - - - + + + + + + - - + + - - + + - + - + - + - - + + - + @@ -13658,52 +13674,52 @@ - + - - + + - + - - + + - + - + - + - + - - + + - + - - + + - + - + @@ -13820,7 +13836,7 @@ - + @@ -13837,7 +13853,7 @@ - + @@ -13857,9 +13873,9 @@ - + - + @@ -13871,83 +13887,83 @@ - + - - + + - - + + - + - - + + - - + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - + + + + - + - + - + - + - + - - + + @@ -13961,69 +13977,69 @@ - - + + - + - - - + + + - - - + + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + @@ -14038,35 +14054,35 @@ - + - + - + - + - + - + - + @@ -14101,7 +14117,7 @@ - + @@ -14109,18 +14125,18 @@ - + - + - + @@ -14139,12 +14155,12 @@ - + - + @@ -14155,21 +14171,21 @@ - + - + - + - + @@ -14189,44 +14205,44 @@ - + - + - + - + - + - - - + + + - + - + @@ -14234,20 +14250,20 @@ - + - + - + - + - + @@ -14255,34 +14271,34 @@ - + - + - - - + + + - - - + + + - - + + - + - + - + @@ -14290,75 +14306,75 @@ - + - - - + + + - + - + - + - + - - + + - + - - + + - + - - - + + + - - + + - + - + - + - + - + - + - + @@ -14366,7 +14382,7 @@ - + @@ -14374,50 +14390,50 @@ - + - + - - + + - + - + - - - + + + - + - + - + - - - - - + + + + + - + @@ -14434,37 +14450,37 @@ - + - + - + - - - - + + + + - - + + - + - + - + @@ -14477,7 +14493,7 @@ - + @@ -14523,7 +14539,7 @@ - + @@ -14533,39 +14549,39 @@ - - + + - - - + + + - - + + - - + + - + - - + + - + - - + + - - - + + + - + @@ -14597,24 +14613,24 @@ - + - + - + - + - + - + @@ -14651,18 +14667,18 @@ - + - + - + - + @@ -14708,7 +14724,7 @@ - + @@ -14725,9 +14741,9 @@ - + - + @@ -14737,9 +14753,9 @@ - + - + @@ -14759,22 +14775,22 @@ - + - + - + - + @@ -14845,26 +14861,26 @@ - - + + - + - - + + - + - + - + @@ -14872,7 +14888,7 @@ - + @@ -14893,27 +14909,27 @@ - + - + - + - + - + @@ -14922,7 +14938,7 @@ - + @@ -14930,19 +14946,19 @@ - + - + - + - + @@ -14950,7 +14966,7 @@ - + @@ -14958,7 +14974,7 @@ - + @@ -14966,18 +14982,18 @@ - + - + - + @@ -14985,7 +15001,7 @@ - + @@ -15013,80 +15029,80 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - + + + @@ -15121,22 +15137,22 @@ - + - - + + - - + + - + - - + + @@ -15147,54 +15163,54 @@ - + - - + + - - + + - - + + - + - - + + - + - + - + - + - - + + - - + + - - + + - - + + @@ -15202,135 +15218,135 @@ - + - - - - + + + + - + - + - + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - + - - + + - + - + - + - + - - + + - - + + - + - - + + - + - + - - - + + + - - - + + + - - + + - + - + - - - - + + + + - - - + + + - + @@ -15342,16 +15358,16 @@ - + - + - + - + @@ -15364,9 +15380,9 @@ - + - + @@ -15389,7 +15405,7 @@ - + @@ -15407,7 +15423,7 @@ - + @@ -15446,18 +15462,18 @@ - + - + - - + + @@ -15465,16 +15481,16 @@ - - + + - + - + @@ -15492,7 +15508,7 @@ - + @@ -15501,8 +15517,8 @@ - - + + @@ -15510,18 +15526,18 @@ - - - - - + + + + + - + - + - + @@ -15544,31 +15560,31 @@ - + - + - + - + - + @@ -15608,21 +15624,21 @@ - + - + - + - + - + @@ -15632,20 +15648,20 @@ - + - + - + - + @@ -15676,27 +15692,27 @@ - + - + - + - + - + @@ -15723,7 +15739,7 @@ - + @@ -15743,7 +15759,7 @@ - + @@ -15771,7 +15787,7 @@ - + @@ -15793,21 +15809,21 @@ - + - + - + - + - + @@ -15820,77 +15836,77 @@ - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - - + + + @@ -15899,21 +15915,21 @@ - - + + - + - + - + - + @@ -15921,7 +15937,7 @@ - + @@ -15929,7 +15945,7 @@ - + @@ -15937,13 +15953,13 @@ - + - + @@ -16017,9 +16033,9 @@ - + - + @@ -16048,13 +16064,13 @@ - + - + @@ -16080,12 +16096,12 @@ - + - - - + + + @@ -16100,93 +16116,93 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - + - + - + - + - + @@ -16196,36 +16212,36 @@ - - - - + + + + - + - - + + - - + + - + - - - + + + - + @@ -16239,7 +16255,7 @@ - + @@ -16247,30 +16263,30 @@ - + - + - + - + - + - + - + @@ -16284,14 +16300,14 @@ - + - + - + @@ -16325,21 +16341,21 @@ - + - + - - + + - + @@ -16348,26 +16364,26 @@ - - + + - + - - + + - + - + - + @@ -16383,7 +16399,7 @@ - + @@ -16418,20 +16434,20 @@ - + - + - + - + @@ -16439,130 +16455,130 @@ - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + @@ -16571,15 +16587,15 @@ - + - - - - - - + + + + + + @@ -16587,9 +16603,9 @@ - - - - + + + + pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy