2323FMT_PASS : Final = {* FMT_OFF , * FMT_SKIP }
2424FMT_ON : Final = {"# fmt: on" , "# fmt:on" , "# yapf: enable" }
2525
26+ COMMENT_EXCEPTIONS = {True : " !:#'" , False : " !:#'%" }
27+
2628
2729@dataclass
2830class ProtoComment :
@@ -42,7 +44,7 @@ class ProtoComment:
4244 consumed : int # how many characters of the original leaf's prefix did we consume
4345
4446
45- def generate_comments (leaf : LN ) -> Iterator [Leaf ]:
47+ def generate_comments (leaf : LN , * , preview : bool ) -> Iterator [Leaf ]:
4648 """Clean the prefix of the `leaf` and generate comments from it, if any.
4749
4850 Comments in lib2to3 are shoved into the whitespace prefix. This happens
@@ -61,12 +63,16 @@ def generate_comments(leaf: LN) -> Iterator[Leaf]:
6163 Inline comments are emitted as regular token.COMMENT leaves. Standalone
6264 are emitted with a fake STANDALONE_COMMENT token identifier.
6365 """
64- for pc in list_comments (leaf .prefix , is_endmarker = leaf .type == token .ENDMARKER ):
66+ for pc in list_comments (
67+ leaf .prefix , is_endmarker = leaf .type == token .ENDMARKER , preview = preview
68+ ):
6569 yield Leaf (pc .type , pc .value , prefix = "\n " * pc .newlines )
6670
6771
6872@lru_cache (maxsize = 4096 )
69- def list_comments (prefix : str , * , is_endmarker : bool ) -> List [ProtoComment ]:
73+ def list_comments (
74+ prefix : str , * , is_endmarker : bool , preview : bool
75+ ) -> List [ProtoComment ]:
7076 """Return a list of :class:`ProtoComment` objects parsed from the given `prefix`."""
7177 result : List [ProtoComment ] = []
7278 if not prefix or "#" not in prefix :
@@ -92,7 +98,7 @@ def list_comments(prefix: str, *, is_endmarker: bool) -> List[ProtoComment]:
9298 comment_type = token .COMMENT # simple trailing comment
9399 else :
94100 comment_type = STANDALONE_COMMENT
95- comment = make_comment (line )
101+ comment = make_comment (line , preview = preview )
96102 result .append (
97103 ProtoComment (
98104 type = comment_type , value = comment , newlines = nlines , consumed = consumed
@@ -102,10 +108,10 @@ def list_comments(prefix: str, *, is_endmarker: bool) -> List[ProtoComment]:
102108 return result
103109
104110
105- def make_comment (content : str ) -> str :
111+ def make_comment (content : str , * , preview : bool ) -> str :
106112 """Return a consistently formatted comment from the given `content` string.
107113
108- All comments (except for "##", "#!", "#:", '#'", "#%%" ) should have a single
114+ All comments (except for "##", "#!", "#:", '#'") should have a single
109115 space between the hash sign and the content.
110116
111117 If `content` didn't start with a hash sign, one is provided.
@@ -123,26 +129,26 @@ def make_comment(content: str) -> str:
123129 and not content .lstrip ().startswith ("type:" )
124130 ):
125131 content = " " + content [1 :] # Replace NBSP by a simple space
126- if content and content [0 ] not in " !:#'%" :
132+ if content and content [0 ] not in COMMENT_EXCEPTIONS [ preview ] :
127133 content = " " + content
128134 return "#" + content
129135
130136
131- def normalize_fmt_off (node : Node ) -> None :
137+ def normalize_fmt_off (node : Node , * , preview : bool ) -> None :
132138 """Convert content between `# fmt: off`/`# fmt: on` into standalone comments."""
133139 try_again = True
134140 while try_again :
135- try_again = convert_one_fmt_off_pair (node )
141+ try_again = convert_one_fmt_off_pair (node , preview = preview )
136142
137143
138- def convert_one_fmt_off_pair (node : Node ) -> bool :
144+ def convert_one_fmt_off_pair (node : Node , * , preview : bool ) -> bool :
139145 """Convert content of a single `# fmt: off`/`# fmt: on` into a standalone comment.
140146
141147 Returns True if a pair was converted.
142148 """
143149 for leaf in node .leaves ():
144150 previous_consumed = 0
145- for comment in list_comments (leaf .prefix , is_endmarker = False ):
151+ for comment in list_comments (leaf .prefix , is_endmarker = False , preview = preview ):
146152 if comment .value not in FMT_PASS :
147153 previous_consumed = comment .consumed
148154 continue
@@ -157,7 +163,7 @@ def convert_one_fmt_off_pair(node: Node) -> bool:
157163 if comment .value in FMT_SKIP and prev .type in WHITESPACE :
158164 continue
159165
160- ignored_nodes = list (generate_ignored_nodes (leaf , comment ))
166+ ignored_nodes = list (generate_ignored_nodes (leaf , comment , preview = preview ))
161167 if not ignored_nodes :
162168 continue
163169
@@ -197,7 +203,9 @@ def convert_one_fmt_off_pair(node: Node) -> bool:
197203 return False
198204
199205
200- def generate_ignored_nodes (leaf : Leaf , comment : ProtoComment ) -> Iterator [LN ]:
206+ def generate_ignored_nodes (
207+ leaf : Leaf , comment : ProtoComment , * , preview : bool
208+ ) -> Iterator [LN ]:
201209 """Starting from the container of `leaf`, generate all leaves until `# fmt: on`.
202210
203211 If comment is skip, returns leaf only.
@@ -221,34 +229,34 @@ def generate_ignored_nodes(leaf: Leaf, comment: ProtoComment) -> Iterator[LN]:
221229 yield leaf .parent
222230 return
223231 while container is not None and container .type != token .ENDMARKER :
224- if is_fmt_on (container ):
232+ if is_fmt_on (container , preview = preview ):
225233 return
226234
227235 # fix for fmt: on in children
228- if contains_fmt_on_at_column (container , leaf .column ):
236+ if contains_fmt_on_at_column (container , leaf .column , preview = preview ):
229237 for child in container .children :
230- if contains_fmt_on_at_column (child , leaf .column ):
238+ if contains_fmt_on_at_column (child , leaf .column , preview = preview ):
231239 return
232240 yield child
233241 else :
234242 yield container
235243 container = container .next_sibling
236244
237245
238- def is_fmt_on (container : LN ) -> bool :
246+ def is_fmt_on (container : LN , preview : bool ) -> bool :
239247 """Determine whether formatting is switched on within a container.
240248 Determined by whether the last `# fmt:` comment is `on` or `off`.
241249 """
242250 fmt_on = False
243- for comment in list_comments (container .prefix , is_endmarker = False ):
251+ for comment in list_comments (container .prefix , is_endmarker = False , preview = preview ):
244252 if comment .value in FMT_ON :
245253 fmt_on = True
246254 elif comment .value in FMT_OFF :
247255 fmt_on = False
248256 return fmt_on
249257
250258
251- def contains_fmt_on_at_column (container : LN , column : int ) -> bool :
259+ def contains_fmt_on_at_column (container : LN , column : int , * , preview : bool ) -> bool :
252260 """Determine if children at a given column have formatting switched on."""
253261 for child in container .children :
254262 if (
@@ -257,7 +265,7 @@ def contains_fmt_on_at_column(container: LN, column: int) -> bool:
257265 or isinstance (child , Leaf )
258266 and child .column == column
259267 ):
260- if is_fmt_on (child ):
268+ if is_fmt_on (child , preview = preview ):
261269 return True
262270
263271 return False
0 commit comments