diff --git a/.gitignore b/.gitignore index ac0d624..a6e519d 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,4 @@ test-tw-gcal-sync.json /.envrc .tool-versions .lvimrc +a diff --git a/pyproject.toml b/pyproject.toml index fa16b76..e769342 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -193,62 +193,42 @@ exclude = [] select = ["ALL"] ignore = [ - # remove them in phases - "ANN001", - "ANN002", - "ANN003", - "ANN101", - "ANN102", "ANN201", - "ANN202", - "ANN204", - "ANN206", - "ARG001", - "ARG002", - "D100", - "D100", - "D101", - "D101", - "D102", + "S101", "D102", "D103", - "D103", + "ANN001", + "ANN202", + "D100", + "FBT001", + "PT009", + "ANN003", + "PGH003", + "N803", + "FBT002", + "FA100", + "TRY003", + "SLF001", + "EM102", + "ARG002", "D105", "D107", - "D107", - "D203", + "EM101", + "ARG001", "D205", - "D213", "D400", - "D401", "D415", - "DTZ004", - "E501", - "E712", - "EM101", - "EM102", - "FA100", - "FA102", - "FBT001", - "FBT002", "INP001", - "N802", - "N803", + "E501", + "SIM118", "N806", - "PGH003", + "ANN002", + "ANN204", + "N802", "PLR0913", - "PLR2004", - "PT009", - "RET504", "RUF012", - "S101", - "S101", - "SIM118", - "SLF001", - "TD002", - "TD003", - "TRY003", - "UP007", + "PLR2004", + "ANN206", ] exclude = [] diff --git a/syncall/aggregator.py b/syncall/aggregator.py index f9b4402..69de1e4 100644 --- a/syncall/aggregator.py +++ b/syncall/aggregator.py @@ -225,7 +225,7 @@ def finish(self) -> None: self._side_B.finish() def inserter_to(self, item: Item, helper: SideHelper) -> ID: - """Inserter. + """Insert an item using the given side helper. Other side already has the item, and I'm also inserting it at this side. """ @@ -246,7 +246,7 @@ def inserter_to(self, item: Item, helper: SideHelper) -> ID: return item_created_id def updater_to(self, item_id: ID, item: Item, helper: SideHelper): - """Updater.""" + """Update an item using the given side helper.""" side, _ = self._get_side_instances(helper) serdes_dir, _ = self._get_serdes_dirs(helper) logger.info( @@ -258,7 +258,7 @@ def updater_to(self, item_id: ID, item: Item, helper: SideHelper): pickle_dump(item, serdes_dir / item_id) def deleter_to(self, item_id: ID, helper: SideHelper): - """Deleter.""" + """Delete an item using the given side helper.""" logger.info(f"[{helper}] Synchronising deleted item, id -> {item_id}...") side, _ = self._get_side_instances(helper) side.delete_single_item(item_id) @@ -269,8 +269,7 @@ def item_getter_for(self, item_id: ID, helper: SideHelper) -> Item: """Item Getter.""" logger.debug(f"Fetching {helper} item for id -> {item_id}") side, _ = self._get_side_instances(helper) - item = side.get_item(item_id) - return item + return side.get_item(item_id) def _item_has_update(self, prev_item: Item, new_item: Item, helper: SideHelper) -> bool: """Determine whether the item has been updated.""" diff --git a/syncall/app_utils.py b/syncall/app_utils.py index fa92868..bd38207 100644 --- a/syncall/app_utils.py +++ b/syncall/app_utils.py @@ -410,9 +410,8 @@ def determine_app_config_fname(side_A_name: str, side_B_name: str) -> str: >>> assert determine_app_config_fname("TW", "Google Tasks") == 'tw__google_tasks__configs.yaml' >>> assert determine_app_config_fname("TW", "Google Calendar") == 'tw__google_calendar__configs.yaml' """ - config_fname = ( + return ( f'{side_A_name.replace(" ", "_").lower()}' "__" f'{side_B_name.replace(" ", "_").lower()}__configs.yaml' ) - return config_fname diff --git a/syncall/asana/asana_task.py b/syncall/asana/asana_task.py index 5b37ed1..6099176 100644 --- a/syncall/asana/asana_task.py +++ b/syncall/asana/asana_task.py @@ -9,6 +9,8 @@ @dataclass class AsanaTask(Mapping): + """Represent an Asana task.""" + completed: bool completed_at: datetime.datetime created_at: datetime.datetime diff --git a/syncall/caldav/caldav_side.py b/syncall/caldav/caldav_side.py index 78259b8..eb5d884 100644 --- a/syncall/caldav/caldav_side.py +++ b/syncall/caldav/caldav_side.py @@ -83,7 +83,7 @@ def get_item(self, item_id: ID, use_cached: bool = False): return item def _find_todo_by_id_raw(self, item_id: ID) -> caldav.CalendarObjectResource | None: - item = next( + return next( ( item for item in calendar_todos(self._calendar) @@ -92,8 +92,6 @@ def _find_todo_by_id_raw(self, item_id: ID) -> caldav.CalendarObjectResource | N None, ) - return item - def _find_todo_by_id(self, item_id: ID) -> dict | None: raw_item = self._find_todo_by_id_raw(item_id=item_id) if raw_item: diff --git a/syncall/caldav/caldav_utils.py b/syncall/caldav/caldav_utils.py index 786398b..1539290 100644 --- a/syncall/caldav/caldav_utils.py +++ b/syncall/caldav/caldav_utils.py @@ -13,7 +13,7 @@ def icalendar_component(obj: caldav.CalendarObjectResource): - """The .icalendar_component isn't picked up by linters + """Get the .icalendar_component isn't picked up by linters Ignore the warning when accessing it. """ @@ -29,9 +29,7 @@ def _parse_vcategory(vcategory: vCategory) -> Sequence[str]: def map_ics_to_item(vtodo) -> dict: - """Utility function that extracts the relevant info from an icalendar_component into a python - dict - """ + """Extract the relevant info from an icalendar_component into a python dict.""" todo_item = {} todo_item["id"] = str(vtodo.get("uid")) diff --git a/syncall/cli.py b/syncall/cli.py index 973cc0f..df24508 100644 --- a/syncall/cli.py +++ b/syncall/cli.py @@ -57,9 +57,7 @@ def decorator(f): # --asana-task-gid is used to ease development and debugging. It is not currently # suitable for regular use. - f = _opt_asana_task_gid(hidden=hidden_gid)(f) - - return f + return _opt_asana_task_gid(hidden=hidden_gid)(f) return decorator @@ -478,8 +476,7 @@ def decorator(f): fn_args = d[1:] f = fn(*fn_args)(f) # type: ignore - f = click.option("-v", "--verbose", count=True)(f) - return f + return click.option("-v", "--verbose", count=True)(f) return decorator diff --git a/syncall/concrete_item.py b/syncall/concrete_item.py index 0ab96be..456825c 100644 --- a/syncall/concrete_item.py +++ b/syncall/concrete_item.py @@ -10,6 +10,8 @@ class KeyType(Enum): + """Possible types of keys in an item.""" + String = auto() Date = auto() Boolean = auto() @@ -18,6 +20,8 @@ class KeyType(Enum): @dataclass class ItemKey: + """Key of an item.""" + name: str type: KeyType diff --git a/syncall/google/gcal_side.py b/syncall/google/gcal_side.py index 4fa90a8..ba2627a 100644 --- a/syncall/google/gcal_side.py +++ b/syncall/google/gcal_side.py @@ -214,8 +214,7 @@ def get_event_time(item: dict, t: str) -> datetime.datetime: if isinstance(item[t], datetime.datetime): return item[t] - dt = GCalSide.parse_datetime(item[t][GCalSide.get_date_key(item[t])]) - return dt + return GCalSide.parse_datetime(item[t][GCalSide.get_date_key(item[t])]) @staticmethod def format_datetime(dt: datetime.datetime) -> str: diff --git a/syncall/google/gkeep_side.py b/syncall/google/gkeep_side.py index e8bf472..458d1e1 100644 --- a/syncall/google/gkeep_side.py +++ b/syncall/google/gkeep_side.py @@ -10,6 +10,8 @@ class GKeepSide(SyncSide): + """Wrapper class to add/modify/delete todo entries from Google Keep.""" + def __init__( self, gkeep_user: str, @@ -17,6 +19,7 @@ def __init__( gkeep_token: Optional[str] = None, **kargs, ): + """Init.""" self._keep: Keep self._gkeep_user = gkeep_user self._gkeep_passwd = gkeep_passwd @@ -53,11 +56,11 @@ def finish(self): self._keep.sync() def _note_has_label(self, note: TopLevelNode, label: Label) -> bool: - """True if the given Google Keep note has the given label.""" + """Return true if the Google Keep note has the said label.""" return any(label == la for la in note.labels.all()) def _note_has_label_str(self, note: TopLevelNode, label_str: str) -> bool: - """True if the given Google Keep note has the given label.""" + """Return true if the Google Keep note has the said label.""" return any(label_str == la.name for la in note.labels.all()) def _get_label_by_name(self, label: str) -> Optional[Label]: diff --git a/syncall/google/google_side.py b/syncall/google/google_side.py index 8502d1c..8bb41af 100644 --- a/syncall/google/google_side.py +++ b/syncall/google/google_side.py @@ -31,7 +31,7 @@ def __init__( self._service = None def _get_credentials(self): - """Gets valid user credentials from storage. + """Get valid user credentials from storage. If nothing has been stored, or if the stored credentials are invalid, the OAuth2 flow is completed to obtain the new credentials. diff --git a/syncall/notion/notion_side.py b/syncall/notion/notion_side.py index 0684e90..3685336 100644 --- a/syncall/notion/notion_side.py +++ b/syncall/notion/notion_side.py @@ -143,10 +143,8 @@ def items_are_identical( @staticmethod def find_todos(page_contents: NotionPageContents) -> Sequence[NotionTodoBlock]: assert page_contents["object"] == "list" - todos = tuple( + return tuple( NotionTodoBlock.from_raw_item(cast(NotionTodoBlockItem, block)) for block in page_contents["results"] if NotionTodoBlock.is_todo(block) ) - - return todos diff --git a/syncall/notion/notion_todo_block.py b/syncall/notion/notion_todo_block.py index d3b5adb..3579f90 100644 --- a/syncall/notion/notion_todo_block.py +++ b/syncall/notion/notion_todo_block.py @@ -15,6 +15,8 @@ class NotionTodoBlock(ConcreteItem): + """Represent a todo block in Notion.""" + def __init__( self, is_archived: bool, diff --git a/syncall/taskwarrior/taskwarrior_side.py b/syncall/taskwarrior/taskwarrior_side.py index e4a10cd..594b06a 100644 --- a/syncall/taskwarrior/taskwarrior_side.py +++ b/syncall/taskwarrior/taskwarrior_side.py @@ -54,7 +54,7 @@ def __init__( config_overrides: Mapping[str, Any] = {}, **kargs, ): - """Constructor. + """Init. :param tags: Only include tasks that have are tagged using *all* the specified tags. Also assign these tags to newly added items diff --git a/syncall/types.py b/syncall/types.py index ad91f10..d910f35 100644 --- a/syncall/types.py +++ b/syncall/types.py @@ -54,12 +54,16 @@ class TaskwarriorRawItem(TypedDict, total=False): class GTaskLink(TypedDict): + """Link part of an item as returned from the Google Tasks Python API on.""" + description: str link: str type: str # "email" class GTasksList(TypedDict): + r"""Dict part of a list as returned from the Google Tasks Python API.""" + etag: str # ETag of the resource. id: str # Task list identifier. kind: str # Type of the resource. This is always "tasks#taskList". @@ -267,11 +271,15 @@ class NotionTodoSection(TypedDict): class NotionTodoBlockItem(NotionRawItem): + """Todo block item as returned from the Notion Python API.""" + to_do: NotionTodoSection # Page contents as returned from the Notion Python API class NotionPageContents(TypedDict): + """Page contents as returned from the Notion Python API.""" + object: Literal["list"] results: list[NotionRawItem] next_cursor: Any @@ -285,6 +293,8 @@ class NotionPageContents(TypedDict): # Task as returned from Asana API. class AsanaRawTask(TypedDict): + """Task as returned from Asana API.""" + completed: bool completed_at: str created_at: str @@ -303,5 +313,7 @@ class AsanaRawTask(TypedDict): # create a Protocol class for instances that have the __str__ method class SupportsStr(Protocol): + """Protocol for instances that have the __str__ method.""" + def __str__(self) -> str: ... diff --git a/tests/conftest.py b/tests/conftest.py index 8f3034f..df535c3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -35,6 +35,8 @@ def emit(self, record): class MockPrefsManager(PrefsManager): + """Mock the PrefsManager class.""" + def __init__(self): self._conts = { "kalimera": {"a": 1, "b": 2, "c": [1, 2, 3]}, diff --git a/tests/conftest_fs.py b/tests/conftest_fs.py index 913cee4..04efbc5 100644 --- a/tests/conftest_fs.py +++ b/tests/conftest_fs.py @@ -34,9 +34,7 @@ def non_existent_python_path(tmpdir_path, fs_file_default_fname) -> Path: @pytest.fixture() def fs_file_empty(tmpdir_path, fs_file_default_fname) -> FilesystemFile: - fs = FilesystemFile(tmpdir_path / fs_file_default_fname) - - return fs + return FilesystemFile(tmpdir_path / fs_file_default_fname) @pytest.fixture() @@ -53,9 +51,7 @@ def python_path_with_content(tmpdir_path, fs_file_default_fname) -> Path: @pytest.fixture() def fs_file_with_content(python_path_with_content: Path) -> FilesystemFile: - fs = FilesystemFile(python_path_with_content) - - return fs + return FilesystemFile(python_path_with_content) def _create_fs_side(filesystem_root: str): diff --git a/tests/conftest_gkeep.py b/tests/conftest_gkeep.py index 6f23e3a..4118b29 100644 --- a/tests/conftest_gkeep.py +++ b/tests/conftest_gkeep.py @@ -186,8 +186,7 @@ def gkeep_list_instance0(gkeep_list0: List) -> List: @pytest.fixture() def gkeep_note_empty_instance(gkeep_note_empty: dict) -> MyGKeepNote: - note = MyGKeepNote.from_raw_item(gkeep_note_empty) - return note + return MyGKeepNote.from_raw_item(gkeep_note_empty) @pytest.fixture() diff --git a/tests/conftest_notion.py b/tests/conftest_notion.py index 5e3841b..2f86d08 100644 --- a/tests/conftest_notion.py +++ b/tests/conftest_notion.py @@ -14,7 +14,7 @@ def notion_todo(request: pytest.FixtureRequest) -> NotionTodoBlockItem: @pytest.fixture() def notion_simple_todo() -> NotionTodoBlockItem: - """Simple to_do block returned by Notion Python SDK. + """Get simple to_do block returned by Notion Python SDK. - Unarchived (not deleted) - Unchecked (not completed) @@ -61,7 +61,7 @@ def notion_simple_checked_todo(notion_simple_todo: NotionTodoBlockItem) -> Notio def notion_simple_diff_edited_time_todo( notion_simple_todo: NotionTodoBlockItem, ) -> NotionTodoBlockItem: - """Completed Notion todo block.""" + """Get completed Notion todo block.""" item = deepcopy(notion_simple_todo) item["last_edited_time"] = "2022-01-04T10:01:00.000Z" return item @@ -71,7 +71,7 @@ def notion_simple_diff_edited_time_todo( def notion_simple_archived_todo( notion_simple_todo: NotionTodoBlockItem, ) -> NotionTodoBlockItem: - """Archived Notion todo block.""" + """Get archived Notion todo block.""" item = deepcopy(notion_simple_todo) item["archived"] = True return item @@ -79,7 +79,7 @@ def notion_simple_archived_todo( @pytest.fixture() def notion_chained_todo() -> NotionTodoBlockItem: - """More complex to_do block returned by Notion Python SDK. + """Get more complex to_do block returned by Notion Python SDK. Represents a todo with the following text (markdown notation in use): diff --git a/tests/test_aggregator.py b/tests/test_aggregator.py index dd3ffc6..3e323a2 100644 --- a/tests/test_aggregator.py +++ b/tests/test_aggregator.py @@ -5,6 +5,8 @@ class MockSide(SyncSide): + """MockSide class.""" + def __init__(self, name: str, fullname: str, *args, **kargs) -> None: self._fullname = fullname self._name = name diff --git a/tests/test_gcal.py b/tests/test_gcal.py index 0c5c6ee..f4c2c0d 100644 --- a/tests/test_gcal.py +++ b/tests/test_gcal.py @@ -10,9 +10,7 @@ # Monkeypatch the function to always return Eruope/Athens for UT determinism def assume_local_tz_if_none_(dt: datetime.datetime): - out = dt if dt.tzinfo is not None else dt.replace(tzinfo=localzone) - - return out + return dt if dt.tzinfo is not None else dt.replace(tzinfo=localzone) side.assume_local_tz_if_none = assume_local_tz_if_none_ diff --git a/tests/test_notion_todo_block.py b/tests/test_notion_todo_block.py index b21a263..22f50f9 100644 --- a/tests/test_notion_todo_block.py +++ b/tests/test_notion_todo_block.py @@ -56,8 +56,8 @@ def test_notion_todo_block_compare4( def test_notion_todo_block0(notion_simple_todo: NotionTodoBlockItem): todo_block = NotionTodoBlock.from_raw_item(notion_simple_todo) assert todo_block.plaintext == "Lacinato kale" - assert todo_block.is_checked == False - assert todo_block.is_archived == False + assert todo_block.is_checked is False + assert todo_block.is_archived is False assert todo_block.last_modified_date == simple_last_modified_date assert todo_block.id == "7de89eb6-4ee1-472c-abcd-8231049e9d8d" @@ -65,8 +65,8 @@ def test_notion_todo_block0(notion_simple_todo: NotionTodoBlockItem): def test_notion_todo_block1(notion_chained_todo: NotionTodoBlockItem): todo_block = NotionTodoBlock.from_raw_item(notion_chained_todo) assert todo_block.plaintext == "Bringing it back with style and glamour" - assert todo_block.is_checked == False - assert todo_block.is_archived == False + assert todo_block.is_checked is False + assert todo_block.is_archived is False assert todo_block.last_modified_date == chained_last_modified_date assert todo_block.id == "9146e728-d7c4-4678-bab4-377a3991ebb8" @@ -74,8 +74,8 @@ def test_notion_todo_block1(notion_chained_todo: NotionTodoBlockItem): def test_notion_todo_block2(notion_simple_checked_todo: NotionTodoBlockItem): todo_block = NotionTodoBlock.from_raw_item(notion_simple_checked_todo) assert todo_block.plaintext == "Lacinato kale" - assert todo_block.is_checked == True - assert todo_block.is_archived == False + assert todo_block.is_checked is True + assert todo_block.is_archived is False assert todo_block.last_modified_date == simple_last_modified_date assert todo_block.id == "7de89eb6-4ee1-472c-abcd-8231049e9d8d" @@ -83,7 +83,7 @@ def test_notion_todo_block2(notion_simple_checked_todo: NotionTodoBlockItem): def test_notion_todo_block3(notion_simple_archived_todo: NotionTodoBlockItem): todo_block = NotionTodoBlock.from_raw_item(notion_simple_archived_todo) assert todo_block.plaintext == "Lacinato kale" - assert todo_block.is_checked == False - assert todo_block.is_archived == True + assert todo_block.is_checked is False + assert todo_block.is_archived is True assert todo_block.last_modified_date == simple_last_modified_date assert todo_block.id == "7de89eb6-4ee1-472c-abcd-8231049e9d8d"