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

Switch from pylint to ruff #68

Merged
merged 1 commit into from
Sep 19, 2023
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
48 changes: 15 additions & 33 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ requests = ">=2.23.0"
urllib3 = [
{ version = ">=1.26", python = ">=3.10,<4" }
]
pydantic = ">=1.8.1"
pydantic = ">=1.8.1,<2"
aiohttp = ">=3.8.1"
ruff = ">=0.0.289"

[tool.poetry.group.dev.dependencies]
pytest = ">=7.1"
Expand All @@ -39,47 +40,28 @@ poethepoet = ">=0.16.4"
[tool.poe.tasks]
build = "poetry build --no-interaction"
test = "pytest"
lint = "pylint src/rtmilk tests --disable=fixme"
lint = "ruff src tests"

[tool.poe.tasks.test-with-coverage]
shell = """
pytest --cov=src || exit 1
coverage xml
"""

[tool.pylint.master]
load-plugins = [
"pylint_quotes",
"pylint.extensions.code_style",
"pylint.extensions.confusing_elif",
"pylint.extensions.bad_builtin",
"pylint.extensions.bad_builtin",
"pylint.extensions.mccabe",
"pylint.extensions.check_elif",
"pylint.extensions.redefined_variable_type",
"pylint.extensions.overlapping_exceptions",
"pylint.extensions.empty_comment",
"pylint.extensions.set_membership",
"pylint.extensions.while_used",
]
enable="useless-suppression"
[tool.ruff]
line-length = 1000
ignore = ["A002", "A003", "ANN", "FBT003", "D", "DTZ", "EM", "ERA001", "FBT001", "FIX", "N802", "I", "N803", "N806", "N815", "PLR0913", "PT013", "PTH", "S101", "S311", "T20", "TCH", "TD", "TRY003", "W191"]
select = ["ALL"]
target-version = "py39"

[tool.pylint.format]
indent-string="\t"
string-quote = "single-avoid-escape"
[tool.ruff.extend-per-file-ignores]
"tests/*" = ["ANN201", "D103", "INP001", "PT006"]
"_properties.py" = ["SLF001"]
"client.py" = ["SLF001"]

[tool.pylint.messages_control]
disable = [
"duplicate-code",
"invalid-name",
"line-too-long",
"logging-fstring-interpolation",
"missing-docstring",
"too-few-public-methods",
"too-many-arguments",
"too-many-public-methods",
"protected-access" # temporary until I figure out the privacy
]
[tool.ruff.flake8-quotes]
inline-quotes = "single"
multiline-quotes = "single"

[tool.pytest.ini_options]
pythonpath = ["src"]
Expand Down
10 changes: 6 additions & 4 deletions src/rtmilk/_properties.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from datetime import date, datetime
from logging import getLogger
from typing import Generic, Optional, TypeVar, Union
Expand All @@ -9,7 +11,7 @@
_T = TypeVar('_T')

class _Property(Generic[_T]):
_value: Optional[_T]
_value: _T | None

def __init__(self, task):
self._task = task
Expand Down Expand Up @@ -113,18 +115,18 @@ def _Parameters(self, value):
'timeline': self._task._client.timeline,
'list_id': self._task._listId,
'taskseries_id': self._task._taskSeriesId,
'task_id': self._task._taskId
'task_id': self._task._taskId,
}
if value is not None:
parameters[self._dateType] = value
parameters[f'has_{self._dateType}_time'] = isinstance(value, datetime)
return parameters

def Set(self, value: Optional[Union[date, datetime]]):
def Set(self, value: date | datetime | None):
parameters = self._Parameters(value)
(self.__class__.F)(self._task._client.api, **parameters) # pylint: disable=no-member

async def SetAsync(self, value: Optional[Union[date, datetime]]):
async def SetAsync(self, value: date | datetime | None):
parameters = self._Parameters(value)
await (self.__class__.FA)(self._task._client.apiAsync, **parameters) # pylint: disable=no-member

Expand Down
26 changes: 13 additions & 13 deletions src/rtmilk/_sansio.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from __future__ import annotations

from datetime import date, datetime
from hashlib import md5
from logging import getLogger
from pprint import pformat
from typing import Optional, Union

from pydantic import stricturl, validate_arguments, ValidationError # pylint: disable=no-name-in-module

Expand Down Expand Up @@ -40,7 +41,7 @@ def _ValidateReturn(type_, rsp):
def ApiSig(sharedSecret, params):
sortedItems = sorted(params.items(), key=lambda x: x[0])
concatenatedParams = ''.join((key + value for key, value in sortedItems))
return md5((sharedSecret + concatenatedParams).encode()).hexdigest()
return md5((sharedSecret + concatenatedParams).encode()).hexdigest() # noqa: S324

