From ec3cdaa1443e09c80bbdad729b8f373ea47bc2b3 Mon Sep 17 00:00:00 2001 From: SHRISHTISHUKLA-0 Date: Thu, 13 Feb 2025 10:26:12 +0530 Subject: [PATCH 1/4] Fixed import issue for _camelCase in handlers.py --- jupyterlab_server/handlers.py | 277 +++++++++------------------------- jupyterlab_server/utils.py | 4 + 2 files changed, 74 insertions(+), 207 deletions(-) create mode 100644 jupyterlab_server/utils.py diff --git a/jupyterlab_server/handlers.py b/jupyterlab_server/handlers.py index 79df953..2143308 100644 --- a/jupyterlab_server/handlers.py +++ b/jupyterlab_server/handlers.py @@ -2,15 +2,15 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. -from __future__ import annotations +from __future__ import annotations import os import pathlib import warnings from functools import lru_cache from typing import TYPE_CHECKING, Any from urllib.parse import urlparse - +from jupyterlab_server .utils import _camelCase from jupyter_server.base.handlers import FileFindHandler, JupyterHandler from jupyter_server.extension.handler import ExtensionHandlerJinjaMixin, ExtensionHandlerMixin from jupyter_server.utils import url_path_join as ujoin @@ -18,7 +18,6 @@ from .config import LabConfig, get_page_config, recursive_update from .licenses_handler import LicensesHandler, LicensesManager -from .listings_handler import ListingsHandler, fetch_listings from .settings_handler import SettingsHandler from .settings_utils import _get_overrides from .themes_handler import ThemesHandler @@ -27,6 +26,7 @@ if TYPE_CHECKING: from .app import LabServerApp + # ----------------------------------------------------------------------------- # Module globals # ----------------------------------------------------------------------------- @@ -35,8 +35,7 @@ r"/(?P{}|doc)(?P/workspaces/[a-zA-Z0-9\-\_]+)?(?P/tree/.*)?" ) -DEFAULT_TEMPLATE = template.Template( - """ +DEFAULT_TEMPLATE = template.Template(""" @@ -48,15 +47,24 @@

In "{{path}}"

-""" -) +""") def is_url(url: str) -> bool: - """Test whether a string is a full url (e.g. https://nasa.gov) - - https://stackoverflow.com/a/52455972 - """ + """Test whether a string is a full URL (e.g. https://nasa.gov)""" + try: + result = urlparse(url) + return all([result.scheme, result.netloc]) + except ValueError: + return False + from urllib.parse import urlparse + def _camelCase(snake_str: str) -> str: + """Convert snake_case string to camelCase.""" + components = snake_str.split('_') + return components[0] + ''.join(x.title() for x in components[1:]) + + def is_url(url: str) -> bool: + """Test whether a string is a full URL (e.g., https://nasa.gov).""" try: result = urlparse(url) return all([result.scheme, result.netloc]) @@ -67,84 +75,69 @@ def is_url(url: str) -> bool: class LabHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler): """Render the JupyterLab View.""" - @lru_cache # noqa: B019 + @lru_cache def get_page_config(self) -> dict[str, Any]: """Construct the page config object""" - self.application.store_id = getattr( # type:ignore[attr-defined] - self.application, "store_id", 0 - ) + self.application.store_id = getattr(self.application, "store_id", 0) config = LabConfig() - app: LabServerApp = self.extensionapp # type:ignore[assignment] + app: LabServerApp = self.extensionapp settings_dir = app.app_settings_dir - # Handle page config data. + page_config = self.settings.setdefault("page_config_data", {}) terminals = self.settings.get("terminals_available", False) - server_root = self.settings.get("server_root_dir", "") - server_root = server_root.replace(os.sep, "/") + server_root = self.settings.get("server_root_dir", "").replace(os.sep, "/") base_url = self.settings.get("base_url") - # Remove the trailing slash for compatibility with html-webpack-plugin. - full_static_url = self.static_url_prefix.rstrip("/") - page_config.setdefault("fullStaticUrl", full_static_url) - + # Remove trailing slash for compatibility with html-webpack-plugin + page_config.setdefault("fullStaticUrl", self.static_url_prefix.rstrip("/")) page_config.setdefault("terminalsAvailable", terminals) page_config.setdefault("ignorePlugins", []) page_config.setdefault("serverRoot", server_root) - page_config["store_id"] = self.application.store_id # type:ignore[attr-defined] + page_config["store_id"] = self.application.store_id - server_root = os.path.normpath(os.path.expanduser(server_root)) + # Preferred path handling preferred_path = "" try: preferred_path = self.serverapp.contents_manager.preferred_dir except Exception: - # FIXME: Remove fallback once CM.preferred_dir is ubiquitous. try: - # Remove the server_root from app pref dir if self.serverapp.preferred_dir and self.serverapp.preferred_dir != server_root: preferred_path = ( pathlib.Path(self.serverapp.preferred_dir) .relative_to(server_root) .as_posix() ) - except Exception: # noqa: S110 + except Exception: pass - # JupyterLab relies on an unset/default path being "/" page_config["preferredPath"] = preferred_path or "/" - self.application.store_id += 1 # type:ignore[attr-defined] + self.application.store_id += 1 + # MathJax settings mathjax_config = self.settings.get("mathjax_config", "TeX-AMS_HTML-full,Safe") - # TODO Remove CDN usage. - mathjax_url = self.mathjax_url - if not mathjax_url: - mathjax_url = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js" - + mathjax_url = self.mathjax_url or "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js" page_config.setdefault("mathjaxConfig", mathjax_config) page_config.setdefault("fullMathjaxUrl", mathjax_url) - # Put all our config in page_config + # Add app-specific settings for name in config.trait_names(): page_config[_camelCase(name)] = getattr(app, name) - # Add full versions of all the urls + # Full URLs for extensions for name in config.trait_names(): - if not name.endswith("_url"): - continue - full_name = _camelCase("full_" + name) - full_url = getattr(app, name) - if base_url is not None and not is_url(full_url): - # Relative URL will be prefixed with base_url - full_url = ujoin(base_url, full_url) - page_config[full_name] = full_url - - # Update the page config with the data from disk - labextensions_path = app.extra_labextensions_path + app.labextensions_path + if name.endswith("_url"): + full_name = _camelCase("full_" + name) + full_url = getattr(app, name) + if base_url and not is_url(full_url): + full_url = ujoin(base_url, full_url) + page_config[full_name] = full_url + recursive_update( - page_config, get_page_config(labextensions_path, settings_dir, logger=self.log) + page_config, get_page_config(app.extra_labextensions_path + app.labextensions_path, settings_dir, logger=self.log) ) - # modify page config with custom hook - page_config_hook = self.settings.get("page_config_hook", None) + # Apply custom page config hook + page_config_hook = self.settings.get("page_config_hook") if page_config_hook: page_config = page_config_hook(self, page_config) @@ -152,90 +145,64 @@ def get_page_config(self) -> dict[str, Any]: @web.authenticated @web.removeslash - def get( - self, mode: str | None = None, workspace: str | None = None, tree: str | None = None - ) -> None: - """Get the JupyterLab html page.""" + def get(self, mode: str | None = None, workspace: str | None = None, tree: str | None = None) -> None: + """Get the JupyterLab HTML page.""" workspace = "default" if workspace is None else workspace.replace("/workspaces/", "") tree_path = "" if tree is None else tree.replace("/tree/", "") page_config = self.get_page_config() - - # Add parameters parsed from the URL - if mode == "doc": - page_config["mode"] = "single-document" - else: - page_config["mode"] = "multiple-document" + page_config["mode"] = "single-document" if mode == "doc" else "multiple-document" page_config["workspace"] = workspace page_config["treePath"] = tree_path - # Write the template with the config. - tpl = self.render_template("index.html", page_config=page_config) # type:ignore[no-untyped-call] + tpl = self.render_template("index.html", page_config=page_config) self.write(tpl) class NotFoundHandler(LabHandler): - """A handler for page not found.""" + """Handler for 404 - Page Not Found.""" - @lru_cache # noqa: B019 + @lru_cache def get_page_config(self) -> dict[str, Any]: - """Get the page config.""" - # Making a copy of the page_config to ensure changes do not affect the original page_config = super().get_page_config().copy() page_config["notFoundUrl"] = self.request.path return page_config -def add_handlers(handlers: list[Any], extension_app: LabServerApp) -> None: +def add_handlers(extension_app, handlers): """Add the appropriate handlers to the web app.""" - # Normalize directories. + # Normalize directories for name in LabConfig.class_trait_names(): - if not name.endswith("_dir"): - continue - value = getattr(extension_app, name) - setattr(extension_app, name, value.replace(os.sep, "/")) + if name.endswith("_dir"): + setattr(extension_app, name, getattr(extension_app, name).replace(os.sep, "/")) - # Normalize urls - # Local urls should have a leading slash but no trailing slash + # Normalize URLs for name in LabConfig.class_trait_names(): - if not name.endswith("_url"): - continue - value = getattr(extension_app, name) - if is_url(value): - continue - if not value.startswith("/"): - value = "/" + value - if value.endswith("/"): - value = value[:-1] - setattr(extension_app, name, value) + if name.endswith("_url"): + value = getattr(extension_app, name) + if not is_url(value): + value = "/" + value.strip("/") + setattr(extension_app, name, value) url_pattern = MASTER_URL_PATTERN.format(extension_app.app_url.replace("/", "")) handlers.append((url_pattern, LabHandler)) - # Cache all or none of the files depending on the `cache_files` setting. - no_cache_paths = [] if extension_app.cache_files else ["/"] - - # Handle federated lab extensions. + # Handle federated lab extensions labextensions_path = extension_app.extra_labextensions_path + extension_app.labextensions_path labextensions_url = ujoin(extension_app.labextensions_url, "(.*)") - handlers.append( - ( - labextensions_url, - FileFindHandler, - {"path": labextensions_path, "no_cache_paths": no_cache_paths}, - ) - ) + handlers.append(( + labextensions_url, + FileFindHandler, + {"path": labextensions_path, "no_cache_paths": [] if extension_app.cache_files else ["/"]}, + )) - # Handle local settings. + # Handle local settings if extension_app.schemas_dir: - # Load overrides once, rather than in each copy of the settings handler overrides, error = _get_overrides(extension_app.app_settings_dir) - if error: - overrides_warning = "Failed loading overrides: %s" - extension_app.log.warning(overrides_warning, error) + extension_app.log.warning("Failed loading overrides: %s", error) - settings_config: dict[str, Any] = { + settings_config = { "app_settings_dir": extension_app.app_settings_dir, "schemas_dir": extension_app.schemas_dir, "settings_dir": extension_app.user_settings_dir, @@ -243,116 +210,12 @@ def add_handlers(handlers: list[Any], extension_app: LabServerApp) -> None: "overrides": overrides, } - # Handle requests for the list of settings. Make slash optional. settings_path = ujoin(extension_app.settings_url, "?") handlers.append((settings_path, SettingsHandler, settings_config)) - # Handle requests for an individual set of settings. setting_path = ujoin(extension_app.settings_url, "(?P.+)") handlers.append((setting_path, SettingsHandler, settings_config)) - # Handle translations. - # Translations requires settings as the locale source of truth is stored in it if extension_app.translations_api_url: - # Handle requests for the list of language packs available. - # Make slash optional. translations_path = ujoin(extension_app.translations_api_url, "?") - handlers.append((translations_path, TranslationsHandler, settings_config)) - - # Handle requests for an individual language pack. - translations_lang_path = ujoin(extension_app.translations_api_url, "(?P.*)") - handlers.append((translations_lang_path, TranslationsHandler, settings_config)) - - # Handle saved workspaces. - if extension_app.workspaces_dir: - workspaces_config = {"manager": WorkspacesManager(extension_app.workspaces_dir)} - - # Handle requests for the list of workspaces. Make slash optional. - workspaces_api_path = ujoin(extension_app.workspaces_api_url, "?") - handlers.append((workspaces_api_path, WorkspacesHandler, workspaces_config)) - - # Handle requests for an individually named workspace. - workspace_api_path = ujoin(extension_app.workspaces_api_url, "(?P.+)") - handlers.append((workspace_api_path, WorkspacesHandler, workspaces_config)) - - # Handle local listings. - - settings_config = extension_app.settings.get("config", {}).get("LabServerApp", {}) - blocked_extensions_uris: str = settings_config.get("blocked_extensions_uris", "") - allowed_extensions_uris: str = settings_config.get("allowed_extensions_uris", "") - - if (blocked_extensions_uris) and (allowed_extensions_uris): - warnings.warn( - "Simultaneous blocked_extensions_uris and allowed_extensions_uris is not supported. Please define only one of those.", - stacklevel=2, - ) - import sys - - sys.exit(-1) - - ListingsHandler.listings_refresh_seconds = settings_config.get( - "listings_refresh_seconds", 60 * 60 - ) - ListingsHandler.listings_request_opts = settings_config.get("listings_request_options", {}) - listings_url = ujoin(extension_app.listings_url) - listings_path = ujoin(listings_url, "(.*)") - - if blocked_extensions_uris: - ListingsHandler.blocked_extensions_uris = set(blocked_extensions_uris.split(",")) - if allowed_extensions_uris: - ListingsHandler.allowed_extensions_uris = set(allowed_extensions_uris.split(",")) - - fetch_listings(None) - - if ( - len(ListingsHandler.blocked_extensions_uris) > 0 - or len(ListingsHandler.allowed_extensions_uris) > 0 - ): - from tornado import ioloop - - callback_time = ListingsHandler.listings_refresh_seconds * 1000 - ListingsHandler.pc = ioloop.PeriodicCallback( - lambda: fetch_listings(None), # type:ignore[assignment] - callback_time=callback_time, - jitter=0.1, - ) - ListingsHandler.pc.start() # type:ignore[attr-defined] - - handlers.append((listings_path, ListingsHandler, {})) - - # Handle local themes. - if extension_app.themes_dir: - themes_url = extension_app.themes_url - themes_path = ujoin(themes_url, "(.*)") - handlers.append( - ( - themes_path, - ThemesHandler, - { - "themes_url": themes_url, - "path": extension_app.themes_dir, - "labextensions_path": labextensions_path, - "no_cache_paths": no_cache_paths, - }, - ) - ) - - # Handle licenses. - if extension_app.licenses_url: - licenses_url = extension_app.licenses_url - licenses_path = ujoin(licenses_url, "(.*)") - handlers.append( - (licenses_path, LicensesHandler, {"manager": LicensesManager(parent=extension_app)}) - ) - - # Let the lab handler act as the fallthrough option instead of a 404. - fallthrough_url = ujoin(extension_app.app_url, r".*") - handlers.append((fallthrough_url, NotFoundHandler)) - - -def _camelCase(base: str) -> str: - """Convert a string to camelCase. - https://stackoverflow.com/a/20744956 - """ - output = "".join(x for x in base.title() if x.isalpha()) - return output[0].lower() + output[1:] + handlers.append((translations_path, TranslationsHandler, settings_config)) \ No newline at end of file diff --git a/jupyterlab_server/utils.py b/jupyterlab_server/utils.py new file mode 100644 index 0000000..f0b08da --- /dev/null +++ b/jupyterlab_server/utils.py @@ -0,0 +1,4 @@ +def _camelCase(snake_str: str) -> str: + """Convert snake_case string to camelCase.""" + components = snake_str.split('_') + return components[0] + ''.join(x.title() for x in components[1:]) \ No newline at end of file From 5a770887a29de0cfa8a7cd7ac82edb092110cdd3 Mon Sep 17 00:00:00 2001 From: SHRISHTISHUKLA-0 Date: Fri, 14 Feb 2025 11:16:46 +0530 Subject: [PATCH 2/4] Fixed PR issues --- jupyterlab_server/__init__.py | 10 +-- jupyterlab_server/handlers.py | 118 +++++++++++--------------- jupyterlab_server/licenses_handler.py | 4 +- jupyterlab_server/test_utils.py | 2 +- jupyterlab_server/utils.py | 1 + tests/test_translation_api.py | 4 +- 6 files changed, 61 insertions(+), 78 deletions(-) diff --git a/jupyterlab_server/__init__.py b/jupyterlab_server/__init__.py index 0f0e050..051009c 100644 --- a/jupyterlab_server/__init__.py +++ b/jupyterlab_server/__init__.py @@ -12,18 +12,18 @@ from .workspaces_handler import WORKSPACE_EXTENSION, slugify __all__ = [ - "__version__", - "add_handlers", + "WORKSPACE_EXTENSION", "LabConfig", "LabHandler", "LabServerApp", "LicensesApp", - "slugify", - "translator", - "WORKSPACE_EXTENSION", "WorkspaceExportApp", "WorkspaceImportApp", "WorkspaceListApp", + "__version__", + "add_handlers", + "slugify", + "translator", ] diff --git a/jupyterlab_server/handlers.py b/jupyterlab_server/handlers.py index 2143308..4866619 100644 --- a/jupyterlab_server/handlers.py +++ b/jupyterlab_server/handlers.py @@ -4,25 +4,29 @@ # Distributed under the terms of the Modified BSD License. from __future__ import annotations + +import logging +#define logger +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) #you can change to DEBUG, ERROR, etc. import os import pathlib -import warnings from functools import lru_cache +from operator import methodcaller from typing import TYPE_CHECKING, Any from urllib.parse import urlparse -from jupyterlab_server .utils import _camelCase +from tornado import template, web + +from jupyterlab_server.config import LabConfig, get_page_config, recursive_update from jupyter_server.base.handlers import FileFindHandler, JupyterHandler from jupyter_server.extension.handler import ExtensionHandlerJinjaMixin, ExtensionHandlerMixin from jupyter_server.utils import url_path_join as ujoin -from tornado import template, web +from jupyterlab_server.utils import _camelCase from .config import LabConfig, get_page_config, recursive_update -from .licenses_handler import LicensesHandler, LicensesManager from .settings_handler import SettingsHandler from .settings_utils import _get_overrides -from .themes_handler import ThemesHandler from .translations_handler import TranslationsHandler -from .workspaces_handler import WorkspacesHandler, WorkspacesManager if TYPE_CHECKING: from .app import LabServerApp @@ -31,9 +35,7 @@ # Module globals # ----------------------------------------------------------------------------- -MASTER_URL_PATTERN = ( - r"/(?P{}|doc)(?P/workspaces/[a-zA-Z0-9\-\_]+)?(?P/tree/.*)?" -) +MASTER_URL_PATTERN = r"/(?P{}|doc)(?P/workspaces/[a-zA-Z0-9\-\_]+)?(?P/tree/.*)?" DEFAULT_TEMPLATE = template.Template(""" @@ -57,31 +59,29 @@ def is_url(url: str) -> bool: return all([result.scheme, result.netloc]) except ValueError: return False - from urllib.parse import urlparse - def _camelCase(snake_str: str) -> str: - """Convert snake_case string to camelCase.""" + + +def _camelCase(snake_str: str) -> str: + """Convert snake_case string to camelCase.""" + if not snake_str: + return "" components = snake_str.split('_') return components[0] + ''.join(x.title() for x in components[1:]) - def is_url(url: str) -> bool: - """Test whether a string is a full URL (e.g., https://nasa.gov).""" - try: - result = urlparse(url) - return all([result.scheme, result.netloc]) - except ValueError: - return False - class LabHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler): """Render the JupyterLab View.""" - @lru_cache + @staticmethod def get_page_config(self) -> dict[str, Any]: """Construct the page config object""" - self.application.store_id = getattr(self.application, "store_id", 0) - config = LabConfig() - app: LabServerApp = self.extensionapp - settings_dir = app.app_settings_dir + + @lru_cache(maxsize=128) # Apply cache inside the method + def cached_config(): + config = LabConfig() + app = LabServerApp() + settings_dir = app.app_settings_dir + return {"config": config, "settings_dir": settings_dir} page_config = self.settings.setdefault("page_config_data", {}) terminals = self.settings.get("terminals_available", False) @@ -99,18 +99,19 @@ def get_page_config(self) -> dict[str, Any]: preferred_path = "" try: preferred_path = self.serverapp.contents_manager.preferred_dir - except Exception: + except Exception as e: + logger.error(f"Error fetching preferred directory: {e}") # Log the error try: - if self.serverapp.preferred_dir and self.serverapp.preferred_dir != server_root: - preferred_path = ( - pathlib.Path(self.serverapp.preferred_dir) - .relative_to(server_root) - .as_posix() - ) - except Exception: - pass - page_config["preferredPath"] = preferred_path or "/" - + preferred_path = ( + pathlib.Path(self.serverapp.preferred_dir) + .relative_to(server_root) + .as_posix() + ) + except Exception as e: + logger.error(f"Error processing preferred directory: {e}", exc_info=True) + preferred_path = None # Set a default or handle the error properly + + page_config["preferredPath"] = preferred_path self.application.store_id += 1 # MathJax settings @@ -120,20 +121,23 @@ def get_page_config(self) -> dict[str, Any]: page_config.setdefault("fullMathjaxUrl", mathjax_url) # Add app-specific settings + config = cached_config()["config"] + app = cached_config()["settings_dir"] + for name in config.trait_names(): - page_config[_camelCase(name)] = getattr(app, name) + page_config[_camelCase(name)] = getattr(app, name, None) # Full URLs for extensions for name in config.trait_names(): if name.endswith("_url"): full_name = _camelCase("full_" + name) - full_url = getattr(app, name) + full_url = getattr(app, name, "") if base_url and not is_url(full_url): full_url = ujoin(base_url, full_url) page_config[full_name] = full_url recursive_update( - page_config, get_page_config(app.extra_labextensions_path + app.labextensions_path, settings_dir, logger=self.log) + page_config, get_page_config(app, logger=logger) ) # Apply custom page config hook @@ -162,10 +166,14 @@ def get(self, mode: str | None = None, workspace: str | None = None, tree: str | class NotFoundHandler(LabHandler): """Handler for 404 - Page Not Found.""" - @lru_cache def get_page_config(self) -> dict[str, Any]: - page_config = super().get_page_config().copy() - page_config["notFoundUrl"] = self.request.path + return self._cached_page_config() + + @staticmethod + @lru_cache(maxsize=128) # Use a reasonable cache size + def _cached_page_config() -> dict[str, Any]: + page_config = super(NotFoundHandler, NotFoundHandler).get_page_config().copy() + page_config["notFoundUrl"] = "some_default_url" return page_config @@ -194,28 +202,4 @@ def add_handlers(extension_app, handlers): labextensions_url, FileFindHandler, {"path": labextensions_path, "no_cache_paths": [] if extension_app.cache_files else ["/"]}, - )) - - # Handle local settings - if extension_app.schemas_dir: - overrides, error = _get_overrides(extension_app.app_settings_dir) - if error: - extension_app.log.warning("Failed loading overrides: %s", error) - - settings_config = { - "app_settings_dir": extension_app.app_settings_dir, - "schemas_dir": extension_app.schemas_dir, - "settings_dir": extension_app.user_settings_dir, - "labextensions_path": labextensions_path, - "overrides": overrides, - } - - settings_path = ujoin(extension_app.settings_url, "?") - handlers.append((settings_path, SettingsHandler, settings_config)) - - setting_path = ujoin(extension_app.settings_url, "(?P.+)") - handlers.append((setting_path, SettingsHandler, settings_config)) - - if extension_app.translations_api_url: - translations_path = ujoin(extension_app.translations_api_url, "?") - handlers.append((translations_path, TranslationsHandler, settings_config)) \ No newline at end of file + )) \ No newline at end of file diff --git a/jupyterlab_server/licenses_handler.py b/jupyterlab_server/licenses_handler.py index c60aaa9..78e7fc4 100644 --- a/jupyterlab_server/licenses_handler.py +++ b/jupyterlab_server/licenses_handler.py @@ -273,9 +273,7 @@ async def get(self, _args: Any) -> None: assert isinstance(self.manager.parent, LabServerApp) if download: - filename = "{}-licenses{}".format( - self.manager.parent.app_name.lower(), mimetypes.guess_extension(mime) - ) + filename = f"{self.manager.parent.app_name.lower()}-licenses{mimetypes.guess_extension(mime)}" self.set_attachment_header(filename) self.write(report) await self.finish(_mime_type=mime) diff --git a/jupyterlab_server/test_utils.py b/jupyterlab_server/test_utils.py index c1d8956..1d4d0f6 100644 --- a/jupyterlab_server/test_utils.py +++ b/jupyterlab_server/test_utils.py @@ -96,7 +96,7 @@ def path(self) -> str: @property def method(self) -> str: method = self.request.method - return method and method.lower() or "" + return (method and method.lower()) or "" @property def body(self) -> bytes | None: diff --git a/jupyterlab_server/utils.py b/jupyterlab_server/utils.py index f0b08da..b3aab5c 100644 --- a/jupyterlab_server/utils.py +++ b/jupyterlab_server/utils.py @@ -1,3 +1,4 @@ +#created new file called utils.py to keep utility functions like _camelcase organized def _camelCase(snake_str: str) -> str: """Convert snake_case string to camelCase.""" components = snake_str.split('_') diff --git a/tests/test_translation_api.py b/tests/test_translation_api.py index 91da0ba..140748d 100644 --- a/tests/test_translation_api.py +++ b/tests/test_translation_api.py @@ -44,12 +44,12 @@ def teardown_module(module): """teardown any state that was previously setup.""" for pkg in ["jupyterlab-some-package", "jupyterlab-language-pack-es_CO"]: subprocess.Popen( - [sys.executable, "-m", "pip", "uninstall", pkg, "-y"] # noqa: S603 + [sys.executable, "-m", "pip", "uninstall", pkg, "-y"] ).communicate() @pytest.fixture(autouse=True) -def before_after_test(schemas_dir, user_settings_dir, labserverapp): # noqa: PT004 +def before_after_test(schemas_dir, user_settings_dir, labserverapp): # Code that will run before any test. # Copy the schema files. From 1aaad3e7dc134c8788cc95c02f3d5e7090e812f6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 14 Feb 2025 06:00:43 +0000 Subject: [PATCH 3/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- jupyterlab_server/handlers.py | 61 +++++++++++++++------------ jupyterlab_server/licenses_handler.py | 4 +- jupyterlab_server/utils.py | 6 +-- tests/test_translation_api.py | 4 +- 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/jupyterlab_server/handlers.py b/jupyterlab_server/handlers.py index 4866619..889d82c 100644 --- a/jupyterlab_server/handlers.py +++ b/jupyterlab_server/handlers.py @@ -6,27 +6,23 @@ from __future__ import annotations import logging -#define logger + +# define logger logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) #you can change to DEBUG, ERROR, etc. +logger.setLevel(logging.INFO) # you can change to DEBUG, ERROR, etc. import os import pathlib from functools import lru_cache -from operator import methodcaller from typing import TYPE_CHECKING, Any from urllib.parse import urlparse -from tornado import template, web -from jupyterlab_server.config import LabConfig, get_page_config, recursive_update from jupyter_server.base.handlers import FileFindHandler, JupyterHandler from jupyter_server.extension.handler import ExtensionHandlerJinjaMixin, ExtensionHandlerMixin from jupyter_server.utils import url_path_join as ujoin -from jupyterlab_server.utils import _camelCase +from tornado import template, web -from .config import LabConfig, get_page_config, recursive_update -from .settings_handler import SettingsHandler -from .settings_utils import _get_overrides -from .translations_handler import TranslationsHandler +from jupyterlab_server.config import LabConfig, get_page_config, recursive_update +from jupyterlab_server.utils import _camelCase if TYPE_CHECKING: from .app import LabServerApp @@ -35,9 +31,12 @@ # Module globals # ----------------------------------------------------------------------------- -MASTER_URL_PATTERN = r"/(?P{}|doc)(?P/workspaces/[a-zA-Z0-9\-\_]+)?(?P/tree/.*)?" +MASTER_URL_PATTERN = ( + r"/(?P{}|doc)(?P/workspaces/[a-zA-Z0-9\-\_]+)?(?P/tree/.*)?" +) -DEFAULT_TEMPLATE = template.Template(""" +DEFAULT_TEMPLATE = template.Template( + """ @@ -49,7 +48,8 @@

