RemoteTraceback:
"""
Traceback (most recent call last):
File "C:\Program Files\Python\3.10\lib\multiprocessing\pool.py", line 125, in worker
result = (True, func(*args, **kwds))
File "C:\Users\Lemonyte\Desktop\bump-pydantic\bump_pydantic\main.py", line 106, in visit_class_def
code = Path(filename).read_text()
File "C:\Program Files\Python\3.10\lib\pathlib.py", line 1135, in read_text
return f.read()
File "C:\Program Files\Python\3.10\lib\encodings\cp1252.py", line 23, in decode
return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8f in position 923: character maps to <undefined>
"""
The above exception was the direct cause of the following exception:
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ C:\Users\Lemonyte\Desktop\bump-pydantic\bump_pydantic\main.py:70 in main │
│ │
│ 67 │ │ task = progress.add_task(description="Looking for Pydantic Models...", total=len │
│ 68 │ │ with multiprocessing.Pool() as pool: │
│ 69 │ │ │ partial_visit_class_def = functools.partial(visit_class_def, metadata_manage │
│ ❱ 70 │ │ │ for local_scratch in pool.imap_unordered(partial_visit_class_def, files): │
│ 71 │ │ │ │ progress.advance(task) │
│ 72 │ │ │ │ for key, value in local_scratch.items(): │
│ 73 │ │ │ │ │ scratch.setdefault(key, value).update(value) │
│ │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ console = <console width=155 ColorSystem.TRUECOLOR> │ │
│ │ diff = False │ │
│ │ disable = [] │ │
│ │ files = [ │ │
│ │ │ 'bump_pydantic\\main.py', │ │
│ │ │ 'bump_pydantic\\__init__.py', │ │
│ │ │ 'bump_pydantic\\__main__.py', │ │
│ │ │ 'bump_pydantic\\codemods\\add_default_none.py', │ │
│ │ │ 'bump_pydantic\\codemods\\class_def_visitor.py', │ │
│ │ │ 'bump_pydantic\\codemods\\field.py', │ │
│ │ │ 'bump_pydantic\\codemods\\replace_config.py', │ │
│ │ │ 'bump_pydantic\\codemods\\replace_generic_model.py', │ │
│ │ │ 'bump_pydantic\\codemods\\replace_imports.py', │ │
│ │ │ 'bump_pydantic\\codemods\\root_model.py', │ │
│ │ │ ... +4 │ │
│ │ ] │ │
│ │ files_str = [ │ │
│ │ │ WindowsPath('bump_pydantic/main.py'), │ │
│ │ │ WindowsPath('bump_pydantic/__init__.py'), │ │
│ │ │ WindowsPath('bump_pydantic/__main__.py'), │ │
│ │ │ WindowsPath('bump_pydantic/codemods/add_default_none.py'), │ │
│ │ │ WindowsPath('bump_pydantic/codemods/class_def_visitor.py'), │ │
│ │ │ WindowsPath('bump_pydantic/codemods/field.py'), │ │
│ │ │ WindowsPath('bump_pydantic/codemods/replace_config.py'), │ │
│ │ │ │ │
│ │ WindowsPath('bump_pydantic/codemods/replace_generic_model.py'), │ │
│ │ │ WindowsPath('bump_pydantic/codemods/replace_imports.py'), │ │
│ │ │ WindowsPath('bump_pydantic/codemods/root_model.py'), │ │
│ │ │ ... +4 │ │
│ │ ] │ │
│ │ key = 'class_def_visitor' │ │
│ │ local_scratch = { │ │
│ │ │ 'class_def_visitor': defaultdict(<class 'set'>, { │ │
│ │ │ │ │ │
│ │ 'bump_pydantic.codemods.replace_generic_model.ReplaceGenericModel… │ │
│ │ { │ │
│ │ │ │ │ 'libcst.codemod.VisitorBasedCodemodCommand' │ │
│ │ │ │ } │ │
│ │ │ }) │ │
│ │ } │ │
│ │ log_file = None │ │
│ │ metadata_manager = <libcst.metadata.full_repo_manager.FullRepoManager object at │ │
│ │ 0x000001D1F3F6FEE0> │ │
│ │ package = WindowsPath('bump_pydantic') │ │
│ │ partial_visit_class_def = functools.partial(<function visit_class_def at │ │
│ │ 0x000001D1F3F5B1C0>, │ │
│ │ <libcst.metadata.full_repo_manager.FullRepoManager object at │ │
│ │ 0x000001D1F3F6FEE0>, WindowsPath('bump_pydantic')) │ │
│ │ pool = <multiprocessing.pool.Pool state=TERMINATE pool_size=12> │ │
│ │ progress = <rich.progress.Progress object at 0x000001D1F3FB0850> │ │
│ │ providers = { │ │
│ │ │ <class │ │
│ │ 'libcst.metadata.name_provider.FullyQualifiedNameProvider'>, │ │
│ │ │ <class 'libcst.metadata.scope_provider.ScopeProvider'> │ │
│ │ } │ │
│ │ scratch = { │ │
│ │ │ 'class_def_visitor': defaultdict(<class 'set'>, { │ │
│ │ │ │ │ │
│ │ 'bump_pydantic.codemods.replace_generic_model.ReplaceGenericModel… │ │
│ │ { │ │
│ │ │ │ │ 'libcst.codemod.VisitorBasedCodemodCommand' │ │
│ │ │ │ } │ │
│ │ │ }) │ │
│ │ } │ │
│ │ task = 0 │ │
│ │ value = defaultdict(<class 'set'>, { │ │
│ │ │ │ │
│ │ 'bump_pydantic.codemods.replace_generic_model.ReplaceGenericModel… │ │
│ │ { │ │
│ │ │ │ 'libcst.codemod.VisitorBasedCodemodCommand' │ │
│ │ │ } │ │
│ │ }) │ │
│ │ version = None │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ C:\Program Files\Python\3.10\lib\multiprocessing\pool.py:873 in next │
│ │
│ 870 │ │ success, value = item │
│ 871 │ │ if success: │
│ 872 │ │ │ return value │
│ ❱ 873 │ │ raise value │
│ 874 │ │
│ 875 │ __next__ = next # XXX │
│ 876 │
│ │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ item = ( │ │
│ │ │ False, │ │
│ │ │ UnicodeDecodeError('charmap', b'import difflib\r\nimport functools\r\nimport │ │
│ │ multiprocessing\r\nimport os\r\nimport time\r\nfrom contextlib import │ │
│ │ nullcontext\r\nfrom pathlib import Path\r\nfrom typing import Any, Callable, Dict, │ │
│ │ Iterable, List, Type, TypeVar, Union\r\n\r\nimport libcst as cst\r\nfrom │ │
│ │ libcst.codemod import CodemodContext, ContextAwareTransformer\r\nfrom │ │
│ │ libcst.helpers import calculate_module_and_package\r\nfrom libcst.metadata import │ │
│ │ FullRepoManager, FullyQualifiedNameProvider, ScopeProvider\r\nfrom rich.console │ │
│ │ import Console\r\nfrom rich.progress import Progress\r\nfrom typer import │ │
│ │ Argument, Exit, Option, Typer, echo\r\nfrom typing_extensions import │ │
│ │ ParamSpec\r\n\r\nfrom bump_pydantic import __version__\r\nfrom │ │
│ │ bump_pydantic.codemods import Rule, gather_codemods\r\nfrom │ │
│ │ bump_pydantic.codemods.class_def_visitor import ClassDefVisitor\r\nfrom │ │
│ │ bump_pydantic.markers.find_base_model import find_base_model\r\n\r\napp = │ │
│ │ Typer(\r\n help="Convert Pydantic from V1 to V2 \xe2\x99\xbb\xef\xb8\x8f",\r\n │ │
│ │ invoke_without_command=True,\r\n add_completion=False,\r\n)\r\n\r\nP = │ │
│ │ ParamSpec("P")\r\nT = TypeVar("T")\r\n\r\n\r\ndef version_callback(value: │ │
│ │ bool):\r\n if value:\r\n echo(f"bump-pydantic version: │ │
│ │ {__version__}")\r\n raise Exit()\r\n\r\n\r\n@app.callback()\r\ndef │ │
│ │ main(\r\n package: Path = Argument(..., exists=True, dir_okay=True, │ │
│ │ allow_dash=False),\r\n diff: bool = Option(False, help="Show diff instead of │ │
│ │ applying changes."),\r\n disable: List[Rule] = Option(default=[], help="Disable │ │
│ │ a rule."),\r\n log_file: Union[Path, None] = Option(None, help="Log file to │ │
│ │ write to."),\r\n version: bool = Option(\r\n None,\r\n │ │
│ │ "--version",\r\n callback=version_callback,\r\n is_eager=True,\r\n │ │
│ │ help="Show the version and exit.",\r\n ),\r\n):\r\n # NOTE: │ │
│ │ LIBCST_PARSER_TYPE=native is required according to │ │
│ │ https://github.com/Instagram/LibCST/issues/487.\r\n │ │
│ │ os.environ["LIBCST_PARSER_TYPE"] = "native"\r\n\r\n console = Console()\r\n │ │
│ │ files_str = list(package.glob("**/*.py"))\r\n files = │ │
│ │ [str(file.relative_to(".")) for file in files_str]\r\n\r\n providers = │ │
│ │ {FullyQualifiedNameProvider, ScopeProvider}\r\n metadata_manager = │ │
│ │ FullRepoManager(".", files, providers=providers) # type: ignore[arg-type]\r\n │ │
│ │ metadata_manager.resolve_cache()\r\n\r\n scratch: dict[str, Any] = {}\r\n │ │
│ │ with Progress(*Progress.get_default_columns(), transient=True) as progress:\r\n │ │
│ │ task = progress.add_task(description="Looking for Pydantic Models...", │ │
│ │ total=len(files))\r\n with multiprocessing.Pool() as pool:\r\n │ │
│ │ partial_visit_class_def = functools.partial(visit_class_def, metadata_manager, │ │
│ │ package)\r\n for local_scratch in │ │
│ │ pool.imap_unordered(partial_visit_class_def, files):\r\n │ │
│ │ progress.advance(task)\r\n for key, value in │ │
│ │ local_scratch.items():\r\n scratch.setdefault(key, │ │
│ │ value).update(value)\r\n\r\n find_base_model(scratch)\r\n\r\n start_time = │ │
│ │ time.time()\r\n\r\n codemods = gather_codemods(disabled=disable)\r\n\r\n │ │
│ │ log_ctx_mgr = log_file.open("a+") if log_file else nullcontext()\r\n │ │
│ │ partial_run_codemods = functools.partial(run_codemods, codemods, metadata_manager, │ │
│ │ scratch, package, diff)\r\n\r\n with Progress(*Progress.get_default_columns(), │ │
│ │ transient=True) as progress:\r\n task = │ │
│ │ progress.add_task(description="Executing codemods...", total=len(files))\r\n │ │
│ │ with multiprocessing.Pool() as pool, log_ctx_mgr as log_fp: # type: │ │
│ │ ignore[attr-defined]\r\n for error_msg in │ │
│ │ pool.imap_unordered(partial_run_codemods, files):\r\n │ │
│ │ progress.advance(task)\r\n if error_msg is None:\r\n │ │
│ │ continue\r\n\r\n if log_fp is None:\r\n │ │
│ │ color_diff(console, error_msg)\r\n else:\r\n │ │
│ │ log_fp.writelines(error_msg)\r\n\r\n if log_fp:\r\n │ │
│ │ log_fp.write("Run successfully!\\n")\r\n\r\n modified = [Path(f) for f in files │ │
│ │ if os.stat(f).st_mtime > start_time]\r\n if modified:\r\n │ │
│ │ print(f"Refactored {len(modified)} files.")\r\n\r\n\r\ndef │ │
│ │ visit_class_def(metadata_manager: FullRepoManager, package: Path, filename: str) │ │
│ │ -> Dict[str, Any]:\r\n code = Path(filename).read_text()\r\n module = │ │
│ │ cst.parse_module(code)\r\n module_and_package = │ │
│ │ calculate_module_and_package(str(package), filename)\r\n\r\n context = │ │
│ │ CodemodContext(\r\n metadata_manager=metadata_manager,\r\n │ │
│ │ filename=filename,\r\n full_module_name=module_and_package.name,\r\n │ │
│ │ full_package_name=module_and_package.package,\r\n )\r\n visitor = │ │
│ │ ClassDefVisitor(context=context)\r\n visitor.transform_module(module)\r\n │ │
│ │ return context.scratch\r\n\r\n\r\ndef capture_exception(func: Callable[P, T]) -> │ │
│ │ Callable[P, Union[T, Iterable[str]]]:\r\n @functools.wraps(func)\r\n def │ │
│ │ wrapper(*args: P.args, **kwargs: P.kwargs) -> Union[T, Iterable[str]]:\r\n │ │
│ │ try:\r\n return func(*args, **kwargs)\r\n except Exception as │ │
│ │ exc:\r\n func_args = [repr(arg) for arg in args]\r\n │ │
│ │ func_kwargs = [f"{key}={repr(value)}" for key, value in kwargs.items()]\r\n │ │
│ │ return [f"{func.__name__}({\', \'.join(func_args + │ │
│ │ func_kwargs)})\\n{exc}"]\r\n\r\n return │ │
│ │ wrapper\r\n\r\n\r\n@capture_exception\r\ndef run_codemods(\r\n codemods: │ │
│ │ List[Type[ContextAwareTransformer]],\r\n metadata_manager: FullRepoManager,\r\n │ │
│ │ scratch: Dict[str, Any],\r\n package: Path,\r\n diff: bool,\r\n filename: │ │
│ │ str,\r\n) -> Union[List[str], None]:\r\n module_and_package = │ │
│ │ calculate_module_and_package(str(package), filename)\r\n context = │ │
│ │ CodemodContext(\r\n metadata_manager=metadata_manager,\r\n │ │
│ │ filename=filename,\r\n full_module_name=module_and_package.name,\r\n │ │
│ │ full_package_name=module_and_package.package,\r\n )\r\n │ │
│ │ context.scratch.update(scratch)\r\n\r\n file_path = Path(filename)\r\n with │ │
│ │ file_path.open("r+") as fp:\r\n code = fp.read()\r\n │ │
│ │ fp.seek(0)\r\n\r\n input_tree = cst.parse_module(code)\r\n\r\n for │ │
│ │ codemod in codemods:\r\n transformer = codemod(context=context)\r\n\r\n │ │
│ │ output_tree = transformer.transform_module(input_tree)\r\n input_tree = │ │
│ │ output_tree\r\n\r\n output_code = input_tree.code\r\n if code != │ │
│ │ output_code:\r\n if diff:\r\n lines = │ │
│ │ difflib.unified_diff(\r\n code.splitlines(keepends=True),\r\n │ │
│ │ output_code.splitlines(keepends=True),\r\n │ │
│ │ fromfile=filename,\r\n tofile=filename,\r\n │ │
│ │ )\r\n return list(lines)\r\n else:\r\n │ │
│ │ fp.write(output_code)\r\n fp.truncate()\r\n\r\n return │ │
│ │ None\r\n\r\n\r\ndef color_diff(console: Console, lines: Iterable[str]) -> │ │
│ │ None:\r\n for line in lines:\r\n line = line.rstrip("\\n")\r\n if │ │
│ │ line.startswith("+"):\r\n console.print(line, style="green")\r\n │ │
│ │ elif line.startswith("-"):\r\n console.print(line, style="red")\r\n │ │
│ │ elif line.startswith("^"):\r\n console.print(line, style="blue")\r\n │ │
│ │ else:\r\n console.print(line, style="white")\r\n', 923, 924, 'character │ │
│ │ maps to <undefined>') │ │
│ │ ) │ │
│ │ self = <multiprocessing.pool.IMapUnorderedIterator object at 0x000001D1F4030F70> │ │
│ │ success = False │ │
│ │ timeout = None │ │
│ │ value = UnicodeDecodeError('charmap', b'import difflib\r\nimport functools\r\nimport │ │
│ │ multiprocessing\r\nimport os\r\nimport time\r\nfrom contextlib import │ │
│ │ nullcontext\r\nfrom pathlib import Path\r\nfrom typing import Any, Callable, Dict, │ │
│ │ Iterable, List, Type, TypeVar, Union\r\n\r\nimport libcst as cst\r\nfrom │ │
│ │ libcst.codemod import CodemodContext, ContextAwareTransformer\r\nfrom │ │
│ │ libcst.helpers import calculate_module_and_package\r\nfrom libcst.metadata import │ │
│ │ FullRepoManager, FullyQualifiedNameProvider, ScopeProvider\r\nfrom rich.console │ │
│ │ import Console\r\nfrom rich.progress import Progress\r\nfrom typer import │ │
│ │ Argument, Exit, Option, Typer, echo\r\nfrom typing_extensions import │ │
│ │ ParamSpec\r\n\r\nfrom bump_pydantic import __version__\r\nfrom │ │
│ │ bump_pydantic.codemods import Rule, gather_codemods\r\nfrom │ │
│ │ bump_pydantic.codemods.class_def_visitor import ClassDefVisitor\r\nfrom │ │
│ │ bump_pydantic.markers.find_base_model import find_base_model\r\n\r\napp = │ │
│ │ Typer(\r\n help="Convert Pydantic from V1 to V2 \xe2\x99\xbb\xef\xb8\x8f",\r\n │ │
│ │ invoke_without_command=True,\r\n add_completion=False,\r\n)\r\n\r\nP = │ │
│ │ ParamSpec("P")\r\nT = TypeVar("T")\r\n\r\n\r\ndef version_callback(value: │ │
│ │ bool):\r\n if value:\r\n echo(f"bump-pydantic version: │ │
│ │ {__version__}")\r\n raise Exit()\r\n\r\n\r\n@app.callback()\r\ndef │ │
│ │ main(\r\n package: Path = Argument(..., exists=True, dir_okay=True, │ │
│ │ allow_dash=False),\r\n diff: bool = Option(False, help="Show diff instead of │ │
│ │ applying changes."),\r\n disable: List[Rule] = Option(default=[], help="Disable │ │
│ │ a rule."),\r\n log_file: Union[Path, None] = Option(None, help="Log file to │ │
│ │ write to."),\r\n version: bool = Option(\r\n None,\r\n │ │
│ │ "--version",\r\n callback=version_callback,\r\n is_eager=True,\r\n │ │
│ │ help="Show the version and exit.",\r\n ),\r\n):\r\n # NOTE: │ │
│ │ LIBCST_PARSER_TYPE=native is required according to │ │
│ │ https://github.com/Instagram/LibCST/issues/487.\r\n │ │
│ │ os.environ["LIBCST_PARSER_TYPE"] = "native"\r\n\r\n console = Console()\r\n │ │
│ │ files_str = list(package.glob("**/*.py"))\r\n files = │ │
│ │ [str(file.relative_to(".")) for file in files_str]\r\n\r\n providers = │ │
│ │ {FullyQualifiedNameProvider, ScopeProvider}\r\n metadata_manager = │ │
│ │ FullRepoManager(".", files, providers=providers) # type: ignore[arg-type]\r\n │ │
│ │ metadata_manager.resolve_cache()\r\n\r\n scratch: dict[str, Any] = {}\r\n │ │
│ │ with Progress(*Progress.get_default_columns(), transient=True) as progress:\r\n │ │
│ │ task = progress.add_task(description="Looking for Pydantic Models...", │ │
│ │ total=len(files))\r\n with multiprocessing.Pool() as pool:\r\n │ │
│ │ partial_visit_class_def = functools.partial(visit_class_def, metadata_manager, │ │
│ │ package)\r\n for local_scratch in │ │
│ │ pool.imap_unordered(partial_visit_class_def, files):\r\n │ │
│ │ progress.advance(task)\r\n for key, value in │ │
│ │ local_scratch.items():\r\n scratch.setdefault(key, │ │
│ │ value).update(value)\r\n\r\n find_base_model(scratch)\r\n\r\n start_time = │ │
│ │ time.time()\r\n\r\n codemods = gather_codemods(disabled=disable)\r\n\r\n │ │
│ │ log_ctx_mgr = log_file.open("a+") if log_file else nullcontext()\r\n │ │
│ │ partial_run_codemods = functools.partial(run_codemods, codemods, metadata_manager, │ │
│ │ scratch, package, diff)\r\n\r\n with Progress(*Progress.get_default_columns(), │ │
│ │ transient=True) as progress:\r\n task = │ │
│ │ progress.add_task(description="Executing codemods...", total=len(files))\r\n │ │
│ │ with multiprocessing.Pool() as pool, log_ctx_mgr as log_fp: # type: │ │
│ │ ignore[attr-defined]\r\n for error_msg in │ │
│ │ pool.imap_unordered(partial_run_codemods, files):\r\n │ │
│ │ progress.advance(task)\r\n if error_msg is None:\r\n │ │
│ │ continue\r\n\r\n if log_fp is None:\r\n │ │
│ │ color_diff(console, error_msg)\r\n else:\r\n │ │
│ │ log_fp.writelines(error_msg)\r\n\r\n if log_fp:\r\n │ │
│ │ log_fp.write("Run successfully!\\n")\r\n\r\n modified = [Path(f) for f in files │ │
│ │ if os.stat(f).st_mtime > start_time]\r\n if modified:\r\n │ │
│ │ print(f"Refactored {len(modified)} files.")\r\n\r\n\r\ndef │ │
│ │ visit_class_def(metadata_manager: FullRepoManager, package: Path, filename: str) │ │
│ │ -> Dict[str, Any]:\r\n code = Path(filename).read_text()\r\n module = │ │
│ │ cst.parse_module(code)\r\n module_and_package = │ │
│ │ calculate_module_and_package(str(package), filename)\r\n\r\n context = │ │
│ │ CodemodContext(\r\n metadata_manager=metadata_manager,\r\n │ │
│ │ filename=filename,\r\n full_module_name=module_and_package.name,\r\n │ │
│ │ full_package_name=module_and_package.package,\r\n )\r\n visitor = │ │
│ │ ClassDefVisitor(context=context)\r\n visitor.transform_module(module)\r\n │ │
│ │ return context.scratch\r\n\r\n\r\ndef capture_exception(func: Callable[P, T]) -> │ │
│ │ Callable[P, Union[T, Iterable[str]]]:\r\n @functools.wraps(func)\r\n def │ │
│ │ wrapper(*args: P.args, **kwargs: P.kwargs) -> Union[T, Iterable[str]]:\r\n │ │
│ │ try:\r\n return func(*args, **kwargs)\r\n except Exception as │ │
│ │ exc:\r\n func_args = [repr(arg) for arg in args]\r\n │ │
│ │ func_kwargs = [f"{key}={repr(value)}" for key, value in kwargs.items()]\r\n │ │
│ │ return [f"{func.__name__}({\', \'.join(func_args + │ │
│ │ func_kwargs)})\\n{exc}"]\r\n\r\n return │ │
│ │ wrapper\r\n\r\n\r\n@capture_exception\r\ndef run_codemods(\r\n codemods: │ │
│ │ List[Type[ContextAwareTransformer]],\r\n metadata_manager: FullRepoManager,\r\n │ │
│ │ scratch: Dict[str, Any],\r\n package: Path,\r\n diff: bool,\r\n filename: │ │
│ │ str,\r\n) -> Union[List[str], None]:\r\n module_and_package = │ │
│ │ calculate_module_and_package(str(package), filename)\r\n context = │ │
│ │ CodemodContext(\r\n metadata_manager=metadata_manager,\r\n │ │
│ │ filename=filename,\r\n full_module_name=module_and_package.name,\r\n │ │
│ │ full_package_name=module_and_package.package,\r\n )\r\n │ │
│ │ context.scratch.update(scratch)\r\n\r\n file_path = Path(filename)\r\n with │ │
│ │ file_path.open("r+") as fp:\r\n code = fp.read()\r\n │ │
│ │ fp.seek(0)\r\n\r\n input_tree = cst.parse_module(code)\r\n\r\n for │ │
│ │ codemod in codemods:\r\n transformer = codemod(context=context)\r\n\r\n │ │
│ │ output_tree = transformer.transform_module(input_tree)\r\n input_tree = │ │
│ │ output_tree\r\n\r\n output_code = input_tree.code\r\n if code != │ │
│ │ output_code:\r\n if diff:\r\n lines = │ │
│ │ difflib.unified_diff(\r\n code.splitlines(keepends=True),\r\n │ │
│ │ output_code.splitlines(keepends=True),\r\n │ │
│ │ fromfile=filename,\r\n tofile=filename,\r\n │ │
│ │ )\r\n return list(lines)\r\n else:\r\n │ │
│ │ fp.write(output_code)\r\n fp.truncate()\r\n\r\n return │ │
│ │ None\r\n\r\n\r\ndef color_diff(console: Console, lines: Iterable[str]) -> │ │
│ │ None:\r\n for line in lines:\r\n line = line.rstrip("\\n")\r\n if │ │
│ │ line.startswith("+"):\r\n console.print(line, style="green")\r\n │ │
│ │ elif line.startswith("-"):\r\n console.print(line, style="red")\r\n │ │
│ │ elif line.startswith("^"):\r\n console.print(line, style="blue")\r\n │ │
│ │ else:\r\n console.print(line, style="white")\r\n', 923, 924, 'character │ │
│ │ maps to <undefined>') │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8f in position 923: character maps to <undefined>