Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Move to ruff. #46

Merged
merged 1 commit into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,18 @@ repos:
- id: check-case-conflict
- id: debug-statements

- repo: https://github.com/PyCQA/flake8
rev: 4.0.1
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.1
hooks:
- id: flake8

- repo: https://github.com/psf/black
rev: 22.6.0
hooks:
- id: black
# Run the linter
- id: ruff
args: ["--fix"]
# Run the formatter
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.971
hooks:
- id: mypy
additional_dependencies:
- types-geoip2

- repo: https://github.com/PyCQA/isort
rev: 5.10.1
hooks:
- id: isort
44 changes: 35 additions & 9 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

137 changes: 137 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,147 @@ tox = "^3.25.0"
tox-gh-actions = "^2.9.1"
mypy = "^0.960"
types-geoip2 = "^3.0.0"
ruff = "^0.2.1"

[tool.poetry.extras]
geoip = ["geoip2"]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"


[tool.ruff]
# By default, always show source code snippets.
output-format = 'full'

extend-exclude = [
"env",
"runtime",
]

[tool.ruff.lint]
select = [
"ASYNC", # flake8-async
"C4", # flake8-comprehensions
"D", # pydocstyle,
"E", "W", # pycodestyle
"F", # pyflakes
"I", # isort
"PL", # pylint
"RUF", # ruff
"S", # flake8-bandit
"SIM", # flake8-simplify
"UP", # pyupgrade
"TCH", # flake8-type-checking
]

ignore = [
## D - pydocstyle ##
# D1XX errors are OK. Don't force people into over-documenting.
"D100", "D101", "D102", "D103", "D104", "D105", "D107",
# These need to be fixed.
"D202", "D205", "D400", "D401",

## E / W - pycodestyle ##
"E501", # line too long
"E203", # whitespace-before-punctuation
"E741", # ambiguous variable name

## PL - pylint ##
# Commented-out rules are rules that we disable in pylint but are not supported by ruff yet.

"PLR6301", # no-self-use
"PLC2701", # import-private-name

# Import order issues
# "PLC0411", # wrong-import-order
# "PLC0412", # wrong-import-position
"PLC0414", # ungrouped-imports
"PLC0415", # import-outside-top-level

# Documentation issues
# "C0114", # missing-module-docstring

# Complexity issues
"PLR0904", # too-many-public-methods
# "PLC0302", # too-many-lines
"PLR1702", # too-many-nested-blocks
# "PLR0902", # too-many-instance-attributes
"PLR0911", # too-many-return-statements
"PLR0915", # too-many-statements
"PLR0912", # too-many-branches
# "PLR0903", # too-few-public-methods
"PLR0914", # too-many-locals
# "PLC0301", # line-too-long
"PLR0913", # too-many-arguments
"PLR0917", # too-many-positional
"PLR2004", # magic-value-comparison
"PLR5501", # collapsible-else-if
"PLW0603", # global-statement
"PLW2901", # redefined-loop-name
"PLC1901", # compare-to-empty-string

## RUF - ruff ##
"RUF001", # ambiguous-unicode-character-string
"RUF002", # ambiguous-unicode-character-docstring
"RUF003", # ambiguous-unicode-character-comment
"RUF012", # mutable-class-default
"RUF018", # assignment-in-assert

# Enable when Poetry supports PEP 621 and we migrate our confguration to it.
# See: https://github.com/python-poetry/poetry-core/pull/567
"RUF200",

"S101", # assert
"S104", # hardcoded-bind-all-interfaces
"S105", # hardcoded-password-string
"S106", # hardcoded-password-func-arg
"S107", # hardcoded-password-default
"S110", # try-except-pass
"S301", # suspicious-pickle-usage
"S303", # suspicious-insecure-hash-usage
"S310", # suspicious-url-open-usage
"S311", # suspicious-non-cryptographic-random-usage
"S324", # hashlib-insecure-hash-function
"S603", # subprocess-without-shell-equals-true
"S607", # start-process-with-partial-path
"S608", # hardcoded-sql-expression

## SIM - flake8-simplify ##
"SIM102", # collapsible-if
"SIM105", # suppressible-exception
"SIM108", # if-else-block-instead-of-if-exp
"SIM114", # if-with-same-arms
"SIM116", # if-else-block-instead-of-dict-lookup
"SIM117", # multiple-with-statements

# Enable when the rule is out of preview and false-positives are handled.
# See: https://docs.astral.sh/ruff/rules/in-dict-keys/
"SIM118", # in-dict-keys

## TCH - flake8-type-checking ##
"TCH001", # typing-only-first-party-import
"TCH002", # typing-only-third-party-import
"TCH003", # typing-only-standard-library-import
]

[tool.ruff.lint.isort]
section-order = [
"future",
"standard-library",
"third-party",
"first-party",
"local-folder",
]

[tool.ruff.lint.pydocstyle]
convention = "pep257"

[tool.ruff.lint.pyupgrade]
# Required by tools like Pydantic that use type information at runtime.
# https://github.com/asottile/pyupgrade/issues/622#issuecomment-1088766572
keep-runtime-typing = true

[tool.ruff.format]
docstring-code-format = true
3 changes: 1 addition & 2 deletions timezones/test_timezones.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import datetime
import os.path

import pytest
Expand Down Expand Up @@ -103,7 +102,7 @@ def test_valid_offset(offset_str, tzname, verbose_name):
offset_hours = abs(offset_full_minutes) // 60
offset_minutes = abs(offset_full_minutes) - (offset_hours * 60)
expected_offset = "%s%02d%02d" % (offset_sign, offset_hours, offset_minutes)
assert offset_str == expected_offset, "Invalid offset for {}".format(tzname)
assert offset_str == expected_offset, f"Invalid offset for {tzname}"

# 3. Test verbose name
assert verbose_name.startswith("(GMT%s) " % expected_offset)
Expand Down
4 changes: 2 additions & 2 deletions timezones/tz_rendering.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ def render_option(value, name, selected=False):
sel_checker["non_selected_yet"] = False
else:
is_selected = ""
return '<option value="%s" %s>%s</option>' % (value, is_selected, name)
return f'<option value="{value}" {is_selected}>{name}</option>'

def render_option_disabled():
return '<option disabled="disabled">--------------------</option>'

if select_id:
select_elm = '<select name="%s" id="%s">' % (select_name, select_id)
select_elm = f'<select name="{select_name}" id="{select_id}">'
else:
select_elm = '<select name="%s">' % select_name

Expand Down
21 changes: 11 additions & 10 deletions timezones/tz_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@
"""
from __future__ import annotations

import zoneinfo as zi
from datetime import datetime, timedelta, tzinfo

import zoneinfo as zi

from . import _defs

try:
Expand Down Expand Up @@ -72,8 +73,9 @@ def guess_timezone_by_ip(ip: str, only_name: bool = False):
Example usage::

from timezones import tz_utils
tz_utils.GEOIP_DATA_LOCATION = '/usr/local/geo_ip/GeoLiteCity.dat'
assert tz_utils.guess_timezone_by_ip('201.246.115.62') == 'Chile/Continental'

tz_utils.GEOIP_DATA_LOCATION = "/usr/local/geo_ip/GeoLiteCity.dat"
assert tz_utils.guess_timezone_by_ip("201.246.115.62") == "Chile/Continental"

"""
geo_lib = _get_geoip_lib()
Expand All @@ -93,9 +95,11 @@ def guess_timezone_by_ip(ip: str, only_name: bool = False):


def get_timezone(tzname: str) -> tzinfo | None:
"""Get a timezone instance by name or return `None`.
"""
Get a timezone instance by name or return `None`.

This getter support fixed offest timezone like `get_timezone('GMT +10:00')`"""
This getter support fixed offest timezone like `get_timezone('GMT +10:00')`
"""
try:
# First, try with the provided name
return zi.ZoneInfo(tzname)
Expand All @@ -117,10 +121,7 @@ def is_valid_timezone(timezone: str) -> bool:
"""Return `True` if the `timezone` is valid. Otherwise `False` is returned."""
try:
tz = get_timezone(timezone)
if tz:
return True
else:
return False
return bool(tz)
except Exception:
return False

Expand Down Expand Up @@ -241,6 +242,6 @@ def _tz_map():
FixedOffset(780, "GMT +13:00"),
]

TZ_MAP = dict([(z.zone, z) for z in timezones])
TZ_MAP = {z.zone: z for z in timezones}

return TZ_MAP
Loading