ctags, vim and python code

DmitrySemenov picture DmitrySemenov · Dec 23, 2017 · Viewed 15k times · Source

I generate ctags with the following command

ctags -R --fields=+l --languages=python --python-kinds=-iv -f ./tags apps/employees/models.py

and this is my code

from django.contrib.auth.models import AbstractUser
from django.contrib.postgres.fields import HStoreField
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

from author.decorators import with_author
from django_extensions.db.models import TimeStampedModel
from django_fsm import FSMField
from imagekit import models as imagekitmodels
from imagekit.processors import ResizeToFill
from phonenumber_field.modelfields import PhoneNumberField
from timezone_field import TimeZoneField

from libs import utils

# Solution to avoid unique_together for email
AbstractUser._meta.get_field('email')._unique = True


def upload_user_media_to(instance, filename):
    """Upload media files to this folder"""
    return '{}/{}/{}'.format(
        instance.__class__.__name__.lower(), instance.id,
        utils.get_random_filename(filename))


__all__ = [
    'Employee']


@with_author
class Employee(AbstractUser, TimeStampedModel):
    """Custom user model.

    Attributes:
        department (Department): What department the employee is in
        avatar (file): user's avatar, cropeed to fill 300x300 px
        notifications (dict): settings for notifications to user
        first_name (str): first name
        last_name (str): last name
        email (str): email (should be unique), this is our username field
        is_staff (bool): designates whether the user can log into
            this admin site
        is_active (bool): designates whether this user should be
            treated as active
        date_joined (datetime): when user joined
    """

    HIRED = 'H'
    ACTIVE = 'A'
    SICK = 'S'
    VACATION = 'V'
    PTO = 'P'
    FIRED = 'F'

    STATUSES = (
        (HIRED, 'hired'),
        (ACTIVE, 'active'),
        (SICK, 'sick'),
        (VACATION, 'vacation'),
        (PTO, 'pto'),
        (FIRED, 'fired'),
    )

    status = FSMField(
        default=HIRED,
        choices=STATUSES,
        protected=True)

    branch = models.ForeignKey(
        'company.Branch',
        null=True,
        related_name='employees',
        editable=True)

    department = models.ForeignKey(
        'company.Department',
        help_text='What department the employee is in',
        null=True,
        related_name='employees',
        editable=True)

    worktype = models.ForeignKey(
        'company.Worktype',
        null=True,
        related_name='employees',
        editable=True)

    recruiter = models.ForeignKey(
        'Employee',
        null=True,
        related_name='recruits',
        editable=True)

    # direct supervisor of the employee
    supervisor = models.ForeignKey(
        'Employee',
        null=True,
        related_name='supervisees',
        editable=True)

    # other people interested in this employee
    # activities
    followers = models.ManyToManyField(
        'self',
        related_name='following')

    username_ldap = models.CharField(
        max_length=255,
        null=True)

    is_utilized = models.BooleanField(
        default=True)

    is_contractor = models.BooleanField(
        default=False)

    is_daily_report_required = models.BooleanField(
        default=True)

    utilization = models.IntegerField(
        default=100,
        validators=[
            MinValueValidator(0),
            MaxValueValidator(100)])

    avatar = imagekitmodels.ProcessedImageField(
        upload_to=upload_user_media_to,
        processors=[ResizeToFill(300, 300)],
        format='PNG',
        options={'quality': 100},
        editable=True,
        null=True,
        blank=False)

    date_start = models.DateTimeField(
        _('date started'),
        null=True,
        default=timezone.now)

    address = models.CharField(
        max_length=255,
        blank=True)

    city = models.CharField(
        max_length=255,
        blank=True)

    state = models.CharField(
        max_length=50,
        blank=True)

    zip_code = models.CharField(
        max_length=20,
        blank=True)

    phone_number = PhoneNumberField(
        blank=True)

    cell_number = PhoneNumberField(
        blank=True)

    skype = models.CharField(
        max_length=255,
        blank=True)

    linkedin = models.CharField(
        max_length=255,
        blank=True)

    twitter = models.CharField(
        max_length=255,
        blank=True)

    instagram = models.CharField(
        max_length=255,
        blank=True)

    facebook = models.CharField(
        max_length=255,
        blank=True)

    website = models.CharField(
        max_length=255,
        blank=True)

    timezone = TimeZoneField()

    birthdate = models.DateField(
        null=True)

    is_birthdate_hidden = models.BooleanField(
        default=False)

    comment = models.TextField(
        blank=True)

    bucket_default_job = models.CharField(
        max_length=255,
        blank=True)

    notifications = HStoreField(
        null=True)

    # so authentication happens by email instead of username
    # and username becomes sort of nick
    USERNAME_FIELD = 'email'

    # Make sure to exclude email from required fields if authentication
    # is done by email
    REQUIRED_FIELDS = ['username']

    def __str__(self):
        return self.username

    class Meta:
        verbose_name = 'Employee'
        verbose_name_plural = 'Employees'

VIM shows a lot of bad tags (blank, defaults, editable etc) which is method arguments (field definition)

I'm using TagBar plugin: https://github.com/majutsushi/tagbar

Question

And it seems the problem is in ctags, how should I configure ctags so that it only outputs class attributes and not their definition params?

Answer

georgexsh picture georgexsh · Dec 23, 2017

Use ctags from universal-ctags, it has resolved this issue, and many other fixes.

a tag which universal-ctags generated:

branch  tagbar_bug.py   /^    branch = models.ForeignKey($/;"   v       class:Employee