cmd2 3.1.1__py3-none-any.whl → 3.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -539,7 +539,7 @@ class ArgparseCompleter:
539
539
  # Check if there are too many CompletionItems to display as a table
540
540
  if len(completions) <= self._cmd2_app.max_completion_items:
541
541
  # If a metavar was defined, use that instead of the dest field
542
- destination = arg_state.action.metavar if arg_state.action.metavar else arg_state.action.dest
542
+ destination = arg_state.action.metavar or arg_state.action.dest
543
543
 
544
544
  # Handle case where metavar was a tuple
545
545
  if isinstance(destination, tuple):
@@ -587,7 +587,7 @@ class ArgparseCompleter:
587
587
  # Generate the hint table string
588
588
  console = Cmd2GeneralConsole()
589
589
  with console.capture() as capture:
590
- console.print(hint_table, end="")
590
+ console.print(hint_table, end="", soft_wrap=False)
591
591
  self._cmd2_app.formatted_completions = capture.get()
592
592
 
593
593
  # Return sorted list of completions
cmd2/argparse_custom.py CHANGED
@@ -290,7 +290,12 @@ from rich_argparse import (
290
290
  RawTextRichHelpFormatter,
291
291
  RichHelpFormatter,
292
292
  )
293
- from typing_extensions import Self
293
+
294
+ if sys.version_info >= (3, 11):
295
+ from typing import Self
296
+ else:
297
+ from typing_extensions import Self
298
+
294
299
 
295
300
  from . import constants
296
301
  from . import rich_utils as ru
@@ -1472,7 +1477,7 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
1472
1477
  usage=usage,
1473
1478
  description=description, # type: ignore[arg-type]
1474
1479
  epilog=epilog, # type: ignore[arg-type]
1475
- parents=parents if parents else [],
1480
+ parents=parents or [],
1476
1481
  formatter_class=formatter_class,
1477
1482
  prefix_chars=prefix_chars,
1478
1483
  fromfile_prefix_chars=fromfile_prefix_chars,
cmd2/cmd2.py CHANGED
@@ -593,11 +593,14 @@ class Cmd:
593
593
  # being printed by a command.
594
594
  self.terminal_lock = threading.RLock()
595
595
 
596
- # Commands that have been disabled from use. This is to support commands that are only available
597
- # during specific states of the application. This dictionary's keys are the command names and its
598
- # values are DisabledCommand objects.
596
+ # Commands disabled during specific application states
597
+ # Key: Command name | Value: DisabledCommand object
599
598
  self.disabled_commands: dict[str, DisabledCommand] = {}
600
599
 
600
+ # Categories of commands to be disabled
601
+ # Key: Category name | Value: Message to display
602
+ self.disabled_categories: dict[str, str] = {}
603
+
601
604
  # The default key for sorting string results. Its default value performs a case-insensitive alphabetical sort.
602
605
  # If natural sorting is preferred, then set this to NATURAL_SORT_KEY.
603
606
  # cmd2 uses this key for sorting:
@@ -755,9 +758,11 @@ class Cmd:
755
758
  list[tuple[str, Callable[..., Any]]],
756
759
  inspect.getmembers(
757
760
  cmdset,
758
- predicate=lambda meth: isinstance(meth, Callable) # type: ignore[arg-type]
759
- and hasattr(meth, '__name__')
760
- and meth.__name__.startswith(COMMAND_FUNC_PREFIX),
761
+ predicate=lambda meth: ( # type: ignore[arg-type]
762
+ isinstance(meth, Callable) # type: ignore[arg-type]
763
+ and hasattr(meth, '__name__')
764
+ and meth.__name__.startswith(COMMAND_FUNC_PREFIX)
765
+ ),
761
766
  ),
762
767
  )
763
768
 
@@ -788,6 +793,12 @@ class Cmd:
788
793
  if default_category and not hasattr(command_method, constants.CMD_ATTR_HELP_CATEGORY):
789
794
  utils.categorize(command_method, default_category)
790
795
 
796
+ # If this command is in a disabled category, then disable it
797
+ command_category = getattr(command_method, constants.CMD_ATTR_HELP_CATEGORY, None)
798
+ if command_category in self.disabled_categories:
799
+ message_to_print = self.disabled_categories[command_category]
800
+ self.disable_command(command, message_to_print)
801
+
791
802
  self._installed_command_sets.add(cmdset)
