Buckets:
| // Copyright (c) 2019, QuantStack and Mamba Contributors | |
| // | |
| // Distributed under the terms of the BSD 3-Clause License. | |
| // | |
| // The full license is in the file LICENSE, distributed with this software. | |
| namespace mamba | |
| { | |
| class Configuration; | |
| enum class ConfigurationLevel | |
| { | |
| kApi = 0, | |
| kCli = 1, | |
| kEnvVar = 2, | |
| kFile = 3, | |
| kDefault = 4 | |
| }; | |
| enum class RCConfigLevel | |
| { | |
| kSystemDir = 0, | |
| kRootPrefix = 1, | |
| kHomeDir = 2, | |
| kTargetPrefix = 3 | |
| }; | |
| } // mamba | |
| namespace YAML | |
| { | |
| template <> | |
| struct convert<mamba::RCConfigLevel> | |
| { | |
| static Node encode(const mamba::RCConfigLevel& rhs) | |
| { | |
| switch (rhs) | |
| { | |
| case mamba::RCConfigLevel::kHomeDir: | |
| return Node("HomeDir"); | |
| case mamba::RCConfigLevel::kRootPrefix: | |
| return Node("RootPrefix"); | |
| case mamba::RCConfigLevel::kSystemDir: | |
| return Node("SystemDir"); | |
| case mamba::RCConfigLevel::kTargetPrefix: | |
| return Node("TargetPrefix"); | |
| default: | |
| break; | |
| } | |
| return Node(); | |
| } | |
| static bool decode(const Node& node, mamba::RCConfigLevel& rhs) | |
| { | |
| if (!node.IsScalar()) | |
| { | |
| return false; | |
| } | |
| auto str = node.as<std::string>(); | |
| if (str == "HomeDir") | |
| { | |
| rhs = mamba::RCConfigLevel::kHomeDir; | |
| } | |
| else if (str == "RootPrefix") | |
| { | |
| rhs = mamba::RCConfigLevel::kRootPrefix; | |
| } | |
| else if (str == "SystemDir") | |
| { | |
| rhs = mamba::RCConfigLevel::kSystemDir; | |
| } | |
| else if (str == "TargetPrefix") | |
| { | |
| rhs = mamba::RCConfigLevel::kTargetPrefix; | |
| } | |
| else | |
| { | |
| return false; | |
| } | |
| return true; | |
| } | |
| }; | |
| } // YAML | |
| namespace mamba | |
| { | |
| namespace detail | |
| { | |
| struct ConfigurableImplBase | |
| { | |
| virtual ~ConfigurableImplBase() = default; | |
| bool rc_configured() const; | |
| bool env_var_configured() const; | |
| bool env_var_active() const; | |
| virtual bool cli_configured() const = 0; | |
| virtual void clear_rc_values() = 0; | |
| virtual void clear_cli_value() = 0; | |
| virtual void set_default_value() = 0; | |
| virtual void set_rc_yaml_value(const YAML::Node& value, const std::string& source) = 0; | |
| virtual void set_rc_yaml_values( | |
| const std::map<std::string, YAML::Node>& values, | |
| const std::vector<std::string>& sources | |
| ) = 0; | |
| virtual void set_cli_yaml_value(const YAML::Node& value) = 0; | |
| virtual void set_cli_yaml_value(const std::string& value) = 0; | |
| virtual void set_yaml_value(const YAML::Node& value) = 0; | |
| virtual void set_yaml_value(const std::string& value) = 0; | |
| virtual void compute(int options, const ConfigurationLevel& level) = 0; | |
| virtual bool is_valid_serialization(const std::string& value) const = 0; | |
| virtual bool is_sequence() const = 0; | |
| virtual YAML::Node yaml_value() const = 0; | |
| virtual void dump_json(nlohmann::json& node, const std::string& name) const = 0; | |
| bool is_config_loading() const; | |
| std::string m_name; | |
| std::string m_group = "Default"; | |
| std::string m_description = "No description provided"; | |
| std::string m_long_description = ""; | |
| Configuration* m_config = nullptr; | |
| std::vector<std::string> m_rc_sources; | |
| std::vector<std::string> m_sources; | |
| std::vector<std::string> m_source; | |
| std::set<std::string> m_needed_configs; | |
| std::set<std::string> m_implied_configs; | |
| bool m_rc_configurable = false; | |
| RCConfigLevel m_rc_configurable_policy = RCConfigLevel::kTargetPrefix; | |
| bool m_rc_configured = false; | |
| bool m_api_configured = false; | |
| std::vector<std::string> m_env_var_names = {}; | |
| bool m_single_op_lifetime = false; | |
| int m_compute_counter = 0; | |
| bool m_lock = false; | |
| using post_context_hook_type = std::function<void()>; | |
| post_context_hook_type p_post_ctx_hook; | |
| }; | |
| template <class T> | |
| struct ConfigurableImpl : ConfigurableImplBase | |
| { | |
| bool cli_configured() const override; | |
| void clear_rc_values() override; | |
| void clear_cli_value() override; | |
| void set_default_value() override; | |
| void set_rc_yaml_value(const YAML::Node& value, const std::string& source) override; | |
| void set_rc_yaml_values( | |
| const std::map<std::string, YAML::Node>& values, | |
| const std::vector<std::string>& sources | |
| ) override; | |
| void set_cli_yaml_value(const YAML::Node& value) override; | |
| void set_cli_yaml_value(const std::string& value) override; | |
| void set_yaml_value(const YAML::Node& value) override; | |
| void set_yaml_value(const std::string& value) override; | |
| void compute(int options, const ConfigurationLevel& level) override; | |
| bool is_valid_serialization(const std::string& value) const override; | |
| bool is_sequence() const override; | |
| YAML::Node yaml_value() const override; | |
| void dump_json(nlohmann::json& node, const std::string& name) const override; | |
| void set_rc_value(const T& value, const std::string& source); | |
| void set_rc_values( | |
| const std::map<std::string, T>& mapped_values, | |
| const std::vector<std::string>& sources | |
| ); | |
| void set_value(const T& value); | |
| using cli_config_type = detail::cli_config<T>; | |
| using cli_storage_type = typename cli_config_type::storage_type; | |
| std::map<std::string, T> m_rc_values; | |
| std::map<std::string, T> m_values; | |
| T m_value; | |
| T m_default_value; | |
| cli_config_type m_cli_config; | |
| T* p_context = 0; | |
| using value_hook_type = std::function<T()>; | |
| using post_merge_hook_type = std::function<void(T&)>; | |
| value_hook_type p_default_value_hook; | |
| value_hook_type p_fallback_value_hook; | |
| post_merge_hook_type p_post_merge_hook; | |
| }; | |
| } | |
| /**************** | |
| * Configurable * | |
| ****************/ | |
| class Configurable | |
| { | |
| public: | |
| template <class T> | |
| Configurable(const std::string& name, T* context); | |
| template <class T> | |
| Configurable(const std::string& name, const T& init); | |
| const std::string& name() const; | |
| const std::string& group() const; | |
| Configurable&& group(const std::string& group); | |
| const std::string& description() const; | |
| Configurable&& description(const std::string& desc); | |
| const std::string& long_description() const; | |
| Configurable&& long_description(const std::string& desc); | |
| const std::vector<std::string>& sources() const; | |
| const std::vector<std::string>& source() const; | |
| const std::set<std::string>& needed() const; | |
| Configurable&& needs(const std::set<std::string>& names); | |
| const std::set<std::string>& implied() const; | |
| Configurable&& implies(const std::set<std::string>& names); | |
| bool rc_configurable() const; | |
| RCConfigLevel rc_configurable_level() const; | |
| Configurable&& set_rc_configurable(RCConfigLevel level = RCConfigLevel::kTargetPrefix); | |
| bool rc_configured() const; | |
| bool env_var_configured() const; | |
| bool cli_configured() const; | |
| bool api_configured() const; | |
| bool configured() const; | |
| bool env_var_active() const; | |
| Configurable&& set_env_var_names(const std::vector<std::string>& names = {}); | |
| bool has_single_op_lifetime() const; | |
| Configurable&& set_single_op_lifetime(); | |
| void reset_compute_counter(); | |
| void lock(); | |
| void free(); | |
| bool locked(); | |
| template <class T> | |
| const T& value() const; | |
| template <class T> | |
| T& value(); | |
| template <class T> | |
| const T& cli_value() const; | |
| template <class T> | |
| const std::vector<T>& values() const; | |
| template <class T> | |
| Configurable&& set_rc_value(const T& value, const std::string& source); | |
| template <class T> | |
| Configurable&& set_rc_values( | |
| const std::map<std::string, T>& mapped_values, | |
| const std::vector<std::string>& sources | |
| ); | |
| template <class T> | |
| Configurable&& set_value(const T& value); | |
| template <class T> | |
| Configurable&& set_default_value(const T& value); | |
| Configurable&& clear_rc_values(); | |
| Configurable&& clear_env_values(); | |
| Configurable&& clear_cli_value(); | |
| Configurable&& clear_api_value(); | |
| Configurable&& clear_values(); | |
| template <class T> | |
| using value_hook_type = typename detail::ConfigurableImpl<T>::value_hook_type; | |
| template <class T> | |
| using post_merge_hook_type = typename detail::ConfigurableImpl<T>::post_merge_hook_type; | |
| using post_context_hook_type = detail::ConfigurableImplBase::post_context_hook_type; | |
| template <class T> | |
| Configurable&& set_default_value_hook(value_hook_type<T> hook); | |
| template <class T> | |
| Configurable&& set_default_value_hook(T (*hook)()); | |
| template <class T> | |
| Configurable&& set_fallback_value_hook(value_hook_type<T> hook); | |
| template <class T> | |
| Configurable&& set_fallback_value_hook(T (*hook)()); | |
| template <class T> | |
| Configurable&& set_post_merge_hook(post_merge_hook_type<T> hook); | |
| template <class T> | |
| Configurable&& set_post_merge_hook(void (*hook)(T&)); | |
| Configurable&& set_post_context_hook(post_context_hook_type hook); | |
| template <class T> | |
| using cli_storage_type = typename detail::ConfigurableImpl<T>::cli_storage_type; | |
| template <class T> | |
| Configurable&& set_cli_value(const T& value); | |
| template <class T> | |
| cli_storage_type<T>& get_cli_config(); | |
| Configurable&& set_rc_yaml_value(const YAML::Node& value, const std::string& source); | |
| Configurable&& set_rc_yaml_values( | |
| const std::map<std::string, YAML::Node>& values, | |
| const std::vector<std::string>& sources | |
| ); | |
| Configurable&& set_cli_yaml_value(const YAML::Node& value); | |
| Configurable&& set_cli_yaml_value(const std::string& value); | |
| Configurable&& set_yaml_value(const YAML::Node& value); | |
| Configurable&& set_yaml_value(const std::string& value); | |
| Configurable&& | |
| compute(int options = 0, const ConfigurationLevel& level = ConfigurationLevel::kDefault); | |
| bool is_valid_serialization(const std::string& value) const; | |
| bool is_sequence() const; | |
| YAML::Node yaml_value() const; | |
| void dump_json(nlohmann::json& node, const std::string& name) const; | |
| void set_configuration(Configuration& config) | |
| { | |
| p_impl->m_config = &config; | |
| assert(p_impl->m_config); | |
| } | |
| private: | |
| template <class T> | |
| detail::ConfigurableImpl<T>& get_wrapped(); | |
| template <class T> | |
| const detail::ConfigurableImpl<T>& get_wrapped() const; | |
| std::unique_ptr<detail::ConfigurableImplBase> p_impl; | |
| }; | |
| const int MAMBA_SHOW_CONFIG_VALUES = 1 << 0; | |
| const int MAMBA_SHOW_CONFIG_SRCS = 1 << 1; | |
| const int MAMBA_SHOW_CONFIG_DESCS = 1 << 2; | |
| const int MAMBA_SHOW_CONFIG_LONG_DESCS = 1 << 3; | |
| const int MAMBA_SHOW_CONFIG_GROUPS = 1 << 4; | |
| const int MAMBA_SHOW_ALL_CONFIGS = 1 << 5; | |
| const int MAMBA_SHOW_ALL_RC_CONFIGS = 1 << 6; | |
| /***************** | |
| * Configuration * | |
| * ***************/ | |
| class Configuration | |
| { | |
| public: | |
| explicit Configuration(Context& ctx); | |
| ~Configuration(); | |
| std::map<std::string, Configurable>& config(); | |
| const std::map<std::string, Configurable>& config() const; | |
| Configurable& at(const std::string& name); | |
| const Configurable& at(const std::string& name) const; | |
| using grouped_config_type = std::pair<std::string, std::vector<const Configurable*>>; | |
| std::vector<grouped_config_type> get_grouped_config() const; | |
| std::vector<fs::u8path> sources() const; | |
| std::vector<fs::u8path> valid_sources() const; | |
| Context& context() | |
| { | |
| return m_context; | |
| } | |
| const Context& context() const | |
| { | |
| return m_context; | |
| } | |
| void set_rc_values(std::vector<fs::u8path> possible_rc_paths, const RCConfigLevel& level); | |
| void load(); | |
| bool is_loading(); | |
| void clear_rc_values(); | |
| void clear_cli_values(); | |
| void clear_values(); | |
| /** | |
| * Pop values that should have a single operation lifetime to avoid memory effect | |
| * between multiple operations. | |
| * It corresponds to CLI values in most of the cases, but may also include API | |
| * values if the `Configurable::has_single_op_lifetime` method returns true. | |
| * RC files and environment variables are always overridden when loading the | |
| * configuration. | |
| */ | |
| void operation_teardown(); | |
| std::string | |
| dump(int opts = MAMBA_SHOW_CONFIG_VALUES, std::vector<std::string> names = {}) const; | |
| Configurable& insert(Configurable configurable, bool allow_redefinition = false); | |
| void reset_configurables(); | |
| protected: | |
| Configuration(const Configuration&) = delete; | |
| Configuration& operator=(const Configuration&) = delete; | |
| Configuration(Configuration&&) = delete; | |
| Configuration& operator=(Configuration&&) = delete; | |
| void set_configurables(); | |
| void reset_compute_counters(); | |
| void compute_loading_sequence(); | |
| void clear_rc_sources(); | |
| void add_to_loading_sequence( | |
| std::vector<std::string>& seq, | |
| const std::string& name, | |
| std::vector<std::string>& | |
| ); | |
| static YAML::Node load_rc_file(const fs::u8path& file); | |
| static std::vector<fs::u8path> | |
| compute_default_rc_sources(const Context& context, const RCConfigLevel& level); | |
| std::vector<fs::u8path> | |
| get_existing_rc_sources(const std::vector<fs::u8path>& possible_rc_paths); | |
| Context& m_context; | |
| std::vector<fs::u8path> m_sources; | |
| std::vector<fs::u8path> m_valid_sources; | |
| std::map<fs::u8path, YAML::Node> m_rc_yaml_nodes_cache; | |
| bool m_load_lock = false; | |
| std::map<std::string, Configurable> m_config; | |
| std::vector<std::string> m_config_order, m_loading_sequence; | |
| }; | |
| /*********************************** | |
| * ConfigurableImpl implementation * | |
| ***********************************/ | |
| namespace detail | |
| { | |
| auto get_root_prefix() -> fs::u8path; | |
| template <class T> | |
| bool ConfigurableImpl<T>::cli_configured() const | |
| { | |
| return m_cli_config.has_value(); | |
| }; | |
| template <class T> | |
| void ConfigurableImpl<T>::clear_rc_values() | |
| { | |
| this->m_rc_sources.clear(); | |
| m_rc_values.clear(); | |
| this->m_rc_configured = false; | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::clear_cli_value() | |
| { | |
| m_cli_config.reset(); | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::set_default_value() | |
| { | |
| m_value = m_default_value; | |
| } | |
| template <class T> | |
| void | |
| ConfigurableImpl<T>::set_rc_yaml_value(const YAML::Node& value, const std::string& source) | |
| { | |
| try | |
| { | |
| set_rc_value(value.as<T>(), source); | |
| } | |
| catch (const YAML::Exception& e) | |
| { | |
| LOG_ERROR << "Bad conversion of configurable '" << this->m_name << "' from source '" | |
| << source << "' : " << e.what(); | |
| } | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::set_rc_yaml_values( | |
| const std::map<std::string, YAML::Node>& values, | |
| const std::vector<std::string>& sources | |
| ) | |
| { | |
| std::map<std::string, T> converted_values; | |
| for (auto& y : values) | |
| { | |
| converted_values.insert({ y.first, y.second.as<T>() }); | |
| } | |
| set_rc_values(converted_values, sources); | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::set_cli_yaml_value(const YAML::Node& value) | |
| { | |
| m_cli_config.storage() = value.as<T>(); | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::set_cli_yaml_value(const std::string& value) | |
| { | |
| m_cli_config.storage() = detail::Source<T>::deserialize(value); | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::set_yaml_value(const YAML::Node& value) | |
| { | |
| set_value(value.as<T>()); | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::set_yaml_value(const std::string& value) | |
| { | |
| try | |
| { | |
| set_value(detail::Source<T>::deserialize(value)); | |
| } | |
| catch (const YAML::Exception& e) | |
| { | |
| LOG_ERROR << "Bad conversion of configurable '" << this->m_name << "' with value '" | |
| << value << "' : " << e.what(); | |
| throw e; | |
| } | |
| } | |
| template <class T> | |
| bool ConfigurableImpl<T>::is_valid_serialization(const std::string& value) const | |
| { | |
| try | |
| { | |
| detail::Source<T>::deserialize(value); | |
| return true; | |
| } | |
| catch (...) | |
| { | |
| return false; | |
| } | |
| } | |
| template <class T> | |
| bool ConfigurableImpl<T>::is_sequence() const | |
| { | |
| return detail::Source<T>::is_sequence(); | |
| } | |
| template <class T> | |
| YAML::Node ConfigurableImpl<T>::yaml_value() const | |
| { | |
| return YAML::Node(m_value); | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::dump_json(nlohmann::json& node, const std::string& name) const | |
| { | |
| node[name] = m_value; | |
| } | |
| template <> | |
| inline void | |
| ConfigurableImpl<fs::u8path>::dump_json(nlohmann::json& node, const std::string& name) const | |
| { | |
| node[name] = m_value.string(); | |
| } | |
| template <> | |
| inline void ConfigurableImpl<std::vector<fs::u8path>>::dump_json( | |
| nlohmann::json& node, | |
| const std::string& name | |
| ) const | |
| { | |
| std::vector<std::string> values(m_value.size()); | |
| std::transform( | |
| m_value.begin(), | |
| m_value.end(), | |
| values.begin(), | |
| [](const auto& value) { return value.string(); } | |
| ); | |
| node[name] = values; | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::set_rc_value(const T& value, const std::string& source) | |
| { | |
| this->m_rc_sources.push_back(source); | |
| m_rc_values[source] = value; | |
| this->m_rc_configured = true; | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::set_rc_values( | |
| const std::map<std::string, T>& mapped_values, | |
| const std::vector<std::string>& sources | |
| ) | |
| { | |
| assert(mapped_values.size() == sources.size()); | |
| this->m_rc_sources.insert(this->m_rc_sources.end(), sources.begin(), sources.end()); | |
| m_rc_values.insert(mapped_values.begin(), mapped_values.end()); | |
| this->m_rc_configured = true; | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::set_value(const T& value) | |
| { | |
| m_value = value; | |
| this->m_api_configured = true; | |
| } | |
| template <class T> | |
| void ConfigurableImpl<T>::compute(int options, const ConfigurationLevel& level) | |
| { | |
| assert(m_config); // REVIEW: should this be a if & throw? | |
| bool hook_disabled = options & MAMBA_CONF_DISABLE_HOOK; | |
| bool force_compute = options & MAMBA_CONF_FORCE_COMPUTE; | |
| if (force_compute) | |
| { | |
| LOG_TRACE << "Update configurable '" << this->m_name << "'"; | |
| } | |
| else | |
| { | |
| LOG_TRACE << "Compute configurable '" << this->m_name << "'"; | |
| } | |
| if (!force_compute && ((is_config_loading() && (m_compute_counter > 0)))) | |
| { | |
| throw std::runtime_error( | |
| "Multiple computation of '" + m_name + "' detected during loading sequence." | |
| ); | |
| } | |
| const auto& ctx = m_config->context(); | |
| m_sources.clear(); | |
| m_values.clear(); | |
| if (this->m_api_configured && (level >= ConfigurationLevel::kApi)) | |
| { | |
| m_sources.push_back("API"); | |
| m_values.insert({ "API", m_value }); | |
| } | |
| if (cli_configured() && (level >= ConfigurationLevel::kCli)) | |
| { | |
| m_sources.push_back("CLI"); | |
| m_values.insert({ "CLI", m_cli_config.value() }); | |
| } | |
| if (env_var_configured() && env_var_active() && (level >= ConfigurationLevel::kEnvVar)) | |
| { | |
| for (const auto& env_var : m_env_var_names) | |
| { | |
| auto env_var_value = util::get_env(env_var); | |
| if (env_var_value) | |
| { | |
| try | |
| { | |
| m_values.insert( | |
| { env_var, detail::Source<T>::deserialize(env_var_value.value()) } | |
| ); | |
| m_sources.push_back(env_var); | |
| } | |
| catch (const YAML::Exception& e) | |
| { | |
| LOG_ERROR << "Bad conversion of configurable '" << this->m_name | |
| << "' from environment variable '" << env_var | |
| << "' with value '" << env_var_value.value() | |
| << "' : " << e.what(); | |
| throw e; | |
| } | |
| } | |
| } | |
| } | |
| if (rc_configured() && !ctx.src_params.no_rc && (level >= ConfigurationLevel::kFile)) | |
| { | |
| m_sources.insert(m_sources.end(), m_rc_sources.begin(), m_rc_sources.end()); | |
| m_values.insert(m_rc_values.begin(), m_rc_values.end()); | |
| } | |
| if ((p_default_value_hook != NULL) && (level >= ConfigurationLevel::kDefault)) | |
| { | |
| m_sources.push_back("default"); | |
| m_values.insert({ "default", p_default_value_hook() }); | |
| } | |
| if (m_sources.empty() && (p_fallback_value_hook != NULL)) | |
| { | |
| m_sources.push_back("fallback"); | |
| m_values.insert({ "fallback", p_fallback_value_hook() }); | |
| } | |
| if (!m_sources.empty()) | |
| { | |
| detail::Source<T>::merge(m_values, m_sources, m_value, m_source); | |
| } | |
| else | |
| { | |
| m_value = m_default_value; | |
| m_source = detail::Source<T>::default_value(m_default_value); | |
| } | |
| if (!hook_disabled && (p_post_merge_hook != NULL)) | |
| { | |
| p_post_merge_hook(m_value); | |
| } | |
| ++m_compute_counter; | |
| if (p_context != nullptr) | |
| { | |
| *p_context = m_value; | |
| } | |
| if (p_post_ctx_hook != nullptr) | |
| { | |
| p_post_ctx_hook(); | |
| } | |
| } | |
| } | |
| /******************************* | |
| * Configurable implementation * | |
| *******************************/ | |
| template <class T> | |
| Configurable::Configurable(const std::string& name, T* context) | |
| : p_impl(std::make_unique<detail::ConfigurableImpl<T>>()) | |
| { | |
| auto& wrapped = get_wrapped<T>(); | |
| wrapped.m_name = name; | |
| wrapped.m_value = *context; | |
| wrapped.m_default_value = *context; | |
| wrapped.m_source = detail::Source<T>::default_value(*context); | |
| wrapped.p_context = context; | |
| } | |
| template <class T> | |
| Configurable::Configurable(const std::string& name, const T& init) | |
| : p_impl(std::make_unique<detail::ConfigurableImpl<T>>()) | |
| { | |
| auto& wrapped = get_wrapped<T>(); | |
| wrapped.m_name = name; | |
| wrapped.m_value = init; | |
| wrapped.m_default_value = init; | |
| wrapped.m_source = detail::Source<T>::default_value(init); | |
| } | |
| template <class T> | |
| const T& Configurable::value() const | |
| { | |
| return const_cast<Configurable*>(this)->value<T>(); | |
| } | |
| template <class T> | |
| T& Configurable::value() | |
| { | |
| if (p_impl->is_config_loading() && p_impl->m_compute_counter == 0) | |
| { | |
| throw std::runtime_error("Using '" + name() + "' value without previous computation."); | |
| } | |
| return get_wrapped<T>().m_value; | |
| } | |
| template <class T> | |
| const T& Configurable::cli_value() const | |
| { | |
| if (!cli_configured()) | |
| { | |
| throw std::runtime_error("Trying to get unset CLI value of '" + name() + "'"); | |
| } | |
| return get_wrapped<T>().m_cli_config.value(); | |
| } | |
| template <class T> | |
| const std::vector<T>& Configurable::values() const | |
| { | |
| return get_wrapped<T>().m_values; | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_rc_value(const T& value, const std::string& source) | |
| { | |
| get_wrapped<T>().set_rc_value(value, source); | |
| return std::move(*this); | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_rc_values( | |
| const std::map<std::string, T>& mapped_values, | |
| const std::vector<std::string>& sources | |
| ) | |
| { | |
| get_wrapped<T>().set_rc_values(mapped_values, sources); | |
| return std::move(*this); | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_value(const T& value) | |
| { | |
| get_wrapped<T>().set_value(value); | |
| return std::move(*this); | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_default_value(const T& value) | |
| { | |
| auto& wrapped = get_wrapped<T>(); | |
| wrapped.m_default_value = value; | |
| wrapped.m_value = value; | |
| return std::move(*this); | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_default_value_hook(value_hook_type<T> hook) | |
| { | |
| get_wrapped<T>().p_default_value_hook = hook; | |
| return std::move(*this); | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_default_value_hook(T (*hook)()) | |
| { | |
| return set_default_value_hook<T>(value_hook_type<T>(hook)); | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_fallback_value_hook(value_hook_type<T> hook) | |
| { | |
| get_wrapped<T>().p_fallback_value_hook = hook; | |
| return std::move(*this); | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_fallback_value_hook(T (*hook)()) | |
| { | |
| return set_fallback_value_hook<T>(value_hook_type<T>(hook)); | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_post_merge_hook(post_merge_hook_type<T> hook) | |
| { | |
| get_wrapped<T>().p_post_merge_hook = hook; | |
| return std::move(*this); | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_post_merge_hook(void (*hook)(T&)) | |
| { | |
| return set_post_merge_hook<T>(post_merge_hook_type<T>(hook)); | |
| } | |
| template <class T> | |
| Configurable&& Configurable::set_cli_value(const T& value) | |
| { | |
| get_wrapped<T>().m_cli_config = value; | |
| return std::move(*this); | |
| } | |
| template <class T> | |
| auto Configurable::get_cli_config() -> cli_storage_type<T>& | |
| { | |
| return get_wrapped<T>().m_cli_config.m_storage; | |
| } | |
| template <class T> | |
| detail::ConfigurableImpl<T>& Configurable::get_wrapped() | |
| { | |
| try | |
| { | |
| auto& derived = dynamic_cast<detail::ConfigurableImpl<T>&>(*p_impl); | |
| return derived; | |
| } | |
| catch (const std::bad_cast& e) | |
| { | |
| LOG_ERROR << "Bad cast of Configurable '" << name() << "'"; | |
| throw e; | |
| } | |
| } | |
| template <class T> | |
| const detail::ConfigurableImpl<T>& Configurable::get_wrapped() const | |
| { | |
| return const_cast<Configurable&>(*this).get_wrapped<T>(); | |
| } | |
| /******************************** | |
| * Configuration implementation * | |
| ********************************/ | |
| inline Configurable& Configuration::insert(Configurable configurable, bool allow_redefinition) | |
| { | |
| std::string name = configurable.name(); | |
| if (m_config.count(name) == 0) | |
| { | |
| auto [it, success] = m_config.insert({ name, std::move(configurable) }); | |
| it->second.set_configuration(*this); | |
| m_config_order.push_back(name); | |
| } | |
| else | |
| { | |
| if (!allow_redefinition) | |
| { | |
| throw std::runtime_error("Redefinition of configurable '" + name + "' not allowed."); | |
| } | |
| } | |
| return m_config.at(name); | |
| } | |
| void use_conda_root_prefix(Configuration& config, bool force = false); | |
| } | |
Xet Storage Details
- Size:
- 30.5 kB
- Xet hash:
- a93b513b9b687a13eaa08f206f479b9f9a59f7bcd574888fab62c35b002cdb51
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.