diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2147d201..74a61b9f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,18 +1,10 @@ repos: - - repo: https://github.com/PyCQA/isort - rev: 5.13.2 - hooks: - - id: isort - args: [ "." ] - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.0 - hooks: - - id: mypy - entry: mypy appium/ test/functional - pass_filenames: false - additional_dependencies: [types-python-dateutil==2.8.19.13] - - repo: https://github.com/psf/black - rev: 24.4.2 - hooks: - - id: black - args: [ ".", "-l", "120", "-S" ] +- repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.6.9 + hooks: + # Run the linter. + - id: ruff + args: [ --fix ] + # Run the formatter. + - id: ruff-format diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index c353824d..00000000 --- a/.pylintrc +++ /dev/null @@ -1,557 +0,0 @@ -[MASTER] - -# 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= - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=CVS - -# Add files or directories matching the regex patterns to the blacklist. The -# regex matches against base names, not paths. -ignore-patterns= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Use multiple processes to speed up Pylint. -jobs=1 - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - -# Pickle collected data for later comparisons. -persistent=yes - -# Specify a configuration file. -#rcfile= - -# When enabled, pylint would attempt to guess common misconfiguration and emit -# user-friendly hints instead of false-positive error messages -suggestion-mode=yes - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED -confidence= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -disable=print-statement, - parameter-unpacking, - unpacking-in-except, - old-raise-syntax, - backtick, - long-suffix, - old-ne-operator, - old-octal-literal, - import-star-module-level, - non-ascii-bytes-literal, - invalid-unicode-literal, - raw-checker-failed, - bad-inline-option, - locally-disabled, - locally-enabled, - file-ignored, - suppressed-message, - useless-suppression, - deprecated-pragma, - apply-builtin, - basestring-builtin, - buffer-builtin, - cmp-builtin, - coerce-builtin, - execfile-builtin, - file-builtin, - long-builtin, - raw_input-builtin, - reduce-builtin, - standarderror-builtin, - unicode-builtin, - xrange-builtin, - coerce-method, - delslice-method, - getslice-method, - setslice-method, - no-absolute-import, - old-division, - dict-iter-method, - dict-view-method, - next-method-called, - metaclass-assignment, - indexing-exception, - raising-string, - reload-builtin, - oct-method, - hex-method, - nonzero-method, - cmp-method, - input-builtin, - round-builtin, - intern-builtin, - unichr-builtin, - map-builtin-not-iterating, - zip-builtin-not-iterating, - range-builtin-not-iterating, - filter-builtin-not-iterating, - using-cmp-argument, - eq-without-hash, - div-method, - idiv-method, - rdiv-method, - exception-message-attribute, - invalid-str-codec, - sys-max-int, - bad-python3-import, - deprecated-string-function, - deprecated-str-translate-call, - deprecated-itertools-function, - deprecated-types-field, - next-method-defined, - dict-items-not-iterating, - dict-keys-not-iterating, - dict-values-not-iterating, - deprecated-operator-function, - deprecated-urllib-function, - xreadlines-attribute, - deprecated-sys-function, - exception-escape, - comprehension-escape, - empty-docstring, - missing-docstring, - too-few-public-methods, - invalid-name, - duplicate-code - -# 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 (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable=c-extension-no-member - - -[REPORTS] - -# 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= - -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio).You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Tells whether to display a full report or only the messages -reports=no - -# Activate the evaluation score. -score=yes - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - -# Complete name of functions that never returns. When checking for -# inconsistent-return-statements if a never returning function is called then -# it will be considered as an explicit return statement and no message will be -# printed. -never-returning-functions=optparse.Values,sys.exit - - -[LOGGING] - -# Logging modules to check that the string format arguments are in logging -# function parameter format -logging-modules=logging - - -[SPELLING] - -# Limits count of emitted suggestions for spelling mistakes -max-spelling-suggestions=4 - -# 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 - - -[SIMILARITIES] - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=no - -# Minimum lines number of a similarity. -min-similarity-lines=4 - - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# 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= - -# 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 - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local - -# 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= - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - - -[VARIABLES] - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# 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 - -# A regular expression matching the name of dummy variables (i.e. expectedly -# not used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.*|^ignored_|^unused_ - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,past.builtins,future.builtins,io,builtins - - -[FORMAT] - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Maximum number of characters on a single line. -max-line-length=128 - -# Maximum number of lines in a module -max-module-lines=1000 - -# 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 - -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no - -# 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 - - -[BASIC] - -# Naming style matching correct argument names -argument-naming-style=snake_case - -# Regular expression matching correct argument names. Overrides argument- -# naming-style -#argument-rgx= - -# Naming style matching correct attribute names -attr-naming-style=snake_case - -# Regular expression matching correct attribute names. Overrides attr-naming- -# style -#attr-rgx= - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo, - bar, - baz, - toto, - tutu, - tata - -# Naming style matching correct class attribute names -class-attribute-naming-style=any - -# Regular expression matching correct class attribute names. Overrides class- -# attribute-naming-style -#class-attribute-rgx= - -# Naming style matching correct class names -class-naming-style=PascalCase - -# Regular expression matching correct class names. Overrides class-naming-style -#class-rgx= - -# Naming style matching correct constant names -const-naming-style=UPPER_CASE - -# Regular expression matching correct constant names. Overrides const-naming- -# style -#const-rgx= - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - -# Naming style matching correct function names -function-naming-style=snake_case - -# Regular expression matching correct function names. Overrides function- -# naming-style -#function-rgx= - -# Good variable names which should always be accepted, separated by a comma -good-names=i, - j, - k, - ex, - Run, - _ - -# Include a hint for the correct naming format with invalid-name -include-naming-hint=no - -# Naming style matching correct inline iteration names -inlinevar-naming-style=any - -# Regular expression matching correct inline iteration names. Overrides -# inlinevar-naming-style -#inlinevar-rgx= - -# Naming style matching correct method names -method-naming-style=snake_case - -# Regular expression matching correct method names. Overrides method-naming- -# style -#method-rgx= - -# Naming style matching correct module names -module-naming-style=snake_case - -# Regular expression matching correct module names. Overrides module-naming- -# style -#module-rgx= - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ - -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -property-classes=abc.abstractproperty - -# Naming style matching correct variable names -variable-naming-style=snake_case - -# Regular expression matching correct variable names. Overrides variable- -# naming-style -#variable-rgx= - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=6 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Maximum number of boolean expressions in a if statement -max-bool-expr=5 - -# Maximum number of branch for function / method body -max-branches=12 - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of statements in function / method body -max-statements=50 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - - -[CLASSES] - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__, - __new__, - setUp - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict, - _fields, - _replace, - _source, - _make - -# 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 - - -[IMPORTS] - -# Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=yes - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub, - TERMIOS, - Bastion, - rexec - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# 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 internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception - -string-quote=single -triple-quote=single -docstring-quote=double diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 00000000..96cebc8f --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,31 @@ +line-length = 128 +indent-width = 4 + +[lint] +select = [ + # Pyflakes + "F", + # Pylint + "PL", + # isort + "I", +] + +[lint.per-file-ignores] +"__init__.py" = [ + # unused-import + "F401", + # import violations + "E402" +] +"**/{test,docs}/*" = [ + # https://docs.astral.sh/ruff/rules/magic-value-comparison/ + "PLR2004" +] + +[lint.pylint] + +max-args = 6 + +[format] +quote-style = "single" diff --git a/Makefile b/Makefile index e363d816..21fe11d1 100644 --- a/Makefile +++ b/Makefile @@ -5,22 +5,28 @@ check-all: ## Run all lint checks and unittest @echo "[Notice] If you'd like to run commands with same env to CI, please run \`tox\`." @bash ci.sh -.PHONY: isort -isort: ## Run isort - python -m isort --profile black $(ARGS) . - -.PHONY: black -black: ## Run black - python -m black $(ARGS) . -l 120 -S - -.PHONY: pylint -pylint: ## Run pylint - # TODO Remove --disable=E1136 when no errors in py39 - python -m pylint $(ARGS) --load-plugins pylint_quotes --rcfile .pylintrc appium test --disable=E1136 - -.PHONY: mypy -mypy: ## Run mypy - python -m mypy appium test/functional +.PHONY: check +check: check-lint check-format + +.PHONY: check-lint +check-lint: + python -m ruff check . + +.PHONY: check-format +check-format: + python -m ruff format --check . + +.PHONY: fix +fix: fix-lint fix-format + +.PHONY: fix-lint +fix-lint: + python -m ruff check --fix . + +.PHONY: fix-format +fix-format: + python -m ruff format . + .PHONY: unittest unittest: ## Run unittest diff --git a/Pipfile b/Pipfile index beea87df..eb26afaf 100644 --- a/Pipfile +++ b/Pipfile @@ -4,17 +4,13 @@ url = "https://pypi.org/simple" verify_ssl = true [dev-packages] -black = "<25.0.0" httpretty = "~=1.1" -isort = "<6.0" -mypy = "<2.0" mock = "~=5.1" pre-commit = "~=2.21" -pylint = "~=3.2.7" -pylint-quotes = "~=0.2.3" pytest = "~=8.3" pytest-cov = "~=5.0" python-dateutil = "~=2.9" +ruff = "~=0.6.9" tox = "~=4.21" types-python-dateutil = "~=2.9" diff --git a/README.md b/README.md index 44cf25a7..2b540d4f 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ [![Functional Tests](https://github.com/appium/python-client/actions/workflows/functional-test.yml/badge.svg)](https://github.com/appium/python-client/actions/workflows/functional-test.yml) -[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) - An extension library for adding [WebDriver Protocol](https://www.w3.org/TR/webdriver/) and Appium commands to the Selenium Python language binding for use with the mobile testing framework [Appium](https://appium.io). ## Getting the Appium Python client @@ -355,7 +353,7 @@ driver = webdriver.Remote(custom_executor, options=options) ## Development - Code Style: [PEP-0008](https://www.python.org/dev/peps/pep-0008/) - - Apply `black`, `isort` and `mypy` as pre commit hook + - Apply `ruff` as pre commit hook - Run `make` command for development. See `make help` output for details - Docstring style: [Google Style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) - `gitchangelog` generates `CHANGELOG.rst` diff --git a/appium/options/android/common/adb/adb_exec_timeout_option.py b/appium/options/android/common/adb/adb_exec_timeout_option.py index ec2d9322..f0ea5b80 100644 --- a/appium/options/android/common/adb/adb_exec_timeout_option.py +++ b/appium/options/android/common/adb/adb_exec_timeout_option.py @@ -38,6 +38,4 @@ def adb_exec_timeout(self, value: Union[timedelta, int]) -> None: Maximum time to wait until single ADB command is executed. 20000 ms by default. """ - self.set_capability( - ADB_EXEC_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value - ) + self.set_capability(ADB_EXEC_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value) diff --git a/appium/options/android/common/app/app_wait_duration_option.py b/appium/options/android/common/app/app_wait_duration_option.py index 82bba760..362cb372 100644 --- a/appium/options/android/common/app/app_wait_duration_option.py +++ b/appium/options/android/common/app/app_wait_duration_option.py @@ -38,6 +38,4 @@ def app_wait_duration(self, value: Union[timedelta, int]) -> None: Maximum amount of time to wait until the application under test is started (e.g. an activity returns the control to the caller). 20000 ms by default. """ - self.set_capability( - APP_WAIT_DURATION, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value - ) + self.set_capability(APP_WAIT_DURATION, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value) diff --git a/appium/options/android/common/avd/avd_launch_timeout_option.py b/appium/options/android/common/avd/avd_launch_timeout_option.py index d791c3a8..017396ef 100644 --- a/appium/options/android/common/avd/avd_launch_timeout_option.py +++ b/appium/options/android/common/avd/avd_launch_timeout_option.py @@ -38,6 +38,4 @@ def avd_launch_timeout(self, value: Union[timedelta, int]) -> None: Maximum timeout to wait until Android Emulator is started. 60000 ms by default. """ - self.set_capability( - AVD_LAUNCH_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value - ) + self.set_capability(AVD_LAUNCH_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value) diff --git a/appium/options/android/common/avd/avd_ready_timeout_option.py b/appium/options/android/common/avd/avd_ready_timeout_option.py index 2a56b45a..c074b319 100644 --- a/appium/options/android/common/avd/avd_ready_timeout_option.py +++ b/appium/options/android/common/avd/avd_ready_timeout_option.py @@ -38,6 +38,4 @@ def avd_ready_timeout(self, value: Union[timedelta, int]) -> None: Maximum timeout to wait until Android Emulator is fully booted and is ready for usage. 60000 ms by default """ - self.set_capability( - AVD_READY_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value - ) + self.set_capability(AVD_READY_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value) diff --git a/appium/options/android/common/context/auto_webview_timeout_option.py b/appium/options/android/common/context/auto_webview_timeout_option.py index c71e1efe..77457431 100644 --- a/appium/options/android/common/context/auto_webview_timeout_option.py +++ b/appium/options/android/common/context/auto_webview_timeout_option.py @@ -38,6 +38,4 @@ def auto_webview_timeout(self, value: Union[timedelta, int]) -> None: """ Timeout to wait until a web view is available. """ - self.set_capability( - AUTO_WEBVIEW_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value - ) + self.set_capability(AUTO_WEBVIEW_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value) diff --git a/appium/options/android/espresso/espresso_build_config_option.py b/appium/options/android/espresso/espresso_build_config_option.py index 41586a99..7a8694f3 100644 --- a/appium/options/android/espresso/espresso_build_config_option.py +++ b/appium/options/android/espresso/espresso_build_config_option.py @@ -43,6 +43,4 @@ def espresso_build_config(self, value: Union[Dict[str, Any], str]) -> None: https://github.com/appium/appium-espresso-driver#espresso-build-config for more information on how to properly construct such config. """ - self.set_capability( - ESPRESSO_BUILD_CONFIG, value if isinstance(value, str) else json.dumps(value, ensure_ascii=False) - ) + self.set_capability(ESPRESSO_BUILD_CONFIG, value if isinstance(value, str) else json.dumps(value, ensure_ascii=False)) diff --git a/appium/options/flutter_integration/base.py b/appium/options/flutter_integration/base.py index 65d1c19a..f67b9a93 100644 --- a/appium/options/flutter_integration/base.py +++ b/appium/options/flutter_integration/base.py @@ -32,7 +32,6 @@ class FlutterOptions( FlutterServerLaunchTimeOutOption, FlutterSystemPortOption, ): - @property def default_capabilities(self) -> Dict: return { diff --git a/appium/options/flutter_integration/flutter_element_wait_timeout_option.py b/appium/options/flutter_integration/flutter_element_wait_timeout_option.py index 6f6b2ae9..bd427977 100644 --- a/appium/options/flutter_integration/flutter_element_wait_timeout_option.py +++ b/appium/options/flutter_integration/flutter_element_wait_timeout_option.py @@ -24,7 +24,6 @@ class FlutterElementWaitTimeOutOption(SupportsCapabilities): - @property def flutter_element_wait_timeout(self) -> Optional[timedelta]: """ diff --git a/appium/options/flutter_integration/flutter_enable_mock_camera_option.py b/appium/options/flutter_integration/flutter_enable_mock_camera_option.py index 7b335b25..b90cb001 100644 --- a/appium/options/flutter_integration/flutter_enable_mock_camera_option.py +++ b/appium/options/flutter_integration/flutter_enable_mock_camera_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -23,7 +22,6 @@ class FlutterEnableMockCameraOption(SupportsCapabilities): - @property def flutter_enable_mock_camera(self) -> bool: """ diff --git a/appium/options/flutter_integration/flutter_server_launch_timeout_option.py b/appium/options/flutter_integration/flutter_server_launch_timeout_option.py index 8f8bea4e..32cea2f9 100644 --- a/appium/options/flutter_integration/flutter_server_launch_timeout_option.py +++ b/appium/options/flutter_integration/flutter_server_launch_timeout_option.py @@ -24,7 +24,6 @@ class FlutterServerLaunchTimeOutOption(SupportsCapabilities): - @property def flutter_server_launch_timeout(self) -> Optional[timedelta]: """ diff --git a/appium/options/flutter_integration/flutter_system_port_option.py b/appium/options/flutter_integration/flutter_system_port_option.py index 2e049dd7..db7ab7f5 100644 --- a/appium/options/flutter_integration/flutter_system_port_option.py +++ b/appium/options/flutter_integration/flutter_system_port_option.py @@ -23,7 +23,6 @@ class FlutterSystemPortOption(SupportsCapabilities): - @property def flutter_system_port(self) -> Optional[int]: """ diff --git a/appium/options/ios/xcuitest/app/app_push_timeout_option.py b/appium/options/ios/xcuitest/app/app_push_timeout_option.py index 261265d1..3f49bde9 100644 --- a/appium/options/ios/xcuitest/app/app_push_timeout_option.py +++ b/appium/options/ios/xcuitest/app/app_push_timeout_option.py @@ -39,6 +39,4 @@ def app_push_timeout(self, value: Union[timedelta, int]) -> None: Works for real devices only. The default value is 30000ms. """ - self.set_capability( - APP_PUSH_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value - ) + self.set_capability(APP_PUSH_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value) diff --git a/appium/options/ios/xcuitest/wda/wda_launch_timeout_option.py b/appium/options/ios/xcuitest/wda/wda_launch_timeout_option.py index 035cdb40..325b7e40 100644 --- a/appium/options/ios/xcuitest/wda/wda_launch_timeout_option.py +++ b/appium/options/ios/xcuitest/wda/wda_launch_timeout_option.py @@ -38,6 +38,4 @@ def wda_launch_timeout(self, value: Union[timedelta, int]) -> None: Timeout to wait for WebDriverAgent to be pingable, after its building is finished. Defaults to 60000ms. """ - self.set_capability( - WDA_LAUNCH_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value - ) + self.set_capability(WDA_LAUNCH_TIMEOUT, int(value.total_seconds() * 1000) if isinstance(value, timedelta) else value) diff --git a/appium/webdriver/appium_service.py b/appium/webdriver/appium_service.py index c84bfeda..5907119a 100644 --- a/appium/webdriver/appium_service.py +++ b/appium/webdriver/appium_service.py @@ -28,6 +28,7 @@ MAIN_SCRIPT_PATH = 'appium/build/lib/main.js' STATUS_URL = '/status' DEFAULT_BASE_PATH = '/' +HTTP_STATUS_ERROR = 400 class AppiumServiceError(RuntimeError): @@ -97,7 +98,7 @@ def start(self, **kwargs: Any) -> sp.Popen: error_msg: Optional[str] = None startup_failure_msg = ( 'Appium server process is unable to start. Make sure proper values have been ' - f'provided to \'node\' ({node}), \'npm\' ({npm}) and \'main_script\' ({main_script}) ' + f"provided to 'node' ({node}), 'npm' ({npm}) and 'main_script' ({main_script}) " f'method arguments.' ) if timeout_ms > 0: @@ -206,7 +207,7 @@ def is_service_listening(url: str, timeout: float = 5, custom_validator: Optiona # noinspection PyUnresolvedReferences try: resp = conn.request('HEAD', url) - if resp.status < 400: + if resp.status < HTTP_STATUS_ERROR: return True except urllib3.exceptions.HTTPError: pass @@ -235,9 +236,7 @@ def find_executable(executable: str) -> Optional[str]: def get_node() -> str: result = find_executable('node') if result is None: - raise AppiumServiceError( - 'NodeJS main executable cannot be found. Make sure it is installed and present in PATH' - ) + raise AppiumServiceError('NodeJS main executable cannot be found. Make sure it is installed and present in PATH') return result diff --git a/appium/webdriver/extensions/device_time.py b/appium/webdriver/extensions/device_time.py index a81717eb..62de92b4 100644 --- a/appium/webdriver/extensions/device_time.py +++ b/appium/webdriver/extensions/device_time.py @@ -60,9 +60,7 @@ def get_device_time(self, format: Optional[str] = None) -> str: try: return self.assert_extension_exists(ext_name).execute_script(ext_name, {'format': format}) except UnknownMethodException: - return self.mark_extension_absence(ext_name).execute(Command.GET_DEVICE_TIME_POST, {'format': format})[ - 'value' - ] + return self.mark_extension_absence(ext_name).execute(Command.GET_DEVICE_TIME_POST, {'format': format})['value'] def _add_commands(self) -> None: # noinspection PyProtectedMember,PyUnresolvedReferences diff --git a/appium/webdriver/extensions/flutter_integration/flutter_commands.py b/appium/webdriver/extensions/flutter_integration/flutter_commands.py index fa9dcaee..1830d0a2 100644 --- a/appium/webdriver/extensions/flutter_integration/flutter_commands.py +++ b/appium/webdriver/extensions/flutter_integration/flutter_commands.py @@ -23,7 +23,6 @@ class FlutterCommand: - def __init__(self, driver: WebDriver) -> None: self.driver = driver @@ -84,7 +83,7 @@ def perform_double_click(self, element: WebElement, offset: Optional[Tuple[int, Returns: None: """ - opts: Dict[str, Union[WebElement, Dict[str, int]]] = {"origin": element} + opts: Dict[str, Union[WebElement, Dict[str, int]]] = {'origin': element} if offset is not None: opts['offset'] = {'x': offset[0], 'y': offset[1]} self.execute_flutter_command('doubleClick', opts) diff --git a/appium/webdriver/extensions/flutter_integration/flutter_finder.py b/appium/webdriver/extensions/flutter_integration/flutter_finder.py index 5243ee94..473976ba 100644 --- a/appium/webdriver/extensions/flutter_integration/flutter_finder.py +++ b/appium/webdriver/extensions/flutter_integration/flutter_finder.py @@ -21,7 +21,6 @@ class FlutterFinder: - def __init__(self, using: str, value: str) -> None: self.using = using self.value = value diff --git a/appium/webdriver/extensions/images_comparison.py b/appium/webdriver/extensions/images_comparison.py index 5d4778af..6913c3fd 100644 --- a/appium/webdriver/extensions/images_comparison.py +++ b/appium/webdriver/extensions/images_comparison.py @@ -103,9 +103,7 @@ def find_image_occurrence( } return self.execute(Command.COMPARE_IMAGES, options)['value'] - def get_images_similarity( - self, base64_image1: bytes, base64_image2: bytes, **opts: Any - ) -> Dict[str, Union[bytes, Dict]]: + def get_images_similarity(self, base64_image1: bytes, base64_image2: bytes, **opts: Any) -> Dict[str, Union[bytes, Dict]]: """Performs images matching to calculate the similarity score between them. The flow there is similar to the one used in diff --git a/appium/webdriver/extensions/keyboard.py b/appium/webdriver/extensions/keyboard.py index 789238f9..fe833ef7 100644 --- a/appium/webdriver/extensions/keyboard.py +++ b/appium/webdriver/extensions/keyboard.py @@ -25,9 +25,7 @@ class Keyboard(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): - def hide_keyboard( - self, key_name: Optional[str] = None, key: Optional[str] = None, strategy: Optional[str] = None - ) -> Self: + def hide_keyboard(self, key_name: Optional[str] = None, key: Optional[str] = None, strategy: Optional[str] = None) -> Self: """Hides the software keyboard on the device. In iOS, use `key_name` to press diff --git a/appium/webdriver/extensions/location.py b/appium/webdriver/extensions/location.py index 4e85ae0f..93a75ca7 100644 --- a/appium/webdriver/extensions/location.py +++ b/appium/webdriver/extensions/location.py @@ -85,7 +85,7 @@ def location(self) -> Dict[str, float]: - longitude (float) - altitude (float) """ - return self.execute(Command.GET_LOCATION)['value'] # pylint: disable=unsubscriptable-object + return self.execute(Command.GET_LOCATION)['value'] def _add_commands(self) -> None: """Add location endpoints. They are not int w3c spec.""" diff --git a/appium/webdriver/extensions/remote_fs.py b/appium/webdriver/extensions/remote_fs.py index 79026791..e7a7fa1e 100644 --- a/appium/webdriver/extensions/remote_fs.py +++ b/appium/webdriver/extensions/remote_fs.py @@ -58,9 +58,7 @@ def pull_folder(self, path: str) -> str: # TODO: Remove the fallback return self.mark_extension_absence(ext_name).execute(Command.PULL_FOLDER, {'path': path})['value'] - def push_file( - self, destination_path: str, base64data: Optional[str] = None, source_path: Optional[str] = None - ) -> Self: + def push_file(self, destination_path: str, base64data: Optional[str] = None, source_path: Optional[str] = None) -> Self: """Puts the data from the file at `source_path`, encoded as Base64, in the file specified as `path`. Specify either `base64data` or `source_path`, if both specified default to `source_path` diff --git a/appium/webdriver/webdriver.py b/appium/webdriver/webdriver.py index f4ae7ad5..d292c0ac 100644 --- a/appium/webdriver/webdriver.py +++ b/appium/webdriver/webdriver.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=too-many-lines,too-many-public-methods,too-many-statements,no-self-use - from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union from selenium import webdriver @@ -212,11 +210,9 @@ def __init__( options: Union[AppiumOptions, List[AppiumOptions], None] = None, ): if strict_ssl is False: - # pylint: disable=E1101 # noinspection PyPackageRequirements import urllib3 - # pylint: disable=E1101 # noinspection PyPackageRequirements import urllib3.exceptions @@ -256,7 +252,7 @@ def __init__( instance = extension(self.execute) method_name = instance.method_name() if hasattr(WebDriver, method_name): - logger.debug(f'Overriding the method \'{method_name}\'') + logger.debug(f"Overriding the method '{method_name}'") # add a new method named 'instance.method_name()' and call it setattr(WebDriver, method_name, getattr(instance, method_name)) @@ -382,9 +378,7 @@ def find_element(self, by: str = AppiumBy.ID, value: Union[str, Dict, None] = No return self.execute(RemoteCommand.FIND_ELEMENT, {'using': by, 'value': value})['value'] - def find_elements( - self, by: str = AppiumBy.ID, value: Union[str, Dict, None] = None - ) -> Union[List[MobileWebElement], List]: + def find_elements(self, by: str = AppiumBy.ID, value: Union[str, Dict, None] = None) -> Union[List[MobileWebElement], List]: """ Find elements given a AppiumBy strategy and locator @@ -471,7 +465,7 @@ def orientation(self, value: str) -> None: if value.upper() in allowed_values: self.execute(Command.SET_SCREEN_ORIENTATION, {'orientation': value}) else: - raise WebDriverException('You can only set the orientation to \'LANDSCAPE\' and \'PORTRAIT\'') + raise WebDriverException("You can only set the orientation to 'LANDSCAPE' and 'PORTRAIT'") def assert_extension_exists(self, ext_name: str) -> Self: """ diff --git a/ci.sh b/ci.sh index 2aff764d..be2986f9 100755 --- a/ci.sh +++ b/ci.sh @@ -2,27 +2,16 @@ EXIT_STATUS=0 -if ! make black ARGS=--check ; then - echo "Please run command 'make black' on your local and commit the result" +if ! make check-lint ; then + echo "Please run command 'make fix' or 'make fix-lint' on your local and commit the result" EXIT_STATUS=1 fi -if ! make isort ARGS=--check-only ; then - echo "Please run command 'make isort' on your local and commit the result" +if ! make check-format ; then + echo "Please run command 'make fix' or 'make fix-format' on your local and commit the result" EXIT_STATUS=1 fi - -if ! make pylint ; then - echo "Please run command 'make pylint' on your local and fix errors" - # TODO: pylint erroneously complains about many things it should not complain about - # EXIT_STATUS=1 -fi - if ! make unittest ARGS=--junitxml=./test/unit/junit.xml ; then EXIT_STATUS=1 fi -if ! make mypy ; then - EXIT_STATUS=1 -fi - exit $EXIT_STATUS diff --git a/script/release.py b/script/release.py index 54a84b0c..ffab74f2 100644 --- a/script/release.py +++ b/script/release.py @@ -33,9 +33,7 @@ def get_current_version(): - current = ( - io.open(os.path.join(os.path.dirname('__file__'), 'appium', 'version.py'), encoding='utf-8').read().rstrip() - ) + current = io.open(os.path.join(os.path.dirname('__file__'), 'appium', 'version.py'), encoding='utf-8').read().rstrip() print('The current version is {}, type a new one'.format(MESSAGE_YELLOW.format(current))) return current @@ -78,8 +76,9 @@ def upload_sdist(new_version_num): call_bash_script('twine upload "{}"'.format(push_file)) except Exception as e: print( - 'Failed to upload {} to pypi. ' - 'Please fix the original error and push it again later. Original error: {}'.format(push_file, e) + 'Failed to upload {} to pypi. ' 'Please fix the original error and push it again later. Original error: {}'.format( + push_file, e + ) ) @@ -96,7 +95,7 @@ def ensure_publication(new_version_num): for line in sys.stdin: if line.rstrip().lower() == 'y': return - exit('Canceled release process.') + sys.exit('Canceled release process.') def build_sdist(): @@ -105,9 +104,9 @@ def build_sdist(): def validate_release_env(): if os.system('which twine') != 0: - exit("Please get twine via 'pip install twine'") + sys.exit("Please get twine via 'pip install twine'") if os.system('which gitchangelog') != 0: - exit( + sys.exit( "Please get twine via 'pip install gitchangelog' or 'pip install git+git://github.com/vaab/gitchangelog.git' for Python 3.7" ) @@ -116,14 +115,13 @@ def build() -> None: shutil.rmtree(BUILT_APPIUM_DIR_PATH, ignore_errors=True) status, output = subprocess.getstatusoutput('{} setup.py install'.format(os.getenv('PYTHON_BIN_PATH'))) if status != 0: - exit(f'Failed to build the package:\n{output}') + sys.exit(f'Failed to build the package:\n{output}') def get_py_files_in_dir(root_dir: str) -> List[str]: return [ file_path[len(root_dir) :] - for file_path in glob.glob(f"{root_dir}/**/*.py", recursive=True) - + glob.glob(f"{root_dir}/**/*.typed", recursive=True) + for file_path in glob.glob(f'{root_dir}/**/*.py', recursive=True) + glob.glob(f'{root_dir}/**/*.typed', recursive=True) ] @@ -142,11 +140,11 @@ def assert_files_count_in_package() -> None: print(f"'{APPIUM_DIR_PATH}' has '{diff}' files than {BUILT_APPIUM_DIR_PATH}") diff = built_files_set.difference(original_files_set) if diff: - print(f"{BUILT_APPIUM_DIR_PATH} has {diff} files than {APPIUM_DIR_PATH}") + print(f'{BUILT_APPIUM_DIR_PATH} has {diff} files than {APPIUM_DIR_PATH}') - exit( + sys.exit( f"Python files in '{BUILT_APPIUM_DIR_PATH}' may differ from '{APPIUM_DIR_PATH}'. " - "Please make sure setup.py is configured properly." + 'Please make sure setup.py is configured properly.' ) diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 347162f5..00000000 --- a/setup.cfg +++ /dev/null @@ -1,19 +0,0 @@ -[isort] -known_third_party = dateutil,httpretty,pytest,selenium,setuptools,urllib3,mock,sauceclient -known_first_party = test,appium -multi_line_output = 3 -include_trailing_comma = True -force_grid_wrap = 0 -use_parentheses = True -ensure_newline_before_comments = True -line_length = 120 - -[mypy] -check_untyped_defs = True -disallow_untyped_calls = True -disallow_untyped_defs = True -follow_imports = skip -ignore_missing_imports = True -strict_optional = True -warn_redundant_casts = True -warn_unused_ignores = False diff --git a/test/functional/flutter_integration/commands_test.py b/test/functional/flutter_integration/commands_test.py index 010c0f8c..f256222e 100644 --- a/test/functional/flutter_integration/commands_test.py +++ b/test/functional/flutter_integration/commands_test.py @@ -21,7 +21,6 @@ class TestFlutterCommands(BaseTestCase): - def test_wait_command(self) -> None: self.__open_screen('Lazy Loading') @@ -76,22 +75,20 @@ def test_scroll_till_visible_with_scroll_params_command(self) -> None: def test_double_click_command(self) -> None: self.__open_screen('Double Tap') - double_tap_button = self.driver.find_element( - AppiumBy.FLUTTER_INTEGRATION_KEY, 'double_tap_button' - ).find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Double Tap') + double_tap_button = self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'double_tap_button').find_element( + AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Double Tap' + ) assert double_tap_button.text == 'Double Tap' self.flutter_command.perform_double_click(double_tap_button) assert ( - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING, 'Successful').text - == 'Double Tap Successful' + self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING, 'Successful').text == 'Double Tap Successful' ) self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Ok').click() self.flutter_command.perform_double_click(double_tap_button, (10, 2)) assert ( - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING, 'Successful').text - == 'Double Tap Successful' + self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING, 'Successful').text == 'Double Tap Successful' ) self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Ok').click() diff --git a/test/functional/flutter_integration/finder_test.py b/test/functional/flutter_integration/finder_test.py index c5faf262..d9bc3f56 100644 --- a/test/functional/flutter_integration/finder_test.py +++ b/test/functional/flutter_integration/finder_test.py @@ -16,11 +16,10 @@ from appium.webdriver.extensions.flutter_integration.flutter_finder import FlutterFinder from test.functional.flutter_integration.helper.test_helper import BaseTestCase -LOGIN_BUTTON_FINDER = FlutterFinder.by_text("Login") +LOGIN_BUTTON_FINDER = FlutterFinder.by_text('Login') class TestFlutterFinders(BaseTestCase): - def test_by_flutter_key(self) -> None: user_name_field_finder = FlutterFinder.by_key('username_text_field') user_name_field = self.driver.find_element(*user_name_field_finder.as_args()) diff --git a/test/functional/flutter_integration/helper/test_helper.py b/test/functional/flutter_integration/helper/test_helper.py index 1cc8e364..7521fb76 100644 --- a/test/functional/flutter_integration/helper/test_helper.py +++ b/test/functional/flutter_integration/helper/test_helper.py @@ -12,20 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -import base64 import os from appium import webdriver from appium.options.flutter_integration.base import FlutterOptions from appium.webdriver.extensions.flutter_integration.flutter_commands import FlutterCommand -from test.functional.test_helper import is_ci from test.helpers.constants import SERVER_URL_BASE from . import desired_capabilities class BaseTestCase(object): - def setup_method(self) -> None: platform_name = os.getenv('PLATFORM', 'android').lower() diff --git a/test/functional/mac/helper/test_helper.py b/test/functional/mac/helper/test_helper.py index 1e5e4c3b..b7640941 100644 --- a/test/functional/mac/helper/test_helper.py +++ b/test/functional/mac/helper/test_helper.py @@ -21,9 +21,7 @@ class BaseTestCase(object): def setup_method(self) -> None: - self.driver = webdriver.Remote( - SERVER_URL_BASE, options=Mac2Options().load_capabilities(get_desired_capabilities()) - ) + self.driver = webdriver.Remote(SERVER_URL_BASE, options=Mac2Options().load_capabilities(get_desired_capabilities())) def teardown_method(self, method) -> None: # type: ignore if not hasattr(self, 'driver'): diff --git a/test/unit/helper/test_helper.py b/test/unit/helper/test_helper.py index 3061ef1f..58e35817 100644 --- a/test/unit/helper/test_helper.py +++ b/test/unit/helper/test_helper.py @@ -146,9 +146,7 @@ def ios_w3c_driver_with_extensions(extensions) -> 'WebDriver': 'automationName': 'XCUITest', } - driver = webdriver.Remote( - SERVER_URL_BASE, options=XCUITestOptions().load_capabilities(desired_caps), extensions=extensions - ) + driver = webdriver.Remote(SERVER_URL_BASE, options=XCUITestOptions().load_capabilities(desired_caps), extensions=extensions) return driver diff --git a/test/unit/webdriver/app_test.py b/test/unit/webdriver/app_test.py index 6fa773ee..13f10809 100644 --- a/test/unit/webdriver/app_test.py +++ b/test/unit/webdriver/app_test.py @@ -47,10 +47,8 @@ def test_remove_app(self): @httpretty.activate def test_app_installed(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}' - ) - result = driver.is_app_installed("com.app.id") + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') + result = driver.is_app_installed('com.app.id') assert { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], @@ -61,10 +59,8 @@ def test_app_installed(self): @httpretty.activate def test_terminate_app(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}' - ) - result = driver.terminate_app("com.app.id") + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') + result = driver.terminate_app('com.app.id') assert { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], @@ -76,7 +72,7 @@ def test_terminate_app(self): def test_activate_app(self): driver = android_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') - result = driver.activate_app("com.app.id") + result = driver.activate_app('com.app.id') assert { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], @@ -118,7 +114,7 @@ def test_app_strings(self): result = driver.app_strings() assert {'args': [{}], 'script': 'mobile: getAppStrings'} == get_httpretty_request_body(httpretty.last_request()) - assert 'You can\'t wipe my data, you are a monkey!' == result['monkey_wipe_data'], result + assert "You can't wipe my data, you are a monkey!" == result['monkey_wipe_data'], result @httpretty.activate def test_app_strings_with_lang(self): @@ -133,7 +129,7 @@ def test_app_strings_with_lang(self): assert {'args': [{'language': 'en'}], 'script': 'mobile: getAppStrings'} == get_httpretty_request_body( httpretty.last_request() ) - assert 'You can\'t wipe my data, you are a monkey!' == result['monkey_wipe_data'], result + assert "You can't wipe my data, you are a monkey!" == result['monkey_wipe_data'], result @httpretty.activate def test_app_strings_with_lang_and_file(self): @@ -149,7 +145,7 @@ def test_app_strings_with_lang_and_file(self): 'args': [{'language': 'en', 'stringFile': 'some_file'}], 'script': 'mobile: getAppStrings', } == get_httpretty_request_body(httpretty.last_request()) - assert 'You can\'t wipe my data, you are a monkey!' == result['monkey_wipe_data'], result + assert "You can't wipe my data, you are a monkey!" == result['monkey_wipe_data'], result class TestWebDriverAppIOS(object): @@ -180,10 +176,8 @@ def test_remove_app(self): @httpretty.activate def test_app_installed(self): driver = ios_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}' - ) - result = driver.is_app_installed("com.app.id") + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') + result = driver.is_app_installed('com.app.id') assert { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], @@ -194,10 +188,8 @@ def test_app_installed(self): @httpretty.activate def test_terminate_app(self): driver = ios_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}' - ) - result = driver.terminate_app("com.app.id") + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') + result = driver.terminate_app('com.app.id') assert { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], @@ -209,7 +201,7 @@ def test_terminate_app(self): def test_activate_app(self): driver = ios_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') - result = driver.activate_app("com.app.id") + result = driver.activate_app('com.app.id') assert { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], @@ -251,7 +243,7 @@ def test_app_strings(self): result = driver.app_strings() assert {'args': [{}], 'script': 'mobile: getAppStrings'} == get_httpretty_request_body(httpretty.last_request()) - assert 'You can\'t wipe my data, you are a monkey!' == result['monkey_wipe_data'], result + assert "You can't wipe my data, you are a monkey!" == result['monkey_wipe_data'], result @httpretty.activate def test_app_strings_with_lang(self): @@ -266,7 +258,7 @@ def test_app_strings_with_lang(self): assert {'args': [{'language': 'en'}], 'script': 'mobile: getAppStrings'} == get_httpretty_request_body( httpretty.last_request() ) - assert 'You can\'t wipe my data, you are a monkey!' == result['monkey_wipe_data'], result + assert "You can't wipe my data, you are a monkey!" == result['monkey_wipe_data'], result @httpretty.activate def test_app_strings_with_lang_and_file(self): @@ -282,4 +274,4 @@ def test_app_strings_with_lang_and_file(self): 'args': [{'language': 'en', 'stringFile': 'some_file'}], 'script': 'mobile: getAppStrings', } == get_httpretty_request_body(httpretty.last_request()) - assert 'You can\'t wipe my data, you are a monkey!' == result['monkey_wipe_data'], result + assert "You can't wipe my data, you are a monkey!" == result['monkey_wipe_data'], result diff --git a/test/unit/webdriver/context_test.py b/test/unit/webdriver/context_test.py index 5352dee3..80c2c0f7 100644 --- a/test/unit/webdriver/context_test.py +++ b/test/unit/webdriver/context_test.py @@ -21,9 +21,7 @@ class TestWebDriverContext(object): @httpretty.activate def test_current_contexts(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.GET, appium_command('/session/1234567890/context'), body='{"value": "NATIVE_APP"}' - ) + httpretty.register_uri(httpretty.GET, appium_command('/session/1234567890/context'), body='{"value": "NATIVE_APP"}') assert driver.current_context == 'NATIVE_APP' @httpretty.activate diff --git a/test/unit/webdriver/device/common_test.py b/test/unit/webdriver/device/common_test.py index 7bf99153..43b069a0 100644 --- a/test/unit/webdriver/device/common_test.py +++ b/test/unit/webdriver/device/common_test.py @@ -24,9 +24,7 @@ def test_open_notifications(self): driver = android_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.open_notifications(), WebDriver) - assert {'args': [], 'script': 'mobile: openNotifications'} == get_httpretty_request_body( - httpretty.last_request() - ) + assert {'args': [], 'script': 'mobile: openNotifications'} == get_httpretty_request_body(httpretty.last_request()) @httpretty.activate def test_current_package(self): diff --git a/test/unit/webdriver/device/display_test.py b/test/unit/webdriver/device/display_test.py index 96adab42..bce0b4e4 100644 --- a/test/unit/webdriver/device/display_test.py +++ b/test/unit/webdriver/device/display_test.py @@ -24,7 +24,5 @@ def test_get_display_density(self): httpretty.register_uri( httpretty.GET, appium_command('/session/1234567890/appium/device/display_density'), body='{"value": 560}' ) - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": 560}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": 560}') assert driver.get_display_density() == 560 diff --git a/test/unit/webdriver/device/keyboard_test.py b/test/unit/webdriver/device/keyboard_test.py index 40e3e289..526f1826 100644 --- a/test/unit/webdriver/device/keyboard_test.py +++ b/test/unit/webdriver/device/keyboard_test.py @@ -32,9 +32,7 @@ def test_press_keycode(self): httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/appium/device/press_keycode'), body='{"value": "86"}' ) - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": "86"}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": "86"}') driver.press_keycode(86) d = get_httpretty_request_body((httpretty.last_request())) assert d.get('keycode', d['args'][0]['keycode']) == 86 @@ -47,9 +45,7 @@ def test_long_press_keycode(self): appium_command('/session/1234567890/appium/device/long_press_keycode'), body='{"value": "86"}', ) - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": "86"}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": "86"}') driver.long_press_keycode(86) d = get_httpretty_request_body((httpretty.last_request())) assert d.get('keycode', d['args'][0]['keycode']) == 86 @@ -60,9 +56,7 @@ def test_keyevent(self): httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/appium/device/keyevent'), body='{keycode: 86}' ) - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": "86"}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": "86"}') assert isinstance(driver.keyevent(86), WebDriver) @httpretty.activate diff --git a/test/unit/webdriver/device/location_test.py b/test/unit/webdriver/device/location_test.py index 512bdb95..fb0112bc 100644 --- a/test/unit/webdriver/device/location_test.py +++ b/test/unit/webdriver/device/location_test.py @@ -24,9 +24,7 @@ class TestWebDriverLocation(object): @httpretty.activate def test_toggle_location_services(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/toggle_location_services') - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/toggle_location_services')) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.toggle_location_services(), WebDriver) diff --git a/test/unit/webdriver/device/lock_test.py b/test/unit/webdriver/device/lock_test.py index 7a357a70..b5469854 100644 --- a/test/unit/webdriver/device/lock_test.py +++ b/test/unit/webdriver/device/lock_test.py @@ -22,9 +22,7 @@ class TestWebDriverLockAndroid(object): @httpretty.activate def test_lock(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}') httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') driver.lock(1) @@ -34,9 +32,7 @@ def test_lock(self): @httpretty.activate def test_lock_no_args(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}') httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') driver.lock() @@ -46,9 +42,7 @@ def test_islocked_false(self): httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/appium/device/is_locked'), body='{"value": false}' ) - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": false}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": false}') assert driver.is_locked() is False @httpretty.activate @@ -57,9 +51,7 @@ def test_islocked_true(self): httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/appium/device/is_locked'), body='{"value": true}' ) - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') assert driver.is_locked() is True @httpretty.activate @@ -77,9 +69,7 @@ class TestWebDriverLockIOS(object): @httpretty.activate def test_lock(self): driver = ios_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}') httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') driver.lock(1) @@ -89,9 +79,7 @@ def test_lock(self): @httpretty.activate def test_lock_no_args(self): driver = ios_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}') httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') driver.lock() @@ -101,9 +89,7 @@ def test_islocked_false(self): httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/appium/device/is_locked'), body='{"value": false}' ) - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": false}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": false}') assert driver.is_locked() is False @httpretty.activate @@ -112,9 +98,7 @@ def test_islocked_true(self): httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/appium/device/is_locked'), body='{"value": true}' ) - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') assert driver.is_locked() is True @httpretty.activate @@ -138,7 +122,7 @@ def test_touch_id(self): } == get_httpretty_request_body(httpretty.last_request()) @httpretty.activate - def test_touch_id(self): + def test_enroll_biometric(self): driver = ios_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.toggle_touch_id_enrollment(), WebDriver) diff --git a/test/unit/webdriver/device/system_bars_test.py b/test/unit/webdriver/device/system_bars_test.py index 2706be3d..79e7c680 100644 --- a/test/unit/webdriver/device/system_bars_test.py +++ b/test/unit/webdriver/device/system_bars_test.py @@ -21,11 +21,11 @@ class TestWebDriverSystemBars(object): @httpretty.activate def test_get_system_bars(self): driver = android_w3c_driver() - body = '''{"value": + body = """{"value": {"statusBar": {"visible": true, "x": 0, "y": 0, "width": 1080, "height": 1920}, "navigationBar": - {"visible": true, "x": 0, "y": 0, "width": 1080, "height": 126}}}''' + {"visible": true, "x": 0, "y": 0, "width": 1080, "height": 126}}}""" httpretty.register_uri( httpretty.GET, appium_command('/session/1234567890/appium/device/system_bars'), diff --git a/test/unit/webdriver/flutter_integration/flutter_actions_test.py b/test/unit/webdriver/flutter_integration/flutter_actions_test.py index 2a21b60c..50a42e59 100644 --- a/test/unit/webdriver/flutter_integration/flutter_actions_test.py +++ b/test/unit/webdriver/flutter_integration/flutter_actions_test.py @@ -25,7 +25,6 @@ class TestFlutterActions(object): - @httpretty.activate def test_double_click(self): driver = flutter_w3c_driver() diff --git a/test/unit/webdriver/flutter_integration/flutter_integration_driver_test.py b/test/unit/webdriver/flutter_integration/flutter_integration_driver_test.py index 2e3aa481..0e97d81c 100644 --- a/test/unit/webdriver/flutter_integration/flutter_integration_driver_test.py +++ b/test/unit/webdriver/flutter_integration/flutter_integration_driver_test.py @@ -22,10 +22,8 @@ class TestFlutterIntegrationDriver: - @httpretty.activate def test_create_session(self): - # Set flutter options flutterOptions = FlutterOptions() flutterOptions.flutter_system_port = 9999 diff --git a/test/unit/webdriver/flutter_integration/flutter_search_context_test.py b/test/unit/webdriver/flutter_integration/flutter_search_context_test.py index e0d20bd0..36e37843 100644 --- a/test/unit/webdriver/flutter_integration/flutter_search_context_test.py +++ b/test/unit/webdriver/flutter_integration/flutter_search_context_test.py @@ -19,7 +19,6 @@ class TestFlutterSearchContext(object): - @httpretty.activate def test_find_element_by_flutter_key(self): driver = flutter_w3c_driver() diff --git a/test/unit/webdriver/flutter_integration/flutter_waits_test.py b/test/unit/webdriver/flutter_integration/flutter_waits_test.py index 338952e2..62f9f7c1 100644 --- a/test/unit/webdriver/flutter_integration/flutter_waits_test.py +++ b/test/unit/webdriver/flutter_integration/flutter_waits_test.py @@ -21,7 +21,6 @@ class TestFlutterWaits(object): - @httpretty.activate def test_wait_for_visible_with_finder(self): driver = flutter_w3c_driver() diff --git a/test/unit/webdriver/log_events_test.py b/test/unit/webdriver/log_events_test.py index 6da85d63..14d41442 100644 --- a/test/unit/webdriver/log_events_test.py +++ b/test/unit/webdriver/log_events_test.py @@ -53,7 +53,7 @@ def test_get_events_args(self): @httpretty.activate def test_log_event(self): driver = ios_w3c_driver() - httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/log_event'), body="") + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/log_event'), body='') vendor_name = 'appium' event_name = 'funEvent' assert isinstance(driver.log_event(vendor_name, event_name), WebDriver) diff --git a/test/unit/webdriver/network_test.py b/test/unit/webdriver/network_test.py index d586fcbd..a9cf7ea9 100644 --- a/test/unit/webdriver/network_test.py +++ b/test/unit/webdriver/network_test.py @@ -24,9 +24,7 @@ class TestWebDriverNetwork(object): @httpretty.activate def test_network_connection(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.GET, appium_command('/session/1234567890/network_connection'), body='{"value": 2}' - ) + httpretty.register_uri(httpretty.GET, appium_command('/session/1234567890/network_connection'), body='{"value": 2}') httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -37,9 +35,7 @@ def test_network_connection(self): @httpretty.activate def test_set_network_connection(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/network_connection'), body='{"value": ""}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/network_connection'), body='{"value": ""}') httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), diff --git a/test/unit/webdriver/settings_test.py b/test/unit/webdriver/settings_test.py index 5f60904e..de9a0e00 100644 --- a/test/unit/webdriver/settings_test.py +++ b/test/unit/webdriver/settings_test.py @@ -34,7 +34,7 @@ def test_update_settings_bool(self): httpretty.POST, appium_command('/session/1234567890/appium/settings'), ) - assert isinstance(driver.update_settings({"sample": True}), WebDriver) + assert isinstance(driver.update_settings({'sample': True}), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) assert d['settings']['sample'] is True @@ -54,7 +54,7 @@ def test_update_settings_string(self): httpretty.POST, appium_command('/session/1234567890/appium/settings'), ) - assert isinstance(driver.update_settings({"sample": 'string'}), WebDriver) + assert isinstance(driver.update_settings({'sample': 'string'}), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) assert d['settings']['sample'] == 'string' diff --git a/test/unit/webdriver/webdriver_test.py b/test/unit/webdriver/webdriver_test.py index f7fa3091..f9a07a04 100644 --- a/test/unit/webdriver/webdriver_test.py +++ b/test/unit/webdriver/webdriver_test.py @@ -82,9 +82,7 @@ def test_create_session_change_session_id(self): body='{ "value": "title on another session id"}', ) - options = ( - UiAutomator2Options().set_capability('deviceName', 'Android Emulator').set_capability('app', 'path/to/app') - ) + options = UiAutomator2Options().set_capability('deviceName', 'Android Emulator').set_capability('app', 'path/to/app') driver = webdriver.Remote(SERVER_URL_BASE, options=options) # current session @@ -198,7 +196,7 @@ def test_get_events_catches_missing_events(self): assert events == {} @httpretty.activate - @patch("appium.webdriver.webdriver.logger.warning") + @patch('appium.webdriver.webdriver.logger.warning') def test_session_catches_error(self, mock_warning): def exceptionCallback(request, uri, headers): raise Exception() @@ -301,9 +299,7 @@ class CustomAppiumConnection(AppiumConnection): remote_server_addr=SERVER_URL_BASE, init_args_for_pool_manager=init_args_for_pool_manager ) - driver = webdriver.Remote( - custom_appium_connection, options=UiAutomator2Options().load_capabilities(desired_caps) - ) + driver = webdriver.Remote(custom_appium_connection, options=UiAutomator2Options().load_capabilities(desired_caps)) request = httpretty.HTTPretty.latest_requests[0] assert request.headers['content-type'] == 'application/json;charset=UTF-8' @@ -347,9 +343,7 @@ class CustomAppiumConnection(AppiumConnection): init_args_for_pool_manager=init_args_for_pool_manager, ) - driver = webdriver.Remote( - custom_appium_connection, options=UiAutomator2Options().load_capabilities(desired_caps) - ) + driver = webdriver.Remote(custom_appium_connection, options=UiAutomator2Options().load_capabilities(desired_caps)) request = httpretty.HTTPretty.latest_requests[0] assert request.headers['content-type'] == 'application/json;charset=UTF-8' @@ -371,9 +365,7 @@ class CustomAppiumConnection(AppiumConnection): @httpretty.activate def test_extention_command_check(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}' - ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') assert ( driver.execute_script( 'mobile: startActivity', diff --git a/test/unit/webdriver/webelement_test.py b/test/unit/webdriver/webelement_test.py index 14b6abb6..23268c3a 100644 --- a/test/unit/webdriver/webelement_test.py +++ b/test/unit/webdriver/webelement_test.py @@ -29,7 +29,7 @@ def test_status(self): httpretty.register_uri( httpretty.GET, appium_command('/status'), - body=json.dumps({"value": response}), + body=json.dumps({'value': response}), ) s = driver.get_status() @@ -77,7 +77,7 @@ def test_get_attribute_with_dict(self): httpretty.register_uri( httpretty.GET, appium_command('/session/1234567890/element/element_id/attribute/rect'), - body=json.dumps({"value": rect_dict}), + body=json.dumps({'value': rect_dict}), ) element = MobileWebElement(driver, 'element_id') @@ -95,7 +95,7 @@ def test_element_location_in_view(self): httpretty.register_uri( httpretty.GET, appium_command('/session/1234567890/element/element_id/location_in_view'), - body=json.dumps({"value": location_in_view}), + body=json.dumps({'value': location_in_view}), ) element = MobileWebElement(driver, 'element_id')