792
803
 
793
804
  self._register_subcommands(cmdset)
@@ -904,9 +915,11 @@ class Cmd:
904
915
 
905
916
  methods: list[tuple[str, Callable[..., Any]]] = inspect.getmembers(
906
917
  cmdset,
907
- predicate=lambda meth: isinstance(meth, Callable) # type: ignore[arg-type]
908
- and hasattr(meth, '__name__')
909
- and meth.__name__.startswith(COMMAND_FUNC_PREFIX),
918
+ predicate=lambda meth: ( # type: ignore[arg-type]
919
+ isinstance(meth, Callable) # type: ignore[arg-type]
920
+ and hasattr(meth, '__name__')
921
+ and meth.__name__.startswith(COMMAND_FUNC_PREFIX)
922
+ ),
910
923
  )
911
924
 
912
925
  for cmd_func_name, command_method in methods:
@@ -950,9 +963,11 @@ class Cmd:
950
963
 
951
964
  methods: list[tuple[str, Callable[..., Any]]] = inspect.getmembers(
952
965
  cmdset,
953
- predicate=lambda meth: isinstance(meth, Callable) # type: ignore[arg-type]
954
- and hasattr(meth, '__name__')
955
- and meth.__name__.startswith(COMMAND_FUNC_PREFIX),
966
+ predicate=lambda meth: ( # type: ignore[arg-type]
967
+ isinstance(meth, Callable) # type: ignore[arg-type]
968
+ and hasattr(meth, '__name__')
969
+ and meth.__name__.startswith(COMMAND_FUNC_PREFIX)
970
+ ),
956
971
  )
957
972
 
958
973
  for cmd_func_name, command_method in methods:
@@ -974,10 +989,12 @@ class Cmd:
974
989
  # find methods that have the required attributes necessary to be recognized as a sub-command
975
990
  methods = inspect.getmembers(
976
991
  cmdset,
977
- predicate=lambda meth: isinstance(meth, Callable) # type: ignore[arg-type]
978
- and hasattr(meth, constants.SUBCMD_ATTR_NAME)
979
- and hasattr(meth, constants.SUBCMD_ATTR_COMMAND)
980
- and hasattr(meth, constants.CMD_ATTR_ARGPARSER),
992
+ predicate=lambda meth: (
993
+ isinstance(meth, Callable) # type: ignore[arg-type]
994
+ and hasattr(meth, constants.SUBCMD_ATTR_NAME)
995
+ and hasattr(meth, constants.SUBCMD_ATTR_COMMAND)
996
+ and hasattr(meth, constants.CMD_ATTR_ARGPARSER)
997
+ ),
981
998
  )
982
999
 
983
1000
  # iterate through all matching methods
@@ -1063,10 +1080,12 @@ class Cmd:
1063
1080
  # find methods that have the required attributes necessary to be recognized as a sub-command
1064
1081
  methods = inspect.getmembers(
1065
1082
  cmdset,
1066
- predicate=lambda meth: isinstance(meth, Callable) # type: ignore[arg-type]
1067
- and hasattr(meth, constants.SUBCMD_ATTR_NAME)
1068
- and hasattr(meth, constants.SUBCMD_ATTR_COMMAND)
1069
- and hasattr(meth, constants.CMD_ATTR_ARGPARSER),
1083
+ predicate=lambda meth: (
1084
+ isinstance(meth, Callable) # type: ignore[arg-type]
1085
+ and hasattr(meth, constants.SUBCMD_ATTR_NAME)
1086
+ and hasattr(meth, constants.SUBCMD_ATTR_COMMAND)
1087
+ and hasattr(meth, constants.CMD_ATTR_ARGPARSER)
1088
+ ),
1070
1089
  )
1071
1090
 
1072
1091
  # iterate through all matching methods
@@ -1250,8 +1269,14 @@ class Cmd:
1250
1269
  :param sep: string to write between printed text. Defaults to " ".
1251
1270
  :param end: string to write at end of printed text. Defaults to a newline.
1252
1271
  :param style: optional style to apply to output
