diff --git a/source/compiler/qsc/src/incremental.rs b/source/compiler/qsc/src/incremental.rs index 1161e1d1b1d..938fd3851a2 100644 --- a/source/compiler/qsc/src/incremental.rs +++ b/source/compiler/qsc/src/incremental.rs @@ -48,10 +48,10 @@ impl Compiler { language_features: LanguageFeatures, mut store: PackageStore, dependencies: &Dependencies, - qsharp_config: FxHashMap, Value>, + qdk_config: FxHashMap, Value>, ) -> Result { - let qsharp_config_rc = Rc::new(qsharp_config); - let mut passes = PassContext::new(qsharp_config_rc.clone()); + let qdk_config_rc = Rc::new(qdk_config); + let mut passes = PassContext::new(qdk_config_rc.clone()); let (mut unit, errors) = compile_with_pass_context( &store, dependencies, @@ -84,7 +84,7 @@ impl Compiler { Ok(Self { store, source_package_id, - passes: PassContext::new(qsharp_config_rc), + passes: PassContext::new(qdk_config_rc), frontend, }) } diff --git a/source/compiler/qsc/src/interpret.rs b/source/compiler/qsc/src/interpret.rs index f476fa06f5e..ef49d9dd0df 100644 --- a/source/compiler/qsc/src/interpret.rs +++ b/source/compiler/qsc/src/interpret.rs @@ -219,7 +219,7 @@ impl Interpreter { language_features: LanguageFeatures, store: PackageStore, dependencies: &Dependencies, - qsharp_config: FxHashMap, Value>, + qdk_config: FxHashMap, Value>, ) -> std::result::Result> { Self::with_sources( ExecGraphConfig::NoDebug, @@ -230,7 +230,7 @@ impl Interpreter { store, dependencies, None, - qsharp_config, + qdk_config, ) } @@ -243,7 +243,7 @@ impl Interpreter { store: PackageStore, dependencies: &Dependencies, circuit_tracer_config: TracerConfig, - qsharp_config: FxHashMap, Value>, + qdk_config: FxHashMap, Value>, ) -> std::result::Result> { Self::with_sources( ExecGraphConfig::NoDebug, @@ -254,7 +254,7 @@ impl Interpreter { store, dependencies, Some(circuit_tracer_config), - qsharp_config, + qdk_config, ) } @@ -270,7 +270,7 @@ impl Interpreter { store: PackageStore, dependencies: &Dependencies, trace_circuit_config: TracerConfig, - qsharp_config: FxHashMap, Value>, + qdk_config: FxHashMap, Value>, ) -> std::result::Result> { Self::with_sources( ExecGraphConfig::Debug, @@ -281,7 +281,7 @@ impl Interpreter { store, dependencies, Some(trace_circuit_config), - qsharp_config, + qdk_config, ) } @@ -295,7 +295,7 @@ impl Interpreter { store: PackageStore, dependencies: &Dependencies, circuit_tracer_config: Option, - qsharp_config: FxHashMap, Value>, + qdk_config: FxHashMap, Value>, ) -> std::result::Result> { let compiler = Compiler::new( sources, @@ -304,7 +304,7 @@ impl Interpreter { language_features, store, dependencies, - qsharp_config, + qdk_config, ) .map_err(into_errors)?; diff --git a/source/compiler/qsc/src/interpret/tests.rs b/source/compiler/qsc/src/interpret/tests.rs index dfd6e87984b..0d8ffd568dd 100644 --- a/source/compiler/qsc/src/interpret/tests.rs +++ b/source/compiler/qsc/src/interpret/tests.rs @@ -2594,8 +2594,8 @@ mod given_interpreter { ) } - fn get_interpreter_with_config(qsharp_config: FxHashMap, Value>) -> Interpreter { - get_interpreter_with_capabilities_and_config(TargetCapabilityFlags::all(), qsharp_config) + fn get_interpreter_with_config(qdk_config: FxHashMap, Value>) -> Interpreter { + get_interpreter_with_capabilities_and_config(TargetCapabilityFlags::all(), qdk_config) } fn get_interpreter_with_capabilities(capabilities: TargetCapabilityFlags) -> Interpreter { @@ -2604,7 +2604,7 @@ mod given_interpreter { fn get_interpreter_with_capabilities_and_config( capabilities: TargetCapabilityFlags, - qsharp_config: FxHashMap, Value>, + qdk_config: FxHashMap, Value>, ) -> Interpreter { let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities); let dependencies = &[(std_id, None)]; @@ -2615,7 +2615,7 @@ mod given_interpreter { LanguageFeatures::default(), store, dependencies, - qsharp_config, + qdk_config, ) .expect("interpreter should be created") } diff --git a/source/compiler/qsc_passes/src/lib.rs b/source/compiler/qsc_passes/src/lib.rs index 83a4be55483..24c408fc813 100644 --- a/source/compiler/qsc_passes/src/lib.rs +++ b/source/compiler/qsc_passes/src/lib.rs @@ -91,7 +91,7 @@ pub fn lower_hir_to_fir( pub struct PassContext { borrow_check: borrowck::Checker, /// Read-only config values exposed to Q# via Std.Core.ConfigValue. - qsharp_config: Rc, Value>>, + qdk_config: Rc, Value>>, } impl Default for PassContext { @@ -102,10 +102,10 @@ impl Default for PassContext { impl PassContext { #[must_use] - pub fn new(qsharp_config: Rc, Value>>) -> Self { + pub fn new(qdk_config: Rc, Value>>) -> Self { Self { borrow_check: borrowck::Checker::default(), - qsharp_config, + qdk_config, } } @@ -134,7 +134,7 @@ impl PassContext { Validator::default().visit_package(package); let config_inline_errors = - config_inline::replace_get_config_calls(core, package, &self.qsharp_config); + config_inline::replace_get_config_calls(core, package, &self.qdk_config); let measurement_decl_errors = measurement::validate_measurement_declarations(package); let reset_decl_errors = reset::validate_reset_declarations(package); diff --git a/source/qdk_package/README.md b/source/qdk_package/README.md index 76ef00427e9..4e81a99cc27 100644 --- a/source/qdk_package/README.md +++ b/source/qdk_package/README.md @@ -107,8 +107,8 @@ For convenience, the following helpers and types are also importable directly fr You can provide configuration at initialization time as a Python dictionary. -In Python, pass `qsharp_config: dict[str, int | float | str | bool]` to `Context(...)`. -If `qsharp_config` is omitted, the configuration map is empty. The map is immutable +In Python, pass `qdk_config: dict[str, int | float | str | bool]` to `Context(...)`. +If `qdk_config` is omitted, the configuration map is empty. The map is immutable after initialization. To use different configuration values, create a new `Context`. In Q#, read values with `Std.Core.ConfigValue(name, defaultValue)`. In Q# code, config @@ -116,14 +116,14 @@ values are immutable: in the same program, repeated calls with the same `(name, defaultValue)` produce the same result. Supported types: `int`, `float`, `str`, and `bool` (corresponding to `Int`, `Double`, -`String` and `Bool` in Q#). The type of each value in `qsharp_config` must match the +`String` and `Bool` in Q#). The type of each value in `qdk_config` must match the type of its corresponding default value. Example: ```python import qdk -context = qdk.Context(qsharp_config={"experiment_name": "baseline", "shots": 1000}) +context = qdk.Context(qdk_config={"experiment_name": "baseline", "shots": 1000}) assert context.eval('Std.Core.ConfigValue("experiment_name", "")') == "baseline" assert context.eval('Std.Core.ConfigValue("shots", 100)') == 1000 assert context.eval('Std.Core.ConfigValue("noise_level", 0.01)') == 0.01 diff --git a/source/qdk_package/qdk/_context.py b/source/qdk_package/qdk/_context.py index 3d3f3968a9d..1f92b2b62f7 100644 --- a/source/qdk_package/qdk/_context.py +++ b/source/qdk_package/qdk/_context.py @@ -186,7 +186,7 @@ def __init__( language_features: Optional[List[str]] = None, _trace_circuit: Optional[bool] = None, _is_global_context: bool = False, - qsharp_config: dict[str, int | float | str | bool] = {}, + qdk_config: dict[str, int | float | str | bool] = {}, ): """ Initializes a new isolated Q# context. @@ -209,7 +209,7 @@ def __init__( the statement form instead (``use q = Qubit();``). It also removes the requirement to use the ``set`` keyword for mutable variable assignments. - :keyword qsharp_config: configuration parameters that will be accessible in Q# + :keyword qdk_config: configuration parameters that will be accessible in Q# code using `Std.Core.ConfigValue`. Keys must be strings. Values must be of type `int`, `float`, `str`, or `bool`. """ @@ -286,7 +286,7 @@ def make_class_weak( make_callable_weak, make_class_weak, _trace_circuit, - qsharp_config, + qdk_config, ) self._config = Config( diff --git a/source/qdk_package/qdk/_interpreter.py b/source/qdk_package/qdk/_interpreter.py index cca90a06cd9..3b7e280b2f6 100644 --- a/source/qdk_package/qdk/_interpreter.py +++ b/source/qdk_package/qdk/_interpreter.py @@ -102,6 +102,7 @@ def init( project_root: Optional[str] = None, language_features: Optional[List[str]] = None, trace_circuit: Optional[bool] = None, + qdk_config: dict[str, int | float | str | bool] = {}, ) -> Config: """ Initializes the Q# interpreter. @@ -128,6 +129,11 @@ def init( Passing `True` is required for the `dump_circuit` function to return a circuit. The `circuit` function is *NOT* affected by this parameter and will always generate a circuit. + + :keyword qdk_config: configuration parameters that will be accessible in Q# + code using `Std.Core.ConfigValue`. Keys must be strings. Values must be of + type `int`, `float`, `str`, or `bool`. + :return: The Q# interpreter configuration. :rtype: Config """ @@ -147,6 +153,7 @@ def init( language_features=language_features, _trace_circuit=trace_circuit, _is_global_context=True, + qdk_config=qdk_config, ) return _default_context._config diff --git a/source/qdk_package/qdk/_native.pyi b/source/qdk_package/qdk/_native.pyi index 3296a5cde6b..7357db50d42 100644 --- a/source/qdk_package/qdk/_native.pyi +++ b/source/qdk_package/qdk/_native.pyi @@ -159,7 +159,7 @@ class Interpreter: make_callable: Optional[Callable[[GlobalCallable, List[str], str, bool], None]], make_class: Optional[Callable[[TypeIR, List[str], str], None]], trace_circuit: Optional[bool], - qsharp_config: Optional[Dict[str, int | float | str | bool]] = None, + qdk_config: Optional[Dict[str, int | float | str | bool]] = None, ) -> None: """ Initializes the Q# interpreter. @@ -173,7 +173,7 @@ class Interpreter: :param trace_circuit: Enables tracing of circuit during execution. Passing `True` is required for the `dump_circuit` function to return a circuit. The `circuit` function is *NOT* affected by this parameter will always generate a circuit. - :param qsharp_config: A dictionary of configuration parameters that will be accessible + :param qdk_config: A dictionary of configuration parameters that will be accessible in Q# code using ``Std.Core.ConfigValue``. """ ... diff --git a/source/qdk_package/src/interpreter.rs b/source/qdk_package/src/interpreter.rs index 7f483d6bcb8..6d3c09e97b7 100644 --- a/source/qdk_package/src/interpreter.rs +++ b/source/qdk_package/src/interpreter.rs @@ -406,11 +406,11 @@ pub(crate) struct Interpreter { thread_local! { static PACKAGE_CACHE: Rc> = Rc::default(); } // Converts Q# config from PyDict to FxHashMap. -fn convert_qsharp_config( - qsharp_config: Option>, +fn convert_qdk_config( + qdk_config: Option>, ) -> PyResult, Value>> { let mut config = FxHashMap::default(); - if let Some(config_dict) = qsharp_config { + if let Some(config_dict) = qdk_config { for (key, value) in config_dict.iter() { let key: String = key.extract()?; let value = if value.is_instance_of::() { @@ -438,7 +438,7 @@ impl Interpreter { #[allow(clippy::too_many_arguments)] #[allow(clippy::needless_pass_by_value)] #[allow(clippy::too_many_lines)] - #[pyo3(signature = (target_profile, language_features=None, project_root=None, read_file=None, list_directory=None, resolve_path=None, fetch_github=None, make_callable=None, make_class=None, trace_circuit=None, qsharp_config=None))] + #[pyo3(signature = (target_profile, language_features=None, project_root=None, read_file=None, list_directory=None, resolve_path=None, fetch_github=None, make_callable=None, make_class=None, trace_circuit=None, qdk_config=None))] #[new] /// Initializes a new Q# interpreter. pub(crate) fn new( @@ -453,7 +453,7 @@ impl Interpreter { make_callable: Option>, make_class: Option>, trace_circuit: Option, - qsharp_config: Option>, + qdk_config: Option>, ) -> PyResult { let target = Into::::into(target_profile).into(); @@ -489,7 +489,7 @@ impl Interpreter { BuildableProgram::new(target, graph) }; - let qsharp_config = convert_qsharp_config(qsharp_config)?; + let qdk_config = convert_qdk_config(qdk_config)?; let trace_circuit = trace_circuit.unwrap_or(false); let interpreter = if trace_circuit { interpret::Interpreter::with_circuit_trace( @@ -508,7 +508,7 @@ impl Interpreter { group_by_scope: false, prune_classical_qubits: false, }, - qsharp_config, + qdk_config, ) } else { interpret::Interpreter::new( @@ -518,7 +518,7 @@ impl Interpreter { buildable_program.user_code.language_features, buildable_program.store, &buildable_program.user_code_dependencies, - qsharp_config, + qdk_config, ) } .map_err(|errors| QSharpError::new_err(format_errors(errors)))?; diff --git a/source/qdk_package/tests/test_context.py b/source/qdk_package/tests/test_context.py index cbc10de5097..d47e775090a 100644 --- a/source/qdk_package/tests/test_context.py +++ b/source/qdk_package/tests/test_context.py @@ -243,9 +243,9 @@ def test_context_released_after_drop() -> None: assert ref() is None -def test_qsharp_config(context: qdk.Context) -> None: +def test_qdk_config(context: qdk.Context) -> None: context = qdk.Context( - qsharp_config={ + qdk_config={ "int_config": 123, "bool_config": True, "string_config": "value", @@ -276,7 +276,7 @@ def test_config_invalid_type(context: qdk.Context) -> None: with pytest.raises( TypeError, match="config value must be bool, int, float, or str" ): - qdk.Context(qsharp_config={"invalid": {"a": 1}}) # type: ignore + qdk.Context(qdk_config={"invalid": {"a": 1}}) # type: ignore with pytest.raises(TypeError, match="'int' object is not an instance of 'str'"): - qdk.Context(qsharp_config={1: 1}) # type: ignore + qdk.Context(qdk_config={1: 1}) # type: ignore diff --git a/source/qdk_package/tests/test_qsharp.py b/source/qdk_package/tests/test_qsharp.py index 0461e665184..942dc4be788 100644 --- a/source/qdk_package/tests/test_qsharp.py +++ b/source/qdk_package/tests/test_qsharp.py @@ -1185,3 +1185,8 @@ def test_swap_label_circuit_from_callable() -> None: q_0 ── X ──── X ── q_1 ────────────── """) + + +def test_qdk_config() -> None: + qsharp.init(qdk_config={"int_config": 123}) + assert qsharp.eval("""Std.Core.ConfigValue("int_config", 0)""") == 123