def find_module(self, full_name: str, path: Optional[str] = None) -> Loader: # We expose Q# namespaces as their own root-level packages. # E.g.: # >>> import Microsoft.Quantum.Intrinsic as mqi # Thus, we need to check if the full name is one that that we can # sensibly load before we proceed. # To check the full name, we ask the client rather than going through # the public API for the qsharp package, so that we can check if the # client is currently busy. This can happen if anything below us in # meta_path needs to handle an import during an execute; this is the # case when ZeroMQ needs to import additional functionality from a # Cython module to handle a message. # See https://github.com/Microsoft/QuantumLibraries/issues/69 for an # example of this failure modality. # If the client is busy, we'll want to forego this request to find a # module and return None early. if qsharp.client.busy: return None # At this point, we should be safe to rely on the public API again. ops = qsharp.get_available_operations_by_namespace() if full_name not in ops: # We may have been given part of the qualified name of a namespace. # E.g., if we try to import Microsoft.Quantum.Intrinsic, we'll # see calls with "Microsoft" and "Microsoft.Quantum" first. if not any(ns_name.startswith(full_name + ".") for ns_name in ops): return None return QSharpModuleLoader()
def __getattr__(self, name): ops = qsharp.get_available_operations_by_namespace() # NB: Our Q# namespace name may not exist as a key, as the namespace # name may be a prefix (e.g.: `Microsoft` and `Microsoft.Quantum.` # may be empty, even though `Microsoft.Quantum.Intrinsic` is not). # # Thus, we need to look for sub-namespaces as well as callables. # While subnamespaces aren't a concept in Q#, they are in Python, # and are needed to make tab completion on imports work correctly. # # Start by looking for sub-namespaces. sub_namespaces = list(self._all_sub_namespaces()) qualified_name = f"{self._qs_name}.{name}" if qualified_name in sub_namespaces: return self.__loader__.load_module(qualified_name) if self._qs_name in ops and name in ops[self._qs_name]: op_cls = new_class(name, (QSharpCallable, )) # Copy over metadata from the operation's header. metadata = qsharp.client.get_operation_metadata( f"{self._qs_name}.{name}") op_cls.__doc__ = metadata.get('documentation', '') op_cls.__file__ = metadata.get('source', None) return op_cls(f"{self._qs_name}.{name}", "workspace") raise AttributeError( f"Q# namespace {self._qs_name} does not contain a callable {name}." )
def _all_sub_namespaces_as_parts(self) -> Iterable[Tuple[str]]: qs_namespaces = qsharp.get_available_operations_by_namespace().keys() all_namespaces = set() for ns in qs_namespaces: parts = tuple(ns.split(".")) all_namespaces.add(parts) for idx_part in range(1, len(parts)): all_namespaces.add(tuple(parts[:-idx_part])) return all_namespaces
def __getattr__(self, name): ops = qsharp.get_available_operations_by_namespace() if name in ops[self._qs_name]: op_cls = new_class(name, (QSharpCallable, )) # Copy over metadata from the operation's header. metadata = qsharp.client.get_operation_metadata(f"{self._qs_name}.{name}") op_cls.__doc__ = metadata.get('documentation', '') op_cls.__file__ = metadata.get('source', None) return op_cls(f"{self._qs_name}.{name}", "workspace") raise AttributeError(f"Q# namespace {self._qs_name} does not contain a callable {name}.")
def find_module(self, full_name: str, path: Optional[str] = None) -> Loader: # We expose Q# namespaces as their own root-level packages. # E.g.: # >>> import Microsoft.Quantum.Primitive as prim # Thus, we need to check if the full name is one that that we can # sensibly load before we proceed. ops = qsharp.get_available_operations_by_namespace() if full_name not in ops: # We may have been given part of the qualified name of a namespace. # E.g., if we try to import Microsoft.Quantum.Primitive, we'll # see calls with "Microsoft" and "Microsoft.Quantum" first. if not any(ns_name.startswith(full_name + ".") for ns_name in ops): return None return QSharpModuleLoader()
def __dir__(self) -> Iterable[str]: ops = qsharp.get_available_operations_by_namespace() return list( sorted( list(self._immediate_sub_namespaces()) + ops.get(self._qs_name, [])))