From 7dd7b57e1ff8d1f58f85ac9ea8d154b8fd5a1fbd Mon Sep 17 00:00:00 2001 From: furtest Date: Sun, 4 Jan 2026 14:31:16 +0100 Subject: [PATCH] synchroniser : Use a consistent docstring format. Edit the docstrings so they use a consistent format. Also add a short module docstring. --- src/unisync/synchroniser.py | 129 ++++++++++++++++++++++++++---------- 1 file changed, 94 insertions(+), 35 deletions(-) diff --git a/src/unisync/synchroniser.py b/src/unisync/synchroniser.py index 6f5cd72..8a39e44 100644 --- a/src/unisync/synchroniser.py +++ b/src/unisync/synchroniser.py @@ -1,6 +1,12 @@ # Copyright (C) 2025-2026 Paul Retourné # SPDX-License-Identifier: GPL-3.0-or-later +"""Exports the Synchroniser class. + +This class is used to perform all the actions that require a connection to +the remote. +""" + import subprocess import os import sys @@ -14,9 +20,37 @@ from unisync.errors import RemoteMountedError, InvalidMountError logger = logging.getLogger(__name__) class Synchroniser: + """Synchroniser used to synchronise with a server. + + It is used to perform every action needing a connection to the remote. + Create an ssh connection. + Perform the various synchronisation steps (files, links). + Update the links on the remote. + Mount the remote directory. + Close the ssh connection. + + Attributes: + remote: The directory to synchronise to on the remote. + local: The directory to synchronise from locally. + user: The user on the remote server. + ip: The ip of the remote server. + port: The ssh port on the remote. + args_bool: + A list of boolean arguments for unison. + They will be passed directly to unison when calling it. + For example : auto will be passed as -auto + args_value: + Same as args_bool but for key value arguments. + Will be passed to unison as "-key value". + ssh_settings: + Settings to pass to the underlying ssh connection. + Currently unused. + """ def __init__(self, remote:str, local:str, user:str, ip:str, port:int=22, args_bool:list=[], args_value:dict={}, ssh_settings:dict={}): + """Initialises an instance of Synchroniser. + """ self.remote_dir:str = remote self.local:str = local self.args_bool:list[str] = args_bool @@ -27,14 +61,21 @@ class Synchroniser: self.remote_port:int = port def create_ssh_master_connection(self, control_path:str="~/.ssh/control_%C", connection_timeout:int=60) -> int: - """ - Creates an ssh master connection so the user only has to authenticate once to the remote server. - The subsequent connections will be made through this master connection which speeds up connecting. - @control_path: Set the location of the ssh control socket - @connection_timeout: - Time given to the user to authenticate to the remote server. - On slow connections one might want to increase this. - Returns 0 on success. + """Creates an ssh master connection. + + It is used so the user only has to authenticate once to the remote server. + The subsequent connections will be made through this master connection + which speeds up connnection. + The users only have to enter their password once per synchronisation. + + Args: + control_path: Set the location of the ssh control socket + connection_timeout: + Time given to the user to authenticate to the remote server. + On slow connections one might want to increase this. + Returns: + An error code (0 success, 1 TimeoutExpired, 2 KeyboardInterrupt). + TODO change that to raising the exception. """ self.control_path = os.path.expanduser(control_path) command = [ @@ -61,8 +102,10 @@ class Synchroniser: def close_ssh_master_connection(self) -> int: - """ - Close the ssh master connection. + """Closes the ssh master connection. + + Returns: + The return code of the ssh call. """ command = [ "/usr/bin/ssh", @@ -75,8 +118,14 @@ class Synchroniser: return close.wait() def sync_files(self, paths:list, force:bool=False) -> int: - """ - Synchronises the files. + """Synchronises the files. + + Args: + paths: List of paths to synchronise. + force: Force the changes from remote to local. + + Returns: + The return code of sync. """ return self.sync( f"ssh://{self.remote_user}@{self.remote_ip}/{self.remote_dir}/.data", @@ -86,8 +135,13 @@ class Synchroniser: ) def sync_links(self, ignore:list) -> int: - """ - Synchronises the links, they must exist already. + """Synchronises the links, they must exist already. + + Args: + ignore: List of paths to ignore. + + Returns: + The return code of sync. """ return self.sync( f"ssh://{self.remote_user}@{self.remote_ip}/{self.remote_dir}/links", @@ -97,17 +151,20 @@ class Synchroniser: def sync(self, remote_root:str, local_root:str, paths:list=[], ignore:list=[], force:bool=False) -> int: - """ - Perform the synchronisation by calling unison. - @remote_root: The remote root, must be a full root usable by unison. - @local_root: The local root, must be a full root usable by unison. - @paths: List of paths to synchronise - @ignore: List of paths to ignore - The paths and everything under them will be ignored. - If you need to ignore some specific files use the arguments. - @force: Force all changes from remote to local. - Used mostly when replacing a link by the file. - Returns: the unison return code see section 6.11 of the documentation + """Performs the synchronisation by calling unison. + + Args: + remote_root: The remote root, must be a full root usable by unison. + local_root: The local root, must be a full root usable by unison. + paths: List of paths to synchronise + ignore: List of paths to ignore + The paths and everything under them will be ignored. + If you need to ignore some specific files use the arguments. + force: Force all changes from remote to local. + Used mostly when replacing a link by the file. + + Returns: + the unison return code see section 6.11 of the documentation """ command = [ "/usr/bin/unison", "-root", remote_root, "-root", local_root ] for arg in self.args_bool: @@ -140,12 +197,13 @@ class Synchroniser: return ret_code def update_links(self, background:bool=True): - """ - Update the links on the remote. + """Updates the links on the remote. + First calls cleanlinks to remove deadlinks and empty directories. Then calls lndir to create the new links. + Args: - - background: controls if the update is done in the background or waited for + background: controls if the update is done in the background or waited for. """ link_update_script = (f"cd {self.remote_dir}/links && " @@ -173,13 +231,14 @@ class Synchroniser: print("Done") def mount_remote_dir(self): - """ - Mount the remote directory to make the local links work. - This is achieved using sshfs. - Raise: - - RemoteMountedError: The .data directory is already a mount point - - InvalidMountError: .data is either not a directory or not empty - - subprocess.CalledProcessError: An error occured with sshfs + """Mounts the remote directory to make the local links work. + + This is achieved using sshfs which may fail. + + Raises: + RemoteMountedError: The .data directory is already a mount point. + InvalidMountError: .data is either not a directory or not empty. + subprocess.CalledProcessError: An error occured with sshfs. """ # Get the absolute path to the correct .data directory resolving symlinks path_to_mount:Path = Path(f"{self.local}/../.data").resolve()