From 70d8a57553d3c2d32fd26e79a86637957b5bbc11 Mon Sep 17 00:00:00 2001 From: cpopa Date: Tue, 19 Aug 2014 17:41:27 +0300 Subject: Add a new warning, 'boolean-datetime', emitted when an instance of 'datetime.time' is used in a boolean context. Closes issue #239. --- ChangeLog | 3 +++ checkers/stdlib.py | 37 ++++++++++++++++++++++++++++++++++++ test/functional/boolean_datetime.py | 30 +++++++++++++++++++++++++++++ test/functional/boolean_datetime.txt | 8 ++++++++ 4 files changed, 78 insertions(+) create mode 100644 test/functional/boolean_datetime.py create mode 100644 test/functional/boolean_datetime.txt diff --git a/ChangeLog b/ChangeLog index 2897f2f..dea94b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -80,6 +80,9 @@ ChangeLog for Pylint * Order of reporting is consistent. + * Add a new warning, 'boolean-datetime', emitted when an instance + of 'datetime.time' is used in a boolean context. Closes issue #239. + 2014-07-26 -- 1.3.0 diff --git a/checkers/stdlib.py b/checkers/stdlib.py index 9913e99..4188429 100644 --- a/checkers/stdlib.py +++ b/checkers/stdlib.py @@ -19,6 +19,7 @@ import re import sys import astroid +from astroid.bases import Instance from pylint.interfaces import IAstroidChecker from pylint.checkers import BaseChecker @@ -40,6 +41,12 @@ class OpenModeChecker(BaseChecker): 'bad-open-mode', 'Python supports: r, w, a modes with b, +, and U options. ' 'See http://docs.python.org/2/library/functions.html#open'), + 'W1502': ('Using datetime.time in a boolean context.', + 'boolean-datetime', + 'Using datetetime.time in a boolean context can hide ' + 'subtle bugs when the time they represent matches ' + 'midnight UTC. This behaviour was fixed in Python 3.5. ' + 'See http://bugs.python.org/issue13936 for reference.'), } @utils.check_messages('bad-open-mode') @@ -51,6 +58,36 @@ class OpenModeChecker(BaseChecker): if getattr(node.func, 'name', None) in ('open', 'file'): self._check_open_mode(node) + @utils.check_messages('boolean-datetime') + def visit_unaryop(self, node): + if node.op == 'not': + self._check_datetime(node.operand) + + @utils.check_messages('boolean-datetime') + def visit_if(self, node): + self._check_datetime(node.test) + + @utils.check_messages('boolean-datetime') + def visit_ifexp(self, node): + self._check_datetime(node.test) + + @utils.check_messages('boolean-datetime') + def visit_boolop(self, node): + for value in node.values: + self._check_datetime(value) + + def _check_datetime(self, node): + """ Check that a datetime was infered. + If so, emit boolean-datetime warning. + """ + try: + infered = next(node.infer()) + except astroid.InferenceError: + return + if (isinstance(infered, Instance) and + infered.qname() == 'datetime.time'): + self.add_message('boolean-datetime', node=node) + def _check_open_mode(self, node): """Check that the mode argument of an open or file call is valid.""" try: diff --git a/test/functional/boolean_datetime.py b/test/functional/boolean_datetime.py new file mode 100644 index 0000000..39a424f --- /dev/null +++ b/test/functional/boolean_datetime.py @@ -0,0 +1,30 @@ +""" Checks for boolean uses of datetime.time. """ + +import datetime + +if datetime.time(0, 0, 0): # [boolean-datetime] + print("datetime.time(0,0,0) is not a bug!") +else: + print("datetime.time(0,0,0) is a bug!") + +if not datetime.time(0, 0, 1): # [boolean-datetime] + print("datetime.time(0,0,1) is not a bug!") +else: + print("datetime.time(0,0,1) is a bug!") + +DATA = not datetime.time(0, 0, 0) # [boolean-datetime] +DATA = True if datetime.time(0, 0, 0) else False # [boolean-datetime] +DATA = datetime.time(0, 0, 0) or True # [boolean-datetime] +DATA = datetime.time(0, 0, 0) and True # [boolean-datetime] +DATA = False or True or datetime.time(0, 0, 0) # [boolean-datetime] +DATA = False and datetime.time(0, 0, 0) or True # [boolean-datetime] + + +def cant_infer(data): + """ Can't infer what data is """ + hophop = not data + troptrop = True if data else False + toptop = data or True + return hophop, troptrop, toptop + +cant_infer(datetime.time(0, 0, 0)) diff --git a/test/functional/boolean_datetime.txt b/test/functional/boolean_datetime.txt new file mode 100644 index 0000000..f3287d4 --- /dev/null +++ b/test/functional/boolean_datetime.txt @@ -0,0 +1,8 @@ +boolean-datetime:5::Using datetime.time in a boolean context. +boolean-datetime:10::Using datetime.time in a boolean context. +boolean-datetime:15::Using datetime.time in a boolean context. +boolean-datetime:16::Using datetime.time in a boolean context. +boolean-datetime:17::Using datetime.time in a boolean context. +boolean-datetime:18::Using datetime.time in a boolean context. +boolean-datetime:19::Using datetime.time in a boolean context. +boolean-datetime:20::Using datetime.time in a boolean context. -- cgit v1.2.1