From 756a1f7f4aa19ec3e1265e6a1ac6b2923b01f216 Mon Sep 17 00:00:00 2001 From: Moritz Makowski Date: Sun, 24 Mar 2024 15:33:43 +0100 Subject: [PATCH] Add many deprecation warnings --- docs/pages/api-reference.md | 51 ++++++++++++++++++++++++++++++++----- tum_esm_utils/context.py | 31 ++++++++++------------ tum_esm_utils/decorators.py | 11 ++++---- tum_esm_utils/files.py | 11 ++++++-- tum_esm_utils/github.py | 15 ++++++++++- tum_esm_utils/logger.py | 4 +++ tum_esm_utils/text.py | 4 +++ tum_esm_utils/timing.py | 2 +- tum_esm_utils/validators.py | 14 +++++++--- 9 files changed, 108 insertions(+), 35 deletions(-) diff --git a/docs/pages/api-reference.md b/docs/pages/api-reference.md index 22743f1..9ade0c5 100644 --- a/docs/pages/api-reference.md +++ b/docs/pages/api-reference.md @@ -15,10 +15,16 @@ Context managers for common tasks. Implements: `ensure_section_duration`, `set_alarm`, `clear_alarm`. +All functions in this module are deprecated and will be removed in the +next breaking release. Use the functions from the `timing` module instead. + ##### `ensure_section_duration` ```python +@deprecated( + "Will be removed in the next breaking release. Use `timing.ensure_section_duration` instead." +) @contextlib.contextmanager def ensure_section_duration(duration: float) -> Generator[None, None, None] ``` @@ -36,6 +42,9 @@ with ensure_section_duration(6): ##### `set_alarm` ```python +@deprecated( + "Will be removed in the next breaking release. Use `timing.set_alarm` instead." +) def set_alarm(timeout: int, label: str) -> None ``` @@ -47,6 +56,9 @@ Set an alarm that will raise a `TimeoutError` after ##### `clear_alarm` ```python +@deprecated( + "Will be removed in the next breaking release. Use `timing.clear_alarm` instead." +) def clear_alarm() -> None ``` @@ -159,7 +171,11 @@ should not interfere. A file "*.lock" will be created and the content of this file will make the wrapped function possibly wait until other programs are done using it. -See https://en.wikipedia.org/wiki/Semaphore_(programming) +See https://en.wikipedia.org/wiki/Semaphore_(programming). + + +Credits for the typing of higher level decorators goes to +https://github.com/python/mypy/issues/1551#issuecomment-253978622. ##### `__init__` @@ -177,7 +193,10 @@ File-related utility functions. Implements: `load_file`, `dump_file`, `load_json_file`, `dump_json_file`, `get_parent_dir_path`, `get_dir_checksum`, -`get_file_checksum`, `load_raw_proffast_output`, `rel_to_abs_path` +`get_file_checksum`, `load_raw_proffast_output`, `rel_to_abs_path`. + +`load_raw_proffast_output` is deprecated and will be removed in the +next breaking release. ##### `get_parent_dir_path` @@ -216,6 +235,9 @@ not spawn a new process. ##### `load_raw_proffast_output` ```python +@deprecated( + "Will be removed in the next breaking release. We will move this functionality into a separate library. The reason for this is that this function is the reason why the utils package requires `polars` which is still at release `0.X`. This results in frequent version conflicts." +) def load_raw_proffast_output( path: str, selected_columns: list[str] = [ @@ -310,6 +332,18 @@ Sends a request and returns the content of the response, as a string. Raises an HTTPError if the response status code is not 200. +**Arguments**: + +- `github_repository` - In the format "owner/repo". +- `filepath` - The path to the file in the repository. +- `access_token` - The GitHub access token. Only required if + the repo is private. + + +**Returns**: + + The content of the file as a string. + ## `tum_esm_utils.interferograms` @@ -670,6 +704,7 @@ Returns `True` if string is in a valid `YYYYMMDD` format ##### `date_range` ```python +@deprecated("Use `timing.date_range` instead") def date_range(from_date_string: str, to_date_string: str) -> list[str] ``` @@ -686,6 +721,7 @@ date_range("20210101", "20210103") == ["20210101", "20210102", "20210103"] ##### `is_datetime_string` ```python +@deprecated("Will be removed in the next breaking release") def is_datetime_string(datetime_string: str) -> bool ``` @@ -705,6 +741,7 @@ format. Caution: The appendix of `+00:00` is required for UTC! ##### `date_is_too_recent` ```python +@deprecated("Will be removed in the next breaking release") def date_is_too_recent(date_string: str, min_days_delay: int = 1) -> bool ``` @@ -805,7 +842,7 @@ parse_timezone_string("UTC+2.0") # returns 2 parse_timezone_string("UTC-02:00") # returns -2 ``` - You are required to pass a datetime object in can the utc offset for the + You are required to pass a datetime object in case the utc offset for the passed timezone is not constant - e.g. for "Europe/Berlin". @@ -813,9 +850,11 @@ parse_timezone_string("UTC-02:00") # returns -2 Implements validator functions for use with pydantic models. -Implements: `validate_bool`, `validate_float`, `validate_int`, -`validate_str`, `validate_list`, `StrictFilePath`, -`StrictDirectoryPath`. +Implements: `StrictFilePath`, `StrictDirectoryPath`. + +Also implements `validate_bool`, `validate_float`, `validate_int`, +`validate_str`, `validate_list` but these are deprecated and will +be removed in the next breaking release. ## `StrictFilePath` Objects diff --git a/tum_esm_utils/context.py b/tum_esm_utils/context.py index 0dc1361..83abb41 100644 --- a/tum_esm_utils/context.py +++ b/tum_esm_utils/context.py @@ -1,13 +1,19 @@ """Context managers for common tasks. -Implements: `ensure_section_duration`, `set_alarm`, `clear_alarm`.""" +Implements: `ensure_section_duration`, `set_alarm`, `clear_alarm`. + +All functions in this module are deprecated and will be removed in the +next breaking release. Use the functions from the `timing` module instead.""" from typing import Generator +from typing_extensions import deprecated import contextlib -import warnings from . import timing +@deprecated( + "Will be removed in the next breaking release. Use `timing.ensure_section_duration` instead." +) @contextlib.contextmanager def ensure_section_duration(duration: float) -> Generator[None, None, None]: """Make sure that the duration of the section is at least the given duration. @@ -20,34 +26,25 @@ def ensure_section_duration(duration: float) -> Generator[None, None, None]: ``` """ - warnings.warn( - "`context.ensure_section_duration` is deprecated, " + - "use `timing.ensure_section_duration` instead", - DeprecationWarning, - ) with timing.ensure_section_duration(duration): yield +@deprecated( + "Will be removed in the next breaking release. Use `timing.set_alarm` instead." +) def set_alarm(timeout: int, label: str) -> None: """Set an alarm that will raise a `TimeoutError` after `timeout` seconds. The message will be formatted as `{label} took too long (timed out after {timeout} seconds)`.""" - warnings.warn( - "`context.set_alarm` is deprecated, " + - "use `timing.set_alarm` instead", - DeprecationWarning, - ) timing.set_alarm(timeout, label) +@deprecated( + "Will be removed in the next breaking release. Use `timing.clear_alarm` instead." +) def clear_alarm() -> None: """Clear the alarm set by `set_alarm`.""" - warnings.warn( - "`context.clear_alarm` is deprecated, " + - "use `timing.clear_alarm` instead", - DeprecationWarning, - ) timing.clear_alarm() diff --git a/tum_esm_utils/decorators.py b/tum_esm_utils/decorators.py index 4101b05..f9f1460 100644 --- a/tum_esm_utils/decorators.py +++ b/tum_esm_utils/decorators.py @@ -7,19 +7,20 @@ import filelock import functools -# typing of higher level decorators: -# https://github.com/python/mypy/issues/1551#issuecomment-253978622 F = TypeVar("F", bound=Callable[..., Any]) class with_filelock: - """ - FileLock = Mark, that a file is being used and other programs + """FileLock = Mark, that a file is being used and other programs should not interfere. A file "*.lock" will be created and the content of this file will make the wrapped function possibly wait until other programs are done using it. - See https://en.wikipedia.org/wiki/Semaphore_(programming) + See https://en.wikipedia.org/wiki/Semaphore_(programming). + + + Credits for the typing of higher level decorators goes to + https://github.com/python/mypy/issues/1551#issuecomment-253978622. """ def __init__(self, lockfile_path: str, timeout: float = -1) -> None: """A timeout of -1 means that the code waits forever.""" diff --git a/tum_esm_utils/files.py b/tum_esm_utils/files.py index a97c212..a8e3f1d 100644 --- a/tum_esm_utils/files.py +++ b/tum_esm_utils/files.py @@ -2,11 +2,15 @@ Implements: `load_file`, `dump_file`, `load_json_file`, `dump_json_file`, `get_parent_dir_path`, `get_dir_checksum`, -`get_file_checksum`, `load_raw_proffast_output`, `rel_to_abs_path`""" +`get_file_checksum`, `load_raw_proffast_output`, `rel_to_abs_path`. + +`load_raw_proffast_output` is deprecated and will be removed in the +next breaking release.""" from __future__ import annotations -import traceback from typing import Any, List, Optional +from typing_extensions import deprecated +import traceback import hashlib import json import os @@ -66,6 +70,9 @@ def get_file_checksum(path: str) -> str: return hashlib.md5(f.read()).hexdigest() +@deprecated( + "Will be removed in the next breaking release. We will move this functionality into a separate library. The reason for this is that this function is the reason why the utils package requires `polars` which is still at release `0.X`. This results in frequent version conflicts." +) def load_raw_proffast_output( path: str, selected_columns: list[str] = [ diff --git a/tum_esm_utils/github.py b/tum_esm_utils/github.py index 3185f19..8c27378 100644 --- a/tum_esm_utils/github.py +++ b/tum_esm_utils/github.py @@ -13,7 +13,17 @@ def request_github_file( ) -> str: """Sends a request and returns the content of the response, as a string. Raises an HTTPError if the response status code - is not 200.""" + is not 200. + + Args: + github_repository: In the format "owner/repo". + filepath: The path to the file in the repository. + access_token: The GitHub access token. Only required if + the repo is private. + + Returns: + The content of the file as a string. + """ response = requests.get( f"https://raw.githubusercontent.com/{github_repository}/main/{filepath}", @@ -25,3 +35,6 @@ def request_github_file( ) response.raise_for_status() return response.text + + +# TODO: add "request gitlab file" diff --git a/tum_esm_utils/logger.py b/tum_esm_utils/logger.py index 70a4295..f88521c 100644 --- a/tum_esm_utils/logger.py +++ b/tum_esm_utils/logger.py @@ -11,6 +11,7 @@ import sys import traceback import datetime +from typing_extensions import deprecated import filelock @@ -204,6 +205,9 @@ def _write_log_line( if (now - Logger.last_archive_time).total_seconds() > 600: self._archive() + @deprecated( + "Will be removed in the next breaking release. The logger will write into the archive by default and optionally keep a separate log file containing the latest x minutes. This makes the archive parsing logic redundant." + ) def _archive(self) -> None: """moves old log lines in "logs/current-logs.log" into an archive file "logs/archive/YYYYMMDD.log". log lines from diff --git a/tum_esm_utils/text.py b/tum_esm_utils/text.py index a826df2..0a494b8 100644 --- a/tum_esm_utils/text.py +++ b/tum_esm_utils/text.py @@ -10,6 +10,7 @@ import datetime import random import string +from typing_extensions import deprecated import warnings from . import timing @@ -47,6 +48,7 @@ def is_date_string(date_string: str) -> bool: return False +@deprecated("Use `timing.date_range` instead") def date_range(from_date_string: str, to_date_string: str) -> list[str]: """Returns a list of dates between `from_date_string` and `to_date_string`. @@ -71,6 +73,7 @@ def date_range(from_date_string: str, to_date_string: str) -> list[str]: return [d.strftime("%Y%m%d") for d in timing.date_range(from_date, to_date)] +@deprecated("Will be removed in the next breaking release") def is_datetime_string(datetime_string: str) -> bool: """Returns `True` if string is in a valid `YYYYMMDD HH:mm:ss` format""" @@ -98,6 +101,7 @@ def is_rfc3339_datetime_string(rfc3339_datetime_string: str) -> bool: return False +@deprecated("Will be removed in the next breaking release") def date_is_too_recent( date_string: str, min_days_delay: int = 1, diff --git a/tum_esm_utils/timing.py b/tum_esm_utils/timing.py index 20af538..c78c92c 100644 --- a/tum_esm_utils/timing.py +++ b/tum_esm_utils/timing.py @@ -86,7 +86,7 @@ def parse_timezone_string( parse_timezone_string("UTC-02:00") # returns -2 ``` - You are required to pass a datetime object in can the utc offset for the + You are required to pass a datetime object in case the utc offset for the passed timezone is not constant - e.g. for "Europe/Berlin".""" offset: float = 0 diff --git a/tum_esm_utils/validators.py b/tum_esm_utils/validators.py index 2f007b0..0eb2215 100644 --- a/tum_esm_utils/validators.py +++ b/tum_esm_utils/validators.py @@ -1,14 +1,17 @@ """Implements validator functions for use with pydantic models. -Implements: `validate_bool`, `validate_float`, `validate_int`, -`validate_str`, `validate_list`, `StrictFilePath`, -`StrictDirectoryPath`.""" +Implements: `StrictFilePath`, `StrictDirectoryPath`. + +Also implements `validate_bool`, `validate_float`, `validate_int`, +`validate_str`, `validate_list` but these are deprecated and will +be removed in the next breaking release.""" from __future__ import annotations from typing import Any, Callable, Optional, TypeVar import os import re import datetime +from typing_extensions import deprecated import warnings import pydantic @@ -52,6 +55,7 @@ def _is_rfc3339_datetime_string(datetime_string: str) -> bool: return False +@deprecated("will be removed in the next breaking release") def validate_bool() -> Callable[[Any, bool], bool]: def f(cls: Any, v: Any) -> bool: if not isinstance(v, bool): @@ -61,6 +65,7 @@ def f(cls: Any, v: Any) -> bool: return f +@deprecated("will be removed in the next breaking release") def validate_float( nullable: bool = False, minimum: Optional[float] = None, @@ -83,6 +88,7 @@ def f(cls: Any, v: float) -> float: return f +@deprecated("will be removed in the next breaking release") def validate_int( nullable: bool = False, minimum: Optional[int] = None, @@ -111,6 +117,7 @@ def f(cls: Any, v: Optional[int]) -> Optional[int]: return f +@deprecated("will be removed in the next breaking release") def validate_str( nullable: bool = False, min_len: Optional[float] = None, @@ -175,6 +182,7 @@ def f(cls: Any, v: str) -> str: T = TypeVar("T") +@deprecated("will be removed in the next breaking release") def validate_list( min_len: Optional[float] = None, max_len: Optional[float] = None,