pdhoolia / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
0 stars 0 forks source link

Improve support for Python 3.13 copy.replace #6

Closed pdhoolia closed 7 hours ago

pdhoolia commented 7 hours ago

What should we add?

We have some classes that act like immutable record types. These often define a custom replace method to allow constructing a new version of the class while making limited changes to a subset of fields. These classes tend now to be the ones defined in Rust space (CircuitInstruction is a prime example, but there may be more).

Python 3.13 formalised this idea into a part of the copy module / pickle protocol, with the user-facing copy.replace and the protocol-level object.replace. We should make sure that Qiskit objects that define a replace function with the same semantics expose the same behaviour as __replace__ to improve interoperability with later language features.

At the time of writing, I'm only aware of CircuitInstruction that does this verbatim, but it's possible that we have other classes that are dataclass-like (for example DataBin) that might want to begin supporting the behaviour.

pdhoolia commented 7 hours ago

To address the issue of improving support for Python 3.13's copy.replace and object.__replace__, we need to ensure that the CircuitInstruction class, and potentially other similar classes, implement the __replace__ method. This will allow these classes to be compatible with the new copy protocol. Below are the suggested changes for each relevant file:

circuit_instruction.py

  1. Implement __replace__ Method:
    • Locate the replace method in the CircuitInstruction class.
    • Implement the __replace__ method to mirror the behavior of the existing replace method.
class CircuitInstruction:
    # existing code...

    def replace(self, **changes):
        # existing logic for replace...
        pass

    def __replace__(self, **changes):
        return self.replace(**changes)

data_bin.py

  1. Check for Similar Patterns:
    • If DataBin or similar classes have a replace method, implement a __replace__ method.
class DataBin:
    # existing code...

    def replace(self, **changes):
        # existing logic for replace...
        pass

    def __replace__(self, **changes):
        return self.replace(**changes)

circuit.py and data.py

  1. Review for Similar Classes:
    • Review these files for any classes that may have a replace method or are dataclass-like.
    • If such classes exist, implement a __replace__ method similar to the above examples.

immutable_utils.py

  1. Utility Functions:
    • If there are utility functions that assist in handling immutable structures, consider adding helper functions to facilitate __replace__ method implementations.
def apply_changes(obj, **changes):
    # Utility function to apply changes immutably
    return obj.__class__(**{**obj.__dict__, **changes})

General Considerations

By implementing these changes, you will align the Qiskit classes with Python 3.13's new copy.replace protocol, enhancing interoperability and future-proofing the codebase.