Skip to content

Upgrading to yacman v1.0

Yacman v1.0 provides two major feature upgrades:

  1. New constructor pattern: Constructors now use YAMLConfigManager.from_x(...) methods to make object creation clearer
  2. Separate read/write locks: Locks are now separated into read locks and write locks, allowing multiple simultaneous readers

If you were using FutureYAMLConfigManager in v0.9.3, update your imports:

Before (v0.9.3):

from yacman import FutureYAMLConfigManager as YAMLConfigManager

After (v1.0.0):

from yacman import YAMLConfigManager

Context managers now use explicit write_lock or read_lock functions:

from yacman import write_lock, read_lock

Before (v0.9.3):

with ym as locked_ym:
locked_ym.write()

After (v1.0.0):

with write_lock(ym) as locked_ym:
locked_ym.rebase()
locked_ym.write()

Important: In v1.0, you must call rebase() before write() if you want to allow for multiple processes that may have written to the file since you read it in.

You can no longer create a YAMLConfigManager object directly. Use the from_x() constructor methods instead:

Before (v0.9.3):

ym = YAMLConfigManager(filepath="config.yaml")
ym = YAMLConfigManager(entries={"key": "value"})

After (v1.0.0):

from yacman import YAMLConfigManager
# From a file
ym = YAMLConfigManager.from_yaml_file("config.yaml")
# From a dictionary
data = {"key": "value"}
ym = YAMLConfigManager.from_obj(data)
# From a YAML string
yaml_data = "key: value"
ym = YAMLConfigManager.from_yaml_data(yaml_data)

Step 4: Update file loading with overrides

Section titled “Step 4: Update file loading with overrides”

In the past, you could load from a file and overwrite some attributes with a dict, all from the constructor. This is now more explicit:

Before (v0.9.3):

ym = YAMLConfigManager(filepath="config.yaml", entries={"override_key": "value"})

After (v1.0.0):

ym = YAMLConfigManager.from_yaml_file("config.yaml")
ym.update_from_obj({"override_key": "value"})
from yacman import YAMLConfigManager, write_lock, read_lock
data = {
"my_list": [1, 2, 3],
"my_int": 8,
"my_str": "hello world!",
"my_dict": {"nested_val": 15}
}
# Create from object
ym = YAMLConfigManager.from_obj(data)
# Access values
print(ym["my_list"])
print(ym["my_int"])
print(ym["my_dict"])
# Modify and write with a write lock
ym["new_var"] = 15
with write_lock(ym) as locked_ym:
locked_ym.rebase() # Capture any changes since file was loaded
locked_ym.write()
# Use a read lock to rebase
# This will replay any in-memory updates on top of whatever is re-read from the file
with read_lock(ym) as locked_ym:
locked_ym.rebase()
# Use a read lock to reset the in-memory object to whatever is on disk
with read_lock(ym) as locked_ym:
locked_ym.reset()

Example 3: Expanding environment variables

Section titled “Example 3: Expanding environment variables”

To expand environment variables in values, use the .exp attribute:

ym = YAMLConfigManager.from_yaml_file("config.yaml")
expanded_value = ym.exp["path_with_env_vars"]
  • Update imports from FutureYAMLConfigManager to YAMLConfigManager
  • Replace direct constructor calls with from_yaml_file(), from_obj(), or from_yaml_data()
  • Update context managers to use write_lock() or read_lock()
  • Add rebase() calls before write() in write-lock contexts
  • Replace combined file+override constructors with explicit update_from_obj() calls
  • Test all file I/O operations
  • Verify environment variable expansion works correctly

The following are deprecated in v1.0 and will be removed in future versions:

  • Direct instantiation of YAMLConfigManager (use from_x() methods instead)
  • Using YAMLConfigManager object as a context manager directly (use write_lock() or read_lock())
  • YacAttMap class (replaced by YAMLConfigManager)