1253
- :param soft_wrap: Enable soft wrap mode. If True, lines of text will not be
1254
- word-wrapped or cropped to fit the terminal width. Defaults to True.
1272
+ :param soft_wrap: Enable soft wrap mode. Defaults to True.
1273
+ If True, text that doesn't fit will run on to the following line,
1274
+ just like with print(). This is useful for raw text and logs.
1275
+ If False, Rich wraps text to fit the terminal width.
1276
+ Set this to False when printing structured Renderables like
1277
+ Tables, Panels, or Columns to ensure they render as expected.
1278
+ For example, when soft_wrap is True Panels truncate text
1279
+ which is wider than the terminal.
1255
1280
  :param emoji: If True, Rich will replace emoji codes (e.g., :smiley:) with their
1256
1281
  corresponding Unicode characters. Defaults to False.
1257
1282
  :param markup: If True, Rich will interpret strings with tags (e.g., [bold]hello[/bold])
@@ -1751,31 +1776,45 @@ class Cmd:
1751
1776
  :return: a list of possible tab completions
1752
1777
  """
1753
1778
  matches = self.basic_complete(text, line, begidx, endidx, match_against)
1779
+ if not matches:
1780
+ return []
1754
1781
 
1755
- # Display only the portion of the match that's being completed based on delimiter
1756
- if matches:
1757
- # Set this to True for proper quoting of matches with spaces
1758
- self.matches_delimited = True
1782
+ # Set this to True for proper quoting of matches with spaces
1783
+ self.matches_delimited = True
1759
1784
 
1760
- # Get the common beginning for the matches
1761
- common_prefix = os.path.commonprefix(matches)
1762
- prefix_tokens = common_prefix.split(delimiter)
1785
+ # Get the common beginning for the matches
1786
+ common_prefix = os.path.commonprefix(matches)
1787
+ prefix_tokens = common_prefix.split(delimiter)
1763
1788
 
1764
- # Calculate what portion of the match we are completing
1765
- display_token_index = 0
1766
- if prefix_tokens:
1767
- display_token_index = len(prefix_tokens) - 1
1789
+ # Calculate what portion of the match we are completing
1790
+ display_token_index = 0
1791
+ if prefix_tokens:
1792
+ display_token_index = len(prefix_tokens) - 1
1768
1793
 
1769
- # Get this portion for each match and store them in self.display_matches
1770
- for cur_match in matches:
1771
- match_tokens = cur_match.split(delimiter)
1772
- display_token = match_tokens[display_token_index]
1794
+ # Remove from each match everything after where the user is completing.
1795
+ # This approach can result in duplicates so we will filter those out.
1796
+ unique_results: dict[str, str] = {}
1773
1797
 
1774
- if not display_token:
1775
- display_token = delimiter
1776
- self.display_matches.append(display_token)
1798
+ for cur_match in matches:
1799
+ match_tokens = cur_match.split(delimiter)
1777
1800
 
1778
- return matches
1801
+ filtered_match = delimiter.join(match_tokens[: display_token_index + 1])
1802
+ display_match = match_tokens[display_token_index]
1803
+
1804
+ # If there are more tokens, then we aren't done completing a full item
1805
+ if len(match_tokens) > display_token_index + 1:
1806
+ filtered_match += delimiter
1807
+ display_match += delimiter
1808
+ self.allow_appended_space = False
1809
+ self.allow_closing_quote = False
1810
+
1811
+ if filtered_match not in unique_results:
1812
+ unique_results[filtered_match] = display_match
1813
+
1814
+ filtered_matches = list(unique_results.keys())
1815
+ self.display_matches = list(unique_results.values())
1816
+
1817
+ return filtered_matches
1779
1818
 
1780
1819
  def flag_based_complete(
1781
1820
  self,
@@ -2233,7 +2272,7 @@ class Cmd:
2233
2272
  # Otherwise use pyreadline3's formatter
2234
2273
  else:
2235
2274
  # Check if we should show display_matches
2236
- matches_to_display = self.display_matches if self.display_matches else matches
2275
+ matches_to_display = self.display_matches or matches
2237
2276
 
2238
2277
  # Add padding for visual appeal
2239
2278
  matches_to_display, _ = self._pad_matches_to_display(matches_to_display)
@@ -4236,7 +4275,7 @@ class Cmd:
4236
4275
  header_grid = Table.grid()
4237
4276
  header_grid.add_row(Text(header, style=Cmd2Style.HELP_HEADER))
4238
4277
  header_grid.add_row(Rule(characters=self.ruler, style=Cmd2Style.TABLE_BORDER))
4239
- self.poutput(header_grid)
4278
+ self.poutput(header_grid, soft_wrap=False)
4240
4279
 
4241
4280
  # Subtract 1 from maxcol to account for a one-space right margin.
4242
4281
  maxcol = min(maxcol, ru.console_width()) - 1
@@ -4304,7 +4343,7 @@ class Cmd:
4304
4343
  topics_table.add_row(command, cmd_desc)
4305
4344
 
4306
4345
  category_grid.add_row(topics_table)
4307
- self.poutput(category_grid)
4346
+ self.poutput(category_grid, soft_wrap=False)
4308
4347
  self.poutput()
4309
4348
 
4310
4349
  def render_columns(self, str_list: list[str] | None, display_width: int = 80) -> str:
@@ -4601,7 +4640,7 @@ class Cmd:
4601
4640
  self.last_result[param] = settable.value
4602
4641
 
4603
4642
  self.poutput()
4604
- self.poutput(settable_table)
4643
+ self.poutput(settable_table, soft_wrap=False)
4605
4644
  self.poutput()
4606
4645
 
4607
4646
  @classmethod
@@ -5799,7 +5838,7 @@ class Cmd:
5799
5838
 
5800
5839
  :param command: the command being enabled
5801
5840
  """
