pyoxidizerlib/starlark/
python_extension_module.rs1use {
6 super::python_resource::ResourceCollectionContext,
7 python_packaging::{
8 resource::{PythonExtensionModule, PythonResource},
9 resource_collection::PythonResourceAddCollectionContext,
10 },
11 starlark::values::{
12 error::{RuntimeError, UnsupportedOperation, ValueError},
13 {Mutable, TypedValue, Value, ValueResult},
14 },
15 std::sync::{Arc, Mutex, MutexGuard},
16};
17
18#[derive(Debug)]
19pub struct PythonExtensionModuleWrapper {
20 pub em: PythonExtensionModule,
21 pub add_context: Option<PythonResourceAddCollectionContext>,
22}
23
24#[derive(Debug, Clone)]
26pub struct PythonExtensionModuleValue {
27 inner: Arc<Mutex<PythonExtensionModuleWrapper>>,
28 name: String,
29}
30
31impl PythonExtensionModuleValue {
32 pub fn new(em: PythonExtensionModule) -> Self {
33 let name = em.name.clone();
34
35 Self {
36 inner: Arc::new(Mutex::new(PythonExtensionModuleWrapper {
37 em,
38 add_context: None,
39 })),
40 name,
41 }
42 }
43
44 pub fn inner(
45 &self,
46 label: &str,
47 ) -> Result<MutexGuard<PythonExtensionModuleWrapper>, ValueError> {
48 self.inner.try_lock().map_err(|e| {
49 ValueError::Runtime(RuntimeError {
50 code: "PYTHON_EXTENSION_MODULE",
51 message: format!("failed to acquire lock: {}", e),
52 label: label.to_string(),
53 })
54 })
55 }
56}
57
58impl ResourceCollectionContext for PythonExtensionModuleValue {
59 fn add_collection_context(
60 &self,
61 ) -> Result<Option<PythonResourceAddCollectionContext>, ValueError> {
62 Ok(self
63 .inner("PythonExtensionModule.add_collection_context()")?
64 .add_context
65 .clone())
66 }
67
68 fn replace_add_collection_context(
69 &mut self,
70 context: PythonResourceAddCollectionContext,
71 ) -> Result<Option<PythonResourceAddCollectionContext>, ValueError> {
72 Ok(self
73 .inner("PythonExtensionModule.replace_add_collection_context()")?
74 .add_context
75 .replace(context))
76 }
77
78 fn as_python_resource(&self) -> Result<PythonResource<'_>, ValueError> {
79 Ok(PythonResource::from(
80 self.inner("PythonExtensionModule.as_python_resource()")?
81 .em
82 .clone(),
83 ))
84 }
85}
86
87impl TypedValue for PythonExtensionModuleValue {
88 type Holder = Mutable<PythonExtensionModuleValue>;
89 const TYPE: &'static str = "PythonExtensionModule";
90
91 fn values_for_descendant_check_and_freeze(&self) -> Box<dyn Iterator<Item = Value>> {
92 Box::new(std::iter::empty())
93 }
94
95 fn to_str(&self) -> String {
96 format!("{}<name={}>", Self::TYPE, self.name)
97 }
98
99 fn to_repr(&self) -> String {
100 self.to_str()
101 }
102
103 fn get_attr(&self, attribute: &str) -> ValueResult {
104 let inner = self.inner(&format!("PythonExtensionModule.{}", attribute))?;
105
106 let v = match attribute {
107 "is_stdlib" => Value::from(inner.em.is_stdlib),
108 "name" => Value::new(inner.em.name.clone()),
109 attr => {
110 drop(inner);
111
112 return if self.add_collection_context_attrs().contains(&attr) {
113 self.get_attr_add_collection_context(attr)
114 } else {
115 Err(ValueError::OperationNotSupported {
116 op: UnsupportedOperation::GetAttr(attr.to_string()),
117 left: Self::TYPE.to_string(),
118 right: None,
119 })
120 };
121 }
122 };
123
124 Ok(v)
125 }
126
127 fn has_attr(&self, attribute: &str) -> Result<bool, ValueError> {
128 Ok(match attribute {
129 "is_stdlib" => true,
130 "name" => true,
131 attr => self.add_collection_context_attrs().contains(&attr),
132 })
133 }
134
135 fn set_attr(&mut self, attribute: &str, value: Value) -> Result<(), ValueError> {
136 if self.add_collection_context_attrs().contains(&attribute) {
137 self.set_attr_add_collection_context(attribute, value)
138 } else {
139 Err(ValueError::OperationNotSupported {
140 op: UnsupportedOperation::SetAttr(attribute.to_string()),
141 left: Self::TYPE.to_owned(),
142 right: None,
143 })
144 }
145 }
146}