Skip to content

Commit

Permalink
Merge branch 'master' into clipboard
Browse files Browse the repository at this point in the history
# Conflicts:
#	CHANGELOG.md
  • Loading branch information
kotfu committed Feb 1, 2023
2 parents 95b27c1 + ee7599f commit a95b8b3
Show file tree
Hide file tree
Showing 35 changed files with 86 additions and 121 deletions.
5 changes: 2 additions & 3 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@ The tables below list all prerequisites along with the minimum required version
#### Prerequisites to run cmd2 applications

| Prerequisite | Minimum Version |
| --------------------------------------------------- | --------------- |
| [python](https://www.python.org/downloads/) | `3.6` |
| [attrs](https://github.com/python-attrs/attrs) | `16.3` |
| --------------------------------------------------- |-----------------|
| [python](https://www.python.org/downloads/) | `3.7` |
| [pyperclip](https://github.com/asweigart/pyperclip) | `1.6` |
| [setuptools](https://pypi.org/project/setuptools/) | `34.4` |
| [wcwidth](https://pypi.python.org/pypi/wcwidth) | `0.1.7` |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/doc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.10"]
python-version: ["3.11"]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.10"]
python-version: ["3.11"]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.10"]
python-version: ["3.11"]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/mypy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.10"]
python-version: ["3.11"]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ Pipfile.lock
.venv

# Commitizen configuration
.cz.toml
.cz.toml

# pyenv version file
.python-version
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## 2.5.0 (TBD)
* Breaking Change
* `cmd2` 2.5 supports Python 3.7+ (removed support for Python 3.6)
* Enhancements
* add `allow_clipboard` initialization parameter and attribute to disable ability to
* Removed dependency on `attrs` and replaced with [dataclasses](https://docs.python.org/3/library/dataclasses.html)
add output to the operating system clipboard

## 2.4.3 (January 27, 2023)
Expand Down
1 change: 0 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ url = "https://pypi.org/simple"
verify_ssl = true

[packages]
attrs = ">=16.3.0"
pyperclip = ">=1.6"
setuptools = ">=34.4"
wcwidth = ">=0.1.7"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ On all operating systems, the latest stable version of `cmd2` can be installed u
pip install -U cmd2
```

cmd2 works with Python 3.6+ on Windows, macOS, and Linux. It is pure Python code with few 3rd-party dependencies.
cmd2 works with Python 3.7+ on Windows, macOS, and Linux. It is pure Python code with few 3rd-party dependencies.

For information on other installation options, see
[Installation Instructions](https://cmd2.readthedocs.io/en/latest/overview/installation.html) in the cmd2
Expand Down
5 changes: 0 additions & 5 deletions cmd2/argparse_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,8 @@ def update_mutex_groups(arg_action: argparse.Action) -> None:
# Check if this action is in a mutually exclusive group
for group in self._parser._mutually_exclusive_groups:
if arg_action in group._group_actions:

# Check if the group this action belongs to has already been completed
if group in completed_mutex_groups:

# If this is the action that completed the group, then there is no error
# since it's allowed to appear on the command line more than once.
completer_action = completed_mutex_groups[group]
Expand Down Expand Up @@ -307,7 +305,6 @@ def update_mutex_groups(arg_action: argparse.Action) -> None:
# Parse all but the last token
#############################################################################################
for token_index, token in enumerate(tokens[:-1]):

# If we're in a positional REMAINDER arg, force all future tokens to go to that
if pos_arg_state is not None and pos_arg_state.is_remainder:
consume_argument(pos_arg_state)
Expand Down Expand Up @@ -339,7 +336,6 @@ def update_mutex_groups(arg_action: argparse.Action) -> None:

# Check the format of the current token to see if it can be an argument's value
if _looks_like_flag(token, self._parser) and not skip_remaining_flags:

# Check if there is an unfinished flag
if (
flag_arg_state is not None
Expand Down Expand Up @@ -484,7 +480,6 @@ def update_mutex_groups(arg_action: argparse.Action) -> None:

# Otherwise check if we have a positional to complete
elif pos_arg_state is not None or remaining_positionals:

# If we aren't current tracking a positional, then get the next positional arg to handle this token
if pos_arg_state is None:
action = remaining_positionals.popleft()
Expand Down
4 changes: 2 additions & 2 deletions cmd2/argparse_custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ def my_completer(self, text, line, begidx, endidx, arg_tokens)
runtime_checkable,
)
except ImportError:
# Remove these imports when we no longer support Python 3.7
from typing_extensions import ( # type: ignore[assignment]
Protocol,
runtime_checkable,
Expand Down Expand Up @@ -807,7 +808,6 @@ def _add_argument_wrapper(
nargs_adjusted: Union[int, str, Tuple[int], Tuple[int, int], Tuple[int, float], None]
# Check if nargs was given as a range
if isinstance(nargs, tuple):

# Handle 1-item tuple by setting max to INFINITY
if len(nargs) == 1:
nargs = (nargs[0], constants.INFINITY)
Expand Down Expand Up @@ -1032,6 +1032,7 @@ def _ArgumentParser_check_value(self: argparse.ArgumentParser, action: argparse.
# Patch argparse._SubParsersAction to add remove_parser function
############################################################################################################


# noinspection PyPep8Naming,PyProtectedMember
def _SubParsersAction_remove_parser(self: argparse._SubParsersAction, name: str) -> None: # type: ignore
"""
Expand Down Expand Up @@ -1123,7 +1124,6 @@ def _format_usage(
# wrap the usage parts if it's too long
text_width = self._width - self._current_indent
if len(prefix) + len(usage) > text_width:

# Begin cmd2 customization

# break usage into wrappable parts
Expand Down
19 changes: 2 additions & 17 deletions cmd2/cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,11 @@
orig_rl_delims = readline.get_completer_delims()

if rl_type == RlType.PYREADLINE:

# Save the original pyreadline3 display completion function since we need to override it and restore it
# noinspection PyProtectedMember,PyUnresolvedReferences
orig_pyreadline_display = readline.rl.mode._display_completions

elif rl_type == RlType.GNU:

# Get the readline lib so we can make changes to it
import ctypes

Expand Down Expand Up @@ -1500,7 +1498,6 @@ def path_complete(

# Used to complete ~ and ~user strings
def complete_users() -> List[str]:

users = []

# Windows lacks the pwd module so we can't get a list of users.
Expand All @@ -1518,10 +1515,8 @@ def complete_users() -> List[str]:

# Iterate through a list of users from the password database
for cur_pw in pwd.getpwall():

# Check if the user has an existing home dir
if os.path.isdir(cur_pw.pw_dir):

# Add a ~ to the user to match against text
cur_user = '~' + cur_pw.pw_name
if cur_user.startswith(text):
Expand Down Expand Up @@ -1607,7 +1602,6 @@ def complete_users() -> List[str]:

# Build display_matches and add a slash to directories
for index, cur_match in enumerate(matches):

# Display only the basename of this path in the tab completion suggestions
self.display_matches.append(os.path.basename(cur_match))

Expand Down Expand Up @@ -1676,7 +1670,6 @@ def _redirect_complete(self, text: str, line: str, begidx: int, endidx: int, com

# Must at least have the command
if len(raw_tokens) > 1:

# True when command line contains any redirection tokens
has_redirection = False

Expand Down Expand Up @@ -1768,7 +1761,6 @@ def _display_matches_gnu_readline(
:param longest_match_length: longest printed length of the matches
"""
if rl_type == RlType.GNU:

# Print hint if one exists and we are supposed to display it
hint_printed = False
if self.always_show_hint and self.completion_hint:
Expand Down Expand Up @@ -1828,7 +1820,6 @@ def _display_matches_pyreadline(self, matches: List[str]) -> None: # pragma: no
:param matches: the tab completion matches to display
"""
if rl_type == RlType.PYREADLINE:

# Print hint if one exists and we are supposed to display it
hint_printed = False
if self.always_show_hint and self.completion_hint:
Expand Down Expand Up @@ -1982,7 +1973,6 @@ def _perform_completion(

# Check if the token being completed has an opening quote
if raw_completion_token and raw_completion_token[0] in constants.QUOTES:

# Since the token is still being completed, we know the opening quote is unclosed.
# Save the quote so we can add a matching closing quote later.
completion_token_quote = raw_completion_token[0]
Expand All @@ -2007,7 +1997,6 @@ def _perform_completion(
self.completion_matches = self._redirect_complete(text, line, begidx, endidx, completer_func)

if self.completion_matches:

# Eliminate duplicates
self.completion_matches = utils.remove_duplicates(self.completion_matches)
self.display_matches = utils.remove_duplicates(self.display_matches)
Expand All @@ -2022,7 +2011,6 @@ def _perform_completion(

# Check if we need to add an opening quote
if not completion_token_quote:

add_quote = False

# This is the tab completion text that will appear on the command line.
Expand Down Expand Up @@ -2105,7 +2093,7 @@ def complete( # type: ignore[override]
# from text and update the indexes. This only applies if we are at the beginning of the command line.
shortcut_to_restore = ''
if begidx == 0 and custom_settings is None:
for (shortcut, _) in self.statement_parser.shortcuts:
for shortcut, _ in self.statement_parser.shortcuts:
if text.startswith(shortcut):
# Save the shortcut to restore later
shortcut_to_restore = shortcut
Expand Down Expand Up @@ -3076,7 +3064,6 @@ def _set_up_cmd2_readline(self) -> _SavedReadlineSettings:
readline_settings = _SavedReadlineSettings()

if self._completion_supported():

# Set up readline for our tab completion needs
if rl_type == RlType.GNU:
# GNU readline automatically adds a closing quote if the text being completed has an opening quote.
Expand Down Expand Up @@ -3110,7 +3097,6 @@ def _restore_readline(self, readline_settings: _SavedReadlineSettings) -> None:
:param readline_settings: the readline settings to restore
"""
if self._completion_supported():

# Restore what we changed in readline
readline.set_completer(readline_settings.completer)
readline.set_completer_delims(readline_settings.delims)
Expand Down Expand Up @@ -3891,7 +3877,7 @@ def select(self, opts: Union[str, List[str], List[Tuple[Any, Optional[str]]]], p
fulloptions.append((opt[0], opt[1]))
except IndexError:
fulloptions.append((opt[0], opt[0]))
for (idx, (_, text)) in enumerate(fulloptions):
for idx, (_, text) in enumerate(fulloptions):
self.poutput(' %2d. %s' % (idx + 1, text))

while True:
Expand Down Expand Up @@ -5043,7 +5029,6 @@ def async_alert(self, alert_msg: str, new_prompt: Optional[str] = None) -> None:

# Sanity check that can't fail if self.terminal_lock was acquired before calling this function
if self.terminal_lock.acquire(blocking=False):

# Windows terminals tend to flicker when we redraw the prompt and input lines.
# To reduce how often this occurs, only update terminal if there are changes.
update_terminal = False
Expand Down
13 changes: 7 additions & 6 deletions cmd2/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
from collections import (
OrderedDict,
)
from dataclasses import (
dataclass,
)
from typing import (
Any,
Callable,
Expand All @@ -19,8 +22,6 @@
overload,
)

import attr

from . import (
utils,
)
Expand All @@ -29,7 +30,7 @@
)


@attr.s(auto_attribs=True, frozen=True)
@dataclass(frozen=True)
class HistoryItem:
"""Class used to represent one command in the history list"""

Expand All @@ -39,10 +40,10 @@ class HistoryItem:
# Used in JSON dictionaries
_statement_field = 'statement'

statement: Statement = attr.ib(default=None, validator=attr.validators.instance_of(Statement))
statement: Statement

def __str__(self) -> str:
"""A convenient human readable representation of the history item"""
"""A convenient human-readable representation of the history item"""
return self.statement.raw

@property
Expand Down Expand Up @@ -90,7 +91,7 @@ def pr(self, idx: int, script: bool = False, expanded: bool = False, verbose: bo
if self.statement.multiline_command:
# This is an approximation and not meant to be a perfect piecing together of lines.
# All newlines will be converted to spaces, including the ones in quoted strings that
# are considered literals. Also if the final line starts with a terminator, then the
# are considered literals. Also, if the final line starts with a terminator, then the
# terminator will have an extra space before it in the 1 line version.
ret_str = ret_str.replace('\n', ' ')

Expand Down
Loading

0 comments on commit a95b8b3

Please sign in to comment.