Skip to content

Commit 54fe5ef

Browse files
MarquessVShadow53
andauthored
feat!: Loading a Qcs Client is now infallible and is the primary client used throughout the library. (#302)
--------- Co-authored-by: Michael Bryant <[email protected]>
1 parent 3866fb4 commit 54fe5ef

27 files changed

+212
-272
lines changed

crates/lib/src/qpu/client.rs renamed to crates/lib/src/client.rs

+30-18
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ pub struct Qcs {
4343

4444
impl Qcs {
4545
/// Create a [`Qcs`] and initialize it with the user's default [`ClientConfiguration`]
46-
pub async fn load() -> Result<Self, LoadError> {
47-
ClientConfiguration::load_default()
48-
.await
49-
.or_else(|_| {
50-
#[cfg(feature = "tracing")]
51-
tracing::info!(
52-
"No QCS client configuration found. QPU data and QCS will be inaccessible and only generic QVMs will be available for execution"
53-
);
54-
Ok(ClientConfiguration::default())
55-
})
56-
.map(Self::with_config)
46+
pub async fn load() -> Self {
47+
let config = if let Ok(config) = ClientConfiguration::load_default().await {
48+
config
49+
} else {
50+
#[cfg(feature = "tracing")]
51+
tracing::info!(
52+
"No QCS client configuration found. QPU data and QCS will be inaccessible and only generic QVMs will be available for execution"
53+
);
54+
ClientConfiguration::default()
55+
};
56+
Self::with_config(config)
5757
}
5858

5959
/// Create a [`Qcs`] and initialize it with the given [`ClientConfiguration`]
@@ -65,17 +65,29 @@ impl Qcs {
6565
}
6666
}
6767

68+
/// Create a [`Qcs`] and initialized with the given `profile`.
69+
///
70+
/// # Errors
71+
///
72+
/// A [`LoadError`] will be returned if QCS credentials are
73+
/// not correctly configured or the given profile is not defined.
74+
pub async fn with_profile(profile: String) -> Result<Qcs, LoadError> {
75+
ClientConfiguration::load_profile(profile)
76+
.await
77+
.map(Self::with_config)
78+
}
79+
6880
/// Enable or disable the use of Gateway service for execution
6981
#[must_use]
7082
pub fn with_use_gateway(mut self, use_gateway: bool) -> Self {
7183
self.use_gateway = use_gateway;
7284
self
7385
}
7486

75-
/// Return a copy of all settings parsed and resolved from configuration sources.
87+
/// Return a reference to the underlying [`ClientConfiguration`] with all settings parsed and resolved from configuration sources.
7688
#[must_use]
77-
pub fn get_config(&self) -> ClientConfiguration {
78-
self.config.clone()
89+
pub fn get_config(&self) -> &ClientConfiguration {
90+
&self.config
7991
}
8092

8193
pub(crate) async fn get_controller_client(
@@ -85,7 +97,7 @@ impl Qcs {
8597
{
8698
let uri = self.get_controller_endpoint(quantum_processor_id).await?;
8799
let channel = get_channel(uri).map_err(|err| GrpcEndpointError::GrpcError(err.into()))?;
88-
let service = wrap_channel_with(channel, self.get_config());
100+
let service = wrap_channel_with(channel, self.get_config().clone());
89101
Ok(ControllerClient::new(service))
90102
}
91103

@@ -96,12 +108,12 @@ impl Qcs {
96108
{
97109
let uri = self.get_controller_endpoint_by_id(endpoint_id).await?;
98110
let channel = get_channel(uri).map_err(|err| GrpcEndpointError::GrpcError(err.into()))?;
99-
let service = wrap_channel_with(channel, self.get_config());
111+
let service = wrap_channel_with(channel, self.get_config().clone());
100112
Ok(ControllerClient::new(service))
101113
}
102114

103115
pub(crate) fn get_openapi_client(&self) -> OpenApiConfiguration {
104-
OpenApiConfiguration::with_qcs_config(self.get_config())
116+
OpenApiConfiguration::with_qcs_config(self.get_config().clone())
105117
}
106118

107119
pub(crate) fn get_translation_client(
@@ -122,7 +134,7 @@ impl Qcs {
122134
> {
123135
let uri = parse_uri(translation_grpc_endpoint)?;
124136
let channel = get_channel(uri)?;
125-
let service = wrap_channel_with(channel, self.get_config());
137+
let service = wrap_channel_with(channel, self.get_config().clone());
126138
Ok(TranslationClient::new(service))
127139
}
128140

crates/lib/src/compiler/quilc.rs

+9-15
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use qcs_api_client_openapi::models::InstructionSetArchitecture;
1212
use super::isa::{self, Compiler};
1313
use super::rpcq;
1414

15-
use crate::qpu::client::Qcs;
15+
use crate::client::Qcs;
1616

1717
/// Number of seconds to wait before timing out.
1818
pub const DEFAULT_COMPILER_TIMEOUT: f64 = 30.0;
@@ -47,8 +47,7 @@ pub fn compile_program(
4747
#[cfg(feature = "tracing")]
4848
tracing::debug!(compiler_options=?options, "compiling quil program with quilc",);
4949

50-
let config = client.get_config();
51-
let endpoint = config.quilc_url();
50+
let endpoint = client.get_config().quilc_url();
5251
let params = QuilcParams::new(quil, isa).with_protoquil(options.protoquil);
5352
let request =
5453
rpcq::RPCRequest::new("quil_to_native_quil", &params).with_timeout(options.timeout);
@@ -428,7 +427,7 @@ mod tests {
428427
let output = compile_program(
429428
"MEASURE 0",
430429
TargetDevice::try_from(qvm_isa()).expect("Couldn't build target device from ISA"),
431-
&Qcs::load().await.unwrap_or_default(),
430+
&Qcs::load().await,
432431
CompilerOpts::default(),
433432
)
434433
.expect("Could not compile");
@@ -446,7 +445,7 @@ MEASURE 1 ro[1]
446445

447446
#[tokio::test]
448447
async fn run_compiled_bell_state_on_qvm() {
449-
let client = Qcs::load().await.unwrap_or_default();
448+
let client = Qcs::load().await;
450449
let output = compile_program(
451450
BELL_STATE,
452451
TargetDevice::try_from(aspen_9_isa()).expect("Couldn't build target device from ISA"),
@@ -456,12 +455,7 @@ MEASURE 1 ro[1]
456455
.expect("Could not compile");
457456
let mut results = crate::qvm::Execution::new(&output.program.to_string(true))
458457
.unwrap()
459-
.run(
460-
10,
461-
&[Cow::Borrowed("ro")],
462-
&HashMap::default(),
463-
&client.get_config(),
464-
)
458+
.run(10, &[Cow::Borrowed("ro")], &HashMap::default(), &client)
465459
.await
466460
.expect("Could not run program on QVM");
467461
for shot in results
@@ -478,7 +472,7 @@ MEASURE 1 ro[1]
478472

479473
#[tokio::test]
480474
async fn test_compile_declare_only() {
481-
let client = Qcs::load().await.unwrap_or_default();
475+
let client = Qcs::load().await;
482476
let output = compile_program(
483477
"DECLARE ro BIT[1]\n",
484478
TargetDevice::try_from(aspen_9_isa()).expect("Couldn't build target device from ISA"),
@@ -492,15 +486,15 @@ MEASURE 1 ro[1]
492486

493487
#[tokio::test]
494488
async fn get_version_info_from_quilc() {
495-
let client = Qcs::load().await.unwrap_or_default();
489+
let client = Qcs::load().await;
496490
let version = get_version_info(&client).expect("Should get version info from quilc");
497491
let semver_re = Regex::new(r"^([0-9]+)\.([0-9]+)\.([0-9]+)$").unwrap();
498492
assert!(semver_re.is_match(&version));
499493
}
500494

501495
#[tokio::test]
502496
async fn test_conjugate_pauli_by_clifford() {
503-
let client = Qcs::load().await.unwrap_or_default();
497+
let client = Qcs::load().await;
504498
let request = ConjugateByCliffordRequest {
505499
pauli: PauliTerm {
506500
indices: vec![0],
@@ -522,7 +516,7 @@ MEASURE 1 ro[1]
522516

523517
#[tokio::test]
524518
async fn test_generate_randomized_benchmark_sequence() {
525-
let client = Qcs::load().await.unwrap_or_default();
519+
let client = Qcs::load().await;
526520
let request = RandomizedBenchmarkingRequest {
527521
depth: 2,
528522
qubits: 1,

0 commit comments

Comments
 (0)