Skip to content

Commit

Permalink
add support for ss64
Browse files Browse the repository at this point in the history
  • Loading branch information
cibere committed Jan 11, 2025
1 parent c772f76 commit e663493
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 4 deletions.
5 changes: 5 additions & 0 deletions plugin/libraries/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .mdn import MdnDocs
from .mkdocs import Mkdocs
from .qmk import QmkDocs
from .ss64 import SS64Bash, SS64Mac, SS64NT, SS64PS

if TYPE_CHECKING:

Check failure on line 16 in plugin/libraries/__init__.py

View workflow job for this annotation

GitHub Actions / Lint on 3.11

Ruff (I001)

plugin/libraries/__init__.py:1:1: I001 Import block is un-sorted or un-formatted

Check failure on line 16 in plugin/libraries/__init__.py

View workflow job for this annotation

GitHub Actions / Lint on 3.12

Ruff (I001)

plugin/libraries/__init__.py:1:1: I001 Import block is un-sorted or un-formatted

Check failure on line 16 in plugin/libraries/__init__.py

View workflow job for this annotation

GitHub Actions / Lint on 3.13

Ruff (I001)

plugin/libraries/__init__.py:1:1: I001 Import block is un-sorted or un-formatted
from collections.abc import Iterable
Expand All @@ -30,6 +31,10 @@
| Lua54
| Discord
| DiscordSex
| SS64Mac
| SS64Bash
| SS64NT
| SS64PS
)

preset_docs: Iterable[type[PresetDocs]] = PresetDocs.__args__
Expand Down
116 changes: 116 additions & 0 deletions plugin/libraries/ss64.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from __future__ import annotations

import asyncio
from functools import partial
from typing import TYPE_CHECKING, Callable, ClassVar

import bs4
from yarl import URL

from ..library import Library

if TYPE_CHECKING:
from aiohttp import ClientSession


class SS64Parser:
def __init__(
self,
data: bytes,
url_builder: Callable[[str], str],
*,
is_powershell: bool = False,
) -> None:
self.data = data
self.soup = bs4.BeautifulSoup(data, "html.parser")
self.cache: dict[str, str] = {}
self.url_builder = url_builder
self.is_powershell = is_powershell

def parse(self) -> dict[str, str]:
container: bs4.Tag = self.soup.find_all("table")[-1]
rows: list[bs4.Tag] = container.find_all("tr")
for row in rows:
tds: list[bs4.Tag] = row.find_all("td")
if not tds:
continue
if tds[0].attrs.get("class") == "ix":
continue

cmd_name_td = tds[1]
atag = cmd_name_td.find("a")
if isinstance(atag, bs4.Tag):
command_name = atag.text.strip()
path = atag.attrs.get("href", "").strip()
else:
command_name = cmd_name_td.text.strip()
path = ""

aliases = []
if self.is_powershell:
raw_aliases = tds[2].text.strip().replace(" ", "")
if raw_aliases:
aliases = raw_aliases.split("/")

if command_name:
short_description = tds[-1].text
url = self.url_builder(path)
name = f"{command_name} - {short_description}"
self.cache[name] = url
for alias in aliases:
self.cache[f"{alias} - {name}"] = url

return self.cache


class SS64Base(Library):
classname: ClassVar[str]
ss64_version: ClassVar[str]
is_preset: ClassVar[bool] = True
favicon_url: ClassVar[str] | None = "https://ss64.com"

def __init__(self, name: str, *, use_cache: bool) -> None:
super().__init__(
name,
URL(f"https://ss64.com/{self.ss64_version}"),
use_cache=use_cache,
)

async def fetch_icon(self) -> str | None:
return await super().fetch_icon()

async def build_cache(self, session: ClientSession, webserver_port: int) -> None:
url = self.url
if url is None:
raise ValueError("Local ss64 manuals are not supported")

async with session.get(url) as res:
raw_content: bytes = await res.content.read()

parser = SS64Parser(
raw_content,
partial(self._build_url, port=webserver_port),
is_powershell=self.ss64_version == "ps",
)

self.cache = await asyncio.to_thread(parser.parse)


class SS64Mac(SS64Base):
classname: ClassVar[str] = "SS64 Mac"
ss64_version: ClassVar[str] = "mac"


class SS64Bash(SS64Base):
classname: ClassVar[str] = "SS64 Linux"
ss64_version: ClassVar[str] = "bash"


class SS64NT(SS64Base):
classname: ClassVar[str] = "SS64 CMD"
ss64_version: ClassVar[str] = "nt"


class SS64PS(SS64Base):
classname: ClassVar[str] = "SS64 PowerShell"
ss64_version: ClassVar[str] = "ps"
12 changes: 8 additions & 4 deletions test.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@

import aiohttp
import json
from plugin.libraries.qmk import QmkDocs
from plugin.libraries.ss64 import SS64Mac, SS64bash, SS64NT, SS64PS


async def main() -> None:
async def main(doc) -> None:
async with aiohttp.ClientSession() as cs:
docs = QmkDocs("d", use_cache=True)
docs = doc("d", use_cache=True)
await docs.build_cache(cs, 0)

with open("cache.json", "w") as f:
json.dump(docs.cache, f, indent=4)
print(f"Done indexing {len(docs.cache)} entries")


import asyncio

asyncio.run(main())
asyncio.run(main(SS64Mac))
asyncio.run(main(SS64bash))
asyncio.run(main(SS64NT))
asyncio.run(main(SS64PS))

0 comments on commit e663493

Please sign in to comment.