예제 #1
0
def post_json(session: requests.Session, url: str,
              json: Any) -> requests.models.Response:
    """
    Post JSON to the Forest endpoint.
    """
    logger.debug("Sending POST request to %s. Body: %s", url, json)
    res = session.post(url, json=json)
    if res.status_code >= 400:
        raise parse_error(res)
    return res
예제 #2
0
def get_json(session: requests.Session,
             url: str,
             params: Optional[Dict[Any, Any]] = None) -> Any:
    """
    Get JSON from a Forest endpoint.
    """
    logger.debug("Sending GET request to %s. Params: %s", url, params)
    res = session.get(url, params=params)
    if res.status_code >= 400:
        raise parse_error(res)
    return res.json()
예제 #3
0
def _parse_auth_token(path: str, required_keys: Iterable[str]) -> Optional[dict]:
    try:
        with open(abspath(expanduser(path)), "r") as f:
            token = json.load(f)
            invalid_values = [k for k in required_keys if not isinstance(token.get(k), str)]
            if len(invalid_values) == 0:
                return token
            logger.warning(f"Failed to parse auth token at {path}.")
            logger.warning(f"Invalid {invalid_values}.")
    except json.decoder.JSONDecodeError:
        logger.warning(f"Failed to parse auth token at {path}. Invalid JSON.")
    except FileNotFoundError:
        logger.debug("Auth token at %s not found.", path)
예제 #4
0
 def __init__(
     self,
     client_public_key: bytes,
     client_secret_key: bytes,
     server_public_key: bytes,
     expires_at: Union[int, float, str],
     qpu_endpoint: str,
     qpu_compiler_endpoint: str,
 ):
     self.client_public_key = client_public_key
     self.client_secret_key = client_secret_key
     self.server_public_key = server_public_key
     self.expires_at = float(expires_at) if expires_at else None
     self.qpu_endpoint = qpu_endpoint
     self.qpu_compiler_endpoint = qpu_compiler_endpoint
     logger.debug("New engagement created: \n%s", self)
예제 #5
0
    def _build_client(self) -> Client:
        endpoint: Optional[str] = None
        if self.endpoint:
            endpoint = self.endpoint
        elif self.session and self.session.config.qpu_url:
            endpoint = self.session.config.qpu_url

        if endpoint is None:
            raise UserMessageError(
                """It looks like you've tried to run a program against a QPU but do
not currently have a reservation on one. To reserve time on Rigetti
QPUs, use the command line interface, qcs, which comes pre-installed
in your QMI. From within your QMI, type:

    qcs reserve --lattice <lattice-name>

For more information, please see the docs at
https://www.rigetti.com/qcs/docs/reservations or reach out to Rigetti
support at [email protected].""")

        logger.debug("QPU Client connecting to %s", endpoint)

        return Client(endpoint, auth_config=self._get_client_auth_config())
예제 #6
0
    def _engage(self) -> Optional["Engagement"]:
        """
        The heart of the QPU authorization process, ``engage`` makes a request to
        the dispatch server for the information needed to communicate with the QPU.

        This is a standard GraphQL request, authenticated using the access token
        retrieved from Forest Server.

        The response includes the endpoints to the QPU and QPU Compiler Server,
        along with the set of keys necessary to connect to the QPU and the time at
        which that key set expires.
        """
        query = """
          mutation Engage($name: String!) {
            engage(input: { lattice: { name: $name }}) {
              success
              message
              engagement {
                type
                qpu {
                    endpoint
                    credentials {
                        clientPublic
                        clientSecret
                        serverPublic
                    }
                }
                compiler {
                    endpoint
                }
                expiresAt
              }
            }
          }
        """
        if not self.lattice_name:
            logger.debug(
                "ForestSession requires lattice_name in order to engage")
            return None

        logger.debug("Requesting engagement from %s", self.config.dispatch_url)
        variables = dict(name=self.lattice_name)
        query_response = self._request_graphql_retry(self.config.dispatch_url,
                                                     query=query,
                                                     variables=variables)

        if query_response.get("errors"):
            errors = query_response.get("errors", [])
            error_messages = map(lambda error: error["message"],
                                 errors)  # type: ignore
            raise UserMessageError(
                f"Failed to engage: {','.join(error_messages)}")

        engagement_response = query_response.get("data",
                                                 {}).get("engage", None)
        if engagement_response and engagement_response.get("success") is True:
            logger.debug("Engagement successful")
            engagement_data = engagement_response.get("engagement", {})
            return Engagement(
                client_secret_key=engagement_data.get("qpu", {}).get(
                    "credentials", {}).get("clientSecret", "").encode("utf-8"),
                client_public_key=engagement_data.get("qpu", {}).get(
                    "credentials", {}).get("clientPublic", "").encode("utf-8"),
                server_public_key=engagement_data.get("qpu", {}).get(
                    "credentials", {}).get("serverPublic", "").encode("utf-8"),
                expires_at=engagement_data.get("expiresAt", {}),
                qpu_endpoint=engagement_data.get("qpu", {}).get("endpoint"),
                qpu_compiler_endpoint=engagement_data.get("compiler",
                                                          {}).get("endpoint"),
            )
        else:
            raise UserMessageError(
                f"Unable to engage {self.lattice_name}: "
                f"{engagement_response.get('message', 'No message')}")