text:
import datetime

from django.contrib import admin
from django.contrib.admin.models import LogEntry
from django.contrib.admin.options import IncorrectLookupParameters
from django.contrib.admin.templatetags.admin_list import pagination
from django.contrib.admin.tests import AdminSeleniumTestCase
from django.contrib.admin.views.main import ALL_VAR, SEARCH_VAR, ChangeList
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.template import Context, Template
from django.test import TestCase, override_settings
from django.test.client import RequestFactory
from django.urls import reverse
from django.utils import formats

from .admin import (
    BandAdmin, ChildAdmin, ChordsBandAdmin, ConcertAdmin,
    CustomPaginationAdmin, CustomPaginator, DynamicListDisplayChildAdmin,
    DynamicListDisplayLinksChildAdmin, DynamicListFilterChildAdmin,
    DynamicSearchFieldsChildAdmin, EmptyValueChildAdmin, EventAdmin,
    FilteredChildAdmin, GroupAdmin, InvitationAdmin,
    NoListDisplayLinksParentAdmin, ParentAdmin, QuartetAdmin, SwallowAdmin,
    site as custom_site,
)
from .models import (
    Band, Child, ChordsBand, ChordsMusician, Concert, CustomIdUser, Event,
    Genre, Group, Invitation, Membership, Musician, OrderedObject, Parent,
    Quartet, Swallow, SwallowOneToOne, UnorderedObject,
)

def get_changelist_args(modeladmin, **kwargs):
    m = modeladmin
    args = (
        kwargs.pop('list_display', m.list_display),
        kwargs.pop('list_display_links', m.list_display_links),
        kwargs.pop('list_filter', m.list_filter),
        kwargs.pop('date_hierarchy', m.date_hierarchy),
        kwargs.pop('search_fields', m.search_fields),
        kwargs.pop('list_select_related', m.list_select_related),
        kwargs.pop('list_per_page', m.list_per_page),
        kwargs.pop('list_max_show_all', m.list_max_show_all),
        kwargs.pop('list_editable', m.list_editable),
        m,
    )
    assert not kwargs, "Unexpected kwarg %s" % kwargs
    return args

