Skip to content

Commit

Permalink
enabling additional ruff rules
Browse files Browse the repository at this point in the history
  • Loading branch information
bandophahita committed Jan 16, 2024
1 parent 454627c commit 8cca57e
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 84 deletions.
112 changes: 55 additions & 57 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,94 +88,81 @@ build-backend = "poetry.core.masonry.api"
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
# McCabe complexity (`C901`) by default.
select = [
"A", # flake8-builtins
"ANN", # flake8-annotations # coming back to this one later to compare against mypy
"ARG", # flake8-unused-arguments
"B", # flake8-bugbear
"BLE", # flake8-blind-except
"C4", # flake8-comprehensions
"D", # pydocstyle
"E", # pycodestyle error
"W", # pycodestyle warning
"EM", # flake8-errmsg
"ERA", # eradicate
"F", # Pyflakes
"FA", # flake8-future-annotations
"FA", # flake8-future-annotations
# "FBT", # flake8-boolean-trap
"FIX", # flake8-fixme
"FLY", # flynt
"I", # isort
"D", # pydocstyle
"C4", # flake8-comprehensions
"TCH", # type checking
"ICN", # flake8-import-conventions
"ISC", # flake8-implicit-str-concat
"PGH", # pygrep-hooks
"PIE", # flake8-pie
"PL", # pylint
"PT", # flake8-pytest-style
"Q", # flake8-quotes
"RET", # flake8-return
"RSE", # flake8-raise
"RUF", # ruff specific
"ANN", # annotations
"SIM", # flake8-simplify
"T10", # flake8-debugger
"TCH", # flake8-type-checking
"TD", #TODOs
"TRY", # tryceratops
"UP", # python upgrade
"B", # bugbear
"SIM", # flake8 simplify
"A", # built-ins
"RET", # flake8 return
"YTT", # flake8-2020
"EXE", # flake8-executable
"ISC", # flake8-implicit-str-concat
"PIE", # flake8-pie
"Q", # flake8-quotes
"RSE", # flake8-raise
"FLY", # flynt
"PERF", # perflint
"PL", # pylint
# "ERA", # eradicate
# "N", # pep8 naming -- dear lord, leave this off
"W", # pycodestyle warning
"YTT", # flake8-2020

# may eventually use but for now these are not helpful
# "FURB", # refurb
# "ARG", # unused arguments
# "PT", # Pytest style
# "TD", #TODOs
# "FBT", # boolean trap
# "FURB", # refurb # needs --preview flag to run
]
ignore = [
# "PT003", # pytest fixture scope implied
# "PT004", # pytest fixture setup doesn't return anything
"RUF100", # blanket noqa
"ANN101", # missing-type-self
"ANN102", # cls
"E501", # line too long -- black will take care of this for us
"E721", # type-comparison WTF?
"B028", # No explicit `stacklevel` keyword argument found
"SIM102", # single if instead of nested -- only sometimes useful
"SIM114", # combine if branches using logical OR -- only sometimes useful
"SIM115", # use context handler for open -- situationally useful
"SIM118", # use x in y instead of y.keys() - sometimes we want the keys
"SIM300", # yoda conditions -- meh
# "SIM300", # yoda conditions -- meh

"PERF203", # `try`-`except` within a loop incurs performance overhead
"PERF401", # use list comp

# NOT OPTIONAL. MUST REMAIN AS SET
# these are all completely unnecessary
"D100", # Missing docstring in public module
"D101", # Missing docstring in public class
"D102", # Missing docstring in public method
"D103", # Missing docstring in public function
"D104", # Missing docstring in public package
"D105", # Missing docstring in magic method
"D106", # Missing docstring in public nested class
"D107", # Missing docstring in `__init__`
"D301", # Use `r"""` if any backslashes in a docstring
"D202", # no blank lines after docstring
"D203", # one-blank-line-before-class
"D204", # blank line required after docstring
"D205", # blank line between summary and description
"D212", # Multi-line summary should start at the first line
"D400", # First line should end with a period
"D401", # imperative mood
"D403", # first word of 1st line caps
"D404", # First word of the docstring should not be "This"
"D405", # Section name should be properly capitalized
"D406", # Section name should end with a newline
"D407", # Missing dashed underline after section
"D411", # Missing blank line before section
"D412", # No blank lines allowed between a section header and its content
"D415", # First line should end with punctuation
"D200", # One-line docstring should fit on one line
"D202", # no blank lines after docstring
"D204", # blank line required after docstring
"D205", # blank line between summary and description
"D203", # one-blank-line-before-class
"D210", # whitespace
"D212", # Multi-line summary should start at the first line
"D214", # Section overindented
"A003", # Class attribute shadow builtin

"PLC0414", # useless-import-alias
"PLR0911", # too-many-return-statements
"PLR0912", # too-many-branches
"PLR0913", # too-many-arguments
"PLR0915", # too-many-statements
"PLR2004", # magic-value-comparison

# 3.8 & 3.9 compatibility
"UP007", # Use `X | Y` for type annotations
Expand Down Expand Up @@ -215,11 +202,25 @@ exclude = [
]

[tool.ruff.lint]
extend-safe-fixes = ["TCH003"]
extend-safe-fixes = [
"EM101",
"EM102",
"TCH001", "TCH002", "TCH003", "TCH004",
# "SIM108"
"C419",
"D200", "D205",
"PT003", "PT006", "PT018",
"RET504",
"UP007",
]

[tool.ruff.per-file-ignores]
"__init__.py" = ["F401"]

"tests/**" = [
"D", # we don't need public-API-polished docstrings in tests.
"FBT", # using a boolean as a test object is useful!
"PLR", # likewise using specific numbers and strings in tests.
]

[tool.ruff.isort]
combine-as-imports = true
Expand All @@ -234,19 +235,16 @@ mark-parentheses = false
ignore-overlong-task-comments = true


#[tool.ruff.flake8-annotations]
#mypy-init-return = true


[tool.ruff.flake8-annotations]
# ignore returns types for functions that implicity or explicitly only return None
suppress-none-returning = true
allow-star-arg-any = true
#mypy-init-return = true


[tool.black]
line-length = 88
target-version = ['py310']
target-version = ['py311']

# 'extend-exclude' excludes files or directories in addition to the defaults
extend-exclude = '''
Expand Down
56 changes: 34 additions & 22 deletions setup_selenium/selenium_module.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Setup selenium for testing"""
from __future__ import annotations

import errno
Expand All @@ -12,7 +13,7 @@
from selenium.webdriver.common.selenium_manager import SeleniumManager
from selenium.webdriver.edge.service import Service as EdgeService
from selenium.webdriver.firefox.service import Service as FirefoxService
from semantic_version import Version # type: ignore
from semantic_version import Version # type: ignore[import-untyped]
from typing_extensions import TypeAlias

if TYPE_CHECKING:
Expand All @@ -38,12 +39,11 @@ def create_logger(name: str) -> logging.Logger:


def set_logger(logr: logging.Logger) -> None:
"""
Set the global logger with a custom logger
"""
"""Set the global logger with a custom logger"""
# Check if the logger is a valid logger
if not isinstance(logr, logging.Logger):
raise ValueError("The logger must be an instance of logging.Logger")
msg = "logger must be an instance of logging.Logger"
raise TypeError(msg)

# Bind the logger input to the global logger
global logger # noqa: PLW0603
Expand Down Expand Up @@ -132,9 +132,7 @@ def __init__(
def make_screenshot_path(
output_dir: str = "./logs", screenshots: str = "screenshots"
) -> str:
"""
Set the output directory for where screenshots should go.
"""
"""Set the output directory for where screenshots should go."""
output_dir = os.path.abspath(os.path.expanduser(output_dir))
if os.path.split(output_dir)[-1].lower() != screenshots:
output_dir = os.path.join(output_dir, screenshots)
Expand All @@ -152,6 +150,7 @@ def make_screenshot_path(
############################################################################
@staticmethod
def log_options(options: ArgOptions) -> None:
"""Logs the browser option in clean format"""
opts = "\n".join(options.arguments)
logger.debug(f"{opts}")

Expand All @@ -163,7 +162,7 @@ def install_driver(
browser_path: str | None = None,
install_browser: bool = False,
) -> tuple[str, str]:
"""install the webdriver and browser if needed."""
"""Install the webdriver and browser if needed."""
browser = Browser[browser.upper()].lower()
driver_version = driver_version or None

Expand Down Expand Up @@ -204,6 +203,7 @@ def create_driver(
binary: str | None = None,
driver_path: str | None = None,
) -> T_WebDriver:
"""Instantiates the browser driver"""
browser = browser.lower()
driver: T_WebDriver
if browser == Browser.FIREFOX:
Expand Down Expand Up @@ -238,12 +238,14 @@ def create_driver(
)

else:
raise ValueError(f"Unknown browser: {browser}")
msg = f"Unknown browser: {browser}"
raise ValueError(msg)

return driver

@staticmethod
def firefox_options() -> webdriver.FirefoxOptions:
"""Default options for firefox"""
options = webdriver.FirefoxOptions()
options.set_capability("unhandledPromptBehavior", "ignore")

Expand All @@ -263,6 +265,7 @@ def firefox(
binary: str | None = None,
options: webdriver.FirefoxOptions = None,
) -> webdriver.Firefox:
"""Instantiates firefox geockodriver"""
options = options or SetupSelenium.firefox_options()
if binary:
options.binary_location = binary
Expand Down Expand Up @@ -301,6 +304,7 @@ def firefox(

@staticmethod
def chrome_options() -> webdriver.ChromeOptions:
"""Default options for chrome"""
logger.debug("Setting up chrome options")
# The list of options set below mostly came from this StackOverflow post
# https://stackoverflow.com/q/48450594/2532408
Expand Down Expand Up @@ -334,6 +338,7 @@ def chrome(
binary: str | None = None,
options: webdriver.ChromeOptions = None,
) -> webdriver.Chrome:
"""Instantiates chromedriver"""
options = options or SetupSelenium.chrome_options()
if binary:
options.binary_location = binary
Expand Down Expand Up @@ -405,6 +410,7 @@ def chrome(

@staticmethod
def set_throttle(driver: webdriver.Chrome):
"""Experimental settings to slow down browser"""
# experimental settings to slow down browser
# @formatter:off
# fmt: off
Expand Down Expand Up @@ -433,6 +439,7 @@ def set_throttle(driver: webdriver.Chrome):

@staticmethod
def edge_options() -> webdriver.EdgeOptions:
"""Default options for edgedriver"""
logger.debug("Setting up edge options")
# The list of options set below mostly came from this StackOverflow post
# https://stackoverflow.com/q/48450594/2532408
Expand All @@ -447,8 +454,6 @@ def edge_options() -> webdriver.EdgeOptions:
# edgedriver crashes without these two in linux
"--no-sandbox",
"--disable-dev-shm-usage",
# it's possible we no longer need to do these
# "--disable-gpu", # https://stackoverflow.com/q/51959986/2532408
)
options = webdriver.EdgeOptions()
for opt in opts:
Expand All @@ -466,6 +471,7 @@ def edge(
binary: str | None = None,
options: webdriver.EdgeOptions = None,
) -> webdriver.Edge:
"""Instantiates edgedriver"""
options = options or SetupSelenium.edge_options()
if binary:
options.binary_location = binary
Expand Down Expand Up @@ -540,6 +546,7 @@ def edge(

############################################################################
def set_window_size(self, size: str = "720") -> None:
"""Helper to set the window size after driver has been instantiated."""
if size == "max":
self.driver.maximize_window()
return
Expand All @@ -550,17 +557,22 @@ def set_window_size(self, size: str = "720") -> None:
self.driver.set_window_size(width, height)

def set_main_window_handle(self, window: str | None = None) -> str:
if not window:
# does the main_window_handle exist and point to an available window?
if not self.main_window_handle:
"""
maintains the initial window handle as an attribute
Most users will never utilize this. It's part of a legacy requirement for
an old test suite
"""
# does the main_window_handle exist and point to an available window?
if not window and not self.main_window_handle:
try:
window = self.driver.current_window_handle
except NoSuchWindowException:
try:
window = self.driver.current_window_handle
except NoSuchWindowException:
try:
window = self.driver.window_handles[0]
except WebDriverException:
# Have we closed all the windows?
raise
window = self.driver.window_handles[0]
except WebDriverException: # noqa: TRY302
# Have we closed all the windows?
raise
if window:
self.main_window_handle = window
return self.main_window_handle
Expand Down
4 changes: 0 additions & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ def pytest_addoption(parser: Parser) -> None:
)


# def pytest_configure(config: Config) -> None:
# config.addinivalue_line("markers", "slow: mark test as slow to run")


def pytest_collection_modifyitems(config: Config, items: Sequence[Item]):
if config.getoption("--runslow"):
# --runslow given in cli: do not skip slow tests
Expand Down
2 changes: 1 addition & 1 deletion tests/test_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ def test_edge_bad_binary_path(create_logger: logging.Logger) -> None:
assert driver.service.is_connectable()


@pytest.fixture
@pytest.fixture()
def create_logger() -> logging.Logger:
"""Create a logger."""
logr = logging.getLogger("testsetupsel")
Expand Down

0 comments on commit 8cca57e

Please sign in to comment.