Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[script.module.soupsieve@matrix] 2.4.1 #2491

Merged
merged 1 commit into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2018 Isaac Muse <[email protected]>
Copyright (c) 2018 - 2023 Isaac Muse <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
73 changes: 0 additions & 73 deletions script.module.soupsieve/README.md

This file was deleted.

32 changes: 16 additions & 16 deletions script.module.soupsieve/addon.xml
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.module.soupsieve" name="Soup Sieve" version="2.1.0+matrix.1" provider-name="Isaac Muse">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
</requires>
<extension point="xbmc.python.module" library="lib" />
<extension point="xbmc.addon.metadata">
<summary lang="en_GB">A CSS selector library</summary>
<description lang="en_GB">Soup Sieve is a CSS selector library designed to be used with Beautiful Soup 4. It aims to provide selecting, matching, and filtering using modern CSS selectors.</description>
<license>MIT</license>
<platform>all</platform>
<website>https://pypi.org/project/soupsieve/</website>
<source>https://github.com/facelessuser/soupsieve</source>
<assets>
<icon>icon.png</icon>
</assets>
</extension>
<addon id="script.module.soupsieve" name="soupsieve" version="2.4.1" provider-name="Isaac Muse">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
</requires>
<extension point="xbmc.python.module" library="lib" />
<extension point="xbmc.addon.metadata">
<summary lang="en_GB">A modern CSS selector implementation for Beautiful Soup.</summary>
<description lang="en_GB">A modern CSS selector implementation for Beautiful Soup.</description>
<license>MIT</license>
<platform>all</platform>
<website>https://facelessuser.github.io/soupsieve/</website>
<source>https://github.com/facelessuser/soupsieve</source>
<assets>
<icon>resources/icon.png</icon>
</assets>
</extension>
</addon>
92 changes: 75 additions & 17 deletions script.module.soupsieve/lib/soupsieve/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
from __future__ import annotations
from .__meta__ import __version__, __version_info__ # noqa: F401
from . import css_parser as cp
from . import css_match as cm
from . import css_types as ct
from .util import DEBUG, SelectorSyntaxError # noqa: F401
import bs4 # type: ignore[import]
from typing import Any, Iterator, Iterable