5802
- # If the commands is already enabled, then return
5841
+ # If the command is already enabled, then return
5803
5842
  if command not in self.disabled_commands:
5804
5843
  return
5805
5844
 
@@ -5831,11 +5870,17 @@ class Cmd:
5831
5870
 
5832
5871
  :param category: the category to enable
5833
5872
  """
5873
+ # If the category is already enabled, then return
5874
+ if category not in self.disabled_categories:
5875
+ return
5876
+
5834
5877
  for cmd_name in list(self.disabled_commands):
5835
5878
  func = self.disabled_commands[cmd_name].command_function
5836
5879
  if getattr(func, constants.CMD_ATTR_HELP_CATEGORY, None) == category:
5837
5880
  self.enable_command(cmd_name)
5838
5881
 
5882
+ del self.disabled_categories[category]
5883
+
5839
5884
  def disable_command(self, command: str, message_to_print: str) -> None:
5840
5885
  """Disable a command and overwrite its functions.
5841
5886
 
@@ -5846,7 +5891,7 @@ class Cmd:
5846
5891
  command being disabled.
5847
5892
  ex: message_to_print = f"{cmd2.COMMAND_NAME} is currently disabled"
5848
5893
  """
5849
- # If the commands is already disabled, then return
5894
+ # If the command is already disabled, then return
5850
5895
  if command in self.disabled_commands:
5851
5896
  return
5852
5897
 
@@ -5885,6 +5930,10 @@ class Cmd:
5885
5930
  of the command being disabled.
5886
5931
  ex: message_to_print = f"{cmd2.COMMAND_NAME} is currently disabled"
5887
5932
  """
5933
+ # If the category is already disabled, then return
5934
+ if category in self.disabled_categories:
5935
+ return
5936
+
5888
5937
  all_commands = self.get_all_commands()
5889
5938
 
5890
5939
  for cmd_name in all_commands:
@@ -5892,6 +5941,8 @@ class Cmd:
5892
5941
  if getattr(func, constants.CMD_ATTR_HELP_CATEGORY, None) == category:
5893
5942
  self.disable_command(cmd_name, message_to_print)
5894
5943
 
5944
+ self.disabled_categories[category] = message_to_print
5945
+
5895
5946
  def _report_disabled_command_usage(self, *_args: Any, message_to_print: str, **_kwargs: Any) -> None:
