forked from pool/python-itemadapter
- 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
This commit is contained in:
23
.gitattributes
vendored
Normal file
23
.gitattributes
vendored
Normal file
@@ -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
|
||||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.osc
|
||||||
3
_multibuild
Normal file
3
_multibuild
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<multibuild>
|
||||||
|
<package>test</package>
|
||||||
|
</multibuild>
|
||||||
3
itemadapter-0.11.0.tar.gz
Normal file
3
itemadapter-0.11.0.tar.gz
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4f5db3ba87d4b9938965f7d208a645cfd6563cdcd2166eb0cadb6a9acb6b08bd
|
||||||
|
size 19493
|
||||||
3
itemadapter-0.9.0.tar.gz
Normal file
3
itemadapter-0.9.0.tar.gz
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:2d848f6a9815161d97aaa18c663766e045c3daa92f98d921a3cd594b6161972f
|
||||||
|
size 17324
|
||||||
148
pydantic2.patch
Normal file
148
pydantic2.patch
Normal file
@@ -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")
|
||||||
99
python-itemadapter.changes
Normal file
99
python-itemadapter.changes
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Feb 7 15:04:35 UTC 2025 - John Paul Adrian Glaubitz <adrian.glaubitz@suse.com>
|
||||||
|
|
||||||
|
- 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 <dmueller@suse.com>
|
||||||
|
|
||||||
|
- 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 <daniel.garcia@suse.com>
|
||||||
|
|
||||||
|
- Add pydantic2.patch to make tests compatible with pydantic2
|
||||||
|
gh#scrapy/itemadapter#76
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Dec 7 22:47:54 UTC 2023 - Dirk Müller <dmueller@suse.com>
|
||||||
|
|
||||||
|
- 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 <yarunachalam@suse.com>
|
||||||
|
|
||||||
|
- 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 <code@bnavigator.de>
|
||||||
|
|
||||||
|
- 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 <tchvatal@suse.com>
|
||||||
|
|
||||||
|
- Switch to multibuild
|
||||||
|
- Fix the sitelib/sitearch and all the dependencies
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Jul 7 23:30:56 UTC 2020 - Jacob W <jacob@jacobwinski.com>
|
||||||
|
|
||||||
|
- 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 <jacob@jacobwinski.com>
|
||||||
|
|
||||||
|
- Initial package of python-itemadapter version 0.1.0
|
||||||
81
python-itemadapter.spec
Normal file
81
python-itemadapter.spec
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#
|
||||||
|
# spec file for package python-itemadapter
|
||||||
|
#
|
||||||
|
# Copyright (c) 2025 SUSE LLC
|
||||||
|
# Copyright (c) 2016, Martin Hauke <mardnh@gmx.de>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
Reference in New Issue
Block a user