# the return parsing is the same for authorized and unauthorized calls
# the signing of parameters is different for authorized and unauthorized calls
Expand Down Expand Up @@ -99,7 +100,7 @@ def Out(cls, **rsp):
AuthorizedCall = Call

class ListsAdd(AuthorizedCall):
def In(self, timeline: str, name: str, filter: Optional[str] = None): # pylint: disable=redefined-builtin
def In(self, timeline: str, name: str, filter: str | None = None): # pylint: disable=redefined-builtin
kwargs = _RebuildArgs(filter=filter) # TODO validate parameter
return self.CommonParams('rtm.lists.add', timeline=timeline, name=name, **kwargs)

Expand Down Expand Up @@ -178,7 +179,7 @@ def Out(cls, **rsp):

class PushSubscribe(AuthorizedCall):
@validate_arguments
def In(self, url: stricturl(allowed_schemes='https'), topics: str, push_format: str, timeline: str, lease_seconds: Optional[int] = None, filter: Optional[str] = None): # pylint: disable=redefined-builtin
def In(self, url: stricturl(allowed_schemes='https'), topics: str, push_format: str, timeline: str, lease_seconds: int | None = None, filter: str | None = None): # pylint: disable=redefined-builtin
kwargs = _RebuildArgs(lease_seconds=lease_seconds, filter=filter) # TODO validate parameters
if 'lease_seconds' in kwargs:
kwargs['lease_seconds'] = str(kwargs['lease_seconds'])
Expand Down Expand Up @@ -221,7 +222,7 @@ def Out(cls, **rsp):
return _ValidateReturn(TagListResponse, rsp)

class TasksAdd(AuthorizedCall):
def In(self, timeline: str, name: str, list_id: Optional[str] = None, parse: Optional[bool] = None, parent_task_id: Optional[str] = None, external_id: Optional[str] = None):
def In(self, timeline: str, name: str, list_id: str | None = None, parse: bool | None = None, parent_task_id: str | None = None, external_id: str | None = None):
kwargs = _RebuildArgs(list_id=list_id, parse=parse, parent_task_id=parent_task_id, external_id=external_id)
return self.CommonParams('rtm.tasks.add', timeline=timeline, name=name, **kwargs)

Expand Down Expand Up @@ -255,11 +256,10 @@ def Out(cls, **rsp):
return _ValidateReturn(TaskResponse, rsp)

class TasksGetList(AuthorizedCall):
def In(self, list_id: Optional[str] = None, filter: Optional[str] = None, last_sync: Optional[datetime] = None): # pylint: disable=redefined-builtin
def In(self, list_id: str | None = None, filter: str | None = None, last_sync: datetime | None = None): # pylint: disable=redefined-builtin
kwargs = _RebuildArgs(list_id=list_id, filter=filter, last_sync=last_sync)
if 'last_sync' in kwargs:
if isinstance(kwargs['last_sync'], (datetime)):
kwargs['last_sync'] = _RtmDatetime(kwargs['last_sync'])
if 'last_sync' in kwargs and isinstance(kwargs['last_sync'], (datetime)):
kwargs['last_sync'] = _RtmDatetime(kwargs['last_sync'])
return self.CommonParams('rtm.tasks.getList', **kwargs)

@classmethod
Expand Down Expand Up @@ -293,7 +293,7 @@ def Out(cls, **rsp):
return _ValidateReturn(TaskResponse, rsp)

class TasksSetDueDate(AuthorizedCall):
def In(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, due: Union[date, datetime, str, None]=None, has_due_time: Optional[bool] = None, parse: Optional[bool] = None):
def In(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, due: date | datetime | str | None = None, has_due_time: bool | None = None, parse: bool | None = None):
kwargs = _RebuildArgs(due=due, has_due_time=has_due_time, parse=parse)
if 'has_due_time' in kwargs:
kwargs['has_due_time'] = '1' if kwargs['has_due_time'] else '0'
Expand All @@ -319,7 +319,7 @@ def Out(cls, **rsp):
return _ValidateReturn(TaskResponse, rsp)

class TasksSetPriority(AuthorizedCall):
def In(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, priority: Optional[PriorityEnum ] = None):
def In(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, priority: PriorityEnum | None = None):
kwargs = _RebuildArgs(priority=priority)
if 'priority' in kwargs: # translate to the string that RTM needs
kwargs['priority'] = kwargs['priority'].value
Expand All @@ -330,7 +330,7 @@ def Out(cls, **rsp):
return _ValidateReturn(TaskPayload, rsp['list'])

