Skip to content

Commit b82117c

Browse files
authored
Merge pull request #1318 from stephenfin/missing-lzma
Handle absent lzma library
2 parents f24fe11 + 63848b9 commit b82117c

File tree

1 file changed

+52
-26
lines changed

1 file changed

+52
-26
lines changed

cmd2/cmd2.py

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4627,7 +4627,7 @@ def do_ipy(self, _: argparse.Namespace) -> Optional[bool]: # pragma: no cover
46274627
)
46284628

46294629
# Start IPython
4630-
start_ipython(config=config, argv=[], user_ns=local_vars)
4630+
start_ipython(config=config, argv=[], user_ns=local_vars) # type: ignore[no-untyped-call]
46314631
self.poutput("Now exiting IPython shell...")
46324632

46334633
# The IPython application is a singleton and won't be recreated next time
@@ -4814,11 +4814,9 @@ def _initialize_history(self, hist_file: str) -> None:
48144814
previous sessions will be included. Additionally, all history will be written
48154815
to this file when the application exits.
48164816
"""
4817-
import json
4818-
import lzma
4819-
48204817
self.history = History()
4821-
# with no persistent history, nothing else in this method is relevant
4818+
4819+
# With no persistent history, nothing else in this method is relevant
48224820
if not hist_file:
48234821
self.persistent_history_file = hist_file
48244822
return
@@ -4839,28 +4837,60 @@ def _initialize_history(self, hist_file: str) -> None:
48394837
self.perror(f"Error creating persistent history file directory '{hist_file_dir}': {ex}")
48404838
return
48414839

4842-
# Read and process history file
4840+
# Read history file
48434841
try:
48444842
with open(hist_file, 'rb') as fobj:
48454843
compressed_bytes = fobj.read()
4846-
history_json = lzma.decompress(compressed_bytes).decode(encoding='utf-8')
4847-
self.history = History.from_json(history_json)
48484844
except FileNotFoundError:
4849-
# Just use an empty history
4850-
pass
4845+
compressed_bytes = bytes()
48514846
except OSError as ex:
48524847
self.perror(f"Cannot read persistent history file '{hist_file}': {ex}")
48534848
return
4854-
except (json.JSONDecodeError, lzma.LZMAError, KeyError, UnicodeDecodeError, ValueError) as ex:
4849+
4850+
# Register a function to write history at save
4851+
import atexit
4852+
4853+
self.persistent_history_file = hist_file
4854+
atexit.register(self._persist_history)
4855+
4856+
# Empty or nonexistent history file. Nothing more to do.
4857+
if not compressed_bytes:
4858+
return
4859+
4860+
# Decompress history data
4861+
try:
4862+
import lzma as decompress_lib
4863+
4864+
decompress_exceptions: Tuple[type[Exception]] = (decompress_lib.LZMAError,)
4865+
except ModuleNotFoundError: # pragma: no cover
4866+
import bz2 as decompress_lib # type: ignore[no-redef]
4867+
4868+
decompress_exceptions: Tuple[type[Exception]] = (OSError, ValueError) # type: ignore[no-redef]
4869+
4870+
try:
4871+
history_json = decompress_lib.decompress(compressed_bytes).decode(encoding='utf-8')
4872+
except decompress_exceptions as ex:
4873+
self.perror(
4874+
f"Error decompressing persistent history data '{hist_file}': {ex}\n"
4875+
f"The history file will be recreated when this application exits."
4876+
)
4877+
return
4878+
4879+
# Decode history json
4880+
import json
4881+
4882+
try:
4883+
self.history = History.from_json(history_json)
4884+
except (json.JSONDecodeError, KeyError, ValueError) as ex:
48554885
self.perror(
4856-
f"Error processing persistent history file '{hist_file}': {ex}\n"
4886+
f"Error processing persistent history data '{hist_file}': {ex}\n"
48574887
f"The history file will be recreated when this application exits."
48584888
)
4889+
return
48594890

48604891
self.history.start_session()
4861-
self.persistent_history_file = hist_file
48624892

4863-
# populate readline history
4893+
# Populate readline history
48644894
if rl_type != RlType.NONE:
48654895
last = None
48664896
for item in self.history:
@@ -4872,25 +4902,21 @@ def _initialize_history(self, hist_file: str) -> None:
48724902
readline.add_history(line)
48734903
last = line
48744904

4875-
# register a function to write history at save
4876-
# if the history file is in plain text format from 0.9.12 or lower
4877-
# this will fail, and the history in the plain text file will be lost
4878-
import atexit
4879-
4880-
atexit.register(self._persist_history)
4881-
48824905
def _persist_history(self) -> None:
48834906
"""Write history out to the persistent history file as compressed JSON"""
4884-
import lzma
4885-
48864907
if not self.persistent_history_file:
48874908
return
48884909

4889-
self.history.truncate(self._persistent_history_length)
48904910
try:
4891-
history_json = self.history.to_json()
4892-
compressed_bytes = lzma.compress(history_json.encode(encoding='utf-8'))
4911+
import lzma as compress_lib
4912+
except ModuleNotFoundError: # pragma: no cover
4913+
import bz2 as compress_lib # type: ignore[no-redef]
4914+
4915+
self.history.truncate(self._persistent_history_length)
4916+
history_json = self.history.to_json()
4917+
compressed_bytes = compress_lib.compress(history_json.encode(encoding='utf-8'))
48934918

4919+
try:
48944920
with open(self.persistent_history_file, 'wb') as fobj:
48954921
fobj.write(compressed_bytes)
48964922
except OSError as ex:

0 commit comments

Comments
 (0)