diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 991d0d6..e6fb94e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ exclude: '^docs/conf.py' repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: trailing-whitespace - id: check-added-large-files @@ -36,12 +36,12 @@ repos: # ] - repo: https://github.com/PyCQA/isort - rev: 5.11.5 + rev: 5.13.2 hooks: - id: isort - repo: https://github.com/psf/black - rev: stable + rev: 24.2.0 hooks: - id: black language_version: python3 @@ -54,7 +54,7 @@ repos: # additional_dependencies: [black] - repo: https://github.com/PyCQA/flake8 - rev: 5.0.4 + rev: 7.0.0 hooks: - id: flake8 ## You can add flake8 plugins via `additional_dependencies`: diff --git a/setup.cfg b/setup.cfg index 6e23dd4..153f45f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,7 +5,7 @@ [metadata] name = wd_fw_update -description = Add a short description here! +description = Updates the firmware of Western Digital SSDs on Ubuntu / Linux Mint. author = Jules Kreuer author_email = contact@juleskreuer.eu license = GPL-3.0-or-later @@ -68,9 +68,9 @@ testing = pytest-cov [options.entry_points] -# Add here console scripts like: -# console_scripts = -# script_name = wd_fw_update.module:function +console_scripts = + wd_fw_update = wd_fw_update.main:run + # For example: # console_scripts = # fibonacci = wd_fw_update.skeleton:run @@ -105,7 +105,7 @@ formats = bdist_wheel [flake8] # Some sane defaults for the code style checker flake8 -max_line_length = 88 +max_line_length = 100 extend_ignore = E203, W503 # ^ Black-compatible # E203 and W503 have edge cases handled by black diff --git a/src/wd_fw_update/main.py b/src/wd_fw_update/main.py new file mode 100644 index 0000000..d4fbd14 --- /dev/null +++ b/src/wd_fw_update/main.py @@ -0,0 +1,133 @@ +import argparse +import logging +import sys + +from wd_fw_update import __version__ + +__author__ = "Jules Kreuer" +__copyright__ = "Jules Kreuer" +__license__ = "GPL-3.0-or-later" + +_logger = logging.getLogger(__name__) + + +def parse_args(args): + """Parse command line parameters + + Args: + args (List[str]): command line parameters as list of strings + (for example ``["--help"]``). + + Returns: + :obj:`argparse.Namespace`: command line parameters namespace + """ + parser = argparse.ArgumentParser(description="Just a Fibonacci demonstration") + parser.add_argument( + "--version", + action="version", + version=f"wd_fw_update {__version__}", + ) + parser.add_argument(dest="n", help="n-th Fibonacci number", type=int, metavar="INT") + parser.add_argument( + "-v", + "--verbose", + dest="loglevel", + help="set loglevel to INFO", + action="store_const", + const=logging.INFO, + ) + parser.add_argument( + "-vv", + "--very-verbose", + dest="loglevel", + help="set loglevel to DEBUG", + action="store_const", + const=logging.DEBUG, + ) + return parser.parse_args(args) + + +def setup_logging(loglevel): + """Setup basic logging + + Args: + loglevel (int): minimum loglevel for emitting messages + """ + logformat = "[%(asctime)s] %(levelname)s:%(name)s:%(message)s" + logging.basicConfig( + level=loglevel, + stream=sys.stdout, + format=logformat, + datefmt="[%Y-%m-%d %H:%M:%S]", + ) + + +def check_dependencies(): + return + + +def get_model(): + return + + +def get_fw_url(): + return + + +def download_fw(): + return + + +def update_fw(): + return + + +def wd_fw_update(): + """Updates the firmware of Western Digital SSDs on Ubuntu / Linux Mint.""" + + # Step 0: Check dependencies + + # Step 1: Get model number and firmware version + + # Step 2: Fetch the device list and find the firmware URL + + # Step 3: Check firmware version dependencies + + # Step 4: Download firmware file + + # Step 5: Update the firmware + + +def main(args): + """Wrapper allowing :func:`wd_fw_update` to be called with string arguments in a CLI fashion + + Instead of returning the value from :func:`wd_fw_update`, it prints the result to the + ``stdout`` in a nicely formatted message. + + Args: + args (List[str]): command line parameters as list of strings + (for example ``["--verbose", "--help"]``). + """ + args = parse_args(args) + setup_logging(args.loglevel) + _logger.debug(args) + + wd_fw_update() + + _logger.info("[END of script]") + + +def run(): + """Calls :func:`main` passing the CLI arguments extracted from :obj:`sys.argv` + + This function is used as entry point to create console scripts with setuptools. + """ + main(sys.argv[1:]) + + +if __name__ == "__main__": + # ^ This is a guard statement that will prevent the following code from + # being executed in the case someone imports this file instead of + # executing it as a script. + # https://docs.python.org/3/library/__main__.html + run() diff --git a/src/wd_fw_update/skeleton.py b/src/wd_fw_update/skeleton.py deleted file mode 100644 index e773c15..0000000 --- a/src/wd_fw_update/skeleton.py +++ /dev/null @@ -1,149 +0,0 @@ -""" -This is a skeleton file that can serve as a starting point for a Python -console script. To run this script uncomment the following lines in the -``[options.entry_points]`` section in ``setup.cfg``:: - - console_scripts = - fibonacci = wd_fw_update.skeleton:run - -Then run ``pip install .`` (or ``pip install -e .`` for editable mode) -which will install the command ``fibonacci`` inside your current environment. - -Besides console scripts, the header (i.e. until ``_logger``...) of this file can -also be used as template for Python modules. - -Note: - This file can be renamed depending on your needs or safely removed if not needed. - -References: - - https://setuptools.pypa.io/en/latest/userguide/entry_point.html - - https://pip.pypa.io/en/stable/reference/pip_install -""" - -import argparse -import logging -import sys - -from wd_fw_update import __version__ - -__author__ = "Jules Kreuer" -__copyright__ = "Jules Kreuer" -__license__ = "GPL-3.0-or-later" - -_logger = logging.getLogger(__name__) - - -# ---- Python API ---- -# The functions defined in this section can be imported by users in their -# Python scripts/interactive interpreter, e.g. via -# `from wd_fw_update.skeleton import fib`, -# when using this Python module as a library. - - -def fib(n): - """Fibonacci example function - - Args: - n (int): integer - - Returns: - int: n-th Fibonacci number - """ - assert n > 0 - a, b = 1, 1 - for _i in range(n - 1): - a, b = b, a + b - return a - - -# ---- CLI ---- -# The functions defined in this section are wrappers around the main Python -# API allowing them to be called directly from the terminal as a CLI -# executable/script. - - -def parse_args(args): - """Parse command line parameters - - Args: - args (List[str]): command line parameters as list of strings - (for example ``["--help"]``). - - Returns: - :obj:`argparse.Namespace`: command line parameters namespace - """ - parser = argparse.ArgumentParser(description="Just a Fibonacci demonstration") - parser.add_argument( - "--version", - action="version", - version=f"wd_fw_update {__version__}", - ) - parser.add_argument(dest="n", help="n-th Fibonacci number", type=int, metavar="INT") - parser.add_argument( - "-v", - "--verbose", - dest="loglevel", - help="set loglevel to INFO", - action="store_const", - const=logging.INFO, - ) - parser.add_argument( - "-vv", - "--very-verbose", - dest="loglevel", - help="set loglevel to DEBUG", - action="store_const", - const=logging.DEBUG, - ) - return parser.parse_args(args) - - -def setup_logging(loglevel): - """Setup basic logging - - Args: - loglevel (int): minimum loglevel for emitting messages - """ - logformat = "[%(asctime)s] %(levelname)s:%(name)s:%(message)s" - logging.basicConfig( - level=loglevel, stream=sys.stdout, format=logformat, datefmt="%Y-%m-%d %H:%M:%S" - ) - - -def main(args): - """Wrapper allowing :func:`fib` to be called with string arguments in a CLI fashion - - Instead of returning the value from :func:`fib`, it prints the result to the - ``stdout`` in a nicely formatted message. - - Args: - args (List[str]): command line parameters as list of strings - (for example ``["--verbose", "42"]``). - """ - args = parse_args(args) - setup_logging(args.loglevel) - _logger.debug("Starting crazy calculations...") - print(f"The {args.n}-th Fibonacci number is {fib(args.n)}") - _logger.info("Script ends here") - - -def run(): - """Calls :func:`main` passing the CLI arguments extracted from :obj:`sys.argv` - - This function can be used as entry point to create console scripts with setuptools. - """ - main(sys.argv[1:]) - - -if __name__ == "__main__": - # ^ This is a guard statement that will prevent the following code from - # being executed in the case someone imports this file instead of - # executing it as a script. - # https://docs.python.org/3/library/__main__.html - - # After installing your project with pip, users can also run your Python - # modules as scripts via the ``-m`` flag, as defined in PEP 338:: - # - # python -m wd_fw_update.skeleton 42 - # - run()