Skip to content

Commit 92bc30c

Browse files
authored
Merge pull request #1020 from vsbogd/no-config-dir-by-default
Make MeTTa runner not read config dir by default
2 parents f120c1b + bef84dd commit 92bc30c

File tree

12 files changed

+81
-70
lines changed

12 files changed

+81
-70
lines changed

c/src/metta.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,8 +1525,7 @@ pub extern "C" fn env_builder_set_working_dir(builder: *mut env_builder_t, path:
15251525
*builder_arg_ref = builder.into();
15261526
}
15271527

1528-
/// @brief Sets the config directory for the environment. A directory at the specified path
1529-
/// will be created, and its contents populated with default values, if one does not already exist
1528+
/// @brief Sets the config directory for the environment.
15301529
/// @ingroup environment_group
15311530
/// @param[in] builder A pointer to the in-process environment builder state
15321531
/// @param[in] path A C-style string specifying a path to the config directory
@@ -1556,15 +1555,15 @@ pub extern "C" fn env_builder_create_config_dir(builder: *mut env_builder_t, sho
15561555
*builder_arg_ref = builder.into();
15571556
}
15581557

1559-
/// @brief Configures the environment so that no config directory will be read nor created
1558+
/// @brief Sets the default config directory for the environment.
15601559
/// @ingroup environment_group
15611560
/// @param[in] builder A pointer to the in-process environment builder state
15621561
///
15631562
#[no_mangle]
1564-
pub extern "C" fn env_builder_disable_config_dir(builder: *mut env_builder_t) {
1563+
pub extern "C" fn env_builder_set_default_config_dir(builder: *mut env_builder_t) {
15651564
let builder_arg_ref = unsafe{ &mut *builder };
15661565
let builder = core::mem::replace(builder_arg_ref, env_builder_t::null()).into_inner();
1567-
let builder = builder.set_no_config_dir();
1566+
let builder = builder.set_default_config_dir();
15681567
*builder_arg_ref = builder.into();
15691568
}
15701569

lib/src/metta/runner/environment.rs

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ impl Environment {
111111
/// NOTE: It is not necessary to use the EnvBuilder if the default environment is acceptable
112112
pub struct EnvBuilder {
113113
env: Environment,
114-
no_cfg_dir: bool,
115114
create_cfg_dir: bool,
116115
caches_dir: Option<PathBuf>,
117116
#[cfg(feature = "pkg_mgmt")]
@@ -135,8 +134,8 @@ impl EnvBuilder {
135134
/// NOTE: Unless otherwise specified, the default working directory will be the current process
136135
/// working dir (`cwd`)
137136
///
138-
/// NOTE: Unless otherwise specified by calling either [Self::set_no_config_dir] or [Self::set_config_dir], the
139-
/// [Environment] will be configured using files in the OS-Specific configuration file locations.
137+
/// NOTE: Unless otherwise specified by calling either [Self::set_default_config_dir] or [Self::set_config_dir], the
138+
/// [Environment] will be configured using no configuration directory.
140139
///
141140
/// Depending on the host OS, the config directory locations will be:
142141
/// * Linux: ~/.config/metta/
@@ -147,9 +146,8 @@ impl EnvBuilder {
147146
pub fn new() -> Self {
148147
Self {
149148
env: Environment::new(),
150-
no_cfg_dir: false,
151149
caches_dir: None,
152-
create_cfg_dir: true,
150+
create_cfg_dir: false,
153151
#[cfg(feature = "pkg_mgmt")]
154152
proto_catalogs: vec![],
155153
#[cfg(feature = "pkg_mgmt")]
@@ -162,7 +160,7 @@ impl EnvBuilder {
162160
/// The `test_env` Environment will not load or create any files. Additionally
163161
/// this method will initialize the logger for the test environment
164162
pub fn test_env() -> Self {
165-
EnvBuilder::new().set_working_dir(None).set_is_test(true).set_no_config_dir()
163+
EnvBuilder::new().set_working_dir(None).set_is_test(true)
166164
}
167165

168166
/// Sets (or unsets) the working_dir for the environment
@@ -174,10 +172,7 @@ impl EnvBuilder {
174172
/// Sets the `config_dir` that the environment will load
175173
pub fn set_config_dir(mut self, config_dir: &Path) -> Self {
176174
self.env.config_dir = Some(config_dir.into());
177-
if self.no_cfg_dir {
178-
panic!("Fatal Error: set_config_dir is incompatible with set_no_config_dir");
179-
}
180-
self
175+
self.set_create_config_dir(true)
181176
}
182177

183178
/// Sets the directory used for caching files, such as those fetched from remote catalogs
@@ -193,20 +188,21 @@ impl EnvBuilder {
193188
/// NOTE: If the config directory exists but some config files are missing, default files will *not* be created.
194189
pub fn set_create_config_dir(mut self, should_create: bool) -> Self {
195190
self.create_cfg_dir = should_create;
196-
if self.no_cfg_dir && should_create {
197-
panic!("Fatal Error: set_create_config_dir(true) is incompatible with set_no_config_dir");
191+
if self.env.config_dir.is_none() && should_create {
192+
panic!("Fatal Error: call set_default_config_dir() or set_config_dir(<path>) before calling set_create_config_dir(true)");
198193
}
199194
self
200195
}
201196

202-
/// Configures the Environment not to load nor create any config files
203-
pub fn set_no_config_dir(mut self) -> Self {
204-
self.no_cfg_dir = true;
205-
self.create_cfg_dir = false;
206-
if self.env.config_dir.is_some() {
207-
panic!("Fatal Error: set_config_dir is incompatible with set_no_config_dir");
197+
/// Sets the `config_dir` to the default configuration directory path
198+
pub fn set_default_config_dir(self) -> Self {
199+
match ProjectDirs::from("io", "TrueAGI", "metta") {
200+
Some(proj_dirs) => self.set_config_dir(proj_dirs.config_dir()),
201+
None => {
202+
eprint!("Failed to initialize config with OS config directory!");
203+
self
204+
}
208205
}
209-
self
210206
}
211207

212208
/// Sets the `is_test` flag for the environment, to specify whether the environment is a unit-test
@@ -283,21 +279,6 @@ impl EnvBuilder {
283279
proto_catalogs.insert(0, ProtoCatalog::Path(working_dir.into()));
284280
}
285281

286-
//Construct the platform-specific config dir location, if an explicit location wasn't provided
287-
if !self.no_cfg_dir {
288-
if env.config_dir.is_none() {
289-
match ProjectDirs::from("io", "TrueAGI", "metta") {
290-
Some(proj_dirs) => {
291-
let cfg_dir: PathBuf = proj_dirs.config_dir().into();
292-
env.config_dir = Some(cfg_dir);
293-
},
294-
None => {
295-
eprint!("Failed to initialize config with OS config directory!");
296-
}
297-
}
298-
}
299-
}
300-
301282
if let Some(config_dir) = &env.config_dir {
302283

303284
let init_metta_path = config_dir.join("init.metta");

lib/src/metta/runner/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,4 +1426,9 @@ mod tests {
14261426
assert_eq!(result, Ok(vec![vec![]]));
14271427
}
14281428

1429+
#[test]
1430+
fn metta_no_config_dir_by_default() {
1431+
let metta = Metta::new(None);
1432+
assert_eq!(metta.environment().config_dir(), None);
1433+
}
14291434
}

python/hyperon/exts/agents/agent_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def _init_metta(self):
144144
# the caller space is not directly accessible as a context,
145145
# except the case when _metta is set via get_agent_atom with parent MeTTa
146146
if self._include_paths is not None:
147-
env_builder = Environment.custom_env(include_paths=self._include_paths)
147+
env_builder = Environment.custom_env(include_paths=self._include_paths, config_dir="")
148148
metta = MeTTa(env_builder=env_builder)
149149
else:
150150
metta = MeTTa()

python/hyperon/metta.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def main():
3131
elif args.file:
3232
parent_dir = os.path.dirname(args.file)
3333
with open(args.file) as f: program = f.read()
34-
metta = hyperon.MeTTa(env_builder=hyperon.Environment.custom_env(working_dir=parent_dir))
34+
metta = hyperon.MeTTa(env_builder=hyperon.Environment.custom_env(working_dir=parent_dir, config_dir=""))
3535
for result in metta.run(program):
3636
print(result)
3737
else:

python/hyperon/runner.py

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ def __init__(self, cmetta = None, space = None, env_builder = None):
116116
space = GroundingSpaceRef()
117117
if env_builder is None:
118118
env_builder = hp.env_builder_start()
119+
hp.env_builder_set_default_config_dir(env_builder)
119120
hp.env_builder_push_fs_module_format(env_builder, _PyFileMeTTaModFmt)
120121
#LP-TODO-Next, add an fs_module_fmt arg to the standardized way to init environments, so that
121122
# the Python user can define additional formats without tweaking any hyperon files. To make
@@ -233,28 +234,53 @@ def config_dir():
233234
else:
234235
return None
235236

236-
def init_common_env(working_dir = None, config_dir = None, create_config = True, disable_config = False, is_test = False, include_paths = []):
237-
"""Initialize the common environment with the supplied args"""
238-
builder = Environment.custom_env(working_dir, config_dir, create_config, disable_config, is_test, include_paths)
237+
def init_common_env(working_dir = None, config_dir = None, create_config = None, is_test = None, include_paths = []):
238+
"""Initialize the common environment with the supplied args
239+
240+
Keyword arguments:
241+
working_dir -- working directory for the environment (default None)
242+
config_dir -- path to the configuration directory, None - no
243+
configuration directory, "" - default configuration directory
244+
(default None)
245+
create_config -- create configuration directory if it doesn't exist
246+
(default None)
247+
is_test -- is environment used in unit-test flag (default None)
248+
include_paths -- additional search paths to search for MeTTa
249+
modules in the file system (default [])
250+
"""
251+
builder = Environment.custom_env(working_dir, config_dir, create_config, is_test, include_paths)
239252
return hp.env_builder_init_common_env(builder)
240253

241254
def test_env():
242255
"""Returns an EnvBuilder object specifying a unit-test environment, that can be used to init a MeTTa runner"""
243256
return hp.env_builder_use_test_env()
244257

245-
def custom_env(working_dir = None, config_dir = None, create_config = True, disable_config = False, is_test = False, include_paths = []):
246-
"""Returns an EnvBuilder object that can be used to init a MeTTa runner, if you need multiple environments to coexist in the same process"""
258+
def custom_env(working_dir = None, config_dir = None, create_config = None, is_test = None, include_paths = []):
259+
"""Returns an EnvBuilder object that can be used to init a MeTTa runner, if you need multiple environments to coexist in the same process
260+
261+
Keyword arguments:
262+
working_dir -- working directory for the environment (default None)
263+
config_dir -- path to the configuration directory, None - no
264+
configuration directory, "" - default configuration directory
265+
(default None)
266+
create_config -- create configuration directory if not found
267+
(default None)
268+
is_test -- is environment used in unit-test flag (default None)
269+
include_paths -- additional search paths to search for MeTTa
270+
modules in the file system (default [])
271+
"""
247272
builder = hp.env_builder_start()
248-
if (working_dir is not None):
273+
if working_dir is not None:
249274
hp.env_builder_set_working_dir(builder, working_dir)
250-
if (config_dir is not None):
251-
hp.env_builder_set_config_dir(builder, config_dir)
252-
if (create_config is False):
253-
hp.env_builder_create_config_dir(builder, False) #Pass False to disable "create if missing" behavior
254-
if (disable_config):
255-
hp.env_builder_disable_config_dir(builder)
256-
if (is_test):
257-
hp.env_builder_set_is_test(builder, True)
275+
if config_dir is not None:
276+
if config_dir == "":
277+
hp.env_builder_set_default_config_dir(builder)
278+
else:
279+
hp.env_builder_set_config_dir(builder, config_dir)
280+
if create_config is not None:
281+
hp.env_builder_create_config_dir(builder, create_config)
282+
if is_test is not None:
283+
hp.env_builder_set_is_test(builder, is_test)
258284
for path in include_paths:
259285
hp.env_builder_push_include_path(builder, path)
260286
return builder

python/hyperonpy.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,8 +1159,8 @@ PYBIND11_MODULE(hyperonpy, m) {
11591159
m.def("env_builder_set_working_dir", [](EnvBuilder& builder, std::string path) { env_builder_set_working_dir(builder.ptr(), path.c_str()); }, "Sets the working dir in the environment");
11601160
m.def("env_builder_set_config_dir", [](EnvBuilder& builder, std::string path) { env_builder_set_config_dir(builder.ptr(), path.c_str()); }, "Sets the config dir in the environment");
11611161
m.def("env_builder_create_config_dir", [](EnvBuilder& builder, bool should_create) { env_builder_create_config_dir(builder.ptr(), should_create); }, "Creates the config dir if it doesn't exist");
1162-
m.def("env_builder_disable_config_dir", [](EnvBuilder& builder) { env_builder_disable_config_dir(builder.ptr()); }, "Disables the config dir in the environment");
1163-
m.def("env_builder_set_is_test", [](EnvBuilder& builder, bool is_test) { env_builder_set_is_test(builder.ptr(), is_test); }, "Disables the config dir in the environment");
1162+
m.def("env_builder_set_default_config_dir", [](EnvBuilder& builder) { env_builder_set_default_config_dir(builder.ptr()); }, "Sets default config directory location");
1163+
m.def("env_builder_set_is_test", [](EnvBuilder& builder, bool is_test) { env_builder_set_is_test(builder.ptr(), is_test); }, "Set true if this environment is used in unit test");
11641164
m.def("env_builder_push_include_path", [](EnvBuilder& builder, std::string path) { env_builder_push_include_path(builder.ptr(), path.c_str()); }, "Adds an include path to the environment");
11651165
m.def("env_builder_push_fs_module_format", [](EnvBuilder& builder, py::object interface) {
11661166
//TODO. We end up leaking this object, but it's a non-issue in practice because environments usually live the life of the program.

python/tests/test_environment.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ def testEnvironment(self):
1111
self.assertTrue(Environment.init_common_env(config_dir = "/tmp/hyperon-test", create_config = True))
1212
self.assertEqual(Environment.config_dir(), "/tmp/hyperon-test")
1313

14-
self.assertFalse(Environment.init_common_env(disable_config = True))
14+
self.assertFalse(Environment.init_common_env())

python/tests/test_extend.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def test_extend(self):
1313
'''
1414
This test verifies that importing from a python-implemnted module along with @register_atoms and @register_tokens works
1515
'''
16-
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), disable_config=True, is_test=True))
16+
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), is_test=True))
1717
self.assertEqual(
1818
metta.run('''
1919
!(import! &self extension)
@@ -30,7 +30,7 @@ def test_extend(self):
3030
[[ValueAtom(12)]])
3131

3232
def test_grounded_noext(self):
33-
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), disable_config=True, is_test=True))
33+
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), is_test=True))
3434

3535
@grounded(metta)
3636
def abs_dif(x, y):
@@ -47,7 +47,7 @@ def test_extend_dir_pymod(self):
4747
'''
4848
This test verifies that importing from a python module directory also works
4949
'''
50-
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), disable_config=True, is_test=True))
50+
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), is_test=True))
5151
self.assertEqual(
5252
metta.run('''
5353
!(import! &self ext_dir)
@@ -67,7 +67,7 @@ def test_extend_dir_pymod(self):
6767
# '''
6868
# This test verifies that importing from a module that imports its own sub-module also works
6969
# '''
70-
# metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), disable_config=True, is_test=True))
70+
# metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), is_test=True))
7171
# self.assertEqual(
7272
# metta.run('''
7373
# !(import! &self ext_sub)
@@ -84,7 +84,7 @@ def test_extend_recursive_pymod(self):
8484
'''
8585
This test verifies that importing from a sub-module will cause the necessary parents to be imported as well
8686
'''
87-
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), disable_config=True, is_test=True))
87+
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), is_test=True))
8888
self.assertEqual(
8989
metta.run('''
9090
!(import! &self ext_recursive:level-2:ext_nested)
@@ -107,7 +107,7 @@ def test_extend_global(self):
107107
from extension import g_object
108108
# Sanity check
109109
self.assertEqual(g_object, None)
110-
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), disable_config=True, is_test=True))
110+
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), is_test=True))
111111
metta.run('''
112112
!(import! &self extension)
113113
!(set-global! 42)
@@ -127,7 +127,7 @@ def test_error_pyext(self):
127127
'''
128128
This test verifies that an error from a Python extension is properly propagated
129129
'''
130-
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), disable_config=True, is_test=True))
130+
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), is_test=True))
131131
result = metta.run("!(import! &self error_pyext)")
132132
self.assertEqual(S('Error'), result[0][0].get_children()[0])
133133

python/tests/test_modules.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def test_python_file_mod_format(self):
1010
Tests that a MeTTa module, implemented as a '.py', file will be correctly identified when the
1111
module system searches in the include directory, and then that it will be sucessfully loaded
1212
"""
13-
runner = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), disable_config=True, is_test=True))
13+
runner = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), is_test=True))
1414

1515
#Make sure the `import!` operation finds the pyfile_test_mod.py file, recognizes it as a
1616
# MeTTa module using the PythonFileModuleFormat, and loads the MeTTa module it sucessfully
@@ -24,7 +24,7 @@ def test_python_file_mod_format(self):
2424
self.assertEqual(result[0].get_object().content, 3.14159)
2525

2626
def test_include(self):
27-
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), disable_config=True, is_test=True))
27+
metta = MeTTa(env_builder=Environment.custom_env(working_dir=os.getcwd(), is_test=True))
2828
result = metta.run("""
2929
(three isprime)
3030
!(match &self ($x isprime) $x)
@@ -43,7 +43,7 @@ def test_py_ops(self):
4343
"""
4444
Tests that a MeTTa module from exts can be imported
4545
"""
46-
runner = MeTTa(env_builder=Environment.custom_env())
46+
runner = MeTTa(env_builder=Environment.custom_env(config_dir=""))
4747
runner.run("!(import! &self py_ops)")
4848
result = runner.run('!(* "a" 4)')
4949
self.assertEqual(result[0][0], ValueAtom('aaaa'))

0 commit comments

Comments
 (0)