diff --git a/requirements.txt b/requirements.txt index d588476..14c74ad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,15 @@ -y-py==0.6.2 +aiosqlite==0.20.0 +anyio==4.3.0 +exceptiongroup==1.2.0 +idna==3.6 +iniconfig==2.0.0 +packaging==24.0 +pluggy==1.4.0 +pyperclip==1.8.2 +ruff==0.3.3 +sniffio==1.3.1 +tomli==2.0.1 +typing_extensions==4.10.0 websockets==12.0 +y-py==0.6.2 ypy-websocket==0.12.4 diff --git a/src/internal/objects/builder.py b/src/internal/objects/builder.py index d6e59a1..b754076 100644 --- a/src/internal/objects/builder.py +++ b/src/internal/objects/builder.py @@ -22,17 +22,27 @@ def build_from_serialized( # because it will be possible that repository and object will have different brokers. # myb we want to restrict that def build_by_type( - type: BoardObjectType, - pub_sub_broker: internal.pub_sub.interfaces.IPubSubBroker, - **kwargs + type: BoardObjectType, pub_sub_broker: internal.pub_sub.interfaces.IPubSubBroker, **kwargs ) -> interfaces.IBoardObjectWithPosition: id = generate_object_id() if 'position' in kwargs and isinstance(kwargs['position'], internal.models.Position): - return TYPE_IMPLS[type](id, datetime.now().replace(microsecond=0), kwargs['position'], pub_sub_broker) + return TYPE_IMPLS[type]( + id, datetime.now().replace(microsecond=0), kwargs['position'], pub_sub_broker + ) if type == BoardObjectType.GROUP and 'children_ids' in kwargs: - return TYPE_IMPLS[type](id, datetime.now().replace(microsecond=0), pub_sub_broker, kwargs['children_ids']) + return TYPE_IMPLS[type]( + id, datetime.now().replace(microsecond=0), pub_sub_broker, kwargs['children_ids'] + ) if type == BoardObjectType.CONNECTOR and 'start_id' in kwargs and 'end_id' in kwargs: - return TYPE_IMPLS[type](id, datetime.now().replace(microsecond=0), pub_sub_broker, kwargs['start_id'], kwargs['end_id']) + return TYPE_IMPLS[type]( + id, + datetime.now().replace(microsecond=0), + pub_sub_broker, + kwargs['start_id'], + kwargs['end_id'], + ) if type == BoardObjectType.PEN and 'points' in kwargs: - return TYPE_IMPLS[type](id, datetime.now().replace(microsecond=0), pub_sub_broker, kwargs['points']) + return TYPE_IMPLS[type]( + id, datetime.now().replace(microsecond=0), pub_sub_broker, kwargs['points'] + ) raise ValueError('No object to build') diff --git a/src/internal/objects/impl/table.py b/src/internal/objects/impl/table.py index 5ea1d9f..c745f2e 100644 --- a/src/internal/objects/impl/table.py +++ b/src/internal/objects/impl/table.py @@ -30,7 +30,7 @@ def __init__( height: float = 30, col_widths: list[float] = None, row_heights: list[float] = None, - linked_objects: dict[str, list] = dict() # noqa + linked_objects: dict[str, list] = None, ): super().__init__(id, types.BoardObjectType.TABLE, create_dttm, position, pub_sub_broker) self.default_width = width @@ -43,7 +43,10 @@ def __init__( self.rows_height = [self.default_height] * rows else: self.rows_height = row_heights - self.linked_objects = linked_objects + if linked_objects: + self.linked_objects = linked_objects + else: + self.linked_objects = {} def serialize(self) -> dict: serialized = super().serialize() @@ -58,7 +61,8 @@ def serialize(self) -> dict: @staticmethod def from_serialized( - data: dict, pub_sub_broker: internal.pub_sub.interfaces.IPubSubBroker, + data: dict, + pub_sub_broker: internal.pub_sub.interfaces.IPubSubBroker, ) -> BoardObjectTable: # TODO: child class should not know how to build parent from serialized data return BoardObjectTable( diff --git a/src/internal/objects/impl/test_table.py b/src/internal/objects/impl/test_table.py index a039d7d..4e9d589 100644 --- a/src/internal/objects/impl/test_table.py +++ b/src/internal/objects/impl/test_table.py @@ -18,13 +18,21 @@ def test_board_object_table_serialization(): height = 30 col_widths = [width] * columns row_heights = [height] * rows - linked_objects = dict() + linked_objects = {} broker = internal.pub_sub.mocks.MockPubSubBroker() table_object = BoardObjectTable( - id, create_dttm, position, broker, - columns, rows, width, height, col_widths, - row_heights, linked_objects + id, + create_dttm, + position, + broker, + columns, + rows, + width, + height, + col_widths, + row_heights, + linked_objects, ) assert table_object.serialize() == { 'id': id, @@ -52,7 +60,7 @@ def test_board_object_table_deserialization(): height = 30 col_widths = [width] * columns row_heights = [height] * rows - linked_objects = dict() + linked_objects = {} serialized = { 'id': id, diff --git a/src/internal/objects/test_builder.py b/src/internal/objects/test_builder.py index 69215bf..2f75092 100644 --- a/src/internal/objects/test_builder.py +++ b/src/internal/objects/test_builder.py @@ -62,7 +62,7 @@ def test_group_building(): 'type': 'group', 'create_dttm': datetime.now().strftime('%Y-%m-%dT%H-%M-%SZ'), 'id': generate_object_id(), - 'children_ids': [generate_object_id, generate_object_id] + 'children_ids': [generate_object_id, generate_object_id], } broker = internal.pub_sub.mocks.MockPubSubBroker() @@ -81,7 +81,7 @@ def test_connector_building(): 'color': 'black', 'width': 2, 'connector_type': 'curved', - 'stroke_style': 'left' + 'stroke_style': 'left', } broker = internal.pub_sub.mocks.MockPubSubBroker() @@ -89,12 +89,13 @@ def test_connector_building(): assert isinstance(connector, BoardObjectConnector) assert connector.serialize() == serialized_connector + def test_table_building(): serialized_table = { 'id': generate_object_id(), 'create_dttm': datetime.now().strftime('%Y-%m-%dT%H-%M-%SZ'), 'type': 'table', - 'position': {'x': 1, 'y': 2, 'z': 3}, + 'position': {'x': 1, 'y': 2, 'z': 3}, 'table-columns': 2, 'table-rows': 2, 'columns-width': [50, 50], @@ -108,4 +109,3 @@ def test_table_building(): table = internal.objects.build_from_serialized(serialized_table, broker) assert isinstance(table, BoardObjectTable) assert table.serialize() == serialized_table - diff --git a/src/internal/repositories/mocks/repository.py b/src/internal/repositories/mocks/repository.py index 1c21377..9fa07e9 100644 --- a/src/internal/repositories/mocks/repository.py +++ b/src/internal/repositories/mocks/repository.py @@ -24,4 +24,4 @@ def delete(self, object_id: internal.objects.interfaces.ObjectId) -> None: raise NotImplementedError() def get_updated(self) -> dict[internal.objects.interfaces.ObjectId, Optional[dict]]: - raise NotImplementedError() \ No newline at end of file + raise NotImplementedError() diff --git a/src/internal/storages/impl/shared_ydoc_storage.py b/src/internal/storages/impl/shared_ydoc_storage.py index 2133b2e..55de681 100644 --- a/src/internal/storages/impl/shared_ydoc_storage.py +++ b/src/internal/storages/impl/shared_ydoc_storage.py @@ -36,7 +36,7 @@ def get_websocket_provider(self, websocket: Websocket): def _transaction_callback_obj(self, event: YMapEvent): for obj_id, change in event.keys.items(): - obj = dict() + obj = {} obj['obj_repr'] = change['newValue'] if change['action'] != 'delete' else None obj['obj_action'] = change['action'] obj['obj_id'] = obj_id diff --git a/src/internal/storages/impl/test_shared_ydoc_storage.py b/src/internal/storages/impl/test_shared_ydoc_storage.py index 51d11d0..ff42a7e 100644 --- a/src/internal/storages/impl/test_shared_ydoc_storage.py +++ b/src/internal/storages/impl/test_shared_ydoc_storage.py @@ -39,7 +39,7 @@ async def test_shared_ydoc_storage_get_updates(): assert obj['obj_repr'] == updates[obj['obj_id']] # client 2 - storage_2 = SharedYDocStorage(board_name) + storage_2 = SharedYDocStorage(board_name, board_key) assert storage_2.is_empty_updates() async with connect(storage_2.get_uri_connection()) as websocket: async with storage_2.get_websocket_provider(websocket): # type: ignore diff --git a/src/internal/view/choose_board/choose_board.py b/src/internal/view/choose_board/choose_board.py index c778cbe..c503369 100644 --- a/src/internal/view/choose_board/choose_board.py +++ b/src/internal/view/choose_board/choose_board.py @@ -22,8 +22,13 @@ def _is_valid_uuid(uuid_to_test, version=4): return str(uuid_obj) == uuid_to_test -def _create_new_board(board_name_entry: ttk.Entry, board_key_entry: ttk.Entry, listbox: tkinter.Listbox, - path_to_file: str, available_boards: dict): +def _create_new_board( + board_name_entry: ttk.Entry, + board_key_entry: ttk.Entry, + listbox: tkinter.Listbox, + path_to_file: str, + available_boards: dict, +): board_name = board_name_entry.get() board_name_entry.delete(0, tkinter.END) @@ -40,7 +45,7 @@ def _create_new_board(board_name_entry: ttk.Entry, board_key_entry: ttk.Entry, l with open(path_to_file, 'a') as file: if available_boards: file.write('\n') - file.write(board_name + "#" + board_key) + file.write(board_name + '#' + board_key) available_boards[board_name] = board_key listbox.insert(tkinter.END, board_name) @@ -63,7 +68,7 @@ def get_board_name_key(): window = tkinter.Tk(className='Choose board') window.geometry('600x300') - path_to_file = "boards.txt" + path_to_file = 'boards.txt' available_boards = _load_from_file(path_to_file) boards_listbox = tkinter.Listbox() @@ -73,45 +78,47 @@ def get_board_name_key(): new_board_name_entry = ttk.Entry() new_board_name_entry.grid(column=1, row=0, padx=6, pady=6, sticky=tkinter.EW) - board_name_label = ttk.Label(text="Название доски") + board_name_label = ttk.Label(text='Название доски') board_name_label.grid(column=0, row=0, padx=6, pady=6, sticky=tkinter.EW) new_board_key_entry = ttk.Entry() new_board_key_entry.grid(column=1, row=1, padx=6, pady=6, sticky=tkinter.EW) - board_key_label = ttk.Label(text="Ключ доступа, если есть") + board_key_label = ttk.Label(text='Ключ доступа, если есть') board_key_label.grid(column=0, row=1, padx=6, pady=6, sticky=tkinter.EW) create_button = ttk.Button( text='Создать новую доску', - command=lambda board_name_entry_arg=new_board_name_entry, - board_key_entry_arg=new_board_key_entry, - boards_listbox_arg=boards_listbox, - path_to_file_arg=path_to_file, - available_boards_arg=available_boards: _create_new_board( + command=lambda board_name_entry_arg=new_board_name_entry, board_key_entry_arg=new_board_key_entry, boards_listbox_arg=boards_listbox, path_to_file_arg=path_to_file, available_boards_arg=available_boards: _create_new_board( board_name_entry_arg, board_key_entry_arg, boards_listbox_arg, path_to_file_arg, - available_boards_arg - ) + available_boards_arg, + ), ) create_button.grid(column=2, row=1, padx=6, pady=6) open_button = ttk.Button( - text='Открыть выбранную доску', command=lambda window_arg=window: window_arg.quit()) + text='Открыть выбранную доску', command=lambda window_arg=window: window_arg.quit() + ) open_button.grid(row=3, column=2, padx=5, pady=5) open_button['state'] = 'disabled' copy_key_button = ttk.Button( text='Скопировать ключ доски', - command=lambda available_boards_arg=available_boards, boards_listbox_arg=boards_listbox: - _copy_key(available_boards_arg, boards_listbox_arg)) + command=lambda available_boards_arg=available_boards, boards_listbox_arg=boards_listbox: _copy_key( + available_boards_arg, boards_listbox_arg + ), + ) copy_key_button.grid(row=3, column=0, padx=5, pady=5) copy_key_button['state'] = 'disabled' - boards_listbox.bind('<>', - lambda _, open_button_arg=open_button, copy_key_button_arg=copy_key_button: - _set_buttons_state_to_normal(open_button_arg, copy_key_button_arg), ) + boards_listbox.bind( + '<>', + lambda _, open_button_arg=open_button, copy_key_button_arg=copy_key_button: _set_buttons_state_to_normal( + open_button_arg, copy_key_button_arg + ), + ) window.mainloop() selected_board = boards_listbox.curselection() diff --git a/src/internal/view/objects/impl/object.py b/src/internal/view/objects/impl/object.py index 20be871..db5a949 100644 --- a/src/internal/view/objects/impl/object.py +++ b/src/internal/view/objects/impl/object.py @@ -89,10 +89,7 @@ def aligning(self, dependencies: internal.view.dependencies.Dependencies): # flag = False top = dependencies.canvas.find_overlapping( - obj_frame[0] - _PADDING, - obj_frame[1] - _PADDING, - obj_frame[2] + _PADDING, - obj_frame[1] + obj_frame[0] - _PADDING, obj_frame[1] - _PADDING, obj_frame[2] + _PADDING, obj_frame[1] ) for item in top: tags = dependencies.canvas.gettags(item) @@ -128,7 +125,7 @@ def aligning(self, dependencies: internal.view.dependencies.Dependencies): obj_frame[0] - _PADDING, obj_frame[3], obj_frame[2] + _PADDING, - obj_frame[3] + _PADDING + obj_frame[3] + _PADDING, ) for item in bottom: tags = dependencies.canvas.gettags(item) @@ -159,10 +156,7 @@ def aligning(self, dependencies: internal.view.dependencies.Dependencies): return self.remove_aligning(dependencies) left = dependencies.canvas.find_overlapping( - obj_frame[0] - _PADDING, - obj_frame[1] - _PADDING, - obj_frame[0], - obj_frame[3] + _PADDING + obj_frame[0] - _PADDING, obj_frame[1] - _PADDING, obj_frame[0], obj_frame[3] + _PADDING ) for item in left: tags = dependencies.canvas.gettags(item) @@ -197,7 +191,7 @@ def aligning(self, dependencies: internal.view.dependencies.Dependencies): obj_frame[2], obj_frame[1] - _PADDING, obj_frame[2] + _PADDING, - obj_frame[3] + _PADDING + obj_frame[3] + _PADDING, ) for item in right: tags = dependencies.canvas.gettags(item) @@ -206,8 +200,7 @@ def aligning(self, dependencies: internal.view.dependencies.Dependencies): continue obj_x1, obj_y1, obj_x2, obj_y2 = dependencies.canvas.bbox(tags[0]) if not ( - obj_y1 in [obj_frame[1], obj_frame[3]] or - obj_y2 in [obj_frame[1], obj_frame[3]] + obj_y1 in [obj_frame[1], obj_frame[3]] or obj_y2 in [obj_frame[1], obj_frame[3]] ): continue