From da8831037048618ffc5f2cd878136ba674207a8f Mon Sep 17 00:00:00 2001 From: bmeares Date: Tue, 23 Jun 2026 00:33:03 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20v3.4.3=20Add=20plugin=20version?= =?UTF-8?q?=20endpoint,=20fix=20shell=20login=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 24 ++++++++++++++++++++++ docs/zensical/llms-full.txt | 24 ++++++++++++++++++++++ docs/zensical/news/changelog.md | 24 ++++++++++++++++++++++ meerschaum/_internal/shell/updates.py | 12 ++++++----- meerschaum/api/routes/_plugins.py | 23 ++++++++++++++++----- meerschaum/config/_version.py | 2 +- meerschaum/connectors/api/_APIConnector.py | 1 + meerschaum/connectors/api/_login.py | 2 ++ meerschaum/connectors/api/_plugins.py | 21 +++++++++++++++++++ meerschaum/utils/dtypes/__init__.py | 15 ++++++++++++++ 10 files changed, 137 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d798a06c..48c3a1501 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,30 @@ This is the current release cycle, so stay tuned for future releases! +### v3.4.3 + +- **Add a plugin version API endpoint.** + The endpoint `/plugins/{name}/version` now returns a plugin's version string. + +- **Hide login warning on plugin updater thread.** + The plugins updater thread no longer will raise a login warning. + +- **Add precision kwarg aliases to `get_current_timestamp()`.** + You may now treat `Pipe.precision` as kwargs for `get_current_timestamp()`: + + ```python + import meerschaum as mrsm + from meerschaum.utils.dtypes import get_current_timestamp + + pipe = mrsm.Pipe( + 'demo', 'precision', 'timestamp', instance='sql:local', + precision={'unit': 's', 'interval': 30}, + ) + now = get_current_timestamp(**pipe.precision) + print(now) + # 2026-06-23 04:30:30+00:00 + ``` + ### v3.4.2 - **Run inline Python with `mrsm python -c`.** diff --git a/docs/zensical/llms-full.txt b/docs/zensical/llms-full.txt index a53a54b6e..3fd7d5528 100644 --- a/docs/zensical/llms-full.txt +++ b/docs/zensical/llms-full.txt @@ -8241,6 +8241,30 @@ Source: https://meerschaum.io/news/changelog/ This is the current release cycle, so stay tuned for future releases! +### v3.4.3 + +- **Add a plugin version API endpoint.** + The endpoint `/plugins/{name}/version` now returns a plugin's version string. + +- **Hide login warning on plugin updater thread.** + The plugins updater thread no longer will raise a login warning. + +- **Add precision kwarg aliases to `get_current_timestamp()`.** + You may now treat `Pipe.precision` as kwargs for `get_current_timestamp()`: + + ```python + import meerschaum as mrsm + from meerschaum.utils.dtypes import get_current_timestamp + + pipe = mrsm.Pipe( + 'demo', 'precision', 'timestamp', instance='sql:local', + precision={'unit': 's', 'interval': 30}, + ) + now = get_current_timestamp(**pipe.precision) + print(now) + # 2026-06-23 04:30:30+00:00 + ``` + ### v3.4.2 - **Run inline Python with `mrsm python -c`.** diff --git a/docs/zensical/news/changelog.md b/docs/zensical/news/changelog.md index 1d798a06c..48c3a1501 100644 --- a/docs/zensical/news/changelog.md +++ b/docs/zensical/news/changelog.md @@ -4,6 +4,30 @@ This is the current release cycle, so stay tuned for future releases! +### v3.4.3 + +- **Add a plugin version API endpoint.** + The endpoint `/plugins/{name}/version` now returns a plugin's version string. + +- **Hide login warning on plugin updater thread.** + The plugins updater thread no longer will raise a login warning. + +- **Add precision kwarg aliases to `get_current_timestamp()`.** + You may now treat `Pipe.precision` as kwargs for `get_current_timestamp()`: + + ```python + import meerschaum as mrsm + from meerschaum.utils.dtypes import get_current_timestamp + + pipe = mrsm.Pipe( + 'demo', 'precision', 'timestamp', instance='sql:local', + precision={'unit': 's', 'interval': 30}, + ) + now = get_current_timestamp(**pipe.precision) + print(now) + # 2026-06-23 04:30:30+00:00 + ``` + ### v3.4.2 - **Run inline Python with `mrsm python -c`.** diff --git a/meerschaum/_internal/shell/updates.py b/meerschaum/_internal/shell/updates.py index 619460036..57ff02f3f 100644 --- a/meerschaum/_internal/shell/updates.py +++ b/meerschaum/_internal/shell/updates.py @@ -164,19 +164,21 @@ def _get_remote_plugin_version( name: str, repo_keys: str, debug: bool = False, -) -> Optional[str]: +) -> Union[str, None]: """Return the latest version of a plugin from its origin repository.""" try: from meerschaum.core import Plugin from meerschaum.connectors.parse import parse_repo_keys conn = parse_repo_keys(repo_keys) + _warn = conn.__dict__.pop('_warn', None) + conn._warn = False plugin = Plugin(name, repo=repo_keys) - attributes = conn.get_plugin_attributes(plugin, debug=debug) + version = conn.get_plugin_version(plugin, debug=debug) + if _warn is not None: + conn._warn = _warn except Exception: return None - if not isinstance(attributes, dict): - return None - return attributes.get('version') + return version def run_version_check_thread(debug: bool = False) -> Union[Thread, None]: diff --git a/meerschaum/api/routes/_plugins.py b/meerschaum/api/routes/_plugins.py index c05ef308c..3bcec4ec4 100644 --- a/meerschaum/api/routes/_plugins.py +++ b/meerschaum/api/routes/_plugins.py @@ -12,9 +12,8 @@ import pathlib import os -import meerschaum as mrsm from meerschaum.core import User -from meerschaum.utils.typing import Optional, List, SuccessTuple, Any, Dict +from meerschaum.utils.typing import Optional, List, SuccessTuple, Any, Dict, Union from meerschaum.api import ( fastapi, @@ -24,7 +23,6 @@ manager, debug, private, - no_auth, default_instance_keys, ScopedAuth, ) @@ -110,7 +108,11 @@ def register_plugin( if curr_user is not None: plugin_user_id = get_api_connector(PLUGINS_INSTANCE_KEYS).get_plugin_user_id(plugin, debug=debug) - curr_user_id = get_api_connector(PLUGINS_INSTANCE_KEYS).get_user_id(curr_user, debug=debug) if curr_user is not None else -1 + curr_user_id = ( + get_api_connector(PLUGINS_INSTANCE_KEYS).get_user_id(curr_user, debug=debug) + if curr_user is not None + else -1 + ) if plugin_user_id is not None and plugin_user_id != curr_user_id: return False, f"User '{curr_user.username}' cannot edit plugin '{plugin}'." plugin.user_id = curr_user_id @@ -154,7 +156,18 @@ def get_plugin_attributes( """ Get a plugin's attributes. """ - return get_api_connector(PLUGINS_INSTANCE_KEYS).get_plugin_attributes(Plugin(name)) + return get_api_connector(PLUGINS_INSTANCE_KEYS).get_plugin_attributes(Plugin(name), debug=debug) + + +@app.get(plugins_endpoint + '/{name}/version') +def get_plugin_version( + name: str, + curr_user = fastapi.Depends(ScopedAuth(['plugins:read'])) if private else None, +) -> Union[str, None]: + """ + Get a plugin's version. + """ + return get_api_connector(PLUGINS_INSTANCE_KEYS).get_plugin_version(Plugin(name), debug=debug) or None @app.get(plugins_endpoint, tags=['Plugins']) diff --git a/meerschaum/config/_version.py b/meerschaum/config/_version.py index 95bd101aa..b5f52bf4f 100644 --- a/meerschaum/config/_version.py +++ b/meerschaum/config/_version.py @@ -2,4 +2,4 @@ Specify the Meerschaum release version. """ -__version__ = "3.4.2" +__version__ = "3.4.3" diff --git a/meerschaum/connectors/api/_APIConnector.py b/meerschaum/connectors/api/_APIConnector.py index ee2f543af..151e3ac93 100644 --- a/meerschaum/connectors/api/_APIConnector.py +++ b/meerschaum/connectors/api/_APIConnector.py @@ -76,6 +76,7 @@ class APIConnector(InstanceConnector): delete_plugin, get_plugins, get_plugin_attributes, + get_plugin_version, ) from ._login import login, test_connection from ._users import ( diff --git a/meerschaum/connectors/api/_login.py b/meerschaum/connectors/api/_login.py index 8c291db2b..ebf725cf9 100644 --- a/meerschaum/connectors/api/_login.py +++ b/meerschaum/connectors/api/_login.py @@ -22,6 +22,8 @@ def login( **kw: Any ) -> SuccessTuple: """Log in and set the session token.""" + if warn and self.__dict__.get('_warn', None) is False: + warn = False if self.login_scheme == 'api_key': validate_response = self.post( STATIC_CONFIG['api']['endpoints']['tokens'] + '/validate', diff --git a/meerschaum/connectors/api/_plugins.py b/meerschaum/connectors/api/_plugins.py index 0a9190eb4..83a5a59cc 100644 --- a/meerschaum/connectors/api/_plugins.py +++ b/meerschaum/connectors/api/_plugins.py @@ -152,6 +152,27 @@ def get_plugin_attributes( return attributes +def get_plugin_version( + self, + plugin: mrsm.core.Plugin, + debug: bool = False +) -> Union[str, None]: + """ + Return a plugin's version. + """ + from meerschaum.utils.warnings import warn + r_url = plugin_r_url(plugin) + '/version' + response = self.get(r_url, use_token=True, debug=debug) + if not response: + return None + try: + version = response.json() + except Exception as e: + warn(f"Cannot parse version for {plugin}:\n{e}") + version = None + return version or None + + def delete_plugin( self, plugin: mrsm.core.Plugin, diff --git a/meerschaum/utils/dtypes/__init__.py b/meerschaum/utils/dtypes/__init__.py index ac109d030..da59b3fa4 100644 --- a/meerschaum/utils/dtypes/__init__.py +++ b/meerschaum/utils/dtypes/__init__.py @@ -1141,6 +1141,8 @@ def get_current_timestamp( round_to: str = 'down', as_pandas: bool = False, as_int: bool = False, + unit: str = _STATIC_CONFIG['dtypes']['datetime']['default_precision_unit'], + interval: int = 1, _now: Union[datetime, int, None] = None, ) -> 'Union[datetime, pd.Timestamp, int]': """ @@ -1176,6 +1178,12 @@ def get_current_timestamp( If `True`, return the timestamp to an integer. Overrides `as_pandas`. + unit: str, default 'us' + Alias for `precision_unit`. + + interval: int, default 1 + Alias for `precision_interval`. + Returns ------- A Pandas Timestamp, datetime object, or integer with precision to the provided unit. @@ -1187,6 +1195,13 @@ def get_current_timestamp( >>> get_current_timestamp('ms') Timestamp('2025-07-17 17:59:16.424000+0000', tz='UTC') """ + default_unit = _STATIC_CONFIG['dtypes']['datetime']['default_precision_unit'] + if unit != precision_unit and precision_unit == default_unit: + precision_unit = unit + + if interval != precision_interval and precision_interval == 1: + precision_interval = interval + true_precision_unit = MRSM_PRECISION_UNITS_ALIASES.get(precision_unit, precision_unit) if true_precision_unit not in MRSM_PRECISION_UNITS_SCALARS: from meerschaum.utils.misc import items_str