Skip to content

Refactor Choices class init, fix inexact type coercion, quote-aware command splitting, and typo fixes#39

Merged
RobertBlackhart merged 2 commits into
mainfrom
copilot/refactor-class-attributes-setting
Apr 14, 2026
Merged

Refactor Choices class init, fix inexact type coercion, quote-aware command splitting, and typo fixes#39
RobertBlackhart merged 2 commits into
mainfrom
copilot/refactor-class-attributes-setting

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 14, 2026

Several independent bugs and code quality issues in choices.py and shell.py.

recline/arg_types/choices.py

  • Remove __new__ for class attribute setup: available_choices and metavar were being set as class attributes inside __new__, which is unconventional. Replaced with explicit post-definition assignment after the inner _Choices class body.

  • Fix inexact=True skipping data_type conversion: When inexact=True, the validate method returned the raw string without applying data_type, causing inconsistent return types. Now data_type(arg) is always applied; only the choice membership check is skipped.

# Before: inexact=True returned raw str regardless of data_type
if inexact:
    return arg  # bypasses data_type conversion

# After: validation skipped, type conversion always applied
if not inexact:
    current_choices = self.choices(eager=True)
    if arg not in current_choices:
        raise ReclineTypeError(...)
try:
    return data_type(arg)

recline/repl/shell.py

  • Quote-aware command splitting: ;, &&, and || were split with str.split(), which breaks on operators inside quoted strings (e.g. echo "foo;bar" would produce two commands). Replaced with _split_unquoted(), a lightweight parser that respects single quotes, double quotes, and backslash escapes.

  • Typo fixes: staringstarting, convienentconvenient, applicatinosapplications.

Original prompt
Please apply the following diffs and create a pull request.
Once the PR is ready, give it a title based on the messages of the fixes being applied.

[{"message":"Setting class attributes in `__new__` is unconventional and can lead to confusion. Class attributes are typically set in the class definition or `__init__`. Consider refactoring to use `__init__` or setting these as instance attributes to improve code clarity.","fixFiles":[{"filePath":"recline/arg_types/choices.py","diff":"diff --git a/recline/arg_types/choices.py b/recline/arg_types/choices.py\n--- a/recline/arg_types/choices.py\n+++ b/recline/arg_types/choices.py\n@@ -48,12 +48,9 @@\n         \"\"\"\n \n         class _Choices(Choices):\n-            def __new__(cls):\n-                instance = super().__new__(cls)\n-                cls.available_choices = available_choices\n-                if isinstance(available_choices, list):\n-                    cls.metavar = f\"<{'|'.join(available_choices)}>\"\n-                return instance\n+            available_choices = available_choices\n+            if isinstance(available_choices, list):\n+                metavar = f\"<{'|'.join(available_choices)}>\"\n \n             def validate(self, arg):\n                 if inexact:\n"}]},{"message":"When `inexact` is True, the function returns the raw argument without type conversion. This bypasses the `data_type` conversion on line 67, leading to inconsistent return types. The function should apply the `data_type` conversion before returning, even when validation is skipped.","fixFiles":[{"filePath":"recline/arg_types/choices.py","diff":"diff --git a/recline/arg_types/choices.py b/recline/arg_types/choices.py\n--- a/recline/arg_types/choices.py\n+++ b/recline/arg_types/choices.py\n@@ -56,13 +56,12 @@\n                 return instance\n \n             def validate(self, arg):\n-                if inexact:\n-                    return arg\n-                current_choices = self.choices(eager=True)\n-                if arg not in current_choices:\n-                    raise ReclineTypeError(\n-                        f\"\\\"{arg}\\\" must be one of {', '.join(current_choices)}.\"\n-                    )\n+                if not inexact:\n+                    current_choices = self.choices(eager=True)\n+                    if arg not in current_choices:\n+                        raise ReclineTypeError(\n+                            f\"\\\"{arg}\\\" must be one of {', '.join(current_choices)}.\"\n+                        )\n                 try:\n                     return data_type(arg)\n                 except Exception:  # pylint: disable=broad-except\n"}]},{"message":"Corrected spelling of 'staring' to 'starting'.","fixFiles":[{"filePath":"recline/repl/shell.py","diff":"diff --git a/recline/repl/shell.py b/recline/repl/shell.py\n--- a/recline/repl/shell.py\n+++ b/recline/repl/shell.py\n@@ -1,7 +1,7 @@\n \"\"\"\n Original © NetApp 2024\n \n-This is the main staring point for a recline application\n+This is the main starting point for a recline application\n \"\"\"\n \n import atexit\n"}]},{"message":"Corrected spelling of 'convienent' to 'convenient'.","fixFiles":[{"filePath":"recline/repl/shell.py","diff":"diff --git a/recline/repl/shell.py b/recline/repl/shell.py\n--- a/recline/repl/shell.py\n+++ b/recline/repl/shell.py\n@@ -56,7 +56,7 @@\n         repl_mode: By default, applications using recline expect to act as a REPL\n             environment where the user will run many commands. These applications\n             can still run a single command if the user passes a -c. But, it is\n-            convienent for some applications to act more like a traditional CLI\n+            convenient for some applications to act more like a traditional CLI\n             command without needing to pass -c. For those applicatinos, repl_mode\n             can be set to False.\n         single_command: This acts a bit like non-repl mode, except in this case\n"}]},{"message":"Corrected spelling of 'applicatinos' to 'applications'.","fixFiles":[{"filePath":"recline/repl/shell.py","diff":"diff --git a/recline/repl/shell.py b/recline/repl/shell.py\n--- a/recline/repl/shell.py\n+++ b/recline/repl/shell.py\n@@ -57,7 +57,7 @@\n             environment where the user will run many commands. These applications\n             can still run a single command if the user passes a -c. But, it is\n             convienent for some applications to act more like a traditional CLI\n-            command without needing to pass -c. For those applicatinos, repl_mode\n+            command without needing to pass -c. For those applications, repl_mode\n             can be set to False.\n         single_command: This acts a bit like non-repl mode, except in this case\n             the user doesn't have to pass any command name as an argument to the\n"}]},{"message":"The semicolon command separator splits naively without respecting quoted strings. A command like `echo \"foo;bar...

…uoted, fix typos

Agent-Logs-Url: https://github.com/NetApp/recline/sessions/bda7b8f0-6028-489a-a229-ac1788166c6e

Co-authored-by: RobertBlackhart <5414318+RobertBlackhart@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor class attribute setting to improve code clarity Refactor Choices class init, fix inexact type coercion, quote-aware command splitting, and typo fixes Apr 14, 2026
Copilot AI requested a review from RobertBlackhart April 14, 2026 22:37
@RobertBlackhart RobertBlackhart marked this pull request as ready for review April 14, 2026 22:55
@RobertBlackhart RobertBlackhart merged commit 468ae52 into main Apr 14, 2026
9 checks passed
@RobertBlackhart RobertBlackhart deleted the copilot/refactor-class-attributes-setting branch April 14, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants