From 4354f02ac3a985e5b594e18913150b46ff31813c33f9f67280e05680364e4901 Mon Sep 17 00:00:00 2001 From: Matej Cepl Date: Fri, 7 Feb 2025 19:05:49 +0000 Subject: [PATCH] - Update to 0.11.0 * Removed functions deprecated in 0.5.0: (#93) - `itemadapter.utils.is_attrs_instance()` - `itemadapter.utils.is_dataclass_instance()` - `itemadapter.utils.is_pydantic_instance()` - `itemadapter.utils.is_scrapy_item()` * Added support for Pydantic 2 (#91). * Added `__all__` to the top-level module to improve type checks (#90). * Improved `pre-commit` and CI configuration (#91), (#92). - from version 0.10.0 * Dropped Python 3.8 support, added official Python 3.13 and PyPy 3.10 support (#79), (#87). * Fixed the typing check when run with Scrapy 2.12.0+ (#88). * Fixed `MANIFEST.in` that was missing some files (#84). * Enabled `pre-commit` (#85). - Drop pydantic2.patch, fixed upstream - Set BuildArch to noarch OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-itemadapter?expand=0&rev=16 --- .gitattributes | 23 ++++++ .gitignore | 1 + _multibuild | 3 + itemadapter-0.11.0.tar.gz | 3 + itemadapter-0.9.0.tar.gz | 3 + pydantic2.patch | 148 +++++++++++++++++++++++++++++++++++++ python-itemadapter.changes | 99 +++++++++++++++++++++++++ python-itemadapter.spec | 81 ++++++++++++++++++++ 8 files changed, 361 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 _multibuild create mode 100644 itemadapter-0.11.0.tar.gz create mode 100644 itemadapter-0.9.0.tar.gz create mode 100644 pydantic2.patch create mode 100644 python-itemadapter.changes create mode 100644 python-itemadapter.spec diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57affb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.osc diff --git a/_multibuild b/_multibuild new file mode 100644 index 0000000..fcc7b97 --- /dev/null +++ b/_multibuild @@ -0,0 +1,3 @@ + + test + diff --git a/itemadapter-0.11.0.tar.gz b/itemadapter-0.11.0.tar.gz new file mode 100644 index 0000000..49a2063 --- /dev/null +++ b/itemadapter-0.11.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f5db3ba87d4b9938965f7d208a645cfd6563cdcd2166eb0cadb6a9acb6b08bd +size 19493 diff --git a/itemadapter-0.9.0.tar.gz b/itemadapter-0.9.0.tar.gz new file mode 100644 index 0000000..b63e4f1 --- /dev/null +++ b/itemadapter-0.9.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d848f6a9815161d97aaa18c663766e045c3daa92f98d921a3cd594b6161972f +size 17324 diff --git a/pydantic2.patch b/pydantic2.patch new file mode 100644 index 0000000..b0e6c41 --- /dev/null +++ b/pydantic2.patch @@ -0,0 +1,148 @@ +Index: itemadapter-0.8.0/README.md +=================================================================== +--- itemadapter-0.8.0.orig/README.md ++++ itemadapter-0.8.0/README.md +@@ -193,7 +193,7 @@ The returned value is taken from the fol + for `dataclass`-based items + * [`attr.Attribute.metadata`](https://www.attrs.org/en/stable/examples.html#metadata) + for `attrs`-based items +- * [`pydantic.fields.FieldInfo`](https://pydantic-docs.helpmanual.io/usage/schema/#field-customisation) ++ * [`pydantic.fields.FieldInfo`](https://docs.pydantic.dev/latest/api/fields/#pydantic.fields.FieldInfo) + for `pydantic`-based items + + #### class method `get_field_names_from_class(item_class: type) -> Optional[list[str]]` +Index: itemadapter-0.8.0/itemadapter/adapter.py +=================================================================== +--- itemadapter-0.8.0.orig/itemadapter/adapter.py ++++ itemadapter-0.8.0/itemadapter/adapter.py +@@ -179,24 +179,24 @@ class PydanticAdapter(AdapterInterface): + + @classmethod + def get_field_names_from_class(cls, item_class: type) -> Optional[List[str]]: +- return list(item_class.__fields__.keys()) # type: ignore[attr-defined] ++ return list(item_class.model_fields.keys()) # type: ignore[attr-defined] + + def field_names(self) -> KeysView: +- return KeysView(self.item.__fields__) ++ return KeysView(self.item.model_fields) + + def __getitem__(self, field_name: str) -> Any: +- if field_name in self.item.__fields__: ++ if field_name in self.item.model_fields: + return getattr(self.item, field_name) + raise KeyError(field_name) + + def __setitem__(self, field_name: str, value: Any) -> None: +- if field_name in self.item.__fields__: ++ if field_name in self.item.model_fields: + setattr(self.item, field_name, value) + else: + raise KeyError(f"{self.item.__class__.__name__} does not support field: {field_name}") + + def __delitem__(self, field_name: str) -> None: +- if field_name in self.item.__fields__: ++ if field_name in self.item.model_fields: + try: + delattr(self.item, field_name) + except AttributeError: +@@ -205,7 +205,7 @@ class PydanticAdapter(AdapterInterface): + raise KeyError(f"{self.item.__class__.__name__} does not support field: {field_name}") + + def __iter__(self) -> Iterator: +- return iter(attr for attr in self.item.__fields__ if hasattr(self.item, attr)) ++ return iter(attr for attr in self.item.model_fields if hasattr(self.item, attr)) + + def __len__(self) -> int: + return len(list(iter(self))) +Index: itemadapter-0.8.0/itemadapter/utils.py +=================================================================== +--- itemadapter-0.8.0.orig/itemadapter/utils.py ++++ itemadapter-0.8.0/itemadapter/utils.py +@@ -23,30 +23,21 @@ def _is_pydantic_model(obj: Any) -> bool + + def _get_pydantic_model_metadata(item_model: Any, field_name: str) -> MappingProxyType: + metadata = {} +- field = item_model.__fields__[field_name].field_info ++ field = item_model.model_fields[field_name] + + for attribute in [ + "alias", + "title", + "description", +- "const", +- "gt", +- "ge", +- "lt", +- "le", +- "multiple_of", +- "min_items", +- "max_items", +- "min_length", +- "max_length", +- "regex", + ]: + value = getattr(field, attribute) + if value is not None: + metadata[attribute] = value +- if not field.allow_mutation: +- metadata["allow_mutation"] = field.allow_mutation +- metadata.update(field.extra) ++ if field.frozen is not None: ++ metadata["frozen"] = field.frozen ++ ++ if field.json_schema_extra is not None: ++ metadata.update(field.json_schema_extra) + + return MappingProxyType(metadata) + +Index: itemadapter-0.8.0/tests/__init__.py +=================================================================== +--- itemadapter-0.8.0.orig/tests/__init__.py ++++ itemadapter-0.8.0/tests/__init__.py +@@ -102,7 +102,7 @@ else: + + + try: +- from pydantic import BaseModel, Field as PydanticField ++ from pydantic import ConfigDict, BaseModel, Field as PydanticField + except ImportError: + PydanticModel = None + PydanticSpecialCasesModel = None +@@ -125,11 +125,9 @@ else: + special_cases: Optional[int] = PydanticField( + default_factory=lambda: None, + alias="special_cases", +- allow_mutation=False, ++ frozen=False, + ) +- +- class Config: +- validate_assignment = True ++ model_config = ConfigDict(validate_assignment=True) + + class PydanticModelNested(BaseModel): + nested: PydanticModel +@@ -139,9 +137,7 @@ else: + set_: set + tuple_: tuple + int_: int +- +- class Config: +- arbitrary_types_allowed = True ++ model_config = ConfigDict(arbitrary_types_allowed=True) + + class PydanticModelSubclassed(PydanticModel): + subclassed: bool = PydanticField( +Index: itemadapter-0.8.0/tests/test_adapter_pydantic.py +=================================================================== +--- itemadapter-0.8.0.orig/tests/test_adapter_pydantic.py ++++ itemadapter-0.8.0/tests/test_adapter_pydantic.py +@@ -73,7 +73,7 @@ class DataclassTestCase(unittest.TestCas + ) + self.assertEqual( + get_field_meta_from_class(PydanticSpecialCasesModel, "special_cases"), +- MappingProxyType({"alias": "special_cases", "allow_mutation": False}), ++ MappingProxyType({"alias": "special_cases", "frozen": False}), + ) + with self.assertRaises(KeyError, msg="PydanticModel does not support field: non_existent"): + get_field_meta_from_class(PydanticModel, "non_existent") diff --git a/python-itemadapter.changes b/python-itemadapter.changes new file mode 100644 index 0000000..e543c48 --- /dev/null +++ b/python-itemadapter.changes @@ -0,0 +1,99 @@ +------------------------------------------------------------------- +Fri Feb 7 15:04:35 UTC 2025 - John Paul Adrian Glaubitz + +- Update to 0.11.0 + * Removed functions deprecated in 0.5.0: (#93) + - `itemadapter.utils.is_attrs_instance()` + - `itemadapter.utils.is_dataclass_instance()` + - `itemadapter.utils.is_pydantic_instance()` + - `itemadapter.utils.is_scrapy_item()` + * Added support for Pydantic 2 (#91). + * Added `__all__` to the top-level module to improve type checks (#90). + * Improved `pre-commit` and CI configuration (#91), (#92). +- from version 0.10.0 + * Dropped Python 3.8 support, added official Python + 3.13 and PyPy 3.10 support (#79), (#87). + * Fixed the typing check when run with Scrapy 2.12.0+ (#88). + * Fixed `MANIFEST.in` that was missing some files (#84). + * Enabled `pre-commit` (#85). +- Drop pydantic2.patch, fixed upstream +- Set BuildArch to noarch + +------------------------------------------------------------------- +Tue May 14 07:56:28 UTC 2024 - Dirk Müller + +- update to 0.9.0: + * Dropped Python 3.7 support, added official Python 3.12 + support + * Updated the documentation and the type hint about + `ItemAdapter.ADAPTER_CLASSES` to say that subclasses can + use any iterable, not just `collections.deque` + * Documented that `Pydantic >= 2` is not supported yet + * Updated CI configuration + +------------------------------------------------------------------- +Wed Mar 20 13:31:31 UTC 2024 - Daniel Garcia + +- Add pydantic2.patch to make tests compatible with pydantic2 + gh#scrapy/itemadapter#76 + +------------------------------------------------------------------- +Thu Dec 7 22:47:54 UTC 2023 - Dirk Müller + +- update to 0.8.0: + * Dropped Python 3.6 support, and made Python 3.11 support + official + * It is now possible to declare custom `ItemAdapter` subclasses + with their own `ADAPTER_CLASSES` attribute, allowing to + support different item types in different parts of the same + code base + * Improved type hint support + +------------------------------------------------------------------- +Thu Sep 29 02:54:38 UTC 2022 - Yogalakshmi Arunachalam + +- Update to 0.7.0 (2022-08-02) + ItemAdapter.get_field_names_from_class (#64) + +- Update to 0.6.0 (2022-05-12) + Slight performance improvement (#62) + +- Update to 0.5.0 (2022-03-18) + Improve performance by removing imports inside functions (#60) + +------------------------------------------------------------------- +Sat Oct 30 13:06:13 UTC 2021 - Ben Greiner + +- Update to v0.4.0 + * Added ItemAdapter.is_item_class and + ItemAdapter.get_field_meta_from_class (#54) + * Added built-in support for pydantic models (#53) + * Adapter interface: added the ability to support arbitrary + types, by implementing a MutableMapping-based interface. By way + of this change, now any type can be used as a Scrapy item. + * Dropped support for Python 3.5 (#38). + * The new get_field_meta_from_class function offers the same + functionality as ItemAdapter.get_field_meta but for an item + class, as opposed to an item object (#34, #35). + * ItemAdapter.__repr__ no longer raises exceptions caused by the + underlying item (#31, #41). +- Disable python36 build due to Scrapy + +------------------------------------------------------------------- +Wed Jul 8 06:54:27 UTC 2020 - Tomáš Chvátal + +- Switch to multibuild +- Fix the sitelib/sitearch and all the dependencies + +------------------------------------------------------------------- +Tue Jul 7 23:30:56 UTC 2020 - Jacob W + +- Update spec file: + * Change to github archive, which includes tests. + * Enable tests. + * Add BuildRequires that is required for tests to pass. + +------------------------------------------------------------------- +Thu Jul 2 20:16:51 UTC 2020 - Jacob W + +- Initial package of python-itemadapter version 0.1.0 diff --git a/python-itemadapter.spec b/python-itemadapter.spec new file mode 100644 index 0000000..20145b2 --- /dev/null +++ b/python-itemadapter.spec @@ -0,0 +1,81 @@ +# +# spec file for package python-itemadapter +# +# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2016, Martin Hauke +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + + +%global flavor @BUILD_FLAVOR@%{nil} +%if "%{flavor}" == "test" +%define psuffix -test +%bcond_without test +%else +%define psuffix %{nil} +%bcond_with test +%endif +%{?sle15_python_module_pythons} +Name: python-itemadapter%{psuffix} +Version: 0.11.0 +Release: 0 +Summary: Wrapper for data container objects +License: BSD-3-Clause +URL: https://github.com/scrapy/itemadapter +Source: https://github.com/scrapy/itemadapter/archive/v%{version}.tar.gz#/itemadapter-%{version}.tar.gz +BuildRequires: %{python_module pip} +BuildRequires: %{python_module setuptools >= 40.5.0} +BuildRequires: %{python_module wheel} +BuildRequires: fdupes +BuildRequires: python-rpm-macros +%if %{with test} +BuildRequires: %{python_module Scrapy >= 2.0} +BuildRequires: %{python_module attrs} +BuildRequires: %{python_module itemadapter >= %{version}} +BuildRequires: %{python_module pydantic} +BuildRequires: %{python_module pytest >= 5.4} +%endif +BuildArch: noarch +%python_subpackages + +%description +The ItemAdapter class is a wrapper for data container objects, providing +a common interface to handle objects of different types in an uniform +manner, regardless of their underlying implementation. + +%prep +%autosetup -p1 -n itemadapter-%{version} + +%build +%pyproject_wheel + +%install +%if !%{with test} +%pyproject_install +%python_expand %fdupes %{buildroot}%{$python_sitelib} +%endif + +%check +%if %{with test} +%pytest +%endif + +%if !%{with test} +%files %{python_files} +%license LICENSE +%doc README.md +%{python_sitelib}/itemadapter +%{python_sitelib}/itemadapter-%{version}.dist-info +%endif + +%changelog