├── .gitignore ├── .pre-commit-config.yaml ├── .pydocstyle ├── .pylintrc ├── .travis.yml ├── AUTHORS.md ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── dev-requirements.txt ├── pytest_monkeytype ├── __init__.py └── plugin.py ├── requirements.txt ├── rever.xsh ├── setup.cfg ├── setup.py ├── tests ├── __init__.py └── test_annotation.py └── tox.ini /.gitignore: -------------------------------------------------------------------------------- 1 | # Py.test generated files 2 | **/__pycache__/ 3 | 4 | # Apple file system litter 5 | .DS_Store 6 | 7 | # Python generated files 8 | *.py[cod] 9 | 10 | # Installer logs 11 | pip-log.txt 12 | 13 | # Unit test / coverage reports 14 | .cache/ 15 | .coverage 16 | nosetests.xml 17 | 18 | # temporary files 19 | *.orig 20 | *~ 21 | .*~ 22 | *.swo 23 | *.swp 24 | 25 | # Virtual environment 26 | **/venv/ 27 | /.tox/ 28 | 29 | # Python autogenerated egg files and folders 30 | *.egg-info 31 | *.egg-ignore 32 | 33 | # Any IDE-generated files (pycharm, Sublime) 34 | .idea 35 | .idea/ 36 | .idea/* 37 | *.sublime-* 38 | .vscode 39 | 40 | # Sphinx docs 41 | tools/sphinx_docgen/docs_rst 42 | tools/sphinx_docgen/docs_html 43 | 44 | # Python package publishing directories 45 | build/ 46 | dist/ 47 | rever/ 48 | .mypy_cache/ 49 | 50 | *.sqlite3 51 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v3.1.0 4 | hooks: 5 | - id: trailing-whitespace 6 | - repo: https://github.com/python/black 7 | rev: 19.10b0 8 | hooks: 9 | - id: black 10 | - repo: https://github.com/pre-commit/mirrors-mypy 11 | rev: v0.782 12 | hooks: 13 | - id: mypy 14 | -------------------------------------------------------------------------------- /.pydocstyle: -------------------------------------------------------------------------------- 1 | [pydocstyle] 2 | ignore = D100,D101,D104,D203,D213,D406,D407,D408,D409,D413 3 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | [MASTER] 2 | 3 | # A comma-separated list of package or module names from where C extensions may 4 | # be loaded. Extensions are loading into the active Python interpreter and may 5 | # run arbitrary code 6 | extension-pkg-whitelist= 7 | 8 | # Add files or directories to the blacklist. They should be base names, not 9 | # paths. 10 | ignore=CVS,venv 11 | 12 | # Add files or directories matching the regex patterns to the blacklist. The 13 | # regex matches against base names, not paths. 14 | ignore-patterns= 15 | 16 | # Python code to execute, usually for sys.path manipulation such as 17 | # pygtk.require(). 18 | #init-hook= 19 | 20 | # Use multiple processes to speed up Pylint. 21 | jobs=1 22 | 23 | # List of plugins (as comma separated values of python modules names) to load, 24 | # usually to register additional checkers. 25 | load-plugins=pylint.extensions.docparams,pylint.extensions.docstyle,pylint.extensions.overlapping_exceptions,pylint.extensions.redefined_variable_type 26 | 27 | # Pickle collected data for later comparisons. 28 | persistent=no 29 | 30 | # Specify a configuration file. 31 | #rcfile= 32 | 33 | # Allow loading of arbitrary C extensions. Extensions are imported into the 34 | # active Python interpreter and may run arbitrary code. 35 | unsafe-load-any-extension=no 36 | 37 | 38 | [MESSAGES CONTROL] 39 | 40 | # Only show warnings with the listed confidence levels. Leave empty to show 41 | # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED 42 | confidence= 43 | 44 | # Disable the message, report, category or checker with the given id(s). You 45 | # can either give multiple identifiers separated by comma (,) or put this 46 | # option multiple times (only on the command line, not in the configuration 47 | # file where it should appear only once).You can also use "--disable=all" to 48 | # disable everything first and then reenable specific checks. For example, if 49 | # you want to run only the similarities checker, you can use "--disable=all 50 | # --enable=similarities". If you want to run only the classes checker, but have 51 | # no Warning level messages displayed, use"--disable=all --enable=classes 52 | # --disable=W" 53 | disable=all 54 | 55 | # Enable the message, report, category or checker with the given id(s). You can 56 | # either give multiple identifier separated by comma (,) or put this option 57 | # multiple time (only on the command line, not in the configuration file where 58 | # it should appear only once). See also the "--disable" option for examples. 59 | enable=abstract-class-instantiated, 60 | access-member-before-definition, 61 | anomalous-backslash-in-string, 62 | anomalous-unicode-escape-in-string, 63 | apply-builtin, 64 | arguments-differ, 65 | assert-on-tuple, 66 | assigning-non-slot, 67 | assignment-from-no-return, 68 | assignment-from-none, 69 | attribute-defined-outside-init, 70 | backtick, 71 | bad-builtin, 72 | bad-except-order, 73 | bad-exception-context, 74 | bad-format-character, 75 | bad-format-string, 76 | bad-format-string-key, 77 | bad-indentation, 78 | bad-open-mode, 79 | bad-reversed-sequence, 80 | bad-staticmethod-argument, 81 | bad-str-strip-call, 82 | bad-super-call, 83 | bare-except, 84 | binary-op-exception, 85 | boolean-datetime 86 | boolean-datetime, 87 | broad-except, 88 | buffer-builtin, 89 | catching-non-exception, 90 | cell-var-from-loop, 91 | cmp-builtin, 92 | cmp-method, 93 | coerce-builtin, 94 | coerce-method, 95 | confusing-with-statement, 96 | continue-in-finally, 97 | dangerous-default-value, 98 | delslice-method, 99 | deprecated-lambda, 100 | deprecated-method, 101 | deprecated-module, 102 | dict-view-method, 103 | duplicate-argument-name, 104 | duplicate-bases, 105 | duplicate-except, 106 | duplicate-key, 107 | eval-used, 108 | exec-used, 109 | execfile-builtin, 110 | expression-not-assigned, 111 | file-builtin, 112 | filter-builtin-not-iterating, 113 | fixme, 114 | format-combined-specification, 115 | format-needs-mapping, 116 | function-redefined, 117 | getslice-method, 118 | global-at-module-level, 119 | global-statement, 120 | global-variable-not-assigned, 121 | global-variable-undefined, 122 | hex-method, 123 | import-error, 124 | import-self, 125 | import-star-module-level, 126 | inconsistent-mro, 127 | indexing-exception, 128 | inherit-non-class, 129 | init-is-generator, 130 | input-builtin, 131 | intern-builtin, 132 | invalid-all-object, 133 | invalid-encoded-data, 134 | invalid-format-index, 135 | invalid-sequence-index, 136 | invalid-slice-index, 137 | invalid-slots, 138 | invalid-slots-object, 139 | invalid-star-assignment-target, 140 | invalid-unary-operand-type, 141 | logging-format-interpolation, 142 | logging-format-truncated, 143 | logging-not-lazy, 144 | logging-too-few-args, 145 | logging-too-many-args, 146 | logging-unsupported-format, 147 | long-builtin, 148 | long-suffix, 149 | lost-exception, 150 | lowercase-l-suffix, 151 | map-builtin-not-iterating, 152 | method-hidden, 153 | misplaced-bare-raise, 154 | misplaced-future, 155 | missing-format-argument-key, 156 | missing-format-attribute, 157 | missing-format-string-key, 158 | missing-kwoa, 159 | missing-super-argument, 160 | mixed-format-string, 161 | mixed-indentation, 162 | next-method-called, 163 | no-init, 164 | no-member, 165 | no-method-argument, 166 | no-name-in-module, 167 | no-self-argument, 168 | no-value-for-parameter, 169 | non-iterator-returned, 170 | non-parent-init-called, 171 | nonexistent-operator, 172 | nonlocal-and-global, 173 | nonlocal-without-binding, 174 | nonstandard-exception, 175 | nonzero-method, 176 | not-a-mapping, 177 | not-an-iterable, 178 | not-async-context-manager, 179 | not-callable, 180 | not-context-manager, 181 | not-in-loop, 182 | notimplemented-raised, 183 | oct-method, 184 | old-division, 185 | old-ne-operator, 186 | old-octal-literal, 187 | old-raise-syntax, 188 | parameter-unpacking, 189 | pointless-statement, 190 | pointless-string-statement, 191 | print-statement, 192 | property-on-old-class, 193 | protected-access, 194 | raising-bad-type, 195 | raising-non-exception, 196 | raising-string, 197 | range-builtin-not-iterating, 198 | raw_input-builtin, 199 | redefine-in-handler, 200 | redefined-builtin, 201 | redefined-outer-name, 202 | reduce-builtin, 203 | redundant-keyword-arg, 204 | redundant-unittest-assert, 205 | reimported, 206 | relative-import, 207 | reload-builtin, 208 | repeated-keyword, 209 | return-arg-in-generator, 210 | return-in-init, 211 | return-outside-function, 212 | round-builtin, 213 | setslice-method, 214 | signature-differs, 215 | slots-on-old-class, 216 | standarderror-builtin, 217 | star-needs-assignment-target, 218 | super-init-not-called, 219 | super-on-old-class, 220 | t-method, 221 | too-few-format-args, 222 | too-many-format-args, 223 | too-many-function-args, 224 | too-many-star-expressions, 225 | truncated-format-string, 226 | undefined-all-variable, 227 | undefined-loop-variable, 228 | undefined-variable, 229 | unexpected-keyword-arg, 230 | unexpected-special-method-signature, 231 | unichr-builtin, 232 | unnecessary-lambda, 233 | unnecessary-pass, 234 | unnecessary-semicolon, 235 | unpacking-in-except, 236 | unpacking-non-sequence, 237 | unreachable, 238 | unsubscriptable-object, 239 | unsupported-binary-operation, 240 | unsupported-membership-test, 241 | unused-format-string-argument 242 | unused-format-string-argument, 243 | unused-format-string-key, 244 | unused-import, 245 | unused-variable, 246 | unused-wildcard-import, 247 | used-before-assignment, 248 | useless-else-on-loop 249 | useless-else-on-loop, 250 | using-cmp-argument, 251 | using-constant-test, 252 | wildcard-import, 253 | yield-inside-async-function, 254 | yield-outside-function, 255 | zip-builtin-not-iterating, 256 | # Extensions 257 | multiple_types, 258 | overlap-except, 259 | docstyle, 260 | # Disabled for now, maybe enable in the future: 261 | # abstract-method, # needs some cleanup first 262 | # basestring-builtin, # will come with Python 3 support 263 | # dict-iter-method, # will come with Python 3 support 264 | # metaclass-assignment, # will come with Python 3 support 265 | # no-absolute-import, # maybe with Python 3 support 266 | # parameter_documentation, # needs some cleanup and maybe configuration 267 | # unicode-builtin, # will come with Python 3 support 268 | # unused-argument, # needs some cleanup and per-line suppression, 269 | # buggy / unclear how to suppress only a single function 270 | # xrange-builtin, # will come with Python 3 support 271 | 272 | 273 | # Consider the following sample rc files for errors to enable/disable: 274 | # https://github.com/datawire/quark/blob/master/.pylintrc 275 | # https://github.com/ClusterHQ/flocker/blob/master/.pylintrc 276 | 277 | 278 | [REPORTS] 279 | 280 | # Python expression which should return a note less than 10 (10 is the highest 281 | # note). You have access to the variables errors warning, statement which 282 | # respectively contain the number of errors / warnings messages and the total 283 | # number of statements analyzed. This is used by the global evaluation report 284 | # (RP0004). 285 | evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) 286 | 287 | # Template used to display messages. This is a python new-style format string 288 | # used to format the message information. See doc for all details 289 | #msg-template= 290 | 291 | # Set the output format. Available formats are text, parseable, colorized, json 292 | # and msvs (visual studio).You can also give a reporter class, eg 293 | # mypackage.mymodule.MyReporterClass. 294 | output-format=text 295 | 296 | # Tells whether to display a full report or only the messages 297 | reports=no 298 | 299 | # Activate the evaluation score. 300 | score=yes 301 | 302 | 303 | [REFACTORING] 304 | 305 | # Maximum number of nested blocks for function / method body 306 | max-nested-blocks=5 307 | 308 | 309 | [BASIC] 310 | 311 | # Naming hint for argument names 312 | argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 313 | 314 | # Regular expression matching correct argument names 315 | argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 316 | 317 | # Naming hint for attribute names 318 | attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 319 | 320 | # Regular expression matching correct attribute names 321 | attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 322 | 323 | # Bad variable names which should always be refused, separated by a comma 324 | bad-names=foo,bar,baz,toto,tutu,tata 325 | 326 | # Naming hint for class attribute names 327 | class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ 328 | 329 | # Regular expression matching correct class attribute names 330 | class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ 331 | 332 | # Naming hint for class names 333 | class-name-hint=[A-Z_][a-zA-Z0-9]+$ 334 | 335 | # Regular expression matching correct class names 336 | class-rgx=[A-Z_][a-zA-Z0-9]+$ 337 | 338 | # Naming hint for constant names 339 | const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ 340 | 341 | # Regular expression matching correct constant names 342 | const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ 343 | 344 | # Minimum line length for functions/classes that require docstrings, shorter 345 | # ones are exempt. 346 | docstring-min-length=-1 347 | 348 | # Naming hint for function names 349 | function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 350 | 351 | # Regular expression matching correct function names 352 | function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 353 | 354 | # Good variable names which should always be accepted, separated by a comma 355 | good-names=i,j,k,ex,Run,_ 356 | 357 | # Include a hint for the correct naming format with invalid-name 358 | include-naming-hint=no 359 | 360 | # Naming hint for inline iteration names 361 | inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ 362 | 363 | # Regular expression matching correct inline iteration names 364 | inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ 365 | 366 | # Naming hint for method names 367 | method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 368 | 369 | # Regular expression matching correct method names 370 | method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 371 | 372 | # Naming hint for module names 373 | module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 374 | 375 | # Regular expression matching correct module names 376 | module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 377 | 378 | # Colon-delimited sets of names that determine each other's naming style when 379 | # the name regexes allow several styles. 380 | name-group= 381 | 382 | # Regular expression which should only match function or class names that do 383 | # not require a docstring. 384 | no-docstring-rgx=^(.*Tests)|(test_) 385 | 386 | # List of decorators that produce properties, such as abc.abstractproperty. Add 387 | # to this list to register other decorators that produce valid properties. 388 | property-classes=abc.abstractproperty 389 | 390 | # Naming hint for variable names 391 | variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 392 | 393 | # Regular expression matching correct variable names 394 | variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ 395 | 396 | 397 | [FORMAT] 398 | 399 | # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. 400 | expected-line-ending-format= 401 | 402 | # Regexp for a line that is allowed to be longer than the limit. 403 | ignore-long-lines=^\s*(# )??$ 404 | 405 | # Number of spaces of indent required inside a hanging or continued line. 406 | indent-after-paren=4 407 | 408 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 409 | # tab). 410 | indent-string=' ' 411 | 412 | # Maximum number of characters on a single line. 413 | max-line-length=100 414 | 415 | # Maximum number of lines in a module 416 | max-module-lines=2000 417 | 418 | # List of optional constructs for which whitespace checking is disabled. `dict- 419 | # separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. 420 | # `trailing-comma` allows a space between comma and closing bracket: (a, ). 421 | # `empty-line` allows space-only lines. 422 | no-space-check= 423 | 424 | # Allow the body of a class to be on the same line as the declaration if body 425 | # contains single statement. 426 | single-line-class-stmt=no 427 | 428 | # Allow the body of an if to be on the same line as the test if there is no 429 | # else. 430 | single-line-if-stmt=no 431 | 432 | 433 | [LOGGING] 434 | 435 | # Logging modules to check that the string format arguments are in logging 436 | # function parameter format 437 | logging-modules=logging 438 | 439 | 440 | [MISCELLANEOUS] 441 | 442 | # List of note tags to take in consideration, separated by a comma. 443 | notes=FIXME,XXX,TODO 444 | 445 | 446 | [SIMILARITIES] 447 | 448 | # Ignore comments when computing similarities. 449 | ignore-comments=yes 450 | 451 | # Ignore docstrings when computing similarities. 452 | ignore-docstrings=yes 453 | 454 | # Ignore imports when computing similarities. 455 | ignore-imports=no 456 | 457 | # Minimum lines number of a similarity. 458 | min-similarity-lines=4 459 | 460 | 461 | [SPELLING] 462 | 463 | # Spelling dictionary name. Available dictionaries: none. To make it working 464 | # install python-enchant package. 465 | spelling-dict= 466 | 467 | # List of comma separated words that should not be checked. 468 | spelling-ignore-words= 469 | 470 | # A path to a file that contains private dictionary; one word per line. 471 | spelling-private-dict-file= 472 | 473 | # Tells whether to store unknown words to indicated private dictionary in 474 | # --spelling-private-dict-file option instead of raising a message. 475 | spelling-store-unknown-words=no 476 | 477 | 478 | [TYPECHECK] 479 | 480 | # List of decorators that produce context managers, such as 481 | # contextlib.contextmanager. Add to this list to register other decorators that 482 | # produce valid context managers. 483 | contextmanager-decorators=contextlib.contextmanager 484 | 485 | # List of members which are set dynamically and missed by pylint inference 486 | # system, and so shouldn't trigger E1101 when accessed. Python regular 487 | # expressions are accepted. 488 | generated-members= 489 | 490 | # Tells whether missing members accessed in mixin class should be ignored. A 491 | # mixin class is detected if its name ends with "mixin" (case insensitive). 492 | ignore-mixin-members=yes 493 | 494 | # This flag controls whether pylint should warn about no-member and similar 495 | # checks whenever an opaque object is returned when inferring. The inference 496 | # can return multiple potential results while evaluating a Python object, but 497 | # some branches might not be evaluated, which results in partial inference. In 498 | # that case, it might be useful to still emit no-member and other checks for 499 | # the rest of the inferred objects. 500 | ignore-on-opaque-inference=yes 501 | 502 | # List of class names for which member attributes should not be checked (useful 503 | # for classes with dynamically set attributes). This supports the use of 504 | # qualified names. 505 | ignored-classes=optparse.Values,thread._local,_thread._local 506 | 507 | # List of module names for which member attributes should not be checked 508 | # (useful for modules/projects where namespaces are manipulated during runtime 509 | # and thus existing member attributes cannot be deduced by static analysis. It 510 | # supports qualified module names, as well as Unix pattern matching. 511 | ignored-modules= 512 | 513 | # Show a hint with possible names when a member name was not found. The aspect 514 | # of finding the hint is based on edit distance. 515 | missing-member-hint=yes 516 | 517 | # The minimum edit distance a name should have in order to be considered a 518 | # similar match for a missing member name. 519 | missing-member-hint-distance=1 520 | 521 | # The total number of similar names that should be taken in consideration when 522 | # showing a hint for a missing member. 523 | missing-member-max-choices=1 524 | 525 | 526 | [VARIABLES] 527 | 528 | # List of additional names supposed to be defined in builtins. Remember that 529 | # you should avoid to define new builtins when possible. 530 | additional-builtins= 531 | 532 | # Tells whether unused global variables should be treated as a violation. 533 | allow-global-unused-variables=yes 534 | 535 | # List of strings which can identify a callback function by name. A callback 536 | # name must start or end with one of those strings. 537 | callbacks=cb_,_cb 538 | 539 | # A regular expression matching the name of dummy variables (i.e. expectedly 540 | # not used). 541 | dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ 542 | 543 | # Argument names that match this expression will be ignored. Default to name 544 | # with leading underscore 545 | ignored-argument-names=_.*|^ignored_|^unused_ 546 | 547 | # Tells whether we should check for unused import in __init__ files. 548 | init-import=no 549 | 550 | # List of qualified module names which can have objects that can redefine 551 | # builtins. 552 | redefining-builtins-modules=six.moves,future.builtins 553 | 554 | 555 | [CLASSES] 556 | 557 | # List of method names used to declare (i.e. assign) instance attributes. 558 | defining-attr-methods=__init__,__new__,setUp 559 | 560 | # List of member names, which should be excluded from the protected access 561 | # warning. 562 | exclude-protected=_asdict,_fields,_replace,_source,_make 563 | 564 | # List of valid names for the first argument in a class method. 565 | valid-classmethod-first-arg=cls 566 | 567 | # List of valid names for the first argument in a metaclass class method. 568 | valid-metaclass-classmethod-first-arg=mcs 569 | 570 | 571 | [DESIGN] 572 | 573 | # Maximum number of arguments for function / method 574 | max-args=5 575 | 576 | # Maximum number of attributes for a class (see R0902). 577 | max-attributes=7 578 | 579 | # Maximum number of boolean expressions in a if statement 580 | max-bool-expr=5 581 | 582 | # Maximum number of branch for function / method body 583 | max-branches=12 584 | 585 | # Maximum number of locals for function / method body 586 | max-locals=15 587 | 588 | # Maximum number of parents for a class (see R0901). 589 | max-parents=7 590 | 591 | # Maximum number of public methods for a class (see R0904). 592 | max-public-methods=20 593 | 594 | # Maximum number of return / yield for function / method body 595 | max-returns=6 596 | 597 | # Maximum number of statements in function / method body 598 | max-statements=50 599 | 600 | # Minimum number of public methods for a class (see R0903). 601 | min-public-methods=2 602 | 603 | 604 | [IMPORTS] 605 | 606 | # Allow wildcard imports from modules that define __all__. 607 | allow-wildcard-with-all=no 608 | 609 | # Analyse import fallback blocks. This can be used to support both Python 2 and 610 | # 3 compatible code, which means that the block might have code that exists 611 | # only in one or another interpreter, leading to false positives when analysed. 612 | analyse-fallback-blocks=no 613 | 614 | # Deprecated modules which should not be used, separated by a comma 615 | deprecated-modules=regsub,TERMIOS,Bastion,rexec 616 | 617 | # Create a graph of external dependencies in the given file (report RP0402 must 618 | # not be disabled) 619 | ext-import-graph= 620 | 621 | # Create a graph of every (i.e. internal and external) dependencies in the 622 | # given file (report RP0402 must not be disabled) 623 | import-graph= 624 | 625 | # Create a graph of internal dependencies in the given file (report RP0402 must 626 | # not be disabled) 627 | int-import-graph= 628 | 629 | # Force import order to recognize a module as part of the standard 630 | # compatibility libraries. 631 | known-standard-library= 632 | 633 | # Force import order to recognize a module as part of a third party library. 634 | known-third-party=enchant 635 | 636 | 637 | [EXCEPTIONS] 638 | 639 | # Exceptions that will emit a warning when being caught. Defaults to 640 | # "Exception" 641 | overgeneral-exceptions=Exception,BaseException 642 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: python 3 | cache: pip 4 | python: 5 | - "3.6" 6 | - "3.7" 7 | - "3.8" 8 | install: 9 | - pip install -r dev-requirements.txt 10 | - pip install -e . 11 | script: 12 | - flake8 pytest_monkeytype/ 13 | - pydocstyle pytest_monkeytype/ 14 | - isort --check-only --verbose --recursive pytest_monkeytype/ 15 | - pylint pytest_monkeytype/ 16 | - bandit -r pytest_monkeytype/ 17 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | Marius van Niekerk 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Current development version 4 | 5 | ## v1.0.3 6 | 7 | - Repackage to improve pypi listing 8 | 9 | ## v1.0.2 10 | 11 | - Added support for test suites that use `gevent` monkey-patching. [#4](https://github.com/kensho-technologies/pytest-monkeytype/pull/4) 12 | 13 | Thanks to `rowillia` for the contribution. 14 | 15 | ## v1.0.1 16 | 17 | - Enabled installation with Python 3.4.* and 3.5.2+ [#3](https://github.com/kensho-technologies/pytest-monkeytype/pull/3) 18 | 19 | Thanks to `Xelia` for the contribution! 20 | 21 | ## v1.0.0 22 | 23 | Initial release. 24 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at 59 | [marius.v.niekerk@gmail.com](mailto:marius.v.niekerk@gmail.com). All 60 | complaints will be reviewed and investigated and will result in a response that 61 | is deemed necessary and appropriate to the circumstances. The project team is 62 | obligated to maintain confidentiality with regard to the reporter of an incident. 63 | Further details of specific enforcement policies may be posted separately. 64 | 65 | Project maintainers who do not follow or enforce the Code of Conduct in good 66 | faith may face temporary or permanent repercussions as determined by other 67 | members of the project's leadership. 68 | 69 | ## Attribution 70 | 71 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 72 | available at [http://contributor-covenant.org/version/1/4][version] 73 | 74 | [homepage]: http://contributor-covenant.org 75 | [version]: http://contributor-covenant.org/version/1/4/ 76 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for taking the time to contribute to this project! 4 | 5 | To get started: 6 | ``` 7 | pip install -r dev-requirements.txt 8 | pip install -r requirements.txt 9 | ``` 10 | 11 | ## Code of Conduct 12 | 13 | This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). 14 | By participating, you are expected to uphold this code. 15 | Please report unacceptable behavior at 16 | [marius.v.niekerk@gmail.com](mailto:marius.v.niekerk@gmail.com). 17 | 18 | ## Contributor License Agreement 19 | 20 | Each contributor is required to agree to our 21 | [Contributor License Agreement](https://www.clahub.com/agreements/kensho-technologies/pytest-monkeytype), 22 | to ensure that their contribution may be safely merged into the project codebase and 23 | released under the existing code license. This agreement does not change contributors' 24 | rights to use the contributions for any other purpose -- it is simply used for the protection 25 | of both the contributors and the project. 26 | 27 | ## Style Guide 28 | 29 | This project follows the 30 | [Google Python style guide](https://google.github.io/styleguide/pyguide.html). 31 | 32 | Additionally, any contributions must pass the following set of lint and style checks with no issues: 33 | ``` 34 | flake8 pytest_monkeytype/ 35 | 36 | pydocstyle pytest_monkeytype/ 37 | 38 | isort --check-only --verbose --recursive pytest_monkeytype/ 39 | 40 | pylint pytest_monkeytype/ 41 | 42 | bandit -r pytest_monkeytype/ 43 | ``` 44 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2018 Marius van Niekerk 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 4 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 5 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 6 | persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 9 | Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 12 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 13 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 14 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE.in 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pytest-monkeytype 2 | 3 | [![Build Status](https://travis-ci.org/mariusvniekerk/pytest-monkeytype.svg?branch=master)](https://travis-ci.org/mariusvniekerk/pytest-monkeytype) 4 | [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/Apache-2.0) 5 | [![PyPI Python](https://img.shields.io/pypi/pyversions/pytest-monkeytype.svg)](https://pypi.python.org/pypi/pytest-monkeytype) 6 | [![PyPI Version](https://img.shields.io/pypi/v/pytest-monkeytype.svg)](https://pypi.python.org/pypi/pytest-monkeytype) 7 | [![PyPI Status](https://img.shields.io/pypi/status/pytest-monkeytype.svg)](https://pypi.python.org/pypi/pytest-monkeytype) 8 | [![PyPI Wheel](https://img.shields.io/pypi/wheel/pytest-monkeytype.svg)](https://pypi.python.org/pypi/pytest-monkeytype) 9 | 10 | 11 | [MonkeyType](https://github.com/Instagram/MonkeyType) as a 12 | [pytest](https://docs.pytest.org/en/latest/) plugin. 13 | 14 | ``` 15 | pip install pytest-monkeytype 16 | 17 | # Generate annotations by running your pytest tests as usual: 18 | py.test --monkeytype-output=./monkeytype.sqlite3 19 | 20 | # Get a listing of modules annotated by monkeytype 21 | monkeytype list-modules 22 | 23 | # Generate a stub file for those annotations using monkeytype: 24 | monkeytype stub some.module 25 | 26 | # Apply these annotations directly 27 | monkeytype apply some.module 28 | ``` 29 | 30 | 31 | This project is inspired by [pytest-annotate](https://github.com/kensho-technologies/pytest-annotate) -------------------------------------------------------------------------------- /dev-requirements.txt: -------------------------------------------------------------------------------- 1 | bandit>=1.4.0 2 | coveralls>=1.1 3 | flake8>=3.3.0 4 | isort>=4.2.15 5 | pydocstyle>=2.0.0 6 | pylint>=1.7.1 7 | -------------------------------------------------------------------------------- /pytest_monkeytype/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "1.1.0" 2 | -------------------------------------------------------------------------------- /pytest_monkeytype/plugin.py: -------------------------------------------------------------------------------- 1 | """Enable MonkeyType tracing & logging to collect type info.""" 2 | 3 | import os 4 | import sys 5 | import typing 6 | 7 | 8 | if typing.TYPE_CHECKING: 9 | from typing import Optional 10 | from monkeytype.tracing import CallTracer 11 | 12 | 13 | class MonkeyTypePlugin(object): 14 | """Enable MonkeyType tracing & logging to collect type info. 15 | 16 | A pytest plugin that profiles function calls to extract type info. 17 | """ 18 | 19 | def __init__(self, typed_dict_size=0): 20 | """Create a new PyAnnotatePlugin that analyzes function calls to extract type info. 21 | 22 | Initialize the plugin that profiles calls to extract type info. 23 | """ 24 | from monkeytype.config import DefaultConfig 25 | 26 | self.typed_dict_size = typed_dict_size 27 | self.config = DefaultConfig() 28 | self.trace_logger = self.config.trace_logger() 29 | self.tracer: "Optional[CallTracer]" = None 30 | 31 | def pytest_collection_finish(self, session): 32 | """Configure MonkeyType and set as profiler after collection. 33 | 34 | Explicitly delay importing until all tests have been collected. This 35 | gives gevent a chance to monkey patch the world before importing 36 | CallTracer. 37 | """ 38 | from monkeytype.tracing import CallTracer 39 | 40 | self.tracer = CallTracer( 41 | logger=self.trace_logger, 42 | max_typed_dict_size=self.typed_dict_size, 43 | code_filter=self.config.code_filter(), 44 | sample_rate=None, 45 | ) 46 | 47 | sys.setprofile(self.tracer) 48 | 49 | def pytest_unconfigure(self, config): 50 | """Unconfigure by disabling profiling and flushing the logger.""" 51 | sys.setprofile(None) 52 | self.trace_logger.flush() 53 | 54 | def pytest_runtest_call(self): 55 | """Start collection by installing the CallTracer as profiler.""" 56 | sys.setprofile(self.tracer) 57 | 58 | def pytest_runtest_teardown(self): 59 | """Stop collection by disabling profiling and flushing the logger.""" 60 | sys.setprofile(None) 61 | self.trace_logger.flush() 62 | 63 | 64 | def pytest_addoption(parser): 65 | """Add our --monkeytype-output option to the pytest option parser.""" 66 | parser.addoption( 67 | "--monkeytype-output", 68 | help=( 69 | "Output file where MonkeyType stats should be saved. Eg:" 70 | ' "monkeytype.sqlite3"' 71 | ), 72 | ) 73 | parser.addoption( 74 | "--monkeytype-max-typed-dict-size", 75 | help=( 76 | "Maximum number of fields to include in generate TypedDict types" 77 | ) 78 | ) 79 | 80 | 81 | def pytest_configure(config): 82 | """Enable and configure the output location.""" 83 | option_value = config.getoption("--monkeytype-output") 84 | typed_dict_size = config.getoption("--monkeytype-max-typed-dict-size") or 0 85 | typed_dict_size = int(typed_dict_size) 86 | 87 | if option_value: 88 | os.environ["MT_DB_PATH"] = os.path.abspath(option_value) 89 | config.pluginmanager.register(MonkeyTypePlugin(typed_dict_size)) 90 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | monkeytype>=20.5.0 2 | pytest>=3.2.5 3 | -------------------------------------------------------------------------------- /rever.xsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env xonsh 2 | $PROJECT = 'pytest-monkeytype' 3 | $ACTIVITIES = [ 4 | 'version_bump', 5 | 'tag', 6 | 'pypi', 7 | 'push_tag', 8 | 'ghrelease' 9 | ] 10 | 11 | $GITHUB_ORG = 'mariusvniekerk' 12 | $GITHUB_REPO = 'pytest-monkeytype' 13 | 14 | $VERSION_BUMP_PATTERNS = [ 15 | # These note where/how to find the version numbers 16 | ('pytest_monkeytype/__init__.py', '__version__\s*=.*', '__version__ = "$VERSION"'), 17 | ('setup.py', 'version\s*=.*,', 'version="$VERSION",'), 18 | ] 19 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 0 3 | 4 | [flake8] 5 | max-line-length = 100 6 | 7 | [pycodestyle] 8 | max-line-length = 100 9 | 10 | [isort] 11 | line_length = 100 12 | multi_line_output = 0 13 | lines_after_imports = 2 14 | force_sort_within_sections = 1 15 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | 4 | package_name = "pytest-monkeytype" 5 | version = "1.0.3" 6 | 7 | with open("README.md", "r") as fh: 8 | long_description = fh.read() 9 | 10 | setup( 11 | name=package_name, 12 | version="1.1.0", 13 | description=( 14 | "pytest-monkeytype: Generate Monkeytype annotations from your pytest tests." 15 | ), 16 | long_description=long_description, 17 | long_description_content_type="text/markdown", 18 | url="https://github.com/mariusvniekerk/pytest-monkeytype", 19 | author="Marius van Niekerk", 20 | author_email="marius.v.niekerk@gmail.com", 21 | license="MIT", 22 | packages=find_packages(), 23 | install_requires=["MonkeyType>=18.2.0", "pytest>=3.2.0"], 24 | entry_points={"pytest11": ["pytest_monkeytype = pytest_monkeytype.plugin",]}, 25 | classifiers=[ 26 | "Development Status :: 4 - Beta", 27 | "Environment :: Console", 28 | "Intended Audience :: Developers", 29 | "Framework :: Pytest", 30 | "License :: OSI Approved :: MIT License", 31 | "Programming Language :: Python :: 3", 32 | "Programming Language :: Python :: 3.6", 33 | "Programming Language :: Python :: 3.7", 34 | "Programming Language :: Python :: 3.8", 35 | "Topic :: Software Development", 36 | "Topic :: Software Development :: Testing", 37 | ], 38 | keywords="pytest py.test types annotations MonkeyType monkeytype pep484", 39 | python_requires=">=3.6", 40 | ) 41 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mariusvniekerk/pytest-monkeytype/2873d498bc529fe7390e8ac99b039087ec708658/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_annotation.py: -------------------------------------------------------------------------------- 1 | def fn(a, b): 2 | return a + b 3 | 4 | 5 | def test_int(): 6 | fn(1, 5) 7 | 8 | 9 | def test_mixed(): 10 | fn(1, 5.0) 11 | 12 | 13 | def test_string(): 14 | fn("1", "5") 15 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # tox (https://tox.readthedocs.io/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | envlist = py36, py37, py38 8 | 9 | [testenv] 10 | deps = 11 | pytest 12 | commands = 13 | pytest {posargs} 14 | --------------------------------------------------------------------------------