Skip to content

Commit 4c9b624

Browse files
ambledclaude
andcommitted
Data-driven merge_config_changes(), bump version (v0.6.1)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 6ac1f9e commit 4c9b624

3 files changed

Lines changed: 87 additions & 195 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## [Unreleased]
44

5+
## [0.6.1] - 2026-02-16
6+
7+
### Changed
8+
- Replaced repetitive `merge_config_changes()` if-blocks with data-driven field descriptors
9+
510
## [0.6.0] - 2026-02-16
611

712
### Changed

src/wnm/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""A service to manage a cluster of decentralized Autonomi nodes"""
22

3-
__version__ = "0.6.0"
3+
__version__ = "0.6.1"

src/wnm/config.py

Lines changed: 81 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -610,232 +610,119 @@ def load_config():
610610
return options
611611

612612

613+
# Field descriptors for data-driven config merging: (field_name, cast_type)
614+
# Cast types: "int", "int_nullable", "float", "str", "port"
615+
_MERGE_FIELDS = [
616+
("node_cap", "int"),
617+
("cpu_less_than", "int"),
618+
("cpu_remove", "int"),
619+
("mem_less_than", "int"),
620+
("mem_remove", "int"),
621+
("hd_less_than", "int"),
622+
("hd_remove", "int"),
623+
("delay_start", "int"),
624+
("delay_restart", "int"),
625+
("delay_upgrade", "int"),
626+
("delay_remove", "int"),
627+
("survey_delay", "int"),
628+
("action_delay", "int_nullable"),
629+
("max_concurrent_upgrades", "int"),
630+
("max_concurrent_starts", "int"),
631+
("max_concurrent_removals", "int"),
632+
("max_concurrent_operations", "int"),
633+
("node_storage", "str"),
634+
("donate_address", "str"),
635+
("max_load_average_allowed", "float"),
636+
("desired_load_average", "float"),
637+
("port_start", "port"),
638+
("hdio_read_less_than", "int"),
639+
("hdio_read_remove", "int"),
640+
("hdio_write_less_than", "int"),
641+
("hdio_write_remove", "int"),
642+
("netio_read_less_than", "int"),
643+
("netio_read_remove", "int"),
644+
("netio_write_less_than", "int"),
645+
("netio_write_remove", "int"),
646+
("crisis_bytes", "int"),
647+
("metrics_port_start", "port"),
648+
("rpc_port_start", "port"),
649+
("environment", "str"),
650+
("start_args", "str"),
651+
("process_manager", "str"),
652+
("antnode_path", "str"),
653+
("antctl_path", "str"),
654+
("antctl_version", "str"),
655+
("highest_node_id_used", "int"),
656+
]
657+
658+
613659
# Merge the changes from the config file with the database
614660
def merge_config_changes(options, machine_config):
615-
# Collect updates
661+
import sys
662+
616663
cfg = {}
617-
if options.node_cap and int(options.node_cap) != machine_config.node_cap:
618-
cfg["node_cap"] = int(options.node_cap)
619-
if (
620-
options.cpu_less_than
621-
and int(options.cpu_less_than) != machine_config.cpu_less_than
622-
):
623-
cfg["cpu_less_than"] = int(options.cpu_less_than)
624-
if options.cpu_remove and int(options.cpu_remove) != machine_config.cpu_remove:
625-
cfg["cpu_remove"] = int(options.cpu_remove)
626-
if (
627-
options.mem_less_than
628-
and int(options.mem_less_than) != machine_config.mem_less_than
629-
):
630-
cfg["mem_less_than"] = int(options.mem_less_than)
631-
if options.mem_remove and int(options.mem_remove) != machine_config.mem_remove:
632-
cfg["mem_remove"] = int(options.mem_remove)
633-
if (
634-
options.hd_less_than
635-
and int(options.hd_less_than) != machine_config.hd_less_than
636-
):
637-
cfg["hd_less_than"] = int(options.hd_less_than)
638-
if options.hd_remove and int(options.hd_remove) != machine_config.hd_remove:
639-
cfg["hd_remove"] = int(options.hd_remove)
640-
if options.delay_start and int(options.delay_start) != machine_config.delay_start:
641-
cfg["delay_start"] = int(options.delay_start)
642-
if (
643-
options.delay_restart
644-
and int(options.delay_restart) != machine_config.delay_restart
645-
):
646-
cfg["delay_restart"] = int(options.delay_restart)
647-
if (
648-
options.delay_upgrade
649-
and int(options.delay_upgrade) != machine_config.delay_upgrade
650-
):
651-
cfg["delay_upgrade"] = int(options.delay_upgrade)
652-
if (
653-
options.delay_remove
654-
and int(options.delay_remove) != machine_config.delay_remove
655-
):
656-
cfg["delay_remove"] = int(options.delay_remove)
657-
if (
658-
options.survey_delay
659-
and int(options.survey_delay) != machine_config.survey_delay
660-
):
661-
cfg["survey_delay"] = int(options.survey_delay)
662-
if (
663-
options.action_delay is not None
664-
and int(options.action_delay) != machine_config.action_delay
665-
):
666-
cfg["action_delay"] = int(options.action_delay)
667-
if (
668-
options.max_concurrent_upgrades
669-
and int(options.max_concurrent_upgrades)
670-
!= machine_config.max_concurrent_upgrades
671-
):
672-
cfg["max_concurrent_upgrades"] = int(options.max_concurrent_upgrades)
673-
if (
674-
options.max_concurrent_starts
675-
and int(options.max_concurrent_starts) != machine_config.max_concurrent_starts
676-
):
677-
cfg["max_concurrent_starts"] = int(options.max_concurrent_starts)
678-
if (
679-
options.max_concurrent_removals
680-
and int(options.max_concurrent_removals)
681-
!= machine_config.max_concurrent_removals
682-
):
683-
cfg["max_concurrent_removals"] = int(options.max_concurrent_removals)
684-
if (
685-
options.max_concurrent_operations
686-
and int(options.max_concurrent_operations)
687-
!= machine_config.max_concurrent_operations
688-
):
689-
cfg["max_concurrent_operations"] = int(options.max_concurrent_operations)
690-
if options.node_storage and options.node_storage != machine_config.node_storage:
691-
cfg["node_storage"] = options.node_storage
664+
665+
# Data-driven: handle all standard fields
666+
for field, cast_type in _MERGE_FIELDS:
667+
opt_val = getattr(options, field, None)
668+
db_val = getattr(machine_config, field)
669+
670+
if cast_type == "int_nullable":
671+
if opt_val is None:
672+
continue
673+
opt_val = int(opt_val)
674+
elif cast_type == "int":
675+
if not opt_val:
676+
continue
677+
opt_val = int(opt_val)
678+
elif cast_type == "float":
679+
if not opt_val:
680+
continue
681+
opt_val = float(opt_val)
682+
elif cast_type == "port":
683+
if not opt_val:
684+
continue
685+
opt_val = normalize_port_start(opt_val)
686+
else: # str
687+
if not opt_val:
688+
continue
689+
690+
if opt_val != db_val:
691+
cfg[field] = opt_val
692+
693+
# Special: rewards_address (validation + exit on failure)
692694
if (
693695
options.rewards_address
694696
and options.rewards_address != machine_config.rewards_address
695697
):
696-
# Validate the new rewards_address
697698
is_valid, error_msg = validate_rewards_address(
698699
options.rewards_address, machine_config.donate_address
699700
)
700701
if not is_valid:
701702
logging.error(f"Invalid rewards_address: {error_msg}")
702703
sys.exit(1)
703704
cfg["rewards_address"] = options.rewards_address
704-
if (
705-
options.donate_address
706-
and options.donate_address != machine_config.donate_address
707-
):
708-
cfg["donate_address"] = options.donate_address
709-
if (
710-
options.max_load_average_allowed
711-
and float(options.max_load_average_allowed)
712-
!= machine_config.max_load_average_allowed
713-
):
714-
cfg["max_load_average_allowed"] = float(options.max_load_average_allowed)
715-
if (
716-
options.desired_load_average
717-
and float(options.desired_load_average) != machine_config.desired_load_average
718-
):
719-
cfg["desired_load_average"] = float(options.desired_load_average)
720-
if (
721-
options.port_start
722-
and normalize_port_start(options.port_start) != machine_config.port_start
723-
):
724-
cfg["port_start"] = normalize_port_start(options.port_start)
725-
if (
726-
options.hdio_read_less_than
727-
and int(options.hdio_read_less_than) != machine_config.hdio_read_less_than
728-
):
729-
cfg["hdio_read_less_than"] = int(options.hdio_read_less_than)
730-
if (
731-
options.hdio_read_remove
732-
and int(options.hdio_read_remove) != machine_config.hdio_read_remove
733-
):
734-
cfg["hdio_read_remove"] = int(options.hdio_read_remove)
735-
if (
736-
options.hdio_write_less_than
737-
and int(options.hdio_write_less_than) != machine_config.hdio_write_less_than
738-
):
739-
cfg["hdio_write_less_than"] = int(options.hdio_write_less_than)
740-
if (
741-
options.hdio_write_remove
742-
and int(options.hdio_write_remove) != machine_config.hdio_write_remove
743-
):
744-
cfg["hdio_write_remove"] = int(options.hdio_write_remove)
745-
if (
746-
options.netio_read_less_than
747-
and int(options.netio_read_less_than) != machine_config.netio_read_less_than
748-
):
749-
cfg["netio_read_less_than"] = int(options.netio_read_less_than)
750-
if (
751-
options.netio_read_remove
752-
and int(options.netio_read_remove) != machine_config.netio_read_remove
753-
):
754-
cfg["netio_read_remove"] = int(options.netio_read_remove)
755-
if (
756-
options.netio_write_less_than
757-
and int(options.netio_write_less_than) != machine_config.netio_write_less_than
758-
):
759-
cfg["netio_write_less_than"] = int(options.netio_write_less_than)
760-
if (
761-
options.netio_write_remove
762-
and int(options.netio_write_remove) != machine_config.netio_write_remove
763-
):
764-
cfg["netio_write_remove"] = int(options.netio_write_remove)
765-
if (
766-
options.crisis_bytes
767-
and int(options.crisis_bytes) != machine_config.crisis_bytes
768-
):
769-
cfg["crisis_bytes"] = int(options.crisis_bytes)
770-
if (
771-
options.metrics_port_start
772-
and normalize_port_start(options.metrics_port_start)
773-
!= machine_config.metrics_port_start
774-
):
775-
cfg["metrics_port_start"] = normalize_port_start(options.metrics_port_start)
776-
if (
777-
options.rpc_port_start
778-
and normalize_port_start(options.rpc_port_start)
779-
!= machine_config.rpc_port_start
780-
):
781-
cfg["rpc_port_start"] = normalize_port_start(options.rpc_port_start)
782-
if options.environment and options.environment != machine_config.environment:
783-
cfg["environment"] = options.environment
784-
if options.start_args and options.start_args != machine_config.start_args:
785-
cfg["start_args"] = options.start_args
786-
# process_manager can only be set during init (not allowed to change after initialization)
787-
# Similar to port_start and metrics_port_start
788-
if (
789-
options.process_manager
790-
and options.process_manager != machine_config.process_manager
791-
):
792-
cfg["process_manager"] = options.process_manager
793-
# Only update no_upnp if explicitly provided (check if in command line or env var)
794-
# Don't update based on store_true default value of False
795-
import sys
796705

706+
# Special: bool flags checked via sys.argv (store_true default is indistinguishable)
797707
if "--no_upnp" in sys.argv or "--no-upnp" in sys.argv or os.getenv("NO_UPNP"):
798708
if bool(options.no_upnp) != bool(machine_config.no_upnp):
799709
cfg["no_upnp"] = bool(options.no_upnp)
800-
# Only update antnode_path if explicitly provided (not None)
801-
if options.antnode_path and options.antnode_path != machine_config.antnode_path:
802-
cfg["antnode_path"] = options.antnode_path
803-
# Only update antctl_path if explicitly provided (not None)
804-
if options.antctl_path and options.antctl_path != machine_config.antctl_path:
805-
cfg["antctl_path"] = options.antctl_path
806-
# Only update antctl_debug if explicitly provided (check if in command line or env var)
807-
# Don't update based on store_true default value of False
710+
808711
if (
809712
"--antctl_debug" in sys.argv
810713
or "--antctl-debug" in sys.argv
811714
or os.getenv("ANTCTL_DEBUG")
812715
):
813716
if bool(options.antctl_debug) != bool(machine_config.antctl_debug):
814717
cfg["antctl_debug"] = bool(options.antctl_debug)
815-
# Only update antctl_version if explicitly provided (not None)
816-
if (
817-
options.antctl_version
818-
and options.antctl_version != machine_config.antctl_version
819-
):
820-
cfg["antctl_version"] = options.antctl_version
821-
822-
# highest_node_id_used override (only with --force_action update_config)
823-
if (
824-
options.highest_node_id_used
825-
and int(options.highest_node_id_used) != machine_config.highest_node_id_used
826-
):
827-
cfg["highest_node_id_used"] = int(options.highest_node_id_used)
828718

829-
# Special handling for --force_action disable_config
830-
# When disable_config is used, specified boolean flags are inverted (set to False)
719+
# Special: disable_config inverts boolean flags
831720
if hasattr(options, "force_action") and options.force_action == "disable_config":
832-
# Check for --antctl_debug flag and set it to False
833721
if "--antctl_debug" in sys.argv or "--antctl-debug" in sys.argv:
834722
if machine_config.antctl_debug != False:
835723
cfg["antctl_debug"] = False
836724
logging.info("disable_config: Setting antctl_debug to False")
837725

838-
# Check for --no_upnp flag and set it to False
839726
if "--no_upnp" in sys.argv or "--no-upnp" in sys.argv:
840727
if machine_config.no_upnp != False:
841728
cfg["no_upnp"] = False

0 commit comments

Comments
 (0)