Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to deepcopy an IBMBackend #899

Closed
cyberteej opened this issue Jun 9, 2023 · 1 comment · Fixed by #902
Closed

Unable to deepcopy an IBMBackend #899

cyberteej opened this issue Jun 9, 2023 · 1 comment · Fixed by #902
Assignees
Labels
bug Something isn't working
Milestone

Comments

@cyberteej
Copy link

Describe the bug

With the old IBMQBackends, deepcopying was allowed. With the new IBMBackends, it results in a recursion error. Loosely, this seems to be because deepcopy checks if _properties is an attribute of IBMBackend (when it is constructing the new, empty IBMBackend), and the __getattr__ function of IBMBackend calls self._get_properties() internally, resulting in an infinite loop of trying to access the attribute _properties which doesn't exist yet. This is also true for _defaults and _configuration.

I'm open to the idea that deepcopying backends should be discouraged for some reason but feel like at least the error should be improved.

Steps to reproduce

from qiskit_ibm_runtime import QiskitRuntimeService
import copy

service = QiskitRuntimeService()
backend = service.get_backend('ibm_perth')
backend_copy = copy.deepcopy(backend)

Expected behavior

A copy of the backend (preferable) or avoiding infinite recursion.

Suggested solutions

Currently, I modify __getattr__ in ibm_backend.py to the following, which is very hacky and I'm worried there's some edge case behaviour I may affect

   def __getattr__(self, name: str) -> Any:
        """Gets attribute from self or configuration

        This magic method executes when user accesses an attribute that
        does not yet exist on IBMBackend class.
        """
        # Lazy load properties and pulse defaults and construct the target object.
        if name not in ['_properties', '_defaults','_configuration']:
            self._get_properties()
            self._get_defaults()
            self._convert_to_target()
        # Check if the attribute now is available on IBMBackend class due to above steps
        try:
            return super().__getattribute__(name)
        except AttributeError:
            pass
        # If attribute is still not available on IBMBackend class,
        # fallback to check if the attribute is available in configuration
        if name not in ['_configuration']:
            try:
                return self._configuration.__getattribute__(name)
            except AttributeError:
                raise AttributeError(
                    "'{}' object has no attribute '{}'".format(
                        self.__class__.__name__, name
                    )
                )

Additional Information

  • qiskit-ibm-runtime version: 0.10.0
  • Python version: 3.8.8
  • Operating system: macOS Ventura
@cyberteej cyberteej added the bug Something isn't working label Jun 9, 2023
@yaelbh
Copy link
Collaborator

yaelbh commented Jun 9, 2023

This was fixed in qiskit-ibm-provider Qiskit/qiskit-ibm-provider#658

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants