From 3e29016a817895078d377856b79d375a679f6290 Mon Sep 17 00:00:00 2001 From: Taneli Hukkinen <3275109+hukkin@users.noreply.github.com> Date: Thu, 19 Dec 2024 22:27:27 +0200 Subject: [PATCH] fix: circular import in plugins that import from `mdformat.renderer` --- docs/users/changelog.md | 7 +++++++ src/mdformat/_cli.py | 15 ++++++++++++++- src/mdformat/_util.py | 13 ------------- src/mdformat/renderer/_context.py | 16 ++++++++++++++-- 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/docs/users/changelog.md b/docs/users/changelog.md index b22cc7b..cf0d214 100644 --- a/docs/users/changelog.md +++ b/docs/users/changelog.md @@ -3,8 +3,15 @@ This log documents all Python API or CLI breaking backwards incompatible changes. Note that there is currently no guarantee for a stable Markdown formatting style across versions. +## 0.7.21 + +- Fixed + - Circular import in plugins that import from `mdformat.renderer`. + ## 0.7.20 +**NOTE:** This release was yanked from PyPI. + - Deprecated - `mdformat.codepoints.ASCII_WHITESPACE`. CommonMark no longer defines this since v0.30. diff --git a/src/mdformat/_cli.py b/src/mdformat/_cli.py index 17c6632..c4eca46 100644 --- a/src/mdformat/_cli.py +++ b/src/mdformat/_cli.py @@ -3,15 +3,17 @@ import argparse from collections.abc import Generator, Iterable, Mapping, Sequence import contextlib +import functools import logging import os.path from pathlib import Path import shutil import sys +import textwrap import mdformat from mdformat._conf import DEFAULT_OPTS, InvalidConfError, read_toml_opts -from mdformat._util import cached_textwrapper, detect_newline_type, is_md_equal +from mdformat._util import detect_newline_type, is_md_equal import mdformat.plugins import mdformat.renderer @@ -406,6 +408,17 @@ def print_error(title: str, paragraphs: Iterable[str] = ()) -> None: print_paragraphs(paragraphs) +@functools.lru_cache +def cached_textwrapper(width: int) -> textwrap.TextWrapper: + return textwrap.TextWrapper( + break_long_words=False, + break_on_hyphens=False, + width=width, + expand_tabs=False, + replace_whitespace=False, + ) + + def wrap_paragraphs(paragraphs: Iterable[str]) -> str: """Wrap and concatenate paragraphs. diff --git a/src/mdformat/_util.py b/src/mdformat/_util.py index ad5492c..c2772f3 100644 --- a/src/mdformat/_util.py +++ b/src/mdformat/_util.py @@ -2,9 +2,7 @@ from collections.abc import Iterable, Mapping from contextlib import nullcontext -import functools import re -import textwrap from types import MappingProxyType from typing import Any, Literal @@ -126,14 +124,3 @@ def detect_newline_type(md: str, eol_setting: str) -> Literal["\n", "\r\n"]: if eol_setting == "crlf": return "\r\n" return "\n" - - -@functools.lru_cache -def cached_textwrapper(width: int) -> textwrap.TextWrapper: - return textwrap.TextWrapper( - break_long_words=False, - break_on_hyphens=False, - width=width, - expand_tabs=False, - replace_whitespace=False, - ) diff --git a/src/mdformat/renderer/_context.py b/src/mdformat/renderer/_context.py index fa40a25..1e2af49 100644 --- a/src/mdformat/renderer/_context.py +++ b/src/mdformat/renderer/_context.py @@ -3,8 +3,10 @@ from collections import defaultdict from collections.abc import Generator, Iterable, Mapping, MutableMapping from contextlib import contextmanager +import functools import logging import re +import textwrap from types import MappingProxyType from typing import TYPE_CHECKING, Any, Literal, NamedTuple @@ -12,7 +14,6 @@ from mdformat import codepoints from mdformat._conf import DEFAULT_OPTS -from mdformat._util import cached_textwrapper from mdformat.renderer._util import ( RE_CHAR_REFERENCE, decimalify_leading, @@ -27,10 +28,10 @@ longest_consecutive_sequence, maybe_add_link_brackets, ) -from mdformat.renderer.typing import Postprocess, Render if TYPE_CHECKING: from mdformat.renderer import RenderTreeNode + from mdformat.renderer.typing import Postprocess, Render LOGGER = logging.getLogger(__name__) @@ -333,6 +334,17 @@ def blockquote(node: RenderTreeNode, context: RenderContext) -> str: return quoted_str +@functools.lru_cache +def cached_textwrapper(width: int) -> textwrap.TextWrapper: + return textwrap.TextWrapper( + break_long_words=False, + break_on_hyphens=False, + width=width, + expand_tabs=False, + replace_whitespace=False, + ) + + def _wrap(text: str, *, width: int | Literal["no"]) -> str: """Wrap text at locations pointed by `WRAP_POINT`s.