Может ли API сказать Pylint не жаловаться в коде клиента? - PullRequest
3 голосов
/ 18 августа 2010

У меня есть код в классе многократного использования, который изменяет некоторые типы.Вот упрощенная версия.

class Foo:
    def __init__(self):
        self.count = 0

    def increment(self):
        self.count += 1

# Add another method outside of the class definition.
# Pylint doesn't care about this, and rates this file 10/10.

Foo.__dict__["current_count"] = lambda self: self.count

В реальном коде «current_count» является переменной, а не фиксированной строкой, поэтому я не написал:

Foo.current_count = lambda self: self.count # Cannot do in my scenario.

СейчасКогда мои клиенты приходят использовать новую функцию, Pylint в ужасе прыгает вверх и вниз.

import server_api

def main():
    foo_count = server_api.Foo()
    foo_count.increment()


    print foo_count.current_count()
    # Pylint complains here:
    #     E1101:  8:main: Instance of 'Foo' has no 'current_count' member
    # I don't want to have to tell pylint to disable that message in every client.

main()

Каждый класс, использующий эту новую функцию, подвергается наказанию, и я вынужден отключить сообщение в каждой ссылке.Я бы СЕЙЧАС поместил некоторый код в API, чтобы сказать Pylint, чтобы он остыл, когда есть неизвестные ссылки на этот класс., и я не смог найти там никаких предложений.

Итак, все сводится к следующему: могу ли я сказать pylint в своем коде API, чтобы отключить правило E1101 по отношению к этому классу, когда клиент ссылается на него?Есть ли другое решение?

Ответы [ 3 ]

5 голосов
/ 18 августа 2010

Вот мое решение, вдохновленное примером из рецепта поваренной книги ActiveState , предоставленным в Йони Х * ответ .

ККласс Foo, я добавил этот бесполезный метод __getattr__.

def __getattr__(self, name):
    # This is only called when the normal mechanism fails, so in practice should never be called.
    # It is only provided to satisfy pylint that it is okay not to raise E1101 errors in the client code.
    raise AttributeError("%r instance has no attribute %r" % (self, name))

Это должно быть почти неотличимо от предыдущей версии.Его не следует вызывать при нормальном ходе событий, но этого достаточно, чтобы убедить pylint хранить молчание об этой ошибке.

ps Вы можете ворчать, что этот код не очень симпатичен.Я разделяю это мнение.Но я думаю, что его преимущества для клиента перевешивают его запах кода.

2 голосов
/ 18 августа 2010

После одного вашего комментария, поскольку вы выбираете тип Enumerated, почему бы не взглянуть на этот вопрос SO или на этот рецепт ActiveState cookbook ?

Из личных предпочтений я бы предпочел добавить перечисленные типы в класс, как один из ответов в ТАК вопрос (бесстыдно скопирован для контекста):

class Animal:
   def __init__(self, name):
       self.name = name

   def __str__(self):
       return self.name

   def __repr__(self):
       return "<Animal: %s>" % self

Animal.DOG = Animal("dog")
Animal.CAT = Animal("cat")
0 голосов
/ 18 августа 2010

С прагматической точки зрения, почему предположение, что пилинт (или любой ворс) должен молчать? Учитывая смещение между ложными срабатываниями и ложными отрицаниями, линты должны отдавать предпочтение первым. Мне кажется, что из-за того, что Pylint выражает свои результаты в виде баллов, люди считают, что они должны быть максимальными, но призовых за «победу» не существует.

С другой стороны, конструкция, на которую она жалуется, безусловно, некрасива. Я понимаю, что server_api упрощен для нашего удобства, но вам действительно нужно копаться с пространством имен модуля? Из вашего клиентского кода видно, что имя метода current_count жестко запрограммировано, почему не на сервере?

...