OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Enables directory-specific presubmit checks to run at upload and/or commit. | 6 """Enables directory-specific presubmit checks to run at upload and/or commit. |
7 """ | 7 """ |
8 | 8 |
9 __version__ = '1.3.5' | 9 __version__ = '1.3.5' |
10 | 10 |
(...skipping 23 matching lines...) Expand all Loading... |
34 import urllib2 # Exposed through the API. | 34 import urllib2 # Exposed through the API. |
35 from warnings import warn | 35 from warnings import warn |
36 | 36 |
37 try: | 37 try: |
38 import simplejson as json | 38 import simplejson as json |
39 except ImportError: | 39 except ImportError: |
40 try: | 40 try: |
41 import json | 41 import json |
42 # Some versions of python2.5 have an incomplete json module. Check to make | 42 # Some versions of python2.5 have an incomplete json module. Check to make |
43 # sure loads exists. | 43 # sure loads exists. |
| 44 # Statement seems to have no effect |
| 45 # pylint: disable=W0104 |
44 json.loads | 46 json.loads |
45 except (ImportError, AttributeError): | 47 except (ImportError, AttributeError): |
46 # Import the one included in depot_tools. | 48 # Import the one included in depot_tools. |
47 sys.path.append(os.path.join(os.path.dirname(__file__), 'third_party')) | 49 sys.path.append(os.path.join(os.path.dirname(__file__), 'third_party')) |
48 import simplejson as json | 50 import simplejson as json |
49 | 51 |
50 # Local imports. | 52 # Local imports. |
51 import gclient_utils | 53 import gclient_utils |
52 import presubmit_canned_checks | 54 import presubmit_canned_checks |
53 import scm | 55 import scm |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 line_number = 0 | 90 line_number = 0 |
89 for line in lines: | 91 for line in lines: |
90 line_number += 1 | 92 line_number += 1 |
91 yield (af, line_number, line) | 93 yield (af, line_number, line) |
92 | 94 |
93 | 95 |
94 class OutputApi(object): | 96 class OutputApi(object): |
95 """This class (more like a module) gets passed to presubmit scripts so that | 97 """This class (more like a module) gets passed to presubmit scripts so that |
96 they can specify various types of results. | 98 they can specify various types of results. |
97 """ | 99 """ |
98 | 100 # Method could be a function |
| 101 # pylint: disable=R0201 |
99 class PresubmitResult(object): | 102 class PresubmitResult(object): |
100 """Base class for result objects.""" | 103 """Base class for result objects.""" |
101 | 104 |
102 def __init__(self, message, items=None, long_text=''): | 105 def __init__(self, message, items=None, long_text=''): |
103 """ | 106 """ |
104 message: A short one-line message to indicate errors. | 107 message: A short one-line message to indicate errors. |
105 items: A list of short strings to indicate where errors occurred. | 108 items: A list of short strings to indicate where errors occurred. |
106 long_text: multi-line text output, e.g. from another tool | 109 long_text: multi-line text output, e.g. from another tool |
107 """ | 110 """ |
108 self._message = message | 111 self._message = message |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 """A warning that should be included in the review request email.""" | 173 """A warning that should be included in the review request email.""" |
171 def __init__(self, *args, **kwargs): | 174 def __init__(self, *args, **kwargs): |
172 super(OutputApi.MailTextResult, self).__init__() | 175 super(OutputApi.MailTextResult, self).__init__() |
173 raise NotImplementedException() | 176 raise NotImplementedException() |
174 | 177 |
175 | 178 |
176 class InputApi(object): | 179 class InputApi(object): |
177 """An instance of this object is passed to presubmit scripts so they can | 180 """An instance of this object is passed to presubmit scripts so they can |
178 know stuff about the change they're looking at. | 181 know stuff about the change they're looking at. |
179 """ | 182 """ |
| 183 # Method could be a function |
| 184 # pylint: disable=R0201 |
180 | 185 |
181 # File extensions that are considered source files from a style guide | 186 # File extensions that are considered source files from a style guide |
182 # perspective. Don't modify this list from a presubmit script! | 187 # perspective. Don't modify this list from a presubmit script! |
183 DEFAULT_WHITE_LIST = ( | 188 DEFAULT_WHITE_LIST = ( |
184 # C++ and friends | 189 # C++ and friends |
185 r".*\.c$", r".*\.cc$", r".*\.cpp$", r".*\.h$", r".*\.m$", r".*\.mm$", | 190 r".*\.c$", r".*\.cc$", r".*\.cpp$", r".*\.h$", r".*\.m$", r".*\.mm$", |
186 r".*\.inl$", r".*\.asm$", r".*\.hxx$", r".*\.hpp$", | 191 r".*\.inl$", r".*\.asm$", r".*\.hxx$", r".*\.hpp$", |
187 # Scripts | 192 # Scripts |
188 r".*\.js$", r".*\.py$", r".*\.sh$", r".*\.rb$", r".*\.pl$", r".*\.pm$", | 193 r".*\.js$", r".*\.py$", r".*\.sh$", r".*\.rb$", r".*\.pl$", r".*\.pm$", |
189 # No extension at all, note that ALL CAPS files are black listed in | 194 # No extension at all, note that ALL CAPS files are black listed in |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 """ | 390 """ |
386 if isinstance(file_item, AffectedFile): | 391 if isinstance(file_item, AffectedFile): |
387 file_item = file_item.AbsoluteLocalPath() | 392 file_item = file_item.AbsoluteLocalPath() |
388 if not file_item.startswith(self.change.RepositoryRoot()): | 393 if not file_item.startswith(self.change.RepositoryRoot()): |
389 raise IOError('Access outside the repository root is denied.') | 394 raise IOError('Access outside the repository root is denied.') |
390 return gclient_utils.FileRead(file_item, mode) | 395 return gclient_utils.FileRead(file_item, mode) |
391 | 396 |
392 | 397 |
393 class AffectedFile(object): | 398 class AffectedFile(object): |
394 """Representation of a file in a change.""" | 399 """Representation of a file in a change.""" |
395 | 400 # Method could be a function |
| 401 # pylint: disable=R0201 |
396 def __init__(self, path, action, repository_root=''): | 402 def __init__(self, path, action, repository_root=''): |
397 self._path = path | 403 self._path = path |
398 self._action = action | 404 self._action = action |
399 self._local_root = repository_root | 405 self._local_root = repository_root |
400 self._is_directory = None | 406 self._is_directory = None |
401 self._properties = {} | 407 self._properties = {} |
402 | 408 |
403 def ServerPath(self): | 409 def ServerPath(self): |
404 """Returns a path string that identifies the file in the SCM system. | 410 """Returns a path string that identifies the file in the SCM system. |
405 | 411 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 modify this file. | 479 modify this file. |
474 """ | 480 """ |
475 raise NotImplementedError() # Implement if/when needed. | 481 raise NotImplementedError() # Implement if/when needed. |
476 | 482 |
477 def __str__(self): | 483 def __str__(self): |
478 return self.LocalPath() | 484 return self.LocalPath() |
479 | 485 |
480 | 486 |
481 class SvnAffectedFile(AffectedFile): | 487 class SvnAffectedFile(AffectedFile): |
482 """Representation of a file in a change out of a Subversion checkout.""" | 488 """Representation of a file in a change out of a Subversion checkout.""" |
| 489 # Method 'NNN' is abstract in class 'NNN' but is not overridden |
| 490 # pylint: disable=W0223 |
483 | 491 |
484 def __init__(self, *args, **kwargs): | 492 def __init__(self, *args, **kwargs): |
485 AffectedFile.__init__(self, *args, **kwargs) | 493 AffectedFile.__init__(self, *args, **kwargs) |
486 self._server_path = None | 494 self._server_path = None |
487 self._is_text_file = None | 495 self._is_text_file = None |
488 | 496 |
489 def ServerPath(self): | 497 def ServerPath(self): |
490 if self._server_path is None: | 498 if self._server_path is None: |
491 self._server_path = scm.SVN.CaptureInfo( | 499 self._server_path = scm.SVN.CaptureInfo( |
492 self.AbsoluteLocalPath()).get('URL', '') | 500 self.AbsoluteLocalPath()).get('URL', '') |
(...skipping 26 matching lines...) Expand all Loading... |
519 self._is_text_file = False | 527 self._is_text_file = False |
520 else: | 528 else: |
521 mime_type = scm.SVN.GetFileProperty(self.AbsoluteLocalPath(), | 529 mime_type = scm.SVN.GetFileProperty(self.AbsoluteLocalPath(), |
522 'svn:mime-type') | 530 'svn:mime-type') |
523 self._is_text_file = (not mime_type or mime_type.startswith('text/')) | 531 self._is_text_file = (not mime_type or mime_type.startswith('text/')) |
524 return self._is_text_file | 532 return self._is_text_file |
525 | 533 |
526 | 534 |
527 class GitAffectedFile(AffectedFile): | 535 class GitAffectedFile(AffectedFile): |
528 """Representation of a file in a change out of a git checkout.""" | 536 """Representation of a file in a change out of a git checkout.""" |
| 537 # Method 'NNN' is abstract in class 'NNN' but is not overridden |
| 538 # pylint: disable=W0223 |
529 | 539 |
530 def __init__(self, *args, **kwargs): | 540 def __init__(self, *args, **kwargs): |
531 AffectedFile.__init__(self, *args, **kwargs) | 541 AffectedFile.__init__(self, *args, **kwargs) |
532 self._server_path = None | 542 self._server_path = None |
533 self._is_text_file = None | 543 self._is_text_file = None |
534 | 544 |
535 def ServerPath(self): | 545 def ServerPath(self): |
536 if self._server_path is None: | 546 if self._server_path is None: |
537 raise NotImplementedException() # TODO(maruel) Implement. | 547 raise NotImplementedException() # TODO(maruel) Implement. |
538 return self._server_path | 548 return self._server_path |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 else: | 999 else: |
990 errors.append(result) | 1000 errors.append(result) |
991 | 1001 |
992 error_count = 0 | 1002 error_count = 0 |
993 for name, items in (('Messages', notifications), | 1003 for name, items in (('Messages', notifications), |
994 ('Warnings', warnings), | 1004 ('Warnings', warnings), |
995 ('ERRORS', errors)): | 1005 ('ERRORS', errors)): |
996 if items: | 1006 if items: |
997 output_stream.write('** Presubmit %s **\n' % name) | 1007 output_stream.write('** Presubmit %s **\n' % name) |
998 for item in items: | 1008 for item in items: |
| 1009 # Access to a protected member XXX of a client class |
| 1010 # pylint: disable=W0212 |
999 if not item._Handle(output_stream, input_stream, | 1011 if not item._Handle(output_stream, input_stream, |
1000 may_prompt=False): | 1012 may_prompt=False): |
1001 error_count += 1 | 1013 error_count += 1 |
1002 output_stream.write('\n') | 1014 output_stream.write('\n') |
1003 | 1015 |
1004 total_time = time.time() - start_time | 1016 total_time = time.time() - start_time |
1005 if total_time > 1.0: | 1017 if total_time > 1.0: |
1006 print "Presubmit checks took %.1fs to calculate." % total_time | 1018 print "Presubmit checks took %.1fs to calculate." % total_time |
1007 | 1019 |
1008 if not errors and warnings and may_prompt: | 1020 if not errors and warnings and may_prompt: |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 options.commit, | 1112 options.commit, |
1101 options.verbose, | 1113 options.verbose, |
1102 sys.stdout, | 1114 sys.stdout, |
1103 sys.stdin, | 1115 sys.stdin, |
1104 options.default_presubmit, | 1116 options.default_presubmit, |
1105 options.may_prompt) | 1117 options.may_prompt) |
1106 | 1118 |
1107 | 1119 |
1108 if __name__ == '__main__': | 1120 if __name__ == '__main__': |
1109 sys.exit(Main(sys.argv)) | 1121 sys.exit(Main(sys.argv)) |
OLD | NEW |