diff --git a/src/ezdxf/entities/dxfns.py b/src/ezdxf/entities/dxfns.py index e22a84d40..4fde9caa0 100644 --- a/src/ezdxf/entities/dxfns.py +++ b/src/ezdxf/entities/dxfns.py @@ -86,6 +86,15 @@ def copy(self, entity: DXFEntity): def __deepcopy__(self, memodict: Optional[dict] = None): return self.copy(self._entity) + def __getstate__(self) -> object: + return self.__dict__ + + def __setstate__(self, state: object) -> None: + if not isinstance(state, dict): + raise TypeError(f"invalid state: {type(state).__name__}") + # bypass __setattr__ + object.__setattr__(self, "__dict__", state) + def reset_handles(self): """Reset handle and owner to None.""" self.__dict__["handle"] = None diff --git a/tests/test_10_issues/test_issue_1231_pickling.py b/tests/test_10_issues/test_issue_1231_pickling.py new file mode 100644 index 000000000..c5e014cab --- /dev/null +++ b/tests/test_10_issues/test_issue_1231_pickling.py @@ -0,0 +1,36 @@ +import io +import pickle +from collections.abc import Iterator +from pathlib import Path + +import pytest + +import ezdxf +from ezdxf.document import Drawing + +EXAMPLES = Path(__file__).parent.parent.parent / "examples_dxf" + + +def example_dxfs() -> Iterator[Path]: + for item in EXAMPLES.iterdir(): + if item.suffix.lower() == ".dxf": + yield item + + +def _to_dxf_str(doc: Drawing) -> str: + stream = io.StringIO() + doc.write(stream) + return stream.getvalue() + + +def test_document_pickle(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr(ezdxf.options, "write_fixed_meta_data_for_testing", True) + + for item in example_dxfs(): + print(f"testing pickling of {item}") + + doc = ezdxf.readfile(item) + doc_serialized = pickle.dumps(doc) + doc_loaded = pickle.loads(doc_serialized) + + assert _to_dxf_str(doc) == _to_dxf_str(doc_loaded)