Source code for repo_helper_pycharm.docs

#!/usr/bin/env python3
#
#  docs.py
"""
Parse PyCharm configuration and open a project's documentation in the default web browser.

.. versionadded:: 0.2.0
"""
#
#  Copyright © 2020 Dominic Davis-Foster <dominic@davis-foster.co.uk>
#
#  Permission is hereby granted, free of charge, to any person obtaining a copy
#  of this software and associated documentation files (the "Software"), to deal
#  in the Software without restriction, including without limitation the rights
#  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#  copies of the Software, and to permit persons to whom the Software is
#  furnished to do so, subject to the following conditions:
#
#  The above copyright notice and this permission notice shall be included in all
#  copies or substantial portions of the Software.
#
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
#  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
#  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
#  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
#  OR OTHER DEALINGS IN THE SOFTWARE.
#

# stdlib
import os
import webbrowser
from typing import Optional

# 3rd party
import platformdirs
from domdf_python_tools.iterative import natmax
from domdf_python_tools.paths import PathPlus
from lxml import objectify  # type: ignore[import]

__all__ = (
		"get_config_dir",
		"open_in_browser",
		"get_docs_port",
		)


[docs]def get_config_dir() -> PathPlus: """ Returns the path to the PyCharm configuration directory. .. versionadded:: 0.2.0 :raises: :exc:`FileNotFoundError` if the directory can't be found. """ config_dir = PathPlus(platformdirs.user_config_dir("JetBrains")) if not config_dir.is_dir(): raise FileNotFoundError(config_dir) try: return config_dir / natmax([p.name for p in config_dir.glob("PyCharm*")]) except (ValueError, IndexError): raise FileNotFoundError(config_dir / "PyCharm[0-9]{4}.[0-9]") from None
[docs]def open_in_browser(url: str) -> None: # pragma: no cover """ Opens the URL in the browser configured in the PyCharm settings. .. versionadded:: 0.2.0 :param url: """ config_dir = get_config_dir() browser_config_file = config_dir / "options" / "web-browsers.xml" if not browser_config_file.is_file(): raise FileNotFoundError(browser_config_file) browser_config = objectify.parse(str(browser_config_file)) root = browser_config.getroot() assert root.component.attrib["name"] == "WebBrowsersConfiguration" default = root.component.attrib["default"] browsers = [browser for browser in root.component.findall("browser")] if default == "first": browser_name = browsers[0].attrib["name"].lower() if browser_name == "firefox": try: profile: Optional[str] = str(browsers[0].settings.profile) except AttributeError: profile = None if profile is not None: os.system(f"firefox -P {profile} {url}") else: os.system(f"firefox {url}") else: webbrowser.get(browsers[0].attrib["name"].lower()) else: raise NotImplementedError(default)
[docs]def get_docs_port() -> int: """ Returns the number of the port used by the PyCharm web server. .. versionadded:: 0.2.0 """ config_dir = get_config_dir() other_config_file = config_dir / "options" / "other.xml" if not other_config_file.is_file(): raise FileNotFoundError(other_config_file) other_config = objectify.parse(str(other_config_file)) root = other_config.getroot() for tag in root.getchildren(): if tag.tag == "component" and tag.attrib["name"] == "BuiltInServerOptions": return int(tag.attrib["builtInServerPort"]) raise ValueError