Repository: GEOS-ESM/mepo

Issue:
Move to mepo status as serial by default
As described in #336, the parallel/starmap path of `mepo status` seems to cause fork-bomb-like behavior at NAS. Indeed, I believe @pchakraborty also saw similar issues on an Intel Mac. This led him to add the `--serial` flag to `mepo status` for this case.

Since both v1 and v2 seem to show this behavior at NAS, I propose making `mepo status --serial` the default and adding a `--parallel` option if someone wants the parallel behavior.

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1c2a00..6831467 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,21 +13,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Changed
 
+- Moved `mepo status` and `mepo restore-state` to default to their serial variants rather than parallel by default. At the same time, we remove the `--serial` option from these commands and add a `--parallel` option if users want to run them in parallel.
+
 ## [2.2.1] - 2025-01-03
 
 ### Fixed
 
 - Fixed bugs in the lesser used options of `mepo clone`, `allrepos` and `registry`
 
-
 ### Added
 
 - Added tests for `mepo clone --allrepos` and `mepo clone --registry`
 
-
 ## [2.2.0] - 2024-12-24
 
-
 ### Added
 
 - Hidden option `--location` for mepo that returns the path to the mepo directory
diff --git a/src/mepo/cmdline/parser.py b/src/mepo/cmdline/parser.py
index 4f70a4c..89a16e1 100644
--- a/src/mepo/cmdline/parser.py
+++ b/src/mepo/cmdline/parser.py
@@ -188,7 +188,7 @@ class MepoArgParser:
             "--hashes", action="store_true", help="Print the exact hash of the HEAD."
         )
         status.add_argument(
-            "--serial", action="store_true", help="Run the serial version."
+            "--parallel", action="store_true", help="Run the parallel version."
         )
 
     def __restore_state(self):
@@ -198,7 +198,7 @@ class MepoArgParser:
             aliases=mepoconfig.get_command_alias("restore-state"),
         )
         restore_state.add_argument(
-            "--serial", action="store_true", help="Run the serial version."
+            "--parallel", action="store_true", help="Run the parallel version."
         )
 
     def __diff(self):
diff --git a/src/mepo/command/restore-state.py b/src/mepo/command/restore-state.py
index bb33ee4..3d9fe86 100644
--- a/src/mepo/command/restore-state.py
+++ b/src/mepo/command/restore-state.py
@@ -9,13 +9,13 @@ from ..utilities import colors
 def run(args):
     print("Checking status...", flush=True)
     allcomps = MepoState.read_state()
-    if args.serial:
+    if args.parallel:
+        with mp.Pool() as pool:
+            result = pool.map(check_component_status, allcomps)
+    else:
         result = []
         for comp in allcomps:
             result.append(check_component_status(comp))
-    else:
-        with mp.Pool() as pool:
-            result = pool.map(check_component_status, allcomps)
     restore_state(allcomps, result)
 
 
diff --git a/src/mepo/command/status.py b/src/mepo/command/status.py
index ad51bb1..6b30911 100644
--- a/src/mepo/command/status.py
+++ b/src/mepo/command/status.py
@@ -20,17 +20,17 @@ def run(args):
     allcomps = MepoState.read_state()
     # max_width = len(max([comp.name for comp in allcomps], key=len))
     max_width = max([len(comp.name) for comp in allcomps])
-    if args.serial:
-        for comp in allcomps:
-            result = check_component_status(comp, args.ignore_permissions)
-            print_component_status(comp, result, max_width, args.nocolor, args.hashes)
-    else:
+    if args.parallel:
         with mp.Pool() as pool:
             result = pool.starmap(
                 check_component_status,
                 [(comp, args.ignore_permissions) for comp in allcomps],
             )
         print_status(allcomps, result, max_width, args.nocolor, args.hashes)
+    else:
+        for comp in allcomps:
+            result = check_component_status(comp, args.ignore_permissions)
+            print_component_status(comp, result, max_width, args.nocolor, args.hashes)
 
 
 def check_component_status(comp, ignore_permissions):


Test patch:
diff --git a/tests/test_mepo_clone.py b/tests/test_mepo_clone.py
index cffcc10..9d1963b 100644
--- a/tests/test_mepo_clone.py
+++ b/tests/test_mepo_clone.py
@@ -23,7 +23,7 @@ def get_mepo_status():
         ignore_permissions=False,
         nocolor=True,
         hashes=False,
-        serial=True,
+        parallel=False,
     )
     with contextlib.redirect_stdout(io.StringIO()) as output:
         mepo_status.run(args)
diff --git a/tests/test_mepo_commands.py b/tests/test_mepo_commands.py
index bbe73b5..fba243f 100644
--- a/tests/test_mepo_commands.py
+++ b/tests/test_mepo_commands.py
@@ -100,7 +100,7 @@ class TestMepoCommands(unittest.TestCase):
             ignore_permissions=False,
             nocolor=True,
             hashes=False,
-            serial=False,
+            parallel=True,
         )
         with contextlib.redirect_stdout(io.StringIO()) as output:
             mepo_status.run(args)
@@ -112,7 +112,7 @@ class TestMepoCommands(unittest.TestCase):
 
     def __mepo_restore_state(self):
         os.chdir(self.__class__.fixture_dir)
-        args = SimpleNamespace(serial=False)
+        args = SimpleNamespace(parallel=True)
         with contextlib.redirect_stdout(io.StringIO()) as _:
             mepo_restore_state.run(args)
         self.__mepo_status(self.__class__.output_clone_status)