Repository: qiskit-community/prototype-zne (language: python)

Issue:
feat(validation): add quality descriptor
<!--
⚠️ If you do not respect this template, your pull request will be closed.
⚠️ Your pull request title should be short detailed and understandable for all.
⚠️ Also, please add a release note file using reno if the change needs to be
  documented in the release notes.
⚠️ If your pull request fixes an open issue, please link to the issue.

- [ ] I have added the tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->

### Summary
Adds `quality` descriptor similar to property but geared towards custom validation.


### Details and comments
Useful for #4



Discussion / hints:

Fix patch:
diff --git a/zne/utils/unset.py b/zne/utils/unset.py
new file mode 100644
index 0000000..aa3466d
--- /dev/null
+++ b/zne/utils/unset.py
@@ -0,0 +1,43 @@
+# This code is part of Qiskit.
+#
+# (C) Copyright IBM 2022.
+#
+# This code is licensed under the Apache License, Version 2.0. You may
+# obtain a copy of this license in the LICENSE.txt file in the root directory
+# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
+#
+# Any modifications or derivative works of this code must retain this
+# copyright notice, and modified files need to carry a notice indicating
+# that they have been altered from the originals.
+
+"""Module for singleton type to represent unset args."""
+
+from __future__ import annotations
+
+from typing import Any
+
+
+class UnsetType:
+    """Singleton type to represent unset args."""
+
+    __slots__ = ()
+
+    def __new__(cls) -> UnsetType:
+        if not hasattr(cls, "instance"):
+            cls.instance = super().__new__(cls)
+        return cls.instance
+
+    def __bool__(self) -> bool:
+        return False
+
+    def __eq__(self, __o: Any) -> bool:
+        return self is __o
+
+    def __copy__(self) -> UnsetType:
+        return self
+
+    def __deepcopy__(self, memo: dict) -> UnsetType:
+        return self
+
+
+UNSET = UnsetType()


Test patch:
diff --git a/test/utils/test_unset.py b/test/utils/test_unset.py
new file mode 100644
index 0000000..a6bac67
--- /dev/null
+++ b/test/utils/test_unset.py
@@ -0,0 +1,43 @@
+# This code is part of Qiskit.
+#
+# (C) Copyright IBM 2022.
+#
+# This code is licensed under the Apache License, Version 2.0. You may
+# obtain a copy of this license in the LICENSE.txt file in the root directory
+# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
+#
+# Any modifications or derivative works of this code must retain this
+# copyright notice, and modified files need to carry a notice indicating
+# that they have been altered from the originals.
+
+from copy import copy, deepcopy
+
+from zne.utils.unset import UNSET, UnsetType
+
+
+class TestUnsetType:
+    """Test `UnsetType` class."""
+
+    def test_singleton(self):
+        """Test that class is a singleton."""
+        assert UnsetType() is UnsetType()
+        assert UNSET is UnsetType()
+
+    def test_bool(self):
+        """Test that instances evaluate to `False`."""
+        assert not UNSET
+        assert not UnsetType()
+
+    def test_eq(self):
+        """Test equality."""
+        assert UnsetType() == UnsetType()
+        assert UNSET == UnsetType()
+
+    def test_copy(self):
+        """Test copy."""
+        assert copy(UNSET) is UNSET
+
+    def test_deepcopy(self):
+        """Test deepcopy."""
+        assert deepcopy(UNSET, memo := {}) is UNSET
+        assert not memo