Skip to content

Commit

Permalink
starlark: use type value API to retrieve resolve_target()
Browse files Browse the repository at this point in the history
The Starlark crate removes direct access to variables from the API in
the 0.3 release. As part of preparing for this, we teach the code to
obtain the resolve_target() Starlark function via the type value API.
This is a bit hacky. But it is a sufficient workaround.
  • Loading branch information
indygreg committed Sep 18, 2020
1 parent 2853001 commit 6b0f92b
Showing 1 changed file with 47 additions and 3 deletions.
50 changes: 47 additions & 3 deletions pyoxidizer/src/starlark/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,24 @@ impl TypedValue for EnvironmentContext {
}
}

/// Starlark type holding context for PyOxidizer.
pub struct PyOxidizerContext {}

impl Default for PyOxidizerContext {
fn default() -> Self {
PyOxidizerContext {}
}
}

impl TypedValue for PyOxidizerContext {
type Holder = Mutable<PyOxidizerContext>;
const TYPE: &'static str = "PyOxidizer";

fn values_for_descendant_check_and_freeze(&self) -> Box<dyn Iterator<Item = Value>> {
Box::new(std::iter::empty())
}
}

pub fn get_context(env: &Environment) -> ValueResult {
env.get("CONTEXT").or_else(|_| {
Err(ValueError::from(RuntimeError {
Expand Down Expand Up @@ -443,6 +461,17 @@ fn starlark_resolve_target(
/// resolve_targets()
#[allow(clippy::ptr_arg)]
fn starlark_resolve_targets(env: &Environment, call_stack: &CallStack) -> ValueResult {
let resolve_target_fn = env
.get_type_value(&Value::new(PyOxidizerContext::default()), "resolve_target")
.ok_or_else(|| {
ValueError::from(RuntimeError {
code: "PYOXIDIZER_BUILD",
message: "could not find resolve_target() function (this should never happen)"
.to_string(),
label: "resolve_targets()".to_string(),
})
})?;

let raw_context = get_context(env)?;
let context = raw_context
.downcast_ref::<EnvironmentContext>()
Expand All @@ -452,9 +481,7 @@ fn starlark_resolve_targets(env: &Environment, call_stack: &CallStack) -> ValueR

println!("resolving {} targets", targets.len());
for target in targets {
let resolve = env.get("resolve_target").unwrap();

resolve.call(
resolve_target_fn.call(
call_stack,
env.clone(),
vec![Value::new(target)],
Expand Down Expand Up @@ -544,6 +571,23 @@ pub fn global_environment(context: &EnvironmentContext) -> Result<Environment, E
Value::from(context.build_target_triple.clone()),
)?;

// We alias various globals as PyOxidizer.* attributes so they are
// available via the type object API. This is a bit hacky. But it allows
// Rust code with only access to the TypeValues dictionary to retrieve
// these globals.
for f in &[
"register_target",
"resolve_target",
"resolve_targets",
"set_build_path",
"CONTEXT",
"CWD",
"CONFIG_PATH",
"BUILD_TARGET_TRIPLE",
] {
env.add_type_value(PyOxidizerContext::TYPE, f, env.get(f)?);
}

Ok(env)
}

Expand Down

0 comments on commit 6b0f92b

Please sign in to comment.