class TasksSetStartDate(AuthorizedCall):
def In(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, start: Union[date, datetime, str, None] = None, has_start_time: Optional[bool] = None, parse: Optional[bool] = None):
def In(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, start: date | datetime | str | None = None, has_start_time: bool | None = None, parse: bool | None = None):
kwargs = _RebuildArgs(start=start, has_start_time=has_start_time, parse=parse)
if 'has_start_time' in kwargs:
kwargs['has_start_time'] = '1' if kwargs['has_start_time'] else '0'
Expand All @@ -348,7 +348,7 @@ def Out(cls, **rsp):
return _ValidateReturn(TaskResponse, rsp)

class TasksSetTags(AuthorizedCall):
def In(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, tags: Optional[list[str]] = None):
def In(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, tags: list[str] | None = None):
kwargs = _RebuildArgs(tags=tags)
if 'tags' in kwargs:
kwargs['tags'] = ','.join(kwargs['tags'])
Expand Down
2 changes: 1 addition & 1 deletion src/rtmilk/_secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
def _ApiSig(sharedSecret, params):
sortedItems = sorted(params.items(), key=lambda x: x[0])
concatenatedParams = ''.join((key + value for key, value in sortedItems))
return md5((sharedSecret + concatenatedParams).encode()).hexdigest()
return md5((sharedSecret + concatenatedParams).encode()).hexdigest() # noqa: S324

@dataclass
class Secrets:
Expand Down
6 changes: 4 additions & 2 deletions src/rtmilk/_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

from datetime import datetime, timezone
from typing import Generic, Optional, TypeVar
from typing import Generic, TypeVar

from pydantic.fields import ModelField # pylint: disable=no-name-in-module

Expand All @@ -12,7 +14,7 @@ def __get_validators__(cls):
yield cls.validate

@classmethod
def validate(cls, v: PydanticField, field: ModelField) -> Optional[PydanticField]:
def validate(cls, v: PydanticField, field: ModelField) -> PydanticField | None:
if v == '':
return None

Expand Down
28 changes: 14 additions & 14 deletions src/rtmilk/api_async.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from __future__ import annotations

from datetime import date, datetime
from json import loads
from logging import getLogger
from typing import Optional, Union

from aiohttp import ClientResponseError, ClientSession
from pydantic import stricturl, validate_arguments # pylint: disable=no-name-in-module
Expand All @@ -15,12 +16,11 @@

async def _CallAsync(params):
try:
async with ClientSession() as session:
async with session.get(REST_URL, params=params) as resp:
text = await resp.text()
return loads(text)['rsp']
async with ClientSession() as session, session.get(REST_URL, params=params) as resp:
text = await resp.text()
return loads(text)['rsp']
except (ClientResponseError, ValueError) as e:
raise RTMError() from e
raise RTMError from e

class UnauthorizedAPIAsync(UnauthorizedAPIBase):
"""Async wrappers for API calls that don't need authorization"""
Expand Down Expand Up @@ -52,7 +52,7 @@ def secrets(self):
return self._authSecrets

@validate_arguments
async def ListsAdd(self, timeline: str, name: str, filter: Optional[str] = None) -> SingleListResponse: # pylint: disable=redefined-builtin
async def ListsAdd(self, timeline: str, name: str, filter: str | None = None) -> SingleListResponse: # pylint: disable=redefined-builtin
return ListsAdd.Out(** await _CallAsync(ListsAdd(self._authSecrets).In(timeline=timeline, name=name, filter=filter)))

@validate_arguments
Expand Down Expand Up @@ -85,7 +85,7 @@ async def PushGetTopics(self) -> TopicListResponse:
return PushGetTopics.Out(** await _CallAsync(PushGetTopics(self._authSecrets).In()))

@validate_arguments
async def PushSubscribe(self, url: stricturl(allowed_schemes='https'), topics: str, push_format: str, timeline: str, lease_seconds: Optional[int] = None, filter: Optional[str] = None) -> SubscriptionResponse: # pylint: disable=redefined-builtin
async def PushSubscribe(self, url: stricturl(allowed_schemes='https'), topics: str, push_format: str, timeline: str, lease_seconds: int | None = None, filter: str | None = None) -> SubscriptionResponse: # pylint: disable=redefined-builtin
return PushSubscribe.Out(** await _CallAsync(PushSubscribe(self._authSecrets).In(url=url, topics=topics, push_format=push_format, timeline=timeline, lease_seconds=lease_seconds, filter=filter)))