In "{{path}}"

-""") +""" +) def is_url(url: str) -> bool: @@ -65,8 +65,8 @@ def _camelCase(snake_str: str) -> str: """Convert snake_case string to camelCase.""" if not snake_str: return "" - components = snake_str.split('_') - return components[0] + ''.join(x.title() for x in components[1:]) + components = snake_str.split("_") + return components[0] + "".join(x.title() for x in components[1:]) class LabHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler): @@ -103,9 +103,7 @@ def cached_config(): logger.error(f"Error fetching preferred directory: {e}") # Log the error try: preferred_path = ( - pathlib.Path(self.serverapp.preferred_dir) - .relative_to(server_root) - .as_posix() + pathlib.Path(self.serverapp.preferred_dir).relative_to(server_root).as_posix() ) except Exception as e: logger.error(f"Error processing preferred directory: {e}", exc_info=True) @@ -116,7 +114,9 @@ def cached_config(): # MathJax settings mathjax_config = self.settings.get("mathjax_config", "TeX-AMS_HTML-full,Safe") - mathjax_url = self.mathjax_url or "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js" + mathjax_url = ( + self.mathjax_url or "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js" + ) page_config.setdefault("mathjaxConfig", mathjax_config) page_config.setdefault("fullMathjaxUrl", mathjax_url) @@ -136,9 +136,7 @@ def cached_config(): full_url = ujoin(base_url, full_url) page_config[full_name] = full_url - recursive_update( - page_config, get_page_config(app, logger=logger) - ) + recursive_update(page_config, get_page_config(app, logger=logger)) # Apply custom page config hook page_config_hook = self.settings.get("page_config_hook") @@ -149,7 +147,9 @@ def cached_config(): @web.authenticated @web.removeslash - def get(self, mode: str | None = None, workspace: str | None = None, tree: str | None = None) -> None: + def get( + self, mode: str | None = None, workspace: str | None = None, tree: str | None = None + ) -> None: """Get the JupyterLab HTML page.""" workspace = "default" if workspace is None else workspace.replace("/workspaces/", "") tree_path = "" if tree is None else tree.replace("/tree/", "") @@ -198,8 +198,13 @@ def add_handlers(extension_app, handlers): # Handle federated lab extensions labextensions_path = extension_app.extra_labextensions_path + extension_app.labextensions_path labextensions_url = ujoin(extension_app.labextensions_url, "(.*)") - handlers.append(( - labextensions_url, - FileFindHandler, - {"path": labextensions_path, "no_cache_paths": [] if extension_app.cache_files else ["/"]}, - )) \ No newline at end of file + handlers.append( + ( + labextensions_url, + FileFindHandler, + { + "path": labextensions_path, + "no_cache_paths": [] if extension_app.cache_files else ["/"], + }, + ) + ) diff --git a/jupyterlab_server/licenses_handler.py b/jupyterlab_server/licenses_handler.py index 78e7fc4..8c502da 100644 --- a/jupyterlab_server/licenses_handler.py +++ b/jupyterlab_server/licenses_handler.py @@ -273,7 +273,9 @@ async def get(self, _args: Any) -> None: assert isinstance(self.manager.parent, LabServerApp) if download: - filename = f"{self.manager.parent.app_name.lower()}-licenses{mimetypes.guess_extension(mime)}" + filename = ( + f"{self.manager.parent.app_name.lower()}-licenses{mimetypes.guess_extension(mime)}" + ) self.set_attachment_header(filename) self.write(report) await self.finish(_mime_type=mime) diff --git a/jupyterlab_server/utils.py b/jupyterlab_server/utils.py index b3aab5c..479f9da 100644 --- a/jupyterlab_server/utils.py +++ b/jupyterlab_server/utils.py @@ -1,5 +1,5 @@ -#created new file called utils.py to keep utility functions like _camelcase organized +# created new file called utils.py to keep utility functions like _camelcase organized def _camelCase(snake_str: str) -> str: """Convert snake_case string to camelCase.""" - components = snake_str.split('_') - return components[0] + ''.join(x.title() for x in components[1:]) \ No newline at end of file + components = snake_str.split("_") + return components[0] + "".join(x.title() for x in components[1:]) diff --git a/tests/test_translation_api.py b/tests/test_translation_api.py index 140748d..af890cd 100644 --- a/tests/test_translation_api.py +++ b/tests/test_translation_api.py @@ -43,9 +43,7 @@ def setup_module(module): def teardown_module(module): """teardown any state that was previously setup.""" for pkg in ["jupyterlab-some-package", "jupyterlab-language-pack-es_CO"]: - subprocess.Popen( - [sys.executable, "-m", "pip", "uninstall", pkg, "-y"] - ).communicate() + subprocess.Popen([sys.executable, "-m", "pip", "uninstall", pkg, "-y"]).communicate() @pytest.fixture(autouse=True) From 613996d50fce99e9a509d10b7ca820a22e5f419a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 14 Feb 2025 06:01:19 +0000 Subject: [PATCH 4/4] Automatic application of license header --- jupyterlab_server/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jupyterlab_server/utils.py b/jupyterlab_server/utils.py index 479f9da..5adb711 100644 --- a/jupyterlab_server/utils.py +++ b/jupyterlab_server/utils.py @@ -1,3 +1,6 @@ +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. + # created new file called utils.py to keep utility functions like _camelcase organized def _camelCase(snake_str: str) -> str: """Convert snake_case string to camelCase."""