general: migrate modules to use 3.9 features

This commit is contained in:
Dima Gerasimov 2024-10-19 22:10:40 +01:00
parent d3f9a8e8b6
commit d915c848e9
125 changed files with 889 additions and 739 deletions

View file

@ -20,6 +20,7 @@ REQUIRES = [
from my.core.hpi_compat import handle_legacy_import
is_legacy_import = handle_legacy_import(
parent_module_name=__name__,
legacy_submodule_name='export',

View file

@ -1,10 +1,10 @@
from typing import Iterator
from my.core import Res, stat, Stats
from collections.abc import Iterator
from my.core import Res, Stats
from my.core.source import import_source
from .common import Message, _merge_messages
src_export = import_source(module_name='my.fbmessenger.export')
src_android = import_source(module_name='my.fbmessenger.android')

View file

@ -4,19 +4,20 @@ Messenger data from Android app database (in =/data/data/com.facebook.orca/datab
from __future__ import annotations
import sqlite3
from collections.abc import Iterator, Sequence
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
import sqlite3
from typing import Iterator, Sequence, Optional, Dict, Union, List
from typing import Union
from my.core import get_files, Paths, datetime_aware, Res, LazyLogger, make_config
from my.core import LazyLogger, Paths, Res, datetime_aware, get_files, make_config
from my.core.common import unique_everseen
from my.core.compat import assert_never
from my.core.error import echain
from my.core.sqlite import sqlite_connection
from my.config import fbmessenger as user_config
from my.config import fbmessenger as user_config # isort: skip
logger = LazyLogger(__name__)
@ -27,7 +28,7 @@ class Config(user_config.android):
# paths[s]/glob to the exported sqlite databases
export_path: Paths
facebook_id: Optional[str] = None
facebook_id: str | None = None
# hmm. this is necessary for default value (= None) to work
@ -42,13 +43,13 @@ def inputs() -> Sequence[Path]:
@dataclass(unsafe_hash=True)
class Sender:
id: str
name: Optional[str]
name: str | None
@dataclass(unsafe_hash=True)
class Thread:
id: str
name: Optional[str] # isn't set for groups or one to one messages
name: str | None # isn't set for groups or one to one messages
# todo not sure about order of fields...
@ -56,14 +57,14 @@ class Thread:
class _BaseMessage:
id: str
dt: datetime_aware
text: Optional[str]
text: str | None
@dataclass(unsafe_hash=True)
class _Message(_BaseMessage):
thread_id: str
sender_id: str
reply_to_id: Optional[str]
reply_to_id: str | None
# todo hmm, on the one hand would be kinda nice to inherit common.Message protocol here
@ -72,7 +73,7 @@ class _Message(_BaseMessage):
class Message(_BaseMessage):
thread: Thread
sender: Sender
reply_to: Optional[Message]
reply_to: Message | None
Entity = Union[Sender, Thread, _Message]
@ -110,7 +111,7 @@ def _normalise_thread_id(key) -> str:
# NOTE: this is sort of copy pasted from other _process_db method
# maybe later could unify them
def _process_db_msys(db: sqlite3.Connection) -> Iterator[Res[Entity]]:
senders: Dict[str, Sender] = {}
senders: dict[str, Sender] = {}
for r in db.execute('SELECT CAST(id AS TEXT) AS id, name FROM contacts'):
s = Sender(
id=r['id'], # looks like it's server id? same used on facebook site
@ -127,7 +128,7 @@ def _process_db_msys(db: sqlite3.Connection) -> Iterator[Res[Entity]]:
# TODO can we get it from db? could infer as the most common id perhaps?
self_id = config.facebook_id
thread_users: Dict[str, List[Sender]] = {}
thread_users: dict[str, list[Sender]] = {}
for r in db.execute('SELECT CAST(thread_key AS TEXT) AS thread_key, CAST(contact_id AS TEXT) AS contact_id FROM participants'):
thread_key = r['thread_key']
user_key = r['contact_id']
@ -193,7 +194,7 @@ def _process_db_msys(db: sqlite3.Connection) -> Iterator[Res[Entity]]:
def _process_db_threads_db2(db: sqlite3.Connection) -> Iterator[Res[Entity]]:
senders: Dict[str, Sender] = {}
senders: dict[str, Sender] = {}
for r in db.execute('''SELECT * FROM thread_users'''):
# for messaging_actor_type == 'REDUCED_MESSAGING_ACTOR', name is None
# but they are still referenced, so need to keep
@ -207,7 +208,7 @@ def _process_db_threads_db2(db: sqlite3.Connection) -> Iterator[Res[Entity]]:
yield s
self_id = config.facebook_id
thread_users: Dict[str, List[Sender]] = {}
thread_users: dict[str, list[Sender]] = {}
for r in db.execute('SELECT * from thread_participants'):
thread_key = r['thread_key']
user_key = r['user_key']
@ -267,9 +268,9 @@ def contacts() -> Iterator[Res[Sender]]:
def messages() -> Iterator[Res[Message]]:
senders: Dict[str, Sender] = {}
msgs: Dict[str, Message] = {}
threads: Dict[str, Thread] = {}
senders: dict[str, Sender] = {}
msgs: dict[str, Message] = {}
threads: dict[str, Thread] = {}
for x in unique_everseen(_entities):
if isinstance(x, Exception):
yield x

View file

@ -1,6 +1,9 @@
from my.core import __NOT_HPI_MODULE__
from __future__ import annotations
from typing import Iterator, Optional, Protocol
from my.core import __NOT_HPI_MODULE__ # isort: skip
from collections.abc import Iterator
from typing import Protocol
from my.core import datetime_aware
@ -10,7 +13,7 @@ class Thread(Protocol):
def id(self) -> str: ...
@property
def name(self) -> Optional[str]: ...
def name(self) -> str | None: ...
class Sender(Protocol):
@ -18,7 +21,7 @@ class Sender(Protocol):
def id(self) -> str: ...
@property
def name(self) -> Optional[str]: ...
def name(self) -> str | None: ...
class Message(Protocol):
@ -29,7 +32,7 @@ class Message(Protocol):
def dt(self) -> datetime_aware: ...
@property
def text(self) -> Optional[str]: ...
def text(self) -> str | None: ...
@property
def thread(self) -> Thread: ...
@ -39,8 +42,11 @@ class Message(Protocol):
from itertools import chain
from more_itertools import unique_everseen
from my.core import warn_if_empty, Res
from my.core import Res, warn_if_empty
@warn_if_empty
def _merge_messages(*sources: Iterator[Res[Message]]) -> Iterator[Res[Message]]:

View file

@ -7,16 +7,15 @@ REQUIRES = [
'git+https://github.com/karlicoss/fbmessengerexport',
]
from collections.abc import Iterator
from contextlib import ExitStack, contextmanager
from dataclasses import dataclass
from typing import Iterator
from my.core import PathIsh, Res, stat, Stats
from my.core.warnings import high
from my.config import fbmessenger as user_config
import fbmessengerexport.dal as messenger
from my.config import fbmessenger as user_config
from my.core import PathIsh, Res, Stats, stat
from my.core.warnings import high
###
# support old style config