@override_settings(ROOT_URLCONF="admin_changelist.urls")
class ChangeListTests(TestCase):

    def setUp(self):
        self.factory = RequestFactory()

    def _create_superuser(self, username):
        return User.objects.create_superuser(username=username, email='a@b.com', password='xxx')

    def _mocked_authenticated_request(self, url, user):
        request = self.factory.get(url)
        request.user = user
        return request

    def test_select_related_preserved(self):
        """
        Regression test for #10348: ChangeList.get_queryset() shouldn't
        overwrite a custom select_related provided by ModelAdmin.get_queryset().
        """
        m = ChildAdmin(Child, custom_site)
        request = self.factory.get('/child/')
        cl = ChangeList(
            request, Child,
            *get_changelist_args(m, list_select_related=m.get_list_select_related(request))
        )
        self.assertEqual(cl.queryset.query.select_related, {'parent': {}})

    def test_select_related_as_tuple(self):
        ia = InvitationAdmin(Invitation, custom_site)
        request = self.factory.get('/invitation/')
        cl = ChangeList(
            request, Child,
            *get_changelist_args(ia, list_select_related=ia.get_list_select_related(request))
        )
        self.assertEqual(cl.queryset.query.select_related, {'player': {}})

    def test_select_related_as_empty_tuple(self):
        ia = InvitationAdmin(Invitation, custom_site)
        ia.list_select_related = ()
        request = self.factory.get('/invitation/')
        cl = ChangeList(
            request, Child,
            *get_changelist_args(ia, list_select_related=ia.get_list_select_related(request))
        )
        self.assertIs(cl.queryset.query.select_related, False)

    def test_get_select_related_custom_method(self):
        class GetListSelectRelatedAdmin(admin.ModelAdmin):
            list_display = ('band', 'player')

            def get_list_select_related(self, request):
                return ('band', 'player')

        ia = GetListSelectRelatedAdmin(Invitation, custom_site)
        request = self.factory.get('/invitation/')
        cl = ChangeList(
            request, Child,
            *get_changelist_args(ia, list_select_related=ia.get_list_select_related(request))
        )
        self.assertEqual(cl.queryset.query.select_related, {'player': {}, 'band': {}})

    def test_result_list_empty_changelist_value(self):
        """
        Regression test for #14982: EMPTY_CHANGELIST_VALUE should be honored
        for relationship fields
        """
        new_child = Child.objects.create(name='name', parent=None)
        request = self.factory.get('/child/')
        m = ChildAdmin(Child, custom_site)
        cl = ChangeList(request, Child, *get_changelist_args(m))
        cl.formset = None
        template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
        context = Context({'cl': cl})
        table_output = template.render(context)
        link = reverse('admin:admin_changelist_child_change', args=(new_child.id,))
        row_html = (
            '

name	'
            '-

' % link
        )
        self.assertNotEqual(table_output.find(row_html), -1, 'Failed to find expected row element: %s' % table_output)

    def test_result_list_set_empty_value_display_on_admin_site(self):
        """
        Empty value display can be set on AdminSite.
        """
        new_child = Child.objects.create(name='name', parent=None)
        request = self.factory.get('/child/')
        # Set a new empty display value on AdminSite.
        admin.site.empty_value_display = '???'
        m = ChildAdmin(Child, admin.site)
        cl = ChangeList(request, Child, *get_changelist_args(m))
        cl.formset = None
        template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
        context = Context({'cl': cl})
        table_output = template.render(context)
        link = reverse('admin:admin_changelist_child_change', args=(new_child.id,))
        row_html = (
            '

name	'
            '???

' % link
        )
        self.assertNotEqual(table_output.find(row_html), -1, 'Failed to find expected row element: %s' % table_output)

    def test_result_list_set_empty_value_display_in_model_admin(self):
        """
        Empty value display can be set in ModelAdmin or individual fields.
        """
        new_child = Child.objects.create(name='name', parent=None)
        request = self.factory.get('/child/')
        m = EmptyValueChildAdmin(Child, admin.site)
        cl = ChangeList(request, Child, *get_changelist_args(m))
        cl.formset = None
        template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
        context = Context({'cl': cl})
        table_output = template.render(context)
        link = reverse('admin:admin_changelist_child_change', args=(new_child.id,))
        row_html = (
            '

name	'
            '&dagger;	-empty-

' % link
        )
        self.assertNotEqual(table_output.find(row_html), -1, 'Failed to find expected row element: %s' % table_output)

    def test_result_list_html(self):
        """
        Inclusion tag result_list generates a table when with default
        ModelAdmin settings.
        """
        new_parent = Parent.objects.create(name='parent')
        new_child = Child.objects.create(name='name', parent=new_parent)
        request = self.factory.get('/child/')
        m = ChildAdmin(Child, custom_site)
        cl = ChangeList(request, Child, *get_changelist_args(m))
        cl.formset = None
        template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
        context = Context({'cl': cl})
        table_output = template.render(context)
        link = reverse('admin:admin_changelist_child_change', args=(new_child.id,))
        row_html = (
            '

name	'
            'Parent object

' % link
        )
        self.assertNotEqual(table_output.find(row_html), -1, 'Failed to find expected row element: %s' % table_output)

    def test_result_list_editable_html(self):
        """
        Regression tests for #11791: Inclusion tag result_list generates a
        table and this checks that the items are nested within the table
        element tags.
        Also a regression test for #13599, verifies that hidden fields
        when list_editable is enabled are rendered in a div outside the
        table.
        """
        new_parent = Parent.objects.create(name='parent')
        new_child = Child.objects.create(name='name', parent=new_parent)
        request = self.factory.get('/child/')
        m = ChildAdmin(Child, custom_site)

        # Test with list_editable fields
        m.list_display = ['id', 'name', 'parent']
        m.list_display_links = ['id']
        m.list_editable = ['name']
        cl = ChangeList(request, Child, *get_changelist_args(m))
        FormSet = m.get_changelist_formset(request)
        cl.formset = FormSet(queryset=cl.result_list)
        template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
        context = Context({'cl': cl})
        table_output = template.render(context)
        # make sure that hidden fields are in the correct place
        hiddenfields_div = (
            '
'
            '<input type="hidden" name="form-0-id" value="%d" id="id_form-0-id" />'
            '
'
        ) % new_child.id
        self.assertInHTML(hiddenfields_div, table_output, msg_prefix='Failed to find hidden fields')

        # make sure that list editable fields are rendered in divs correctly
        editable_name_field = (
            '<input name="form-0-name" value="name" class="vTextField" '
            'maxlength="30" type="text" id="id_form-0-name" />'
        )
        self.assertInHTML(
            '%s	' % editable_name_field,
            table_output,
            msg_prefix='Failed to find "name" list_editable field',
        )

    def test_result_list_editable(self):
        """
        Regression test for #14312: list_editable with pagination
        """
        new_parent = Parent.objects.create(name='parent')
        for i in range(200):
            Child.objects.create(name='name %s' % i, parent=new_parent)
        request = self.factory.get('/child/', data={'p': -1})  # Anything outside range
        m = ChildAdmin(Child, custom_site)

        # Test with list_editable fields
        m.list_display = ['id', 'name', 'parent']
        m.list_display_links = ['id']
        m.list_editable = ['name']
        with self.assertRaises(IncorrectLookupParameters):
            ChangeList(request, Child, *get_changelist_args(m))

    def test_custom_paginator(self):
        new_parent = Parent.objects.create(name='parent')
        for i in range(200):
            Child.objects.create(name='name %s' % i, parent=new_parent)

        request = self.factory.get('/child/')
        m = CustomPaginationAdmin(Child, custom_site)

        cl = ChangeList(request, Child, *get_changelist_args(m))
        cl.get_results(request)
        self.assertIsInstance(cl.paginator, CustomPaginator)

    def test_distinct_for_m2m_in_list_filter(self):
        """
        Regression test for #13902: When using a ManyToMany in list_filter,
        results shouldn't appear more than once. Basic ManyToMany.
        """
        blues = Genre.objects.create(name='Blues')
        band = Band.objects.create(name='B.B. King Review', nr_of_members=11)

        band.genres.add(blues)
        band.genres.add(blues)

        m = BandAdmin(Band, custom_site)
        request = self.factory.get('/band/', data={'genres': blues.pk})

        cl = ChangeList(request, Band, *get_changelist_args(m))
        cl.get_results(request)

        # There's only one Group instance
        self.assertEqual(cl.result_count, 1)

    def test_distinct_for_through_m2m_in_list_filter(self):
        """
        Regression test for #13902: When using a ManyToMany in list_filter,
        results shouldn't appear more than once. With an intermediate model.
        """
        lead = Musician.objects.create(name='Vox')
        band = Group.objects.create(name='The Hype')
        Membership.objects.create(group=band, music=lead, role='lead voice')
        Membership.objects.create(group=band, music=lead, role='bass player')

        m = GroupAdmin(Group, custom_site)
        request = self.factory.get('/group/', data={'members': lead.pk})

        cl = ChangeList(request, Group, *get_changelist_args(m))
        cl.get_results(request)

        # There's only one Group instance
        self.assertEqual(cl.result_count, 1)

    def test_distinct_for_through_m2m_at_second_level_in_list_filter(self):
        """
        When using a ManyToMany in list_filter at the second level behind a
        ForeignKey, distinct() must be called and results shouldn't appear more
        than once.
        """
        lead = Musician.objects.create(name='Vox')
        band = Group.objects.create(name='The Hype')
        Concert.objects.create(name='Woodstock', group=band)
        Membership.objects.create(group=band, music=lead, role='lead voice')
        Membership.objects.create(group=band, music=lead, role='bass player')

        m = ConcertAdmin(Concert, custom_site)
        request = self.factory.get('/concert/', data={'group__members': lead.pk})

        cl = ChangeList(request, Concert, *get_changelist_args(m))
        cl.get_results(request)

        # There's only one Concert instance
        self.assertEqual(cl.result_count, 1)

    def test_distinct_for_inherited_m2m_in_list_filter(self):
        """
        Regression test for #13902: When using a ManyToMany in list_filter,
        results shouldn't appear more than once. Model managed in the
        admin inherits from the one that defins the relationship.
        """
        lead = Musician.objects.create(name='John')
        four = Quartet.objects.create(name='The Beatles')
        Membership.objects.create(group=four, music=lead, role='lead voice')
        Membership.objects.create(group=four, music=lead, role='guitar player')

        m = QuartetAdmin(Quartet, custom_site)
        request = self.factory.get('/quartet/', data={'members': lead.pk})

        cl = ChangeList(request, Quartet, *get_changelist_args(m))
        cl.get_results(request)

        # There's only one Quartet instance
        self.assertEqual(cl.result_count, 1)

    def test_distinct_for_m2m_to_inherited_in_list_filter(self):
        """
        Regression test for #13902: When using a ManyToMany in list_filter,
        results shouldn't appear more than once. Target of the relationship
        inherits from another.
        """
        lead = ChordsMusician.objects.create(name='Player A')
        three = ChordsBand.objects.create(name='The Chords Trio')
        Invitation.objects.create(band=three, player=lead, instrument='guitar')
        Invitation.objects.create(band=three, player=lead, instrument='bass')

        m = ChordsBandAdmin(ChordsBand, custom_site)
        request = self.factory.get('/chordsband/', data={'members': lead.pk})

        cl = ChangeList(request, ChordsBand, *get_changelist_args(m))
        cl.get_results(request)

        # There's only one ChordsBand instance
        self.assertEqual(cl.result_count, 1)

    def test_distinct_for_non_unique_related_object_in_list_filter(self):
        """
        Regressions tests for #15819: If a field listed in list_filters
        is a non-unique related object, distinct() must be called.
        """
        parent = Parent.objects.create(name='Mary')
        # Two children with the same name
        Child.objects.create(parent=parent, name='Daniel')
        Child.objects.create(parent=parent, name='Daniel')

        m = ParentAdmin(Parent, custom_site)
        request = self.factory.get('/parent/', data={'child__name': 'Daniel'})

        cl = ChangeList(request, Parent, *get_changelist_args(m))
        # Make sure distinct() was called
        self.assertEqual(cl.queryset.count(), 1)

    def test_distinct_for_non_unique_related_object_in_search_fields(self):
        """
        Regressions tests for #15819: If a field listed in search_fields
        is a non-unique related object, distinct() must be called.
        """
        parent = Parent.objects.create(name='Mary')
        Child.objects.create(parent=parent, name='Danielle')
        Child.objects.create(parent=parent, name='Daniel')

        m = ParentAdmin(Parent, custom_site)
        request = self.factory.get('/parent/', data={SEARCH_VAR: 'daniel'})

        cl = ChangeList(request, Parent, *get_changelist_args(m))
        # Make sure distinct() was called
        self.assertEqual(cl.queryset.count(), 1)

    def test_distinct_for_many_to_many_at_second_level_in_search_fields(self):
        """
        When using a ManyToMany in search_fields at the second level behind a
        ForeignKey, distinct() must be called and results shouldn't appear more
        than once.
        """
        lead = Musician.objects.create(name='Vox')
        band = Group.objects.create(name='The Hype')
        Concert.objects.create(name='Woodstock', group=band)
        Membership.objects.create(group=band, music=lead, role='lead voice')
        Membership.objects.create(group=band, music=lead, role='bass player')

        m = ConcertAdmin(Concert, custom_site)
        request = self.factory.get('/concert/', data={SEARCH_VAR: 'vox'})

        cl = ChangeList(request, Concert, *get_changelist_args(m))
        # There's only one Concert instance
        self.assertEqual(cl.queryset.count(), 1)

    def test_no_distinct_for_m2m_in_list_filter_without_params(self):
        """
        If a ManyToManyField is in list_filter but isn't in any lookup params,
        the changelist's query shouldn't have distinct.
        """
        m = BandAdmin(Band, custom_site)
        for lookup_params in ({}, {'name': 'test'}):
            request = self.factory.get('/band/', lookup_params)
            cl = ChangeList(request, Band, *get_changelist_args(m))
            self.assertFalse(cl.queryset.query.distinct)

        # A ManyToManyField in params does have distinct applied.
        request = self.factory.get('/band/', {'genres': '0'})
        cl = ChangeList(request, Band, *get_changelist_args(m))
        self.assertTrue(cl.queryset.query.distinct)

    def test_pagination(self):
        """
        Regression tests for #12893: Pagination in admins changelist doesn't
        use queryset set by modeladmin.
        """
        parent = Parent.objects.create(name='anything')
        for i in range(30):
            Child.objects.create(name='name %s' % i, parent=parent)
            Child.objects.create(name='filtered %s' % i, parent=parent)

        request = self.factory.get('/child/')

        # Test default queryset
        m = ChildAdmin(Child, custom_site)
        cl = ChangeList(request, Child, *get_changelist_args(m))
        self.assertEqual(cl.queryset.count(), 60)
        self.assertEqual(cl.paginator.count, 60)
        self.assertEqual(list(cl.paginator.page_range), [1, 2, 3, 4, 5, 6])

        # Test custom queryset
        m = FilteredChildAdmin(Child, custom_site)
        cl = ChangeList(request, Child, *get_changelist_args(m))
        self.assertEqual(cl.queryset.count(), 30)
        self.assertEqual(cl.paginator.count, 30)
        self.assertEqual(list(cl.paginator.page_range), [1, 2, 3])

    def test_computed_list_display_localization(self):
        """
        Regression test for #13196: output of functions should be  localized
        in the changelist.
        """
        superuser = User.objects.create_superuser(username='super', email='super@localhost', password='secret')
        self.client.force_login(superuser)
        event = Event.objects.create(date=datetime.date.today())
        response = self.client.get(reverse('admin:admin_changelist_event_changelist'))
        self.assertContains(response, formats.localize(event.date))
        self.assertNotContains(response, str(event.date))

    def test_dynamic_list_display(self):
        """
        Regression tests for #14206: dynamic list_display support.
        """
        parent = Parent.objects.create(name='parent')
        for i in range(10):
            Child.objects.create(name='child %s' % i, parent=parent)

        user_noparents = self._create_superuser('noparents')
        user_parents = self._create_superuser('parents')

        # Test with user 'noparents'
        m = custom_site._registry[Child]
        request = self._mocked_authenticated_request('/child/', user_noparents)
        response = m.changelist_view(request)
        self.assertNotContains(response, 'Parent object')

        list_display = m.get_list_display(request)
        list_display_links = m.get_list_display_links(request, list_display)
        self.assertEqual(list_display, ['name', 'age'])
        self.assertEqual(list_display_links, ['name'])

        # Test with user 'parents'
        m = DynamicListDisplayChildAdmin(Child, custom_site)
        request = self._mocked_authenticated_request('/child/', user_parents)
        response = m.changelist_view(request)
        self.assertContains(response, 'Parent object')

        custom_site.unregister(Child)

        list_display = m.get_list_display(request)
        list_display_links = m.get_list_display_links(request, list_display)
        self.assertEqual(list_display, ('parent', 'name', 'age'))
        self.assertEqual(list_display_links, ['parent'])

        # Test default implementation
        custom_site.register(Child, ChildAdmin)
        m = custom_site._registry[Child]
        request = self._mocked_authenticated_request('/child/', user_noparents)
        response = m.changelist_view(request)
        self.assertContains(response, 'Parent object')

    def test_show_all(self):
        parent = Parent.objects.create(name='anything')
        for i in range(30):
            Child.objects.create(name='name %s' % i, parent=parent)
            Child.objects.create(name='filtered %s' % i, parent=parent)

        # Add "show all" parameter to request
        request = self.factory.get('/child/', data={ALL_VAR: ''})

        # Test valid "show all" request (number of total objects is under max)
        m = ChildAdmin(Child, custom_site)
        m.list_max_show_all = 200
        # 200 is the max we'll pass to ChangeList
        cl = ChangeList(request, Child, *get_changelist_args(m))
        cl.get_results(request)
        self.assertEqual(len(cl.result_list), 60)

        # Test invalid "show all" request (number of total objects over max)
        # falls back to paginated pages
        m = ChildAdmin(Child, custom_site)
        m.list_max_show_all = 30
        # 30 is the max we'll pass to ChangeList for this test
        cl = ChangeList(request, Child, *get_changelist_args(m))
        cl.get_results(request)
        self.assertEqual(len(cl.result_list), 10)

    def test_dynamic_list_display_links(self):
        """
        Regression tests for #16257: dynamic list_display_links support.
        """
        parent = Parent.objects.create(name='parent')
        for i in range(1, 10):
            Child.objects.create(id=i, name='child %s' % i, parent=parent, age=i)

        m = DynamicListDisplayLinksChildAdmin(Child, custom_site)
        superuser = self._create_superuser('superuser')
        request = self._mocked_authenticated_request('/child/', superuser)
        response = m.changelist_view(request)
        for i in range(1, 10):
            link = reverse('admin:admin_changelist_child_change', args=(i,))
            self.assertContains(response, '%s' % (link, i))

        list_display = m.get_list_display(request)
        list_display_links = m.get_list_display_links(request, list_display)
        self.assertEqual(list_display, ('parent', 'name', 'age'))
        self.assertEqual(list_display_links, ['age'])

    def test_no_list_display_links(self):
        """#15185 -- Allow no links from the 'change list' view grid."""
        p = Parent.objects.create(name='parent')
        m = NoListDisplayLinksParentAdmin(Parent, custom_site)
        superuser = self._create_superuser('superuser')
        request = self._mocked_authenticated_request('/parent/', superuser)
        response = m.changelist_view(request)
        link = reverse('admin:admin_changelist_parent_change', args=(p.pk,))
        self.assertNotContains(response, '' % link)

    def test_tuple_list_display(self):
        swallow = Swallow.objects.create(origin='Africa', load='12.34', speed='22.2')
        swallow2 = Swallow.objects.create(origin='Africa', load='12.34', speed='22.2')
        swallow_o2o = SwallowOneToOne.objects.create(swallow=swallow2)

        model_admin = SwallowAdmin(Swallow, custom_site)
        superuser = self._create_superuser('superuser')
        request = self._mocked_authenticated_request('/swallow/', superuser)
        response = model_admin.changelist_view(request)
        # just want to ensure it doesn't blow up during rendering
        self.assertContains(response, str(swallow.origin))
        self.assertContains(response, str(swallow.load))
        self.assertContains(response, str(swallow.speed))
        # Reverse one-to-one relations should work.
        self.assertContains(response, '-	')
        self.assertContains(response, '%s	' % swallow_o2o)

    def test_multiuser_edit(self):
        """
        Simultaneous edits of list_editable fields on the changelist by
        different users must not result in one user's edits creating a new
        object instead of modifying the correct existing object (#11313).
        """
        # To replicate this issue, simulate the following steps:
        # 1. User1 opens an admin changelist with list_editable fields.
        # 2. User2 edits object "Foo" such that it moves to another page in
        #    the pagination order and saves.
        # 3. User1 edits object "Foo" and saves.
        # 4. The edit made by User1 does not get applied to object "Foo" but
        #    instead is used to create a new object (bug).

        # For this test, order the changelist by the 'speed' attribute and
        # display 3 objects per page (SwallowAdmin.list_per_page = 3).

        # Setup the test to reflect the DB state after step 2 where User2 has
        # edited the first swallow object's speed from '4' to '1'.
        a = Swallow.objects.create(origin='Swallow A', load=4, speed=1)
        b = Swallow.objects.create(origin='Swallow B', load=2, speed=2)
        c = Swallow.objects.create(origin='Swallow C', load=5, speed=5)
        d = Swallow.objects.create(origin='Swallow D', load=9, speed=9)

        superuser = self._create_superuser('superuser')
        self.client.force_login(superuser)
        changelist_url = reverse('admin:admin_changelist_swallow_changelist')

        # Send the POST from User1 for step 3. It's still using the changelist
        # ordering from before User2's edits in step 2.
        data = {
            'form-TOTAL_FORMS': '3',
            'form-INITIAL_FORMS': '3',
            'form-MIN_NUM_FORMS': '0',
            'form-MAX_NUM_FORMS': '1000',
            'form-0-id': str(d.pk),
            'form-1-id': str(c.pk),
            'form-2-id': str(a.pk),
            'form-0-load': '9.0',
            'form-0-speed': '9.0',
            'form-1-load': '5.0',
            'form-1-speed': '5.0',
            'form-2-load': '5.0',
            'form-2-speed': '4.0',
            '_save': 'Save',
        }
        response = self.client.post(changelist_url, data, follow=True, extra={'o': '-2'})

        # The object User1 edited in step 3 is displayed on the changelist and
        # has the correct edits applied.
        self.assertContains(response, '1 swallow was changed successfully.')
        self.assertContains(response, a.origin)
        a.refresh_from_db()
        self.assertEqual(a.load, float(data['form-2-load']))
        self.assertEqual(a.speed, float(data['form-2-speed']))
        b.refresh_from_db()
        self.assertEqual(b.load, 2)
        self.assertEqual(b.speed, 2)
        c.refresh_from_db()
        self.assertEqual(c.load, float(data['form-1-load']))
        self.assertEqual(c.speed, float(data['form-1-speed']))
        d.refresh_from_db()
        self.assertEqual(d.load, float(data['form-0-load']))
        self.assertEqual(d.speed, float(data['form-0-speed']))
        # No new swallows were created.
        self.assertEqual(len(Swallow.objects.all()), 4)

    def test_deterministic_order_for_unordered_model(self):
        """
        The primary key is used in the ordering of the changelist's results to
        guarantee a deterministic order, even when the model doesn't have any
        default ordering defined (#17198).
        """
        superuser = self._create_superuser('superuser')

        for counter in range(1, 51):
            UnorderedObject.objects.create(id=counter, bool=True)

        class UnorderedObjectAdmin(admin.ModelAdmin):
            list_per_page = 10

        def check_results_order(ascending=False):
            custom_site.register(UnorderedObject, UnorderedObjectAdmin)
            model_admin = UnorderedObjectAdmin(UnorderedObject, custom_site)
            counter = 0 if ascending else 51
            for page in range(0, 5):
                request = self._mocked_authenticated_request('/unorderedobject/?p=%s' % page, superuser)
                response = model_admin.changelist_view(request)
                for result in response.context_data['cl'].result_list:
                    counter += 1 if ascending else -1
                    self.assertEqual(result.id, counter)
            custom_site.unregister(UnorderedObject)

        # When no order is defined at all, everything is ordered by '-pk'.
        check_results_order()

        # When an order field is defined but multiple records have the same
        # value for that field, make sure everything gets ordered by -pk as well.
        UnorderedObjectAdmin.ordering = ['bool']
        check_results_order()

        # When order fields are defined, including the pk itself, use them.
        UnorderedObjectAdmin.ordering = ['bool', '-pk']
        check_results_order()
        UnorderedObjectAdmin.ordering = ['bool', 'pk']
        check_results_order(ascending=True)
        UnorderedObjectAdmin.ordering = ['-id', 'bool']
        check_results_order()
        UnorderedObjectAdmin.ordering = ['id', 'bool']
        check_results_order(ascending=True)

    def test_deterministic_order_for_model_ordered_by_its_manager(self):
        """
        The primary key is used in the ordering of the changelist's results to
        guarantee a deterministic order, even when the model has a manager that
        defines a default ordering (#17198).
        """
        superuser = self._create_superuser('superuser')

        for counter in range(1, 51):
            OrderedObject.objects.create(id=counter, bool=True, number=counter)

        class OrderedObjectAdmin(admin.ModelAdmin):
            list_per_page = 10

        def check_results_order(ascending=False):
            custom_site.register(OrderedObject, OrderedObjectAdmin)
            model_admin = OrderedObjectAdmin(OrderedObject, custom_site)
            counter = 0 if ascending else 51
            for page in range(0, 5):
                request = self._mocked_authenticated_request('/orderedobject/?p=%s' % page, superuser)
                response = model_admin.changelist_view(request)
                for result in response.context_data['cl'].result_list:
                    counter += 1 if ascending else -1
                    self.assertEqual(result.id, counter)
            custom_site.unregister(OrderedObject)

        # When no order is defined at all, use the model's default ordering (i.e. 'number')
        check_results_order(ascending=True)

        # When an order field is defined but multiple records have the same
        # value for that field, make sure everything gets ordered by -pk as well.
        OrderedObjectAdmin.ordering = ['bool']
        check_results_order()

        # When order fields are defined, including the pk itself, use them.
        OrderedObjectAdmin.ordering = ['bool', '-pk']
        check_results_order()
        OrderedObjectAdmin.ordering = ['bool', 'pk']
        check_results_order(ascending=True)
        OrderedObjectAdmin.ordering = ['-id', 'bool']
        check_results_order()
        OrderedObjectAdmin.ordering = ['id', 'bool']
        check_results_order(ascending=True)

    def test_dynamic_list_filter(self):
        """
        Regression tests for ticket #17646: dynamic list_filter support.
        """
        parent = Parent.objects.create(name='parent')
        for i in range(10):
            Child.objects.create(name='child %s' % i, parent=parent)

        user_noparents = self._create_superuser('noparents')
        user_parents = self._create_superuser('parents')

        # Test with user 'noparents'
        m = DynamicListFilterChildAdmin(Child, custom_site)
        request = self._mocked_authenticated_request('/child/', user_noparents)
        response = m.changelist_view(request)
        self.assertEqual(response.context_data['cl'].list_filter, ['name', 'age'])

        # Test with user 'parents'
        m = DynamicListFilterChildAdmin(Child, custom_site)
        request = self._mocked_authenticated_request('/child/', user_parents)
        response = m.changelist_view(request)
        self.assertEqual(response.context_data['cl'].list_filter, ('parent', 'name', 'age'))

    def test_dynamic_search_fields(self):
        child = self._create_superuser('child')
        m = DynamicSearchFieldsChildAdmin(Child, custom_site)
        request = self._mocked_authenticated_request('/child/', child)
        response = m.changelist_view(request)
        self.assertEqual(response.context_data['cl'].search_fields, ('name', 'age'))

    def test_pagination_page_range(self):
        """
        Regression tests for ticket #15653: ensure the number of pages
        generated for changelist views are correct.
        """
        # instantiating and setting up ChangeList object
        m = GroupAdmin(Group, custom_site)
        request = self.factory.get('/group/')
        cl = ChangeList(request, Group, *get_changelist_args(m))
        per_page = cl.list_per_page = 10

        for page_num, objects_count, expected_page_range in [
            (0, per_page, []),
            (0, per_page * 2, list(range(2))),
            (5, per_page * 11, list(range(11))),
            (5, per_page * 12, [0, 1, 2, 3, 4, 5, 6, 7, 8, '.', 10, 11]),
            (6, per_page * 12, [0, 1, '.', 3, 4, 5, 6, 7, 8, 9, 10, 11]),
            (6, per_page * 13, [0, 1, '.', 3, 4, 5, 6, 7, 8, 9, '.', 11, 12]),
        ]:
            # assuming we have exactly `objects_count` objects
            Group.objects.all().delete()
            for i in range(objects_count):
                Group.objects.create(name='test band')

            # setting page number and calculating page range
            cl.page_num = page_num
            cl.get_results(request)
            real_page_range = pagination(cl)['page_range']

            self.assertListEqual(
                expected_page_range,
                list(real_page_range),
            )

    def test_object_tools_displayed_no_add_permission(self):
        """
        When ModelAdmin.has_add_permission() returns False, the object-tools
        block is still shown.
        """
        superuser = self._create_superuser('superuser')
        m = EventAdmin(Event, custom_site)
        request = self._mocked_authenticated_request('/event/', superuser)
        self.assertFalse(m.has_add_permission(request))
        response = m.changelist_view(request)
        self.assertIn('
', response.rendered_content)
        # The "Add" button inside the object-tools shouldn't appear.
        self.assertNotIn('Add ', response.rendered_content)

class AdminLogNodeTestCase(TestCase):

    def test_get_admin_log_templatetag_custom_user(self):
        """
        Regression test for ticket #20088: admin log depends on User model
        having id field as primary key.

        The old implementation raised an AttributeError when trying to use
        the id field.
        """
        context = Context({'user': CustomIdUser()})
        template_string = '{% load log %}{% get_admin_log 10 as admin_log for_user user %}'

        template = Template(template_string)

        # Rendering should be u'' since this templatetag just logs,
        # it doesn't render any string.
        self.assertEqual(template.render(context), '')

    def test_get_admin_log_templatetag_no_user(self):
        """
        The {% get_admin_log %} tag should work without specifying a user.
        """
        user = User(username='jondoe', password='secret', email='super@example.com')
        user.save()
        ct = ContentType.objects.get_for_model(User)
        LogEntry.objects.log_action(user.pk, ct.pk, user.pk, repr(user), 1)

        t = Template(
            '{% load log %}'
            '{% get_admin_log 100 as admin_log %}'
            '{% for entry in admin_log %}'
            '{{ entry|safe }}'
            '{% endfor %}'
        )
        self.assertEqual(t.render(Context({})), 'Added "<User: jondoe>".')

@override_settings(ROOT_URLCONF='admin_changelist.urls')
class SeleniumTests(AdminSeleniumTestCase):

    available_apps = ['admin_changelist'] + AdminSeleniumTestCase.available_apps

    def setUp(self):
        User.objects.create_superuser(username='super', password='secret', email=None)

    def test_add_row_selection(self):
        """
        The status line for selected rows gets updated correctly (#22038).
        """
        self.admin_login(username='super', password='secret')
        self.selenium.get(self.live_server_url + reverse('admin:auth_user_changelist'))

        form_id = '#changelist-form'

        # Test amount of rows in the Changelist
        rows = self.selenium.find_elements_by_css_selector(
            '%s #result_list tbody tr' % form_id)
        self.assertEqual(len(rows), 1)

        # Test current selection
        selection_indicator = self.selenium.find_element_by_css_selector(
            '%s .action-counter' % form_id)
        self.assertEqual(selection_indicator.text, "0 of 1 selected")

        # Select a row and check again
        row_selector = self.selenium.find_element_by_css_selector(
            '%s #result_list tbody tr:first-child .action-select' % form_id)
        row_selector.click()
        self.assertEqual(selection_indicator.text, "1 of 1 selected")


text:
class ProjectileElectricShock : public Projectile
{
public:
	ProjectileElectricShock();
	virtual ~ProjectileElectricShock();

};

#endif // !defined(AFX_PROJECTILEELECTRICSHOCK_H__947CF2F7_E98A_4FEA_8B6A_D9B8042561D6__INCLUDED_)

redpajama_set_name: RedPajamaGithub


text:
/**
 * Async helpers.
 */
package com.hillwater.async;


text:
/**
 * A JMS implementation of a LiveData client.
 */
package com.opengamma.livedata.client;


text:
[*back to contents*](https://github.com/gyuho/learn#contents)

# Go: spell check

- [Reference](#reference)
- [Spell check algorithm](#spell-check-algorithm)
- [](#)

[↑ top](#go-spell-check)

#### Reference

- [How to Write a Spelling Corrector by Peter Norvig](http://norvig.com/spell-correct.html)

[↑ top](#go-spell-check)

#### Spell check algorithm

Try [this](http://play.golang.org/p/Fc2JxOVfTm):

```go
package main

import (
	"bufio"
	"fmt"
	"io"
	"strings"
)

func main() {
	fmap := Frequency(strings.NewReader("Francisco, Francisco"))
	fmt.Println(Suggest("Fransisco", fmap))
	// Francisco
}

// Frequency counts the frequency of each word.
func Frequency(reader io.Reader) map[string]int {
	scanner := bufio.NewScanner(reader)
	//
	// This must be called before Scan.
	// The default split function is bufio.ScanLines.
	scanner.Split(bufio.ScanWords)
	//
	fmap := make(map[string]int)
	//
	for scanner.Scan() {
		// Remove all leading and trailing Unicode code points.
		word := strings.Trim(scanner.Text(), ",-!;:\"?.")
		if _, exist := fmap[word]; exist {
			fmap[word]++
		} else {
			fmap[word] = 1
		}
	}
	return fmap
}

// distanceOne sends all possible corrections
// with edit distance 1 to the channel one.
// This is much more probable than the one with 2 edit distance.
func distanceOne(txt string, one chan string) {
	const alphabet = "abcdefghijklmnopqrstuvwxyz"
	type pair struct {
		front, back string
	}
	pairs := []pair{}
	for i := 0; i <= len(txt); i++ {
		pairs = append(pairs, pair{txt[:i], txt[i:]})
	}
	for _, pair := range pairs {
		// deletion of pair.back[0]
		if len(pair.back) > 0 {
			one <- pair.front + pair.back[1:]
		}
		// transpose of pair.back[0] and pair.back[1]
		if len(pair.back) > 1 {
			one <- pair.front + string(pair.back[1]) + string(pair.back[0]) + pair.back[2:]
		}
		// replace of pair.back[0]
		for _, elem := range alphabet {
			if len(pair.back) > 0 {
				one <- pair.front + string(elem) + pair.back[1:]
			}
		}
		// insertion
		for _, elem := range alphabet {
			one <- pair.front + string(elem) + pair.back
		}
	}
}

// distanceMore sends other possible corrections
// based on the results from distanceOne.
func distanceMore(word string, other chan string) {
	one := make(chan string, 1024*1024)
	go func() {
		distanceOne(word, one)
		close(one)
	}()
	// retrieve from distanceOne results and break when it's done
	for v := range one {
		// run distanceOne in addition to the results from the first distanceOne
		distanceOne(v, other)
	}
}

// known returns the word with maximum frequencies.
func known(txt string, distFunc func(string, chan string), fmap map[string]int) string {
	words := make(chan string, 1024*1024)
	go func() {
		distFunc(txt, words)
		close(words)
	}()
	maxFq := 0
	suggest := ""
	for wd := range words {
		if freq, exist := fmap[wd]; exist && freq > maxFq {
			maxFq, suggest = freq, wd
		}
	}
	return suggest
}

// Suggest suggests the correct spelling based on the sample data.
func Suggest(txt string, fmap map[string]int) string {
	// edit distance 0
	if _, exist := fmap[txt]; exist {
		return txt
	}
	if v := known(txt, distanceOne, fmap); v != "" {
		return v
	}
	if v := known(txt, distanceMore, fmap); v != "" {
		return v
	}
	// edit distance 3, 4, and more ...
	return txt
}

```

[↑ top](#go-spell-check)


text:
package org.apache.solr.handler.component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.solr.common.params.FacetParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;

/**
 * Models a single field somewhere in a hierarchy of fields as part of a pivot facet. This pivot
 * field contains {@link PivotFacetValue}s which may each contain a nested {@link PivotFacetField}
 * child. This PivotFacetField may itself be a child of a {@link PivotFacetValue}
 * parent.
 *
 * @see PivotFacetValue
 * @see PivotFacetFieldValueCollection
 */
public class PivotFacetField {

  public final String field;

  // null if this is a top level pivot,
  // otherwise the value of the parent pivot we are nested under
  public final PivotFacetValue parentValue;

  public final PivotFacetFieldValueCollection valueCollection;

  // Facet parameters relating to this field
  private final int facetFieldLimit;
  private final int facetFieldMinimumCount;
  private final int facetFieldOffset;
  private final String facetFieldSort;

  private final Map<Integer, Integer> numberOfValuesContributedByShard = new HashMap<>();
  private final Map<Integer, Integer> shardLowestCount = new HashMap<>();

  private boolean needRefinementAtThisLevel = true;

  private PivotFacetField(ResponseBuilder rb, PivotFacetValue parent, String fieldName) {

    field = fieldName;
    parentValue = parent;

    // facet params
    SolrParams parameters = rb.req.getParams();
    facetFieldMinimumCount = parameters.getFieldInt(field, FacetParams.FACET_PIVOT_MINCOUNT, 1);
    facetFieldOffset = parameters.getFieldInt(field, FacetParams.FACET_OFFSET, 0);
    facetFieldLimit = parameters.getFieldInt(field, FacetParams.FACET_LIMIT, 100);
    String defaultSort =
        (facetFieldLimit > 0) ? FacetParams.FACET_SORT_COUNT : FacetParams.FACET_SORT_INDEX;
    facetFieldSort = parameters.getFieldParam(field, FacetParams.FACET_SORT, defaultSort);

    valueCollection =
        new PivotFacetFieldValueCollection(
            facetFieldMinimumCount, facetFieldOffset, facetFieldLimit, facetFieldSort);

    if ((facetFieldLimit < 0)
        ||
        // TODO: possible refinement issue if limit=0 & mincount=0 & missing=true
        // (ie: we only want the missing count for this field)
        (facetFieldLimit <= 0 && facetFieldMinimumCount == 0)
        || (facetFieldSort.equals(FacetParams.FACET_SORT_INDEX) && facetFieldMinimumCount <= 0)) {
      // in any of these cases, there's no need to refine this level of the pivot
      needRefinementAtThisLevel = false;
    }
  }

  /**
   * A recursive method that walks up the tree of pivot fields/values to build a list of String
   * representations of the values that lead down to this PivotFacetField.
   *
   * @return A mutable List of the pivot values leading down to this pivot field, will never be null
   *     but may contain nulls and may be empty if this is a top level pivot field
   * @see PivotFacetValue#getValuePath
   */
  public List<String> getValuePath() {
    if (null != parentValue) {
      return parentValue.getValuePath();
    }
    return new ArrayList<String>(3);
  }

  /**
   * A recursive method to construct a new PivotFacetField object from the contents of
   * the {@link NamedList}s provided by the specified shard, relative to a parent value (if this is
   * not the top field in the pivot hierarchy)
   *
   *
The associated child {@link PivotFacetValue}s will be recursively built as well.
   *
   * @see PivotFacetValue#createFromNamedList
   * @param shardNumber the id of the shard that provided this data
   * @param rb The response builder of the current request
   * @param owner the parent value in the current pivot (may be null)
   * @param pivotValues the data from the specified shard for this pivot field, may be null or empty
   * @return the new PivotFacetField, null if pivotValues is null or empty.
   */
  public static PivotFacetField createFromListOfNamedLists(
      int shardNumber,
      ResponseBuilder rb,
      PivotFacetValue owner,
      List<NamedList<Object>> pivotValues) {

    if (null == pivotValues || pivotValues.size() <= 0) return null;

    NamedList<Object> firstValue = pivotValues.get(0);
    PivotFacetField createdPivotFacetField =
        new PivotFacetField(rb, owner, PivotFacetHelper.getField(firstValue));

    int lowestCount = Integer.MAX_VALUE;

    for (NamedList<Object> pivotValue : pivotValues) {

      lowestCount = Math.min(lowestCount, PivotFacetHelper.getCount(pivotValue));

      PivotFacetValue newValue =
          PivotFacetValue.createFromNamedList(shardNumber, rb, createdPivotFacetField, pivotValue);
      createdPivotFacetField.valueCollection.add(newValue);
    }

    createdPivotFacetField.shardLowestCount.put(shardNumber, lowestCount);
    createdPivotFacetField.numberOfValuesContributedByShard.put(shardNumber, pivotValues.size());

    return createdPivotFacetField;
  }

  /**
   * Destructive method that recursively prunes values from the data structure based on the counts
   * for those values and the effective sort, mincount, limit, and offset being used for each field.
   *
   *
This method should only be called after all refinement is completed just prior calling
   * {@link #convertToListOfNamedLists}
   *
   * @see PivotFacet#getTrimmedPivotsAsListOfNamedLists
   * @see PivotFacetFieldValueCollection#trim
   */
  public void trim() {
    // SOLR-6331...
    //
    // we can probably optimize the memory usage by trimming each level of the pivot once
    // we know we've fully refined the values at that level
    // (ie: fold this logic into refineNextLevelOfFacets)
    this.valueCollection.trim();
  }

  /**
   * Recursively sorts the collection of values associated with this field, and any sub-pivots those
   * values have.
   *
   * @see FacetParams#FACET_SORT
   * @see PivotFacetFieldValueCollection#sort
   */
  public void sort() {
    this.valueCollection.sort();
  }

  /**
   * A recursive method for generating NamedLists from this field suitable for
   * including in a pivot facet response to the original distributed request.
   */
  public List<NamedList<Object>> convertToListOfNamedLists() {

    List<NamedList<Object>> convertedPivotList = null;

    if (valueCollection.size() > 0) {
      convertedPivotList = new ArrayList<>();
      for (PivotFacetValue pivot : valueCollection)
        convertedPivotList.add(pivot.convertToNamedList());
    }

    return convertedPivotList;
  }

  /**
   * A recursive method for determining which {@link PivotFacetValue}s need to be refined for this
   * pivot.
   *
   * @see PivotFacet#queuePivotRefinementRequests
   */
  public void queuePivotRefinementRequests(PivotFacet pf) {

    if (needRefinementAtThisLevel) {

      if (0 < facetFieldMinimumCount) {
        // missing is always a candidate for refinement if at least one shard met the minimum
        PivotFacetValue missing = valueCollection.getMissingValue();
        if (null != missing) {
          processDefiniteCandidateElement(pf, valueCollection.getMissingValue());
        }
      }

      if (!valueCollection.getExplicitValuesList().isEmpty()) {

        if (FacetParams.FACET_SORT_COUNT.equals(facetFieldSort)) {
          // we only need to things that are currently in our limit,
          // or might be in our limit if we get increased counts from shards that
          // didn't include this value the first time
          final int indexOfCountThreshold =
              Math.min(
                      valueCollection.getExplicitValuesListSize(),
                      facetFieldOffset + facetFieldLimit)
                  - 1;
          final int countThreshold = valueCollection.getAt(indexOfCountThreshold).getCount();

          int positionInResults = 0;

          for (PivotFacetValue value : valueCollection.getExplicitValuesList()) {
            if (positionInResults <= indexOfCountThreshold) {
              // This element is within the top results, so we need to get information
              // from all of the shards.
              processDefiniteCandidateElement(pf, value);
            } else {
              // This element is not within the top results, but may still need to be refined.
              processPossibleCandidateElement(pf, value, countThreshold);
            }

            positionInResults++;
          }
        } else { // FACET_SORT_INDEX
          // everything needs refined to see what the per-shard mincount excluded
          for (PivotFacetValue value : valueCollection.getExplicitValuesList()) {
            processDefiniteCandidateElement(pf, value);
          }
        }
      }

      needRefinementAtThisLevel = false;
    }

    if (pf.isRefinementsRequired()) {
      // if any refinements are needed, then we need to stop and wait to
      // see how the picture may change before drilling down to child pivot fields
      return;
    } else {
      // Since outstanding requests have been filled, then we can drill down
      // to the next deeper level and check it.
      refineNextLevelOfFacets(pf);
    }
  }

  /**
   * Adds refinement requests for the value for each shard that has not already contributed a count
   * for this value.
   */
  private void processDefiniteCandidateElement(PivotFacet pf, PivotFacetValue value) {

    for (int shard = pf.knownShards.nextSetBit(0);
        0 <= shard;
        shard = pf.knownShards.nextSetBit(shard + 1)) {
      if (!value.shardHasContributed(shard)) {
        if ( // if we're doing index order, we need to refine anything
        // (mincount may have excluded from a shard)
        FacetParams.FACET_SORT_INDEX.equals(facetFieldSort)
            || ( // 'missing' value isn't affected by limit, needs refined if shard didn't provide
            null == value.getValue()
                ||
                // if we are doing count order, we need to refine if the limit was hit
                // (if not, the shard doesn't have the value or it would have returned already)
                numberOfValuesContributedByShardWasLimitedByFacetFieldLimit(shard))) {
          pf.addRefinement(shard, value);
        }
      }
    }
  }

  private boolean numberOfValuesContributedByShardWasLimitedByFacetFieldLimit(int shardNumber) {
    return facetFieldLimit <= numberOfValuesContributedByShard(shardNumber);
  }

  private int numberOfValuesContributedByShard(final int shardNumber) {
    return numberOfValuesContributedByShard.containsKey(shardNumber)
        ? numberOfValuesContributedByShard.get(shardNumber)
        : 0;
  }

  /**
   * Checks the {@link #lowestCountContributedbyShard} for each shard, combined with the counts we
   * already know, to see if this value is a viable candidate -- Does not make sense when using
   * {@link FacetParams#FACET_SORT_INDEX}
   *
   * @see #processDefiniteCandidateElement
   */
  private void processPossibleCandidateElement(
      PivotFacet pf, PivotFacetValue value, final int refinementThreshold) {

    assert FacetParams.FACET_SORT_COUNT.equals(facetFieldSort)
        : "Method only makes sense when sorting by count";

    int maxPossibleCountAfterRefinement = value.getCount();

    for (int shard = pf.knownShards.nextSetBit(0);
        0 <= shard;
        shard = pf.knownShards.nextSetBit(shard + 1)) {
      if (!value.shardHasContributed(shard)) {
        maxPossibleCountAfterRefinement += lowestCountContributedbyShard(shard);
      }
    }

    if (refinementThreshold <= maxPossibleCountAfterRefinement) {
      processDefiniteCandidateElement(pf, value);
    }
  }

  private int lowestCountContributedbyShard(int shardNumber) {
    return (shardLowestCount.containsKey(shardNumber)) ? shardLowestCount.get(shardNumber) : 0;
  }

  private void refineNextLevelOfFacets(PivotFacet pf) {

    List<PivotFacetValue> explicitValsToRefine = valueCollection.getNextLevelValuesToRefine();

    for (PivotFacetValue value : explicitValsToRefine) {
      if (null != value.getChildPivot()) {
        value.getChildPivot().queuePivotRefinementRequests(pf);
      }
    }

    PivotFacetValue missing = this.valueCollection.getMissingValue();
    if (null != missing && null != missing.getChildPivot()) {
      missing.getChildPivot().queuePivotRefinementRequests(pf);
    }
  }

  private void incrementShardValueCount(int shardNumber) {
    if (!numberOfValuesContributedByShard.containsKey(shardNumber)) {
      numberOfValuesContributedByShard.put(shardNumber, 1);
    } else {
      numberOfValuesContributedByShard.put(
          shardNumber, numberOfValuesContributedByShard.get(shardNumber) + 1);
    }
  }

  private void contributeValueFromShard(
      int shardNumber, ResponseBuilder rb, NamedList<Object> shardValue) {

    incrementShardValueCount(shardNumber);

    @SuppressWarnings("rawtypes")
    Comparable value = PivotFacetHelper.getValue(shardValue);
    int count = PivotFacetHelper.getCount(shardValue);

    // We're changing values so we most mark the collection as dirty
    valueCollection.markDirty();

    if ((!shardLowestCount.containsKey(shardNumber)) || shardLowestCount.get(shardNumber) > count) {
      shardLowestCount.put(shardNumber, count);
    }

    PivotFacetValue facetValue = valueCollection.get(value);
    if (null == facetValue) {
      // never seen before, we need to create it from scratch
      facetValue = PivotFacetValue.createFromNamedList(shardNumber, rb, this, shardValue);
      this.valueCollection.add(facetValue);
    } else {
      facetValue.mergeContributionFromShard(shardNumber, rb, shardValue);
    }
  }

  /**
   * Recursively merges the contributions from the specified shard for each {@link PivotFacetValue}
   * represended in the response.
   *
   * @see PivotFacetValue#mergeContributionFromShard
   * @param shardNumber the id of the shard that provided this data
   * @param rb The response builder of the current request
   * @param response the data from the specified shard for this pivot field, may be null
   */
  public void contributeFromShard(
      int shardNumber, ResponseBuilder rb, List<NamedList<Object>> response) {
    if (null == response) return;

    for (NamedList<Object> responseValue : response) {
      contributeValueFromShard(shardNumber, rb, responseValue);
    }
  }

  @Override
  public String toString() {
    return String.format(Locale.ROOT, "P:%s F:%s V:%s", parentValue, field, valueCollection);
  }
}


text:
#ifndef HALIDE_SCHEDULE_PARAM_H
#define HALIDE_SCHEDULE_PARAM_H

#include <type_traits>

#include "IR.h"
#include "ObjectInstanceRegistry.h"

/** \file
 *
 * Classes for declaring scalar parameters to halide pipelines
 */

namespace Halide {

namespace Internal {

class GeneratorBase;

class ScheduleParamBase {
public:
    const std::string &name() const {
        return sp_name;
    }

    bool is_looplevel_param() const {
        return type == Handle();
    }

    const Type &scalar_type() const {
        internal_assert(!is_looplevel_param());
        return type;
    }

    operator Expr() const {
        user_assert(!is_looplevel_param()) << "Only scalar ScheduleParams can be converted to Expr.";
        return scalar_expr;
    }

    operator LoopLevel() const {
        user_assert(is_looplevel_param()) << "Only ScheduleParam<LoopLevel> can be converted to LoopLevel.";
        return loop_level;
    }

    // overload the set() function to call the right virtual method based on type.
    // This allows us to attempt to set a ScheduleParam via a
    // plain C++ type, even if we don't know the specific templated
    // subclass. Attempting to set the wrong type will assert.
    //
    // It's always a bit iffy to use macros for this, but IMHO it clarifies the situation here.
#define HALIDE_SCHEDULE_PARAM_TYPED_SETTER(TYPE) \
    virtual void set(const TYPE &new_value) = 0;

    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(bool)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(int8_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(int16_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(int32_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(int64_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(uint8_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(uint16_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(uint32_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(uint64_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(float)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(double)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(LoopLevel)

#undef HALIDE_SCHEDULE_PARAM_TYPED_SETTER

protected:
    friend class GeneratorBase;

    std::string sp_name;
    Type type;
    Internal::Parameter scalar_parameter;
    Expr scalar_expr;
    LoopLevel loop_level;

    EXPORT ScheduleParamBase(const Type &t, const std::string &name, bool is_explicit_name);
    EXPORT virtual ~ScheduleParamBase();

    // This is provided only for GeneratorBase; other code should not need to use it.
    virtual void set_from_string(const std::string &new_value_string) = 0;

    EXPORT explicit ScheduleParamBase(const ScheduleParamBase &);
    EXPORT ScheduleParamBase &operator=(const ScheduleParamBase &);
};

}  // namespace Internal

// This is strictly some syntactic sugar to suppress certain compiler warnings.
template<typename FROM, typename TO>
struct Convert {
    template <typename TO2 = TO, typename std::enable_if<!std::is_same<TO2, bool>::value>::type * = nullptr>
    inline static TO2 value(const FROM &from) { return static_cast<TO2>(from); }

    template <typename TO2 = TO, typename std::enable_if<std::is_same<TO2, bool>::value>::type * = nullptr>
    inline static TO2 value(const FROM &from) { return from != 0; }
};

/** A ScheduleParam is a "Param" that can contain a scalar Expr or a LoopLevel;
 * unlike Param<>, its value cannot be set at runtime. All ScheduleParam values
 * are finalized just before lowering, and must translate into a constant scalar
 * value (or a well-defined LoopLevel) at that point. The value of
 * should be bound to an actual value of type T using the set method
 * before you realize the function uses this. If you're statically
 * compiling, this param should *not* appear in the argument list.
 */
template <typename T>
class ScheduleParam : public Internal::ScheduleParamBase {
    using ScheduleParamBase = Internal::ScheduleParamBase;

    template <typename T2 = T,
              typename std::enable_if<std::is_arithmetic<T2>::value>::type * = nullptr>
    static Type get_param_type() {
        return type_of<T>();
    }

    template <typename T2 = T,
              typename std::enable_if<!std::is_arithmetic<T2>::value>::type * = nullptr>
    static Type get_param_type() {
        return Handle();
    }

    template <typename T2, typename std::enable_if<std::is_arithmetic<T>::value &&
                                                   std::is_convertible<T2, T>::value>::type * = nullptr>
    HALIDE_ALWAYS_INLINE void typed_setter_impl(const T2 &value, const char *type) {
        // Arithmetic types must roundtrip losslessly.
        if (!std::is_same<T, T2>::value &&
            std::is_arithmetic<T>::value &&
            std::is_arithmetic<T2>::value) {
            const T t = Convert<T2, T>::value(value);
            const T2 t2 = Convert<T, T2>::value(t);
            if (t2 != value) {
                user_error << "The ScheduleParam " << name() << " cannot be set with a value of type " << type << ".\n";
            }
        }
        scalar_parameter.set_scalar<T>(Convert<T2, T>::value(value));
    }

    template <typename T2, typename std::enable_if<std::is_same<T2, LoopLevel>::value>::type * = nullptr>
    HALIDE_ALWAYS_INLINE void typed_setter_impl(const LoopLevel &value, const char *msg) {
        user_assert(is_looplevel_param()) << "Only ScheduleParam<LoopLevel> can be set withLoopLevel.";
        loop_level.copy_from(value);
    }

    template <typename T2, typename std::enable_if<!std::is_convertible<T2, T>::value>::type * = nullptr>
    HALIDE_ALWAYS_INLINE void typed_setter_impl(const T2 &value, const char *type) {
        user_error << "The ScheduleParam " << name() << " cannot be set with a value of type " << type << ".\n";
    }

    template <typename T2 = T,
              typename std::enable_if<std::is_same<T2, LoopLevel>::value>::type * = nullptr>
    NO_INLINE void set_from_string_impl(const std::string &new_value_string) {
        if (new_value_string == "root") {
            set(LoopLevel::root());
        } else if (new_value_string == "inline") {
            set(LoopLevel::inlined());
        } else {
            user_error << "Unable to parse " << name() << ": " << new_value_string;
        }
    }

    template <typename T2 = T,
              typename std::enable_if<std::is_same<T2, bool>::value>::type * = nullptr>
    NO_INLINE void set_from_string_impl(const std::string &new_value_string) {
        if (new_value_string == "true") {
            set(true);
        } else if (new_value_string == "false") {
            set(false);
        } else {
            user_error << "Unable to parse " << name() << ": " << new_value_string;
        }
    }

    template <typename T2 = T,
              typename std::enable_if<std::is_arithmetic<T2>::value && !std::is_same<T2, bool>::value>::type * = nullptr>
    NO_INLINE void set_from_string_impl(const std::string &new_value_string) {
        std::istringstream iss(new_value_string);
        T t;
        iss >> t;
        user_assert(!iss.fail() && iss.get() == EOF) << "Unable to parse " << name() << ": " << new_value_string;
        set(t);
    }

protected:
    void set_from_string(const std::string &new_value_string) override {
        set_from_string_impl(new_value_string);
    }

public:
    ScheduleParam() : ScheduleParamBase(get_param_type(), "", false) {}

    explicit ScheduleParam(const std::string &name) : ScheduleParamBase(get_param_type(), name, true) {}

    ScheduleParam(const std::string &name, const T &value) : ScheduleParamBase(get_param_type(), name, true) {
        set(value);
    }

    // TODO hide?
    explicit ScheduleParam(const ScheduleParamBase &that) : ScheduleParamBase(that) {}

#define HALIDE_SCHEDULE_PARAM_TYPED_SETTER(TYPE) \
    void set(const TYPE &new_value) override { typed_setter_impl<TYPE>(new_value, #TYPE); }

    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(bool)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(int8_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(int16_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(int32_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(int64_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(uint8_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(uint16_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(uint32_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(uint64_t)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(float)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(double)
    HALIDE_SCHEDULE_PARAM_TYPED_SETTER(LoopLevel)

#undef HALIDE_SCHEDULE_PARAM_TYPED_SETTER

    // Note that we deliberately do not provide a way to retrieve the non-Expr value
    // of ScheduleParam: this is because the value is probably inaccurate at the point
    // you'd be tempted to examine it, since it won't be finalized until the start of lowering.
    // Here's the code that we'd use to do so, if we find we need to:

    // template <typename T2 = T,
    //           typename std::enable_if<std::is_arithmetic<T2>::value>::type * = nullptr>
    // operator T() const {
    //     return scalar_parameter.get_scalar<T>();
    // }

    // template <typename T2 = T,
    //           typename std::enable_if<std::is_same<T2, LoopLevel>::value>::type * = nullptr>
    // operator T() const {
    //     return loop_level;
    // }
};

}  // namespace Halide

#endif


text:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.banana.banana.setting.AlarmActivity" >
       <TextView
                android:id="@+id/text_sound"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="소리모드"
                android:textAppearance="?android:attr/textAppearanceMedium" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/btn_on"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="ON" />

        <Button
            android:id="@+id/btn_off"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="OFF" />
    </LinearLayout>

     <TextView
                android:id="@+id/text_popup"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="메세지 팝업"
                android:textAppearance="?android:attr/textAppearanceMedium" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/popup_on"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="ON" />

        <Button
            android:id="@+id/popup_off"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="OFF" />
    </LinearLayout>

</LinearLayout>


text:
import datetime
import inspect

import pandas as pd
from pandas.core.window import Rolling as pd_Rolling
from numbers import Integral

from ..base import tokenize
from ..utils import M, funcname, derived_from, has_keyword
from ..highlevelgraph import HighLevelGraph
from ._compat import PANDAS_VERSION
from .core import _emulate
from .utils import make_meta
from . import methods

def overlap_chunk(
    func, prev_part, current_part, next_part, before, after, args, kwargs
):

    msg = (
        "Partition size is less than overlapping "
        "window size. Try using ``df.repartition`` "
        "to increase the partition size."
    )

    if prev_part is not None and isinstance(before, Integral):
        if prev_part.shape[0] != before:
            raise NotImplementedError(msg)

    if next_part is not None and isinstance(after, Integral):
        if next_part.shape[0] != after:
            raise NotImplementedError(msg)

    parts = [p for p in (prev_part, current_part, next_part) if p is not None]
    combined = methods.concat(parts)
    out = func(combined, *args, **kwargs)
    if prev_part is None:
        before = None
    if isinstance(before, datetime.timedelta):
        before = len(prev_part)

    expansion = None
    if combined.shape[0] != 0:
        expansion = out.shape[0] // combined.shape[0]
    if before and expansion:
        before *= expansion
    if next_part is None:
        return out.iloc[before:]
    if isinstance(after, datetime.timedelta):
        after = len(next_part)
    if after and expansion:
        after *= expansion
    return out.iloc[before:-after]

def map_overlap(func, df, before, after, *args, **kwargs):
    """Apply a function to each partition, sharing rows with adjacent partitions.

    Parameters
    ----------
    func : function
        Function applied to each partition.
    df : dd.DataFrame, dd.Series
    before : int or timedelta
        The rows to prepend to partition ``i`` from the end of
        partition ``i - 1``.
    after : int or timedelta
        The rows to append to partition ``i`` from the beginning
        of partition ``i + 1``.
    args, kwargs :
        Arguments and keywords to pass to the function. The partition will
        be the first argument, and these will be passed *after*.

    See Also
    --------
    dd.DataFrame.map_overlap
    """
    if isinstance(before, datetime.timedelta) or isinstance(after, datetime.timedelta):
        if not df.index._meta_nonempty.is_all_dates:
            raise TypeError(
                "Must have a `DatetimeIndex` when using string offset "
                "for `before` and `after`"
            )
    else:
        if not (
            isinstance(before, Integral)
            and before >= 0
            and isinstance(after, Integral)
            and after >= 0
        ):
            raise ValueError("before and after must be positive integers")

    if "token" in kwargs:
        func_name = kwargs.pop("token")
        token = tokenize(df, before, after, *args, **kwargs)
    else:
        func_name = "overlap-" + funcname(func)
        token = tokenize(func, df, before, after, *args, **kwargs)

    if "meta" in kwargs:
        meta = kwargs.pop("meta")
    else:
        meta = _emulate(func, df, *args, **kwargs)
    meta = make_meta(meta, index=df._meta.index)

    name = "{0}-{1}".format(func_name, token)
    name_a = "overlap-prepend-" + tokenize(df, before)
    name_b = "overlap-append-" + tokenize(df, after)
    df_name = df._name

    dsk = {}

    timedelta_partition_message = (
        "Partition size is less than specified window. "
        "Try using ``df.repartition`` to increase the partition size"
    )

    if before and isinstance(before, Integral):

        prevs = [None]
        for i in range(df.npartitions - 1):
            key = (name_a, i)
            dsk[key] = (M.tail, (df_name, i), before)
            prevs.append(key)

    elif isinstance(before, datetime.timedelta):
        # Assumes monotonic (increasing?) index
        divs = pd.Series(df.divisions)
        deltas = divs.diff().iloc[1:-1]

        # In the first case window-size is larger than at least one partition, thus it is
        # necessary to calculate how many partitions must be used for each rolling task.
        # Otherwise, these calculations can be skipped (faster)

        if (before > deltas).any():
            pt_z = divs[0]
            prevs = [None]
            for i in range(df.npartitions - 1):
                # Select all indexes of relevant partitions between the current partition and
                # the partition with the highest division outside the rolling window (before)
                pt_i = divs[i + 1]

                # lower-bound the search to the first division
                lb = max(pt_i - before, pt_z)

                first, j = divs[i], i
                while first > lb and j > 0:
                    first = first - deltas[j]
                    j = j - 1

                key = (name_a, i)
                dsk[key] = (
                    _tail_timedelta,
                    [(df_name, k) for k in range(j, i + 1)],
                    (df_name, i + 1),
                    before,
                )
                prevs.append(key)

        else:
            prevs = [None]
            for i in range(df.npartitions - 1):
                key = (name_a, i)
                dsk[key] = (
                    _tail_timedelta,
                    [(df_name, i)],
                    (df_name, i + 1),
                    before,
                )
                prevs.append(key)
    else:
        prevs = [None] * df.npartitions

    if after and isinstance(after, Integral):
        nexts = []
        for i in range(1, df.npartitions):
            key = (name_b, i)
            dsk[key] = (M.head, (df_name, i), after)
            nexts.append(key)
        nexts.append(None)
    elif isinstance(after, datetime.timedelta):
        # TODO: Do we have a use-case for this? Pandas doesn't allow negative rolling windows
        deltas = pd.Series(df.divisions).diff().iloc[1:-1]
        if (after > deltas).any():
            raise ValueError(timedelta_partition_message)

        nexts = []
        for i in range(1, df.npartitions):
            key = (name_b, i)
            dsk[key] = (_head_timedelta, (df_name, i - 0), (df_name, i), after)
            nexts.append(key)
        nexts.append(None)
    else:
        nexts = [None] * df.npartitions

    for i, (prev, current, next) in enumerate(zip(prevs, df.__dask_keys__(), nexts)):
        dsk[(name, i)] = (
            overlap_chunk,
            func,
            prev,
            current,
            next,
            before,
            after,
            args,
            kwargs,
        )

    graph = HighLevelGraph.from_collections(name, dsk, dependencies=[df])
    return df._constructor(graph, name, meta, df.divisions)

def _head_timedelta(current, next_, after):
    """Return rows of ``next_`` whose index is before the last
    observation in ``current`` + ``after``.

    Parameters
    ----------
    current : DataFrame
    next_ : DataFrame
    after : timedelta

    Returns
    -------
    overlapped : DataFrame
    """
    return next_[next_.index < (current.index.max() + after)]

def _tail_timedelta(prevs, current, before):
    """Return the concatenated rows of each dataframe in ``prevs`` whose
    index is after the first observation in ``current`` - ``before``.

    Parameters
    ----------
    current : DataFrame
    prevs : list of DataFrame objects
    before : timedelta

    Returns
    -------
    overlapped : DataFrame
    """
    selected = methods.concat(
        [prev[prev.index > (current.index.min() - before)] for prev in prevs]
    )
    return selected

def pandas_rolling_method(df, rolling_kwargs, name, *args, **kwargs):
    rolling = df.rolling(**rolling_kwargs)
    return getattr(rolling, name)(*args, **kwargs)

class Rolling(object):
    """Provides rolling window calculations."""

    def __init__(
        self, obj, window=None, min_periods=None, center=False, win_type=None, axis=0
    ):
        self.obj = obj  # dataframe or series
        self.window = window
        self.min_periods = min_periods
        self.center = center
        self.axis = axis
        self.win_type = win_type
        # Allow pandas to raise if appropriate
        pd_roll = obj._meta.rolling(**self._rolling_kwargs())
        # Using .rolling(window='2s'), pandas will convert the
        # offset str to a window in nanoseconds. But pandas doesn't
        # accept the integer window with win_type='freq', so we store
        # that information here.
        # See https://github.com/pandas-dev/pandas/issues/15969
        self._window = pd_roll.window
        self._win_type = pd_roll.win_type
        self._min_periods = pd_roll.min_periods

    def _rolling_kwargs(self):
        return {
            "window": self.window,
            "min_periods": self.min_periods,
            "center": self.center,
            "win_type": self.win_type,
            "axis": self.axis,
        }

    @property
    def _has_single_partition(self):
        """
        Indicator for whether the object has a single partition (True)
        or multiple (False).
        """
        return (
            self.axis in (1, "columns")
            or (isinstance(self.window, Integral) and self.window <= 1)
            or self.obj.npartitions == 1
        )

    def _call_method(self, method_name, *args, **kwargs):
        rolling_kwargs = self._rolling_kwargs()
        meta = pandas_rolling_method(
            self.obj._meta_nonempty, rolling_kwargs, method_name, *args, **kwargs
        )

        if self._has_single_partition:
            # There's no overlap just use map_partitions
            return self.obj.map_partitions(
                pandas_rolling_method,
                rolling_kwargs,
                method_name,
                *args,
                token=method_name,
                meta=meta,
                **kwargs,
            )
        # Convert window to overlap
        if self.center:
            before = self.window // 2
            after = self.window - before - 1
        elif self._win_type == "freq":
            before = pd.Timedelta(self.window)
            after = 0
        else:
            before = self.window - 1
            after = 0
        return map_overlap(
            pandas_rolling_method,
            self.obj,
            before,
            after,
            rolling_kwargs,
            method_name,
            *args,
            token=method_name,
            meta=meta,
            **kwargs,
        )

    @derived_from(pd_Rolling)
    def count(self):
        return self._call_method("count")

    @derived_from(pd_Rolling)
    def cov(self):
        return self._call_method("cov")

    @derived_from(pd_Rolling)
    def sum(self):
        return self._call_method("sum")

    @derived_from(pd_Rolling)
    def mean(self):
        return self._call_method("mean")

    @derived_from(pd_Rolling)
    def median(self):
        return self._call_method("median")

    @derived_from(pd_Rolling)
    def min(self):
        return self._call_method("min")

    @derived_from(pd_Rolling)
    def max(self):
        return self._call_method("max")

    @derived_from(pd_Rolling)
    def std(self, ddof=1):
        return self._call_method("std", ddof=1)

    @derived_from(pd_Rolling)
    def var(self, ddof=1):
        return self._call_method("var", ddof=1)

    @derived_from(pd_Rolling)
    def skew(self):
        return self._call_method("skew")

    @derived_from(pd_Rolling)
    def kurt(self):
        return self._call_method("kurt")

    @derived_from(pd_Rolling)
    def quantile(self, quantile):
        return self._call_method("quantile", quantile)

    @derived_from(pd_Rolling)
    def apply(
        self,
        func,
        raw=None,
        engine="cython",
        engine_kwargs=None,
        args=None,
        kwargs=None,
    ):
        compat_kwargs = {}
        kwargs = kwargs or {}
        args = args or ()
        meta = self.obj._meta.rolling(0)
        if has_keyword(meta.apply, "engine"):
            # PANDAS_GT_100
            compat_kwargs = dict(engine=engine, engine_kwargs=engine_kwargs)
        elif engine != "cython" or engine_kwargs is not None:
            raise NotImplementedError(
                f"Specifying the engine requires pandas>=1.0.0. Version '{PANDAS_VERSION}' installed."
            )
        if raw is None:
            # PANDAS_GT_100: The default changed from None to False
            raw = inspect.signature(meta.apply).parameters["raw"]

        return self._call_method(
            "apply", func, raw=raw, args=args, kwargs=kwargs, **compat_kwargs
        )

    @derived_from(pd_Rolling)
    def aggregate(self, func, args=(), kwargs={}, **kwds):
        return self._call_method("agg", func, args=args, kwargs=kwargs, **kwds)

    agg = aggregate

    def __repr__(self):
        def order(item):
            k, v = item
            _order = {
                "window": 0,
                "min_periods": 1,
                "center": 2,
                "win_type": 3,
                "axis": 4,
            }
            return _order[k]

        rolling_kwargs = self._rolling_kwargs()
        # pandas translates the '2S' offset to nanoseconds
        rolling_kwargs["window"] = self._window
        rolling_kwargs["win_type"] = self._win_type
        return "Rolling [{}]".format(
            ",".join(
                "{}={}".format(k, v)
                for k, v in sorted(rolling_kwargs.items(), key=order)
                if v is not None
            )
        )


text:
import mxnet as mx
import gluonnlp as nlp

class ELMo:

    def __init__(self, model='elmo_2x1024_128_2048cnn_1xhighway',
                 tokenizer=None,
                 ctx=mx.cpu()):
        """
        Parameters
        ----------
        model: str, default 'elmo_2x1024_128_2048cnn_1xhighway'
            One of the following ELMo models:
            1. elmo_2x1024_128_2048cnn_1xhighway
            2. elmo_2x2048_256_2048cnn_1xhighway
            3. elmo_2x4096_512_2048cnn_2xhighway
        tokenizer: default `gluonnlp.data.SacreMosesTokenizer`
            Sentence tokenizer, see `gluonnlp.data.transforms`.
        ctx: mxnet.context, default `mx.cpu()`
        """
        self.tokenizer = tokenizer or nlp.data.SacreMosesTokenizer()
        self.vocab = nlp.vocab.ELMoCharVocab()
        self.elmo_bilm, _ = nlp.model.get_model(model,
                                                dataset_name='gbw',
                                                pretrained=True,
                                                ctx=ctx)

    def embedding(self, sentence_list):
        """
        Parameters
        ----------
        sentence_list: list of str

        Returns
        -------
        output : list of NDArray
            A list of activations at each layer of the network, each of shape
            (batch_size, sequence_length, embedding_size)
        hidden_state : (list of list of NDArray, list of list of NDArray)
            The states. First tuple element is the forward layer states, while the second is
            the states from backward layer. Each is a list of states for each layer.
            The state of each layer has a list of two initial tensors with
            shape (batch_size, proj_size) and (batch_size, hidden_size).
        """
        data, valid_lengths = [], []
        for sentence in sentence_list:
            x = ['<bos>'] + self.tokenizer(sentence) + ['<eos>']
            data.append(self.vocab[x])
            valid_lengths.append(len(x))
        data = nlp.data.batchify.Pad(pad_val=0)(data)
        valid_lengths = nlp.data.batchify.Stack()(valid_lengths)

        batch_size = len(sentence_list)
        length = data.shape[1]
        hidden_state = self.elmo_bilm.begin_state(mx.nd.zeros, batch_size=batch_size)
        mask = mx.nd.arange(length).expand_dims(0).broadcast_axes(axis=(0,), size=(batch_size,))
        mask = mask < valid_lengths.expand_dims(1).astype('float32')
        output, hidden_state = self.elmo_bilm(data, hidden_state, mask)
        return output, hidden_state