From 6eb71cfe63b8a44ce2c8e655fa6e273b2ab6f6fb Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 18 Jun 2018 10:42:07 -0400 Subject: [PATCH 1/4] Add pylint and run before tests --- .pylintrc | 578 +++++++++++++++++++++++++++++++++++++++++++++++++++ Pipfile | 1 + Pipfile.lock | 72 ++++++- script/test | 2 + 4 files changed, 652 insertions(+), 1 deletion(-) create mode 100644 .pylintrc diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 00000000..2612f2e7 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,578 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore= + +# Pickle collected data for later comparisons. +persistent=no + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Use multiple processes to speed up Pylint. +# DO NOT CHANGE THIS VALUES >1 HIDE RESULTS!!!!! +jobs=1 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + +# Allow optimization of some AST trees. This will activate a peephole AST +# optimizer, which will apply various small optimizations. For instance, it can +# be used to obtain the result of joining multiple strings with the addition +# operator. Joining a lot of strings can lead to a maximum recursion error in +# Pylint and this flag can prevent that. It has one side effect, the resulting +# AST will be different than the one from reality. +optimize-ast=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +disable=all + +enable=import-error, + import-self, + reimported, + misplaced-future, + relative-import, + deprecated-module, + unpacking-non-sequence, + invalid-all-object, + undefined-all-variable, + used-before-assignment, + cell-var-from-loop, + global-variable-undefined, + redefined-builtin, + redefine-in-handler, + unused-import, + global-variable-not-assigned, + undefined-loop-variable, + global-statement, + global-at-module-level, + bad-open-mode, + redundant-unittest-assert, + boolean-datetime, + bad-indentation, + mixed-indentation, + unnecessary-semicolon, + unused-variable, + pointless-statement, + pointless-string-statement, + unnecessary-pass, + unreachable, + bad-super-call, + missing-super-argument, + too-few-format-args, + print-statement, + not-callable, + redundant-keyword-arg, + repeated-keyword, + too-many-function-args, + bare-except, + duplicate-argument-name, + return-in-init, + return-outside-function, + +# Things we'd like to enable someday: +# redefined-outer-name (requires a bunch of work to clean up our code first) +# undefined-variable (re-enable when pylint fixes https://github.com/PyCQA/pylint/issues/760) +# no-name-in-module (giving us spurious warnings https://github.com/PyCQA/pylint/issues/73) +# unused-argument (need to clean up or code a lot, e.g. prefix unused_?) + +# Things we'd like to try. +# Procedure: +# 1. Enable a bunch. +# 2. See if there's spurious ones; if so disable. +# 3. Record above. +# 4. Remove from this list. + # wildcard-import, + # unused-wildcard-import, + # deprecated-method, + # anomalous-unicode-escape-in-string, + # anomalous-backslash-in-string, + # not-in-loop, + # function-redefined, + # continue-in-finally, + # abstract-class-instantiated, + # star-needs-assignment-target, + # too-many-star-expressions, + # nonlocal-and-global, + # return-arg-in-generator, + # invalid-star-assignment-target, + # bad-reversed-sequence, + # nonexistent-operator, + # yield-outside-function, + # init-is-generator, + # nonlocal-without-binding, + # lost-exception, + # assert-on-tuple, + # dangerous-default-value, + # duplicate-key, + # useless-else-on-loop, + # expression-not-assigned, + # confusing-with-statement, + # unnecessary-lambda, + # eval-used, + # exec-used, + # bad-builtin, + # using-constant-test, + # deprecated-lambda, + # slots-on-old-class, + # super-on-old-class, + # property-on-old-class, + # not-an-iterable, + # not-a-mapping, + # format-needs-mapping, + # truncated-format-string, + # missing-format-string-key, + # mixed-format-string, + # bad-str-strip-call, + # too-many-format-args, + # bad-format-character, + # format-combined-specification, + # bad-format-string-key, + # bad-format-string, + # missing-format-attribute, + # missing-format-argument-key, + # unused-format-string-argument, + # unused-format-string-key, + # invalid-format-index, + # lowercase-l-suffix, + # fixme, + # invalid-encoded-data, + # unpacking-in-except, + # import-star-module-level, + # parameter-unpacking, + # long-suffix, + # old-octal-literal, + # old-ne-operator, + # backtick, + # old-raise-syntax, + # metaclass-assignment, + # next-method-called, + # dict-iter-method, + # dict-view-method, + # indexing-exception, + # raising-string, + # standarderror-builtin, + # using-cmp-argument, + # cmp-method, + # coerce-method, + # delslice-method, + # getslice-method, + # hex-method, + # nonzero-method, + # oct-method, + # setslice-method, + # apply-builtin, + # basestring-builtin, + # buffer-builtin, + # cmp-builtin, + # coerce-builtin, + # old-division, + # execfile-builtin, + # file-builtin, + # filter-builtin-not-iterating, + # no-absolute-import, + # input-builtin, + # intern-builtin, + # long-builtin, + # map-builtin-not-iterating, + # range-builtin-not-iterating, + # raw_input-builtin, + # reduce-builtin, + # reload-builtin, + # round-builtin, + # unichr-builtin, + # unicode-builtin, + # xrange-builtin, + # zip-builtin-not-iterating, + # logging-format-truncated, + # logging-too-few-args, + # logging-too-many-args, + # logging-unsupported-format, + # logging-not-lazy, + # logging-format-interpolation, + # invalid-unary-operand-type, + # unsupported-binary-operation, + # no-member, + # assignment-from-no-return, + # assignment-from-none, + # not-context-manager, + # missing-kwoa, + # no-value-for-parameter, + # invalid-sequence-index, + # invalid-slice-index, + # unexpected-keyword-arg, + # unsupported-membership-test, + # unsubscriptable-object, + # access-member-before-definition, + # method-hidden, + # assigning-non-slot, + # duplicate-bases, + # inconsistent-mro, + # inherit-non-class, + # invalid-slots, + # invalid-slots-object, + # no-method-argument, + # no-self-argument, + # unexpected-special-method-signature, + # non-iterator-returned, + # protected-access, + # arguments-differ, + # attribute-defined-outside-init, + # no-init, + # abstract-method, + # signature-differs, + # bad-staticmethod-argument, + # non-parent-init-called, + # super-init-not-called, + # bad-except-order, + # catching-non-exception, + # bad-exception-context, + # notimplemented-raised, + # raising-bad-type, + # raising-non-exception, + # misplaced-bare-raise, + # duplicate-except, + # broad-except, + # nonstandard-exception, + # binary-op-exception, + # not-async-context-manager, + # yield-inside-async-function, + +# ... +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=parseable + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=100 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). This supports can work +# with qualified names. +ignored-classes= + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=^_|^dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[BASIC] + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,input + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for function names +function-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for variable names +variable-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for attribute names +attr-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for argument names +argument-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for method names +method-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + + +[ELIF] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/Pipfile b/Pipfile index 01bd0616..d82be36b 100644 --- a/Pipfile +++ b/Pipfile @@ -14,6 +14,7 @@ pytest = "==3.6.0" pytest-tornado = "==0.5.0" ipython = "*" ipdb = "*" +pylint = "*" [requires] python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index 726f64cc..b613f8c2 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2299d6143992989417d01bd11d7d99a8a239a388321dc1546815d8b49c8151b8" + "sha256": "3ee82a3d0081be8881d2c211c6d0333b179e78754e953b609e10a51a4ab87c88" }, "pipfile-spec": 6, "requires": { @@ -66,6 +66,13 @@ "markers": "sys_platform == 'darwin'", "version": "==0.1.0" }, + "astroid": { + "hashes": [ + "sha256:0ef2bf9f07c3150929b25e8e61b5198c27b0dca195e156f0e4d5bdd89185ca1a", + "sha256:fc9b582dba0366e63540982c3944a9230cbc6f303641c51483fa547dcc22393a" + ], + "version": "==1.6.5" + }, "atomicwrites": { "hashes": [ "sha256:240831ea22da9ab882b551b31d4225591e5e447a68c5e188db5b89ca1d487585", @@ -116,6 +123,14 @@ ], "version": "==0.2.0" }, + "isort": { + "hashes": [ + "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", + "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", + "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" + ], + "version": "==4.3.4" + }, "jedi": { "hashes": [ "sha256:1972f694c6bc66a2fac8718299e2ab73011d653a6d8059790c3476d2353b99ad", @@ -123,6 +138,47 @@ ], "version": "==0.12.0" }, + "lazy-object-proxy": { + "hashes": [ + "sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", + "sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39", + "sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019", + "sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088", + "sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b", + "sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e", + "sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6", + "sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b", + "sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5", + "sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff", + "sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd", + "sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7", + "sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff", + "sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d", + "sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2", + "sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35", + "sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4", + "sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514", + "sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252", + "sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109", + "sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f", + "sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c", + "sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92", + "sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577", + "sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d", + "sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d", + "sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f", + "sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a", + "sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b" + ], + "version": "==1.3.1" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, "more-itertools": { "hashes": [ "sha256:2b6b9893337bfd9166bee6a62c2b0c9fe7735dcf85948b387ec8cba30e85d8e8", @@ -190,6 +246,14 @@ ], "version": "==2.2.0" }, + "pylint": { + "hashes": [ + "sha256:a48070545c12430cfc4e865bf62f5ad367784765681b3db442d8230f0960aa3c", + "sha256:fff220bcb996b4f7e2b0f6812fd81507b72ca4d8c4d05daf2655c333800cb9b3" + ], + "index": "pypi", + "version": "==1.9.2" + }, "pytest": { "hashes": [ "sha256:39555d023af3200d004d09e51b4dd9fdd828baa863cded3fd6ba2f29f757ae2d", @@ -243,6 +307,12 @@ "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" ], "version": "==0.1.7" + }, + "wrapt": { + "hashes": [ + "sha256:d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6" + ], + "version": "==1.10.11" } } } diff --git a/script/test b/script/test index 56549b39..9682f660 100755 --- a/script/test +++ b/script/test @@ -6,5 +6,7 @@ set -e # Ensure we are in the app root directory (not the /script directory) cd "$(dirname "${0}")/.." +pipenv run pylint --errors-only atst + # Run unit tests pipenv run python -m pytest -s $* From 64c71c0aa794c485084f035d512c2bcd83d69ea5 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 18 Jun 2018 10:44:06 -0400 Subject: [PATCH 2/4] Inject dependencies into tornado app --- app.py | 5 +++-- atst/app.py | 25 +++++++++++++++++-------- config/base.ini | 1 + tests/__init__.py | 0 tests/conftest.py | 14 ++++++++++++-- tests/mocks.py | 32 ++++++++++++++++++++++++++++++++ 6 files changed, 65 insertions(+), 12 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/mocks.py diff --git a/app.py b/app.py index 7d524e7d..766f0caa 100755 --- a/app.py +++ b/app.py @@ -2,10 +2,11 @@ import tornado.ioloop -from atst.app import make_app, make_config +from atst.app import make_app, make_deps, make_config config = make_config() -app = make_app(config) +deps = make_deps(config) +app = make_app(config, deps) if __name__ == '__main__': port = int(config['default']['PORT']) diff --git a/atst/app.py b/atst/app.py index a1bf7966..c38b20b7 100644 --- a/atst/app.py +++ b/atst/app.py @@ -16,17 +16,14 @@ from atst.api_client import ApiClient ENV = os.getenv("TORNADO_ENV", "dev") -def make_app(config,**kwargs): - - authz_client = ApiClient(config["default"]["AUTHZ_BASE_URL"]) - authnid_client = ApiClient(config["default"]["AUTHNID_BASE_URL"]) +def make_app(config, deps, **kwargs): routes = [ url(r"/", Home, {"page": "login"}, name="main"), url( r"/login", Login, - {"authnid_client": authnid_client}, + {"authnid_client": deps["authnid_client"]}, name="login", ), url(r"/home", MainHandler, {"page": "home"}, name="home"), @@ -34,15 +31,19 @@ def make_app(config,**kwargs): url( r"/workspaces", Workspace, - {"page": "workspaces", "authz_client": authz_client}, + {"page": "workspaces", "authz_client": deps["authz_client"]}, name="workspaces", ), url(r"/requests", Request, {"page": "requests"}, name="requests"), - url(r"/requests/new", RequestNew, {"page": "requests_new"}, name="request_new"), + url( + r"/requests/new", + RequestNew, + {"page": "requests_new", "requests_client": deps["requests_client"]}, + name="request_new"), url( r"/requests/new/([0-9])", RequestNew, - {"page": "requests_new"}, + {"page": "requests_new", "requests_client": deps["requests_client"]}, name="request_form", ), url(r"/users", MainHandler, {"page": "users"}, name="users"), @@ -67,6 +68,14 @@ def make_app(config,**kwargs): return app +def make_deps(config): + return { + 'authz_client': ApiClient(config["default"]["AUTHZ_BASE_URL"]), + 'authnid_client': ApiClient(config["default"]["AUTHNID_BASE_URL"]), + 'requests_client': ApiClient(config["default"]["REQUESTS_QUEUE_BASE_URL"]) + } + + def make_config(): BASE_CONFIG_FILENAME = os.path.join( os.path.dirname(__file__), diff --git a/config/base.ini b/config/base.ini index fd9962b3..ee980cbf 100644 --- a/config/base.ini +++ b/config/base.ini @@ -7,3 +7,4 @@ AUTHNID_BASE_URL= http://localhost COOKIE_SECRET = some-secret-please-replace SECRET = change_me_into_something_secret CAC_URL = http://localhost:8888/home +REQUESTS_QUEUE_BASE_URL = http://localhost:8003 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/conftest.py b/tests/conftest.py index 19aa9794..5f28746d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,19 @@ import pytest -from atst.app import make_app, make_config +from atst.app import make_app, make_deps, make_config +from tests.mocks import MockApiClient @pytest.fixture def app(): + TEST_DEPS = { + 'authz_client': MockApiClient('authz'), + 'requests_client': MockApiClient('requests'), + 'authnid_client': MockApiClient('authnid'), + } + config = make_config() - return make_app(config) + deps = make_deps(config) + deps.update(TEST_DEPS) + + return make_app(config, deps) diff --git a/tests/mocks.py b/tests/mocks.py new file mode 100644 index 00000000..e58e46d8 --- /dev/null +++ b/tests/mocks.py @@ -0,0 +1,32 @@ +import tornado.gen +from tornado.httpclient import HTTPRequest, HTTPResponse + + +class MockApiClient(object): + def __init__(self, service): + self.service = service + + @tornado.gen.coroutine + def get(self, path, **kwargs): + return self._get_response('GET', path) + + @tornado.gen.coroutine + def put(self, path, **kwargs): + return self._get_response('PUT', path) + + @tornado.gen.coroutine + def patch(self, path, **kwargs): + return self._get_response('PATCH', path) + + @tornado.gen.coroutine + def post(self, path, **kwargs): + return self._get_response('POST', path) + + @tornado.gen.coroutine + def delete(self, path, **kwargs): + return self._get_response('DELETE', path) + + def _get_response(self, verb, path): + response = HTTPResponse(request=HTTPRequest(path, verb), code=200) + setattr(response, 'json', {}) + return response From 9527fa3abce92a8625066e7013c6fa594ce0def9 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 18 Jun 2018 10:44:51 -0400 Subject: [PATCH 3/4] Some cleanup, thanks to pylint --- atst/handler.py | 3 +-- atst/handlers/home.py | 1 - atst/handlers/main.py | 1 - atst/handlers/request_new.py | 1 + 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/atst/handler.py b/atst/handler.py index 637fdf35..afe80fa8 100644 --- a/atst/handler.py +++ b/atst/handler.py @@ -1,4 +1,3 @@ -import os from webassets import Environment, Bundle import tornado.web from atst.home import home @@ -29,7 +28,7 @@ class BaseHandler(tornado.web.RequestHandler): if self.get_secure_cookie('atst'): return True else: - False + return False # this is a temporary implementation until we have real sessions def _start_session(self): diff --git a/atst/handlers/home.py b/atst/handlers/home.py index d600dfaa..4ab45889 100644 --- a/atst/handlers/home.py +++ b/atst/handlers/home.py @@ -1,4 +1,3 @@ -import tornado from atst.handler import BaseHandler class Home(BaseHandler): diff --git a/atst/handlers/main.py b/atst/handlers/main.py index 71ff1395..98cf405d 100644 --- a/atst/handlers/main.py +++ b/atst/handlers/main.py @@ -1,4 +1,3 @@ -import atst import tornado from atst.handler import BaseHandler diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index 97edf84d..21a756d2 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -7,6 +7,7 @@ from atst.forms.readiness import ReadinessForm from atst.forms.review import ReviewForm import tornado.httputil + class RequestNew(BaseHandler): screens = [ { 'title' : 'Details of Use', From e48533441f20e33369a2fce504f14198f36dcbd2 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 18 Jun 2018 10:50:21 -0400 Subject: [PATCH 4/4] Consume requests client --- atst/handlers/request_new.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index 21a756d2..5b5f7f40 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -40,8 +40,9 @@ class RequestNew(BaseHandler): } ] - def initialize(self, page): + def initialize(self, page, requests_client): self.page = page + self.requests_client = requests_client @tornado.web.authenticated def post(self, screen = 1):