__all__ = (
'DEBUG', 'SelectorSyntaxError', 'SoupSieve',
Expand All @@ -40,16 +43,16 @@
SoupSieve = cm.SoupSieve


def compile(pattern, namespaces=None, flags=0, **kwargs): # noqa: A001
def compile( # noqa: A001
pattern: str,
namespaces: dict[str, str] | None = None,
flags: int = 0,
*,
custom: dict[str, str] | None = None,
**kwargs: Any
) -> cm.SoupSieve:
"""Compile CSS pattern."""

if namespaces is not None:
namespaces = ct.Namespaces(**namespaces)

custom = kwargs.get('custom')
if custom is not None:
custom = ct.CustomSelectors(**custom)

if isinstance(pattern, SoupSieve):
if flags:
raise ValueError("Cannot process 'flags' argument on a compiled selector list")
Expand All @@ -59,53 +62,108 @@ def compile(pattern, namespaces=None, flags=0, **kwargs): # noqa: A001
raise ValueError("Cannot process 'custom' argument on a compiled selector list")
return pattern

return cp._cached_css_compile(pattern, namespaces, custom, flags)
return cp._cached_css_compile(
pattern,
ct.Namespaces(namespaces) if namespaces is not None else namespaces,
ct.CustomSelectors(custom) if custom is not None else custom,
flags
)


def purge():
def purge() -> None:
"""Purge cached patterns."""

cp._purge_cache()


def closest(select, tag, namespaces=None, flags=0, **kwargs):
def closest(
select: str,
tag: 'bs4.Tag',
namespaces: dict[str, str] | None = None,
flags: int = 0,
*,
custom: dict[str, str] | None = None,
**kwargs: Any
) -> 'bs4.Tag':
"""Match closest ancestor."""

return compile(select, namespaces, flags, **kwargs).closest(tag)


def match(select, tag, namespaces=None, flags=0, **kwargs):
def match(
select: str,
tag: 'bs4.Tag',
namespaces: dict[str, str] | None = None,
flags: int = 0,
*,
custom: dict[str, str] | None = None,
**kwargs: Any
) -> bool:
"""Match node."""

return compile(select, namespaces, flags, **kwargs).match(tag)


def filter(select, iterable, namespaces=None, flags=0, **kwargs): # noqa: A001
def filter( # noqa: A001
select: str,
iterable: Iterable['bs4.Tag'],
namespaces: dict[str, str] | None = None,
flags: int = 0,
*,
custom: dict[str, str] | None = None,
**kwargs: Any
) -> list['bs4.Tag']:
"""Filter list of nodes."""

return compile(select, namespaces, flags, **kwargs).filter(iterable)


def select_one(select, tag, namespaces=None, flags=0, **kwargs):
def select_one(
select: str,
tag: 'bs4.Tag',
namespaces: dict[str, str] | None = None,
flags: int = 0,
*,
custom: dict[str, str] | None = None,
**kwargs: Any
) -> 'bs4.Tag':
"""Select a single tag."""

return compile(select, namespaces, flags, **kwargs).select_one(tag)


def select(select, tag, namespaces=None, limit=0, flags=0, **kwargs):
def select(
select: str,
tag: 'bs4.Tag',
namespaces: dict[str, str] | None = None,
limit: int = 0,
flags: int = 0,
*,
custom: dict[str, str] | None = None,
**kwargs: Any
) -> list['bs4.Tag']:
"""Select the specified tags."""

return compile(select, namespaces, flags, **kwargs).select(tag, limit)


def iselect(select, tag, namespaces=None, limit=0, flags=0, **kwargs):
def iselect(
select: str,
tag: 'bs4.Tag',
namespaces: dict[str, str] | None = None,
limit: int = 0,
flags: int = 0,
*,
custom: dict[str, str] | None = None,
**kwargs: Any
) -> Iterator['bs4.Tag']:
"""Iterate the specified tags."""

for el in compile(select, namespaces, flags, **kwargs).iselect(tag, limit):
yield el


def escape(ident):
def escape(ident: str) -> str:
"""Escape identifier."""

return cp.escape(ident)
28 changes: 18 additions & 10 deletions script.module.soupsieve/lib/soupsieve/__meta__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Meta related things."""
from __future__ import annotations
from collections import namedtuple
import re

Expand Down Expand Up @@ -79,7 +80,11 @@ class Version(namedtuple("Version", ["major", "minor", "micro", "release", "pre"

"""

def __new__(cls, major, minor, micro, release="final", pre=0, post=0, dev=0):
def __new__(
cls,
major: int, minor: int, micro: int, release: str = "final",
pre: int = 0, post: int = 0, dev: int = 0
) -> Version:
"""Validate version info."""

# Ensure all parts are positive integers.
Expand Down Expand Up @@ -115,27 +120,27 @@ def __new__(cls, major, minor, micro, release="final", pre=0, post=0, dev=0):

return super(Version, cls).__new__(cls, major, minor, micro, release, pre, post, dev)

def _is_pre(self):
def _is_pre(self) -> bool:
"""Is prerelease."""

return self.pre > 0
return bool(self.pre > 0)

def _is_dev(self):
def _is_dev(self) -> bool:
"""Is development."""

return bool(self.release < "alpha")

def _is_post(self):
def _is_post(self) -> bool:
"""Is post."""

return self.post > 0
return bool(self.post > 0)

def _get_dev_status(self): # pragma: no cover
def _get_dev_status(self) -> str: # pragma: no cover
"""Get development status string."""

return DEV_STATUS[self.release]

def _get_canonical(self):
def _get_canonical(self) -> str:
"""Get the canonical output string."""

# Assemble major, minor, micro version and append `pre`, `post`, or `dev` if needed..
Expand All @@ -153,11 +158,14 @@ def _get_canonical(self):
return ver


def parse_version(ver, pre=False):
def parse_version(ver: str) -> Version:
"""Parse version into a comparable Version tuple."""

m = RE_VER.match(ver)

if m is None:
raise ValueError("'{}' is not a valid version".format(ver))

# Handle major, minor, micro
major = int(m.group('major'))
minor = int(m.group('minor')) if m.group('minor') else 0
Expand Down Expand Up @@ -185,5 +193,5 @@ def parse_version(ver, pre=False):
return Version(major, minor, micro, release, pre, post, dev)


__version_info__ = Version(2, 1, 0, "final")
__version_info__ = Version(2, 4, 1, "final")
__version__ = __version_info__._get_canonical()
Loading