<commit_before>import io
from urllib.parse import urlparse
from collections import defaultdict

from legistar.base import Base
from legistar.fields import FieldAggregator


class TableRow(FieldAggregator):
    '''Provides access to table rows.
    '''
    def __init__(self, data, view, **kwargs):
        self.view = view
        self.field_data = defaultdict(list)
        for key, field in data:
            self.field_data[key].append(field)

    def get_detail_page(self):
        DetailView = self.view.viewmeta.detail.View
        detail_view = DetailView(url=self.get_detail_url())
        detail_view.inherit_chainmap_from(self.view)
        return detail_view


class Table(Base):
    '''Provides access to row data in tabular search results data.
    Tables inherit the context of the view's form. So self.doc on a table
    is really self.doc on the form.
    '''
    def __init__(self, view):
        self.view = view

    @property
    def table_element(self):
        els = self.doc.xpath(self.cfg.RESULTS_TABLE_XPATH)
        assert len(els) == 1
        return els.pop()

    def _gen_header_text(self):
        for th in self.table_element.xpath('.//th[contains(@class, "rgHeader")]'):
            # Remove nonbreaking spaces.
            text = th.text_content().replace('\xa0', ' ')
            yield text.strip()

    def get_header_text(self):
        return tuple(self._gen_header_text())

    def gen_rows(self):
        '''Yield table row objects.<commit_msg>Make fetching of DetailClass overridable<commit_after>import io
from urllib.parse import urlparse
from collections import defaultdict

from legistar.base import Base
from legistar.fields import FieldAggregator


class TableRow(FieldAggregator):
    '''Provides access to table rows.
    '''
    def __init__(self, data, view, **kwargs):
        self.view = view
        self.field_data = defaultdict(list)
        for key, field in data:
            self.field_data[key].append(field)

    def get_detail_viewtype(self):
        return self.view.viewmeta.detail.View

    def get_detail_page(self):
        DetailView = self.get_detail_viewtype()
        detail_view = DetailView(url=self.get_detail_url())
        detail_view.inherit_chainmap_from(self.view)
        return detail_view


class Table(Base):
    '''Provides access to row data in tabular search results data.
    Tables inherit the context of the view's form. So self.doc on a table
    is really self.doc on the form.
    '''
    def __init__(self, view):
        self.view = view

    @property
    def table_element(self):
        els = self.doc.xpath(self.cfg.RESULTS_TABLE_XPATH)
        assert len(els) == 1
        return els.pop()

    def _gen_header_text(self):
        for th in self.table_element.xpath('.//th[contains(@class, "rgHeader")]'):
            # Remove nonbreaking spaces.
            text = th.text_content().replace('\xa0', ' ')
            yield text.strip()

    def get_header_text(self):
        return tuple(self._gen_header_text())

    def gen_rows(self):
        '''Yield table row objects.
{'fraction_non_alphanumeric': 0.09957696062479661, 'fraction_numerical': 0.0013016596160104132, 'mean_word_length': 2.7810578105781056, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '3992363', 'n_tokens_mistral': 924, 'n_tokens_neox': 902, 'n_words': 245}