<commit_before># coding=utf-8

from lxml import etree


class Selector:
    def __init__(self, html=None, root=None):
        if html is not None:
            if not isinstance(html, str):
                raise TypeError("'html' argument should be of type {}".format(str))
            root = etree.HTML(html)
        elif root is None:
            raise ValueError("Selector needs either 'html' or 'root' argument")
        self._root = root

    def xpath(self, xpath):
        try:
            res = self._root.xpath(xpath, smart_strings=False)
        except Exception:
            return SelectorList([])
        if not isinstance(res, list):
            res = [res]
        return SelectorList([self.__class__(root=i) for i in res])

    @property
    def html(self):
        try:
            return etree.tostring(self._root, encoding="unicode", method="html", with_tail=False)
        except TypeError:
            return str(self._root)

    @property
    def text(self):
        try:
            return etree.tostring(self._root, encoding="unicode", method="text", with_tail=False)
        except TypeError:
            return str(self._root)


class SelectorList(list):
    def __getitem__(self, item):
        obj = super().__getitem__(item)
        return self.__class__(obj) if isinstance(item, slice) else obj

    def xpath(self, xpath):
        res = self.__class__()
        for i in self:
            res += i.xpath(xpath)
        return res

    @property
    def html(self):
        return [i.html for i in self]

    @property
    def text(self):
        return [i.text for i in self]<commit_msg>add xpath keyword arguments<commit_after># coding=utf-8

from lxml import etree


class Selector:
    def __init__(self, html=None, root=None):
        if html is not None:
            if not isinstance(html, str):
                raise TypeError("'html' argument should be of type {}".format(str))
            root = etree.HTML(html)
        elif root is None:
            raise ValueError("Selector needs either 'html' or 'root' argument")
        self._root = root

    def xpath(self, xpath, **kwargs):
        try:
            res = self._root.xpath(xpath, smart_strings=False, **kwargs)
        except Exception:
            return SelectorList([])
        if not isinstance(res, list):
            res = [res]
        return SelectorList([self.__class__(root=i) for i in res])

    @property
    def html(self):
        try:
            return etree.tostring(self._root, encoding="unicode", method="html", with_tail=False)
        except TypeError:
            return str(self._root)

    @property
    def text(self):
        try:
            return etree.tostring(self._root, encoding="unicode", method="text", with_tail=False)
        except TypeError:
            return str(self._root)


class SelectorList(list):
    def __getitem__(self, item):
        obj = super().__getitem__(item)
        return self.__class__(obj) if isinstance(item, slice) else obj

    def xpath(self, xpath, **kwargs):
        res = self.__class__()
        for i in self:
            res += i.xpath(xpath, **kwargs)
        return res

    @property
    def html(self):
        return [i.html for i in self]

    @property
    def text(self):
        return [i.text for i in self]
{'fraction_non_alphanumeric': 0.1070559610705596, 'fraction_numerical': 0.0006082725060827251, 'mean_word_length': 2.16859344894027, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7612720', 'n_tokens_mistral': 966, 'n_tokens_neox': 945, 'n_words': 284}