5896
5947
  """Report when a disabled command has been run or had help called on it.
5897
5948
 
@@ -63,9 +63,11 @@ def with_default_category(category: str, *, heritable: bool = True) -> Callable[
63
63
  # 3. Must be a member of the class being decorated and not one inherited from a parent declaration
64
64
  methods = inspect.getmembers(
65
65
  cls,
66
- predicate=lambda meth: inspect.isfunction(meth)
67
- and meth.__name__.startswith(COMMAND_FUNC_PREFIX)
68
- and meth in inspect.getmro(cls)[0].__dict__.values(),
66
+ predicate=lambda meth: (
67
+ inspect.isfunction(meth)
68
+ and meth.__name__.startswith(COMMAND_FUNC_PREFIX)
69
+ and meth in inspect.getmro(cls)[0].__dict__.values()
70
+ ),
69
71
  )
70
72
  category_decorator = with_category(category)
71
73
  for method in methods:
cmd2/parsing.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  import re
4
4
  import shlex
5
+ import sys
5
6
  from collections.abc import Iterable
6
7
  from dataclasses import (
7
8
  dataclass,
@@ -9,7 +10,10 @@ from dataclasses import (
9
10
  )
10
11
  from typing import Any
11
12
 
12
- from typing_extensions import Self
13
+ if sys.version_info >= (3, 11):
14
+ from typing import Self
15
+ else:
16
+ from typing_extensions import Self
13
17
 
14
18
  from . import (
15
19
  constants,
cmd2/utils.py CHANGED
@@ -1,7 +1,6 @@
1
1
  """Shared utility functions."""
2
2
 
3
3
  import argparse
4
- import collections
5
4
  import contextlib
6
5
  import functools
7
6
  import glob
@@ -192,10 +191,7 @@ def remove_duplicates(list_to_prune: list[_T]) -> list[_T]:
192
191
  :param list_to_prune: the list being pruned of duplicates
193
192
  :return: The pruned list
194
193
  """
195
- temp_dict: collections.OrderedDict[_T, Any] = collections.OrderedDict()
196
- for item in list_to_prune:
197
- temp_dict[item] = None
198
-
194
+ temp_dict = dict.fromkeys(list_to_prune)
199
195
  return list(temp_dict.keys())
200
196
 
201
197
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cmd2
3
- Version: 3.1.1
3
+ Version: 3.1.3
4
4
  Summary: cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python
5
5
  Author: cmd2 Contributors
6
6
  License-Expression: MIT
@@ -28,6 +28,7 @@ Requires-Dist: pyperclip>=1.8.2
28
28
  Requires-Dist: pyreadline3>=3.4; platform_system == "Windows"
29
29
  Requires-Dist: rich>=14.3.0
30
30
  Requires-Dist: rich-argparse>=1.7.1
31
+ Requires-Dist: typing-extensions; python_version == "3.10"
31
32
  Dynamic: license-file
32
33
 
33
34
  <h1 align="center">cmd2 : immersive interactive command line applications</h1>
@@ -1,15 +1,15 @@
1
1
  cmd2/__init__.py,sha256=JG-jiy2MMArRTujSiU8usvQpdgQbl3KLTim4tU5SCJw,2278
2
- cmd2/argparse_completer.py,sha256=8hK5_QUnHgeHVY60C89kMKn2b91AUyDjyq4dykzjCRA,35680
3
- cmd2/argparse_custom.py,sha256=7h68TXurxjDoMsCzoZy1uyy6tvTEEi3RornPQ9ZHJoA,68767
2
+ cmd2/argparse_completer.py,sha256=4ex9-DZI4vjTMEpg9keeWz2ufBqduPAUZlkOxdoasYA,35667
3
+ cmd2/argparse_custom.py,sha256=_qB60hRbuCQTT1QGczulL3Fo1IqyTRlHfO4XeGUp_zY,68826
4
4
  cmd2/clipboard.py,sha256=5PSKTe3uDe2pFFEDUEMMwAmzcyPkbXXz14SOQxFFncg,515
5
- cmd2/cmd2.py,sha256=rHSkJ2RF9QQiYdIktd5DHJYJL-X7swwzyVqM6TMbSZU,272373
5
+ cmd2/cmd2.py,sha256=qW4F3cuNtqRa_tPvIcUejnh9jZqjWbSypHi5RbYDM6U,274471
6
6
  cmd2/colors.py,sha256=gLAU8gjhPwZud9MNVk53RGE9ZSdwspLnye_kReeZKjc,7848
