Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

different code on the second pass of the formatter. #2563

Closed
andgineer opened this issue Oct 23, 2021 · 6 comments · Fixed by #2822
Closed

different code on the second pass of the formatter. #2563

andgineer opened this issue Oct 23, 2021 · 6 comments · Fixed by #2822
Labels
C: unstable formatting Formatting changed on the second pass T: bug Something isn't working

Comments

@andgineer
Copy link

produce error

error: cannot format /Users/SOROKAN6/projects/idse-pqsar-api/tests/test_ellipsize.py: INTERNAL ERROR: Black produced different code on the second pass of the formatter.

run black for the file and it will show the error.
but there is impossible to attach py-file

Environment (please complete the following information):

black, version 21.8b0
Python 3.7.6
MacOS 11.6

Does this bug also happen on main?
No

Additional context

blk_9gtrwz8w.log

@andgineer andgineer added the T: bug Something isn't working label Oct 23, 2021
@HassanAbouelela
Copy link
Contributor

HassanAbouelela commented Oct 23, 2021

Hi, could you paste your code directly into here? You can use the Insert Code button in the GitHub markdown tab while writing your comment (shortcut: ctrl+e).

Alternatively, you can paste a black playground link.

@andgineer
Copy link
Author

`"""Pretty reducing huge Python objects to visualise them nicely."""
from pprint import pformat, pprint
from typing import Any, Dict

class Dots(dict): # type: ignore # inherit from dict to blend with expected type
"""Show dots inside Python objects repr."""

 def __repr__(self) -> str:
     """Show dots."""
     return ".."

def ellipsize(
obj: Any,
max_list_items_to_show: int = 10,
max_item_length: int = 1024,
) -> Any:
"""Reduce huge list/dict to show on screen.

 In lists (including dict items) show only 1st `max_list_items_to_show`
 and add ".." if there is more.
 Limit max dict/list length at max_item_length.
 """
 if isinstance(obj, (int, float)):
     return obj
 if isinstance(obj, list):
     if len(obj) == 0:
         return obj
     if isinstance(obj[0], dict):  # Heuristic to pretty show list of dicts with huge items
         result_list = [
             ellipsize(
                 val,
                 max_list_items_to_show=max_list_items_to_show,
                 max_item_length=max_item_length,
             )
             for val in obj[:max_list_items_to_show]
         ]
         if len(obj) > max_list_items_to_show:
             result_list.append(Dots())
         return result_list
     result = [
         ellipsize(
             item,
             max_list_items_to_show=max_list_items_to_show,
             max_item_length=max_item_length,
         )
         for item in obj[:max_list_items_to_show]
     ]
     if len(obj) > max_list_items_to_show:
         result.append(Dots())
     return result

 if isinstance(obj, dict):
     result_dict: Dict[str, Any] = {}
     for key, val in obj.items():
         result_dict[key] = ellipsize(
             val, max_list_items_to_show=max_list_items_to_show, max_item_length=max_item_length
         )
     return result_dict
 suffix = ".." if len(str(obj)) > max_item_length else ""
 return str(obj)[:max_item_length] + suffix

`

@andgineer
Copy link
Author

andgineer commented Oct 23, 2021

andgineer/ellipsize@163812c
on the last version of the code the problem gone

@HassanAbouelela
Copy link
Contributor

Okay, here's a minimal reproduction:

assert (
    a_function(very_long_arguments_that_surpass_the_limit, which_is_eighty_eight_in_this_case_plus_a_bit_more)
    == {"x": "this need to pass the line limit as well", "b": "but only by a little bit"}
)

From what I gather, during the first pass, the dictionary is not expanded for some reason (still digging), but on the second pass it is expanded. This is only true if the dictionary passes the limit before the first pass, but not after the second pass. I'm not sure why it isn't expanding from the get go.

From what I gather, the expansion in the second pass is indeed correct, so understanding why it doesn't expand for the first pass will be the first step towards solving this issue.

@ichard26 ichard26 added the C: unstable formatting Formatting changed on the second pass label Oct 23, 2021
@lmasikl
Copy link

lmasikl commented Nov 4, 2021

I have same problem. May be my log

Mode(target_versions=set(), line_length=79, string_normalization=True, experimental_string_processing=False, is_pyi=False)
--- source
+++ first pass
@@ -7,14 +7,14 @@
             return False
 
         if request.user.is_superuser or request.user.is_company:
             return True
 
-        if (
-            request.method.upper() in ("POST", "DELETE") and 
-            view.action not in ("timescores", "telemetry")
-        ):
+        if request.method.upper() in (
+            "POST",
+            "DELETE",
+        ) and view.action not in ("timescores", "telemetry"):
             return False
 
         if request.user.is_driver and view.action == "switch":
             return False
 
--- first pass
+++ second pass
@@ -7,14 +7,18 @@
             return False
 
         if request.user.is_superuser or request.user.is_company:
             return True
 
-        if request.method.upper() in (
-            "POST",
-            "DELETE",
-        ) and view.action not in ("timescores", "telemetry"):
+        if (
+            request.method.upper()
+            in (
+                "POST",
+                "DELETE",
+            )
+            and view.action not in ("timescores", "telemetry")
+        ):
             return False
 
         if request.user.is_driver and view.action == "switch":
             return False
 

and full file code

from api.permissions import IsAuthenticatedAndIsActive


class DriverPermission(IsAuthenticatedAndIsActive):
    def has_permission(self, request, view):
        if not super().has_permission(request, view):
            return False

        if request.user.is_superuser or request.user.is_company:
            return True

        if (
            request.method.upper() in ("POST", "DELETE") and 
            view.action not in ("timescores", "telemetry")
        ):
            return False

        if request.user.is_driver and view.action == "switch":
            return False

        if request.user.is_driver:
            return True

        return False

will be helpful

@JelleZijlstra
Copy link
Collaborator

The example from #2563 (comment) above still crashes on current main, where we always do two passes. (I was trying to include this case in #2815.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: unstable formatting Formatting changed on the second pass T: bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants