PyCQA / isort

A Python utility / library to sort imports.
https://pycqa.github.io/isort/
MIT License
6.51k stars 582 forks source link

`ERROR: Unrecoverable exception thrown when parsing ./userdetails/models.py! This should NEVER happen.` when running isort multiple times #2131

Open LenaWil opened 1 year ago

LenaWil commented 1 year ago
./userdetails/models.py ```python from allauth.socialaccount.models import SocialApp from django.conf import settings from django.contrib.auth.models import AbstractUser, Group from django.contrib.auth.models import UserManager as DjangoUserManager, GroupManager from django.core.exceptions import ValidationError from django.db import models from django.utils import timezone from django.utils.functional import cached_property class UserManager(DjangoUserManager): def get_by_natural_key(self, username): # See https://docs.djangoproject.com/en/4.1/topics/serialization/#natural-keys # Allow the use of id to lookup as well if isinstance(username, int): return self.get(id=username) return self.get(username=username) class User(AbstractUser): email = models.EmailField("email address", unique=True) allergies = models.CharField( max_length=100, blank=True, help_text="E.g. gluten or vegetarian. Leave empty if not applicable.", verbose_name="food allergies or preferences" ) objects = UserManager() def clean(self): # By default, Django uses case-sensitive usernames. This means that # users 'asdf' and 'Asdf' are considered different users. The allauth # library handles it differently and considers them the same users. # This doesn't play well together. # # We fix it using a case-insensitive uniqueness check on the username, # in the model validation below. In the future, we could consider # normalizing usernames to lowercase, or removing the allauth library # for something more lightweight (custom code). qs = self.__class__.objects.filter(username__iexact=self.username) # Exclude own entry if self.pk: qs = qs.exclude(pk=self.pk) if qs.exists(): raise ValidationError({ 'username': ValidationError('A user with that username already exists.', code='unique'), }) def __str__(self): return "{} {}".format(self.first_name, self.last_name).strip() or "@{}".format(self.username) def is_verified(self): """Whether this user is verified as part of a Scala association.""" links = UserMembership.objects.filter(related_user=self) for membership in links: if membership.is_verified: return True return False @cached_property def boards(self): """Returns all associations of which this member has board access.""" return Association.objects.filter(user=self).all() @cached_property def requires_action(self): """Whether some action is required by the user.""" for board in self.boards: if board.requires_action: return True return False @cached_property def requires_information_updates(self): from general.views import SiteUpdateView return SiteUpdateView.has_new_update(self) @cached_property def requires_information_rules(self): from general.views import RulesPageView return RulesPageView.has_new_update(self) def has_any_perm(self): """Returns true if the user has one or more permissions.""" for group in self.groups.all(): if group.permissions.count() > 0: return True if self.user_permissions.count() > 0: return True return False def has_admin_site_access(self): return self.is_active and (self.has_any_perm() or self.is_superuser) def is_board_of(self, association_id): """Returns if user is a board member of association identified by given id.""" return self.groups.filter(id=association_id).exists() def is_verified_member_of(self, association): """Returns if the user is a verified member of the association.""" return self.get_verified_memberships().filter(association=association).exists() def get_verified_memberships(self): return self.usermembership_set.filter(is_verified=True) def has_min_balance_exception(self): """Whether this user is allowed unlimited debt. For this to hold, the association membership must be verified. """ exceptions = [membership.association.has_min_exception for membership in self.get_verified_memberships()] return True in exceptions class AssociationManager(GroupManager): def get_by_natural_key(self, slug): # See https://docs.djangoproject.com/en/4.1/topics/serialization/#natural-keys return self.get(slug=slug) class Association(Group): slug = models.SlugField(max_length=10) image = models.ImageField(blank=True, null=True) icon_image = models.ImageField(blank=True, null=True) is_choosable = models.BooleanField(default=True, help_text="If checked, this association can be chosen as membership by users.") has_min_exception = models.BooleanField(default=False, help_text="If checked, this association has an exception to the minimum balance.") social_app = models.ForeignKey(SocialApp, on_delete=models.PROTECT, null=True, blank=True, help_text="A user automatically becomes member of the association " "if they sign up using this social app.") balance_update_instructions = models.TextField(max_length=512, default="to be defined") has_site_stats_access = models.BooleanField(default=False) objects = AssociationManager() @cached_property def requires_action(self): """Whether some action needs to be done by the board. Used for display of notifications on the site. """ return self.has_new_member_requests() def has_new_member_requests(self): return UserMembership.objects.filter(association=self, verified_on__isnull=True).exists() class UserMembership(models.Model): """Stores membership information.""" related_user = models.ForeignKey(User, on_delete=models.CASCADE) association = models.ForeignKey(Association, on_delete=models.CASCADE) is_verified = models.BooleanField(default=False) verified_on = models.DateTimeField(blank=True, null=True, default=None) created_on = models.DateTimeField(default=timezone.now) def get_verified_state(self): """Returns the verified state as True/False/None. Returns: True=verified, False=rejected, None=pending. """ if self.is_verified: return True if self.verified_on is not None: return False return None def is_member(self): if not self.is_verified and self.verified_on: # It is not verified, but has verification date, so is rejected return False return True def __str__(self): return "{user} - {association}".format(user=self.related_user, association=self.association) def set_verified(self, verified): """Sets the verified state to the value of verified (True or False) and set verified_on to now and save.""" self.is_verified = verified self.verified_on = timezone.now() self.save() def set_pending(self): """Sets the state to pending. This method does not save the model for you. """ self.is_verified = False self.verified_on = None def is_frozen(self): """A membership is frozen, i.e. can't be changed, if it was verified or rejected too recently.""" if not self.verified_on: return False age = timezone.now() - self.verified_on if self.is_verified: return age < settings.DURATION_AFTER_MEMBERSHIP_CONFIRMATION else: return age < settings.DURATION_AFTER_MEMBERSHIP_REJECTION def is_rejected(self): return self.get_verified_state() is False def is_pending(self): return self.get_verified_state() is None ```

I was experimenting with isort, and this is my config:

[tool.isort]
profile = "pycharm"
line_length = 127
include_trailing_comma = true
use_parentheses = true
split_on_trailing_comma = true

When I run it multiple times I get this error:

ERROR: Unrecoverable exception thrown when parsing ./userdetails/models.py! This should NEVER happen.
If encountered, please open an issue: https://github.com/PyCQA/isort/issues/new
Traceback (most recent call last):
  File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/bin/isort", line 8, in <module>
    sys.exit(main())
  File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/main.py", line 1226, in main
    for sort_attempt in attempt_iterator:
  File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/main.py", line 1210, in <genexpr>
    sort_imports(  # type: ignore
  File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/main.py", line 93, in sort_imports
    incorrectly_sorted = not api.sort_file(
  File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/api.py", line 429, in sort_file
    changed = sort_stream(
  File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/api.py", line 210, in sort_stream
    changed = core.process(
  File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/core.py", line 422, in process
    parsed_content = parse.file_contents(import_section, config=config)
  File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/parse.py", line 522, in file_contents
    if "," in import_string.split(just_imports[-1])[-1]:
IndexError: list index out of range

I am following the instructions by opening a issue.

Full log ~/Documents/Knights/Scala-Dining-WebApp isort-bug .venv ❯ isort _ _ (_) ___ ___ _ __| |_ | |/ _/ / _ \/ '__ _/ | |\__ \/\_\/| | | |_ |_|\___/\___/\_/ \_/ isort your imports, so you don't have to. VERSION 5.12.0 Nothing to do: no files or paths have have been passed in! Try one of the following: `isort .` - sort all Python files, starting from the current directory, recursively. `isort . --interactive` - Do the same, but ask before making any changes. `isort . --check --diff` - Check to see if imports are correctly sorted within this project. `isort --help` - In-depth information about isort's available command-line options. Visit https://pycqa.github.io/isort/ for complete information about how to use isort. ~/Documents/Knights/Scala-Dining-WebApp isort-bug .venv ❯ isort . Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/manage.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/allauthproviders/quadrivium/provider.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/allauthproviders/quadrivium/urls.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/allauthproviders/quadrivium/views.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/receivers.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/models.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/forms.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/admin.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/csv.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/urls.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/views.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/templatetags/credit_tags.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0012_auto_20200824_0135.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0004_auto_20190203_2324.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0011_account_transaction.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0010_auto_20200817_1230.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0015_auto_20220428_2113.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0008_pendingdiningtransaction.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0006_auto_20190213_1452.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0013_auto_20210319_2310.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0002_auto_20190203_1923.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0001_initial.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/migrations/0017_remove_cancel_column.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/creditmanagement/tests/test_models.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/models.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/externalaccounts.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/views_association.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/views_user_settings.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/forms.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/forms_allauth.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/admin.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/urls.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/views.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0009_user_is_staff.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0005_auto_20190207_1510.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0012_auto_20190429_1306.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0020_auto_20210319_2310.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0007_association_is_choosable.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0002_auto_20190203_2324.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0006_auto_20190207_1744.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0010_auto_20190304_2050.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0011_auto_20190429_1303.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0015_auto_20190508_1905.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0017_association_balance_update_instructions.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0019_auto_20200823_1602.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0001_initial.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0004_user_external_link.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0018_association_has_site_stats_access.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0021_auto_20221224_1346.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0016_association_social_app.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/migrations/0013_auto_20190429_2232.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/tests/test_models.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/tests/test_externalaccounts.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/general/forms.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/general/urls.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/general/mail_control.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/general/views.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/general/migrations/0001_initial.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/general/migrations/0002_auto_20190227_1203.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/scaladining/scala_settings.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/scaladining/settings.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/scaladining/urls.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/scaladining/wsgi.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/utils/testing/patch_utils.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/utils/testing/__init__.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/models.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/forms.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/admin.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/urls.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/datesequence.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/views.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/templatetags/dining_tags.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0021_create_paymentreminderlock.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0018_auto_20210319_2310.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0015_auto_20190513_2104.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0027_deletedlist_and_more.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0016_auto_20190514_1317.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0017_auto_20200824_0138.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0026_diningcomment_increase_length.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0002_auto_20190203_2149.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0013_auto_20190513_1505.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0007_auto_20190423_1651.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0003_auto_20190203_2324.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0008_auto_20190507_0112.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0005_auto_20190221_2339.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0009_auto_20190508_0230.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0012_auto_20190728_1359.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0028_alter_dininglist_payment_link.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0011_auto_20190508_1905.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0023_add_new_help_stats.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/migrations/0001_initial.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/tests/test_forms.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/tests/test_forms_diningentry.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/tests/test_datesequence.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/tests/test_forms_sendreminderform.py Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/dining/tests/test_models.py Skipped 2 files ~/Documents/Knights/Scala-Dining-WebApp isort-bug* .venv ❯ isort . Fixing /Users/lena/Documents/Knights/Scala-Dining-WebApp/userdetails/models.py Skipped 2 files ~/Documents/Knights/Scala-Dining-WebApp isort-bug* .venv ❯ isort . ERROR: Unrecoverable exception thrown when parsing ./userdetails/models.py! This should NEVER happen. If encountered, please open an issue: https://github.com/PyCQA/isort/issues/new Traceback (most recent call last): File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/bin/isort", line 8, in sys.exit(main()) File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/main.py", line 1226, in main for sort_attempt in attempt_iterator: File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/main.py", line 1210, in sort_imports( # type: ignore File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/main.py", line 93, in sort_imports incorrectly_sorted = not api.sort_file( File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/api.py", line 429, in sort_file changed = sort_stream( File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/api.py", line 210, in sort_stream changed = core.process( File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/core.py", line 422, in process parsed_content = parse.file_contents(import_section, config=config) File "/Users/lena/Documents/Knights/Scala-Dining-WebApp/.venv/lib/python3.10/site-packages/isort/parse.py", line 522, in file_contents if "," in import_string.split(just_imports[-1])[-1]: IndexError: list index out of range ~/Documents/Knights/Scala-Dining-WebApp isort-bug* .venv ❯
TidalPaladin commented 12 months ago

I was facing a similar error. After digging a bit I found I had an import statement with a subtle error

from ..import X

Making the following correction fixed the error.

from .. import X