7
- cmd2/command_definition.py,sha256=4FQgivn-9aZegU5tbUl6XsK_G_gZTMfsbGDortz-Ir8,7992
7
+ cmd2/command_definition.py,sha256=HNldq20DH1DArxz19VSn5oGt1xLiOuLoLdb_cu9D8hQ,8032
8
8
  cmd2/constants.py,sha256=yDcaeEG4Y2DHmLwUpV-_lEiHkiYUZEuyf9mpDdAzmkg,1773
9
9
  cmd2/decorators.py,sha256=_xxagAxlcUROLZowqjW5RYP935uNMEJyr2h8FkWalGw,17356
10
10
  cmd2/exceptions.py,sha256=J8Ck0dhusB2cfVksRLkM4WVgBTGQnPdEcU26RfBjjRw,3440
11
11
  cmd2/history.py,sha256=QNg5QOe3854hFsu9qw7QlqtnTQvmtXojOWgMZlg6JoQ,14755
12
- cmd2/parsing.py,sha256=-8TfpXZAZnlLbCJem_EziaC2JqZvmOkIUoera1xmM4Y,28035
12
+ cmd2/parsing.py,sha256=8tXTn5fwzQutqq6LQqBpoC2dYqTrDjbVyJwpy7sWY-k,28116
13
13
  cmd2/plugin.py,sha256=_KD44QaHPXncT3qSOWXyzesxKvEbJp5tQeMJ569mLNw,827
14
14
  cmd2/py.typed,sha256=qrkHrYJvGoZpU2BpVLNxJB44LlhqVSKyYOwD_L_1m3s,10
15
15
  cmd2/py_bridge.py,sha256=oD7EwT59HvWSvF9FACWDi-_izkQY6mfitOYX20Y5daI,5190
@@ -19,9 +19,9 @@ cmd2/string_utils.py,sha256=7F8ORonOc2xS0ZC56hjhQcnZhonE3lDFdQxij6v54dA,4430
19
19
  cmd2/styles.py,sha256=rh7N-4A2moKDEH82Co-yTrmzAknU75d2c0oR2G1euEg,2762
20
20
  cmd2/terminal_utils.py,sha256=AOk1VjOAzxn7jou2wbALeD6FRIRlKgkQ0VCzIEY51DA,6052
21
21
  cmd2/transcript.py,sha256=5a_1HGDzhhG1I47g9QnrVNWnOI6Mt_z7jGMH7wFm2XQ,9210
22
- cmd2/utils.py,sha256=4jlhcHfgr8yoymP2hRPeCr7_1J37vI4MIIBkszyPK6M,32292
23
- cmd2-3.1.1.dist-info/licenses/LICENSE,sha256=7JL3v4rPUpHV8b0yWAOl64e9r4YmwbHgl3SH_RGbsK8,1099
24
- cmd2-3.1.1.dist-info/METADATA,sha256=KL2uOqWMRRCYFEWwYiSbejEAtzY0IqYTIZR7mSwgz0M,16346
25
- cmd2-3.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
26
- cmd2-3.1.1.dist-info/top_level.txt,sha256=gJbOJmyrARwLhm5diXAtzlNQdxbDZ8iRJ8HJi65_5hg,5
27
- cmd2-3.1.1.dist-info/RECORD,,
22
+ cmd2/utils.py,sha256=3eRyAXeD3Rb_3LiBXizusX4r_JFBhLzESQGPSf2jTw4,32179
23
+ cmd2-3.1.3.dist-info/licenses/LICENSE,sha256=7JL3v4rPUpHV8b0yWAOl64e9r4YmwbHgl3SH_RGbsK8,1099
24
+ cmd2-3.1.3.dist-info/METADATA,sha256=98Bhip01B0tX-qngQXy_kDpEYW6_Pt09MPlyPjocs8Y,16405
25
+ cmd2-3.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
26
+ cmd2-3.1.3.dist-info/top_level.txt,sha256=gJbOJmyrARwLhm5diXAtzlNQdxbDZ8iRJ8HJi65_5hg,5
27
+ cmd2-3.1.3.dist-info/RECORD,,
File without changes