@validate_arguments
Expand All @@ -102,7 +102,7 @@ async def TagsGetList(self) -> TagListResponse:
return TagsGetList.Out(** await _CallAsync(TagsGetList(self._authSecrets).In()))

@validate_arguments
async def TasksAdd(self, timeline: str, name: str, list_id: Optional[str] = None, parse: Optional[bool] = None, parent_task_id: Optional[str] = None, external_id: Optional[str] = None) -> TaskResponse:
async def TasksAdd(self, timeline: str, name: str, list_id: str | None = None, parse: bool | None = None, parent_task_id: str | None = None, external_id: str | None = None) -> TaskResponse:
return TasksAdd.Out(** await _CallAsync(TasksAdd(self._authSecrets).In(timeline=timeline, name=name, list_id=list_id, parse=parse, parent_task_id=parent_task_id, external_id=external_id)))

@validate_arguments
Expand All @@ -122,7 +122,7 @@ async def TasksDelete(self, timeline: str, list_id: str, taskseries_id: str, tas
return TasksDelete.Out(** await _CallAsync(TasksDelete(self._authSecrets).In(timeline=timeline, list_id=list_id, taskseries_id=taskseries_id, task_id=task_id)))

@validate_arguments
async def TasksGetList(self, list_id: Optional[str] = None, filter: Optional[str] = None, last_sync: Optional[datetime] = None) -> TaskListResponse: # pylint: disable=redefined-builtin
async def TasksGetList(self, list_id: str | None = None, filter: str | None = None, last_sync: datetime | None = None) -> TaskListResponse: # pylint: disable=redefined-builtin
return TasksGetList.Out(** await _CallAsync(TasksGetList(self._authSecrets).In(list_id=list_id, filter=filter, last_sync=last_sync)))

@validate_arguments
Expand All @@ -138,21 +138,21 @@ async def TasksRemoveTags(self, timeline: str, list_id: str, taskseries_id: str,
return TasksRemoveTags.Out(** await _CallAsync(TasksRemoveTags(self._authSecrets).In(timeline=timeline, list_id=list_id, taskseries_id=taskseries_id, task_id=task_id, tags=tags)))

@validate_arguments
async def TasksSetDueDate(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, due: Union[date, datetime, str, None]=None, has_due_time: Optional[bool] = None, parse: Optional[bool] = None) -> TaskResponse:
async def TasksSetDueDate(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, due: date | datetime | str | None = None, has_due_time: bool | None = None, parse: bool | None = None) -> TaskResponse:
return TasksSetDueDate.Out(** await _CallAsync(TasksSetDueDate(self._authSecrets).In(timeline=timeline, list_id=list_id, taskseries_id=taskseries_id, task_id=task_id, due=due, has_due_time=has_due_time, parse=parse)))

@validate_arguments
async def TasksSetName(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, name: str) -> TaskResponse:
return TasksSetName.Out(** await _CallAsync(TasksSetName(self._authSecrets).In(timeline=timeline, list_id=list_id, taskseries_id=taskseries_id, task_id=task_id, name=name)))

@validate_arguments
async def TasksSetPriority(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, priority: Optional[PriorityEnum ] = None) -> TaskPayload:
async def TasksSetPriority(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, priority: PriorityEnum | None = None) -> TaskPayload:
return TasksSetPriority.Out(** await _CallAsync(TasksSetPriority(self._authSecrets).In(timeline=timeline, list_id=list_id, taskseries_id=taskseries_id, task_id=task_id, priority=priority)))

@validate_arguments
async def TasksSetStartDate(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, start: Union[date, datetime, str, None] = None, has_start_time: Optional[bool] = None, parse: Optional[bool] = None) -> TaskResponse:
async def TasksSetStartDate(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, start: date | datetime | str | None = None, has_start_time: bool | None = None, parse: bool | None = None) -> TaskResponse:
return TasksSetStartDate.Out(** await _CallAsync(TasksSetStartDate(self._authSecrets).In(timeline=timeline, list_id=list_id, taskseries_id=taskseries_id, task_id=task_id, start=start, has_start_time=has_start_time, parse=parse)))

@validate_arguments
async def TasksSetTags(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, tags: Optional[list[str]] = None) -> TaskResponse:
async def TasksSetTags(self, timeline: str, list_id: str, taskseries_id: str, task_id: str, tags: list[str] | None = None) -> TaskResponse:
return TasksSetTags.Out(** await _CallAsync(TasksSetTags(self._authSecrets).In(timeline=timeline, list_id=list_id, taskseries_id=taskseries_id, task_id=task_id, tags=tags)))
Loading
Loading