erickguan commented on code in PR #7883:
URL: https://github.com/apache/opendal/pull/7883#discussion_r3556434379


##########
dev/src/generate/python.j2:
##########
@@ -81,3 +82,123 @@ impl_enum_to_str!(
 {%- endfor %}
     }
 );
+
+pub trait ConfigBuilder: Send + Sync {
+    fn build(&self) -> PyResult<ocore::Operator>;
+    fn scheme(&self) -> &'static str;
+    fn to_map(&self) -> HashMap<String, String>;
+    fn is_picklable(&self) -> bool;
+}
+
+/// Base class for all service configs.
+#[pyclass(module = "opendal.services", subclass)]
+pub struct ServiceConfig(pub Box<dyn ConfigBuilder>);
+
+#[pymethods]
+impl ServiceConfig {
+    /// The service scheme this config targets, e.g. ``"s3"``.
+    #[getter]
+    pub fn scheme(&self) -> &'static str {
+        self.0.scheme()
+    }
+}
+{% for name in srvs %}
+#[cfg(feature = "{{ service_to_feature(name) }}")]
+{{ config_class_doc(name) }}
+#[pyclass(module = "opendal.services", extends = ServiceConfig, frozen, 
skip_from_py_object)]
+#[derive(Clone)]
+pub struct {{ service_to_pascal(name) }}Config(ocore::services::{{ 
service_to_pascal(name) }}Config);
+
+#[cfg(feature = "{{ service_to_feature(name) }}")]
+#[allow(deprecated)]
+impl ConfigBuilder for {{ service_to_pascal(name) }}Config {
+    fn build(&self) -> PyResult<ocore::Operator> {
+        ocore::Operator::from_config(self.0.clone()).map_err(format_pyerr)
+    }
+    fn scheme(&self) -> &'static str {
+        "{{ snake_to_kebab_case(name) }}"
+    }
+    fn to_map(&self) -> HashMap<String, String> {
+        #[allow(unused_mut)]
+        let mut map = HashMap::new();
+{%- for field in srvs[name].config %}
+{%- set line = config_to_map(field) %}
+{%- if line %}
+        {{ line }}
+{%- endif %}
+{%- endfor %}
+        map
+    }
+    fn is_picklable(&self) -> bool {
+        #[allow(unused_mut)]
+        let mut ok = true;
+{%- for field in srvs[name].config %}
+{%- set line = config_picklable(field) %}
+{%- if line %}
+        {{ line }}
+{%- endif %}
+{%- endfor %}
+        ok
+    }
+}
+
+#[cfg(feature = "{{ service_to_feature(name) }}")]
+#[allow(deprecated)]
+#[pymethods]
+impl {{ service_to_pascal(name) }}Config {
+    #[new]

Review Comment:
   If these classes are mutable, can we just build __init__?



##########
bindings/python/python/opendal/operator.pyi:
##########
@@ -162,6 +162,35 @@ class AsyncOperator:
             An awaitable that returns True if the path exists, False otherwise.
         """
     @classmethod
+    def from_config(cls, /, config: ServiceConfig) -> AsyncOperator:
+        """
+        Create a new `AsyncOperator` from a typed service config.
+
+        The config binds its own scheme, so there is no scheme argument and no
+        way to pair a config with the wrong service.

Review Comment:
   The function doesn't have a scheme argument. So this paragraph is explaining 
the same thing again. We can remove it.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to