예제 #1
0
파일: loader.py 프로젝트: vxfield/iqsharp
    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()
예제 #2
0
    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}."
        )
예제 #3
0
    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
예제 #4
0
    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}.")
예제 #5
0
    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()
예제 #6
0
 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, [])))