<commit_before>from __future__ import absolute_import, print_function

import pytest

from mock import patch

import logging

from copy import copy

import bokeh.document.document as document

from bokeh.io.doc import curdoc
from bokeh.models import ColumnDataSource
from bokeh.document.events import (ColumnsPatchedEvent, ColumnsStreamedEvent, ModelChangedEvent, RootAddedEvent,
                                   RootRemovedEvent, SessionCallbackAdded, SessionCallbackRemoved, TitleChangedEvent)
from bokeh.protocol.messages.patch_doc import process_document_events
from bokeh.util.logconfig import basicConfig

from .setup import AnotherModelInTestDocument, SomeModelInTestDocument, ModelThatOverridesName, ModelWithSpecInTestDocument

# needed for caplog tests to function
basicConfig()

class TestDocumentHold(object):

    @pytest.mark.parametrize('policy', document.HoldPolicy)
    @pytest.mark.unit
    def test_hold(self, policy):
        d = document.Document()
        assert d._hold == None
        assert d._held_events == []

        d.hold(policy)
        assert d._hold == policy

    def test_hold_bad_policy(self):
        d = document.Document()
        with pytest.raises(ValueError):
            d.hold("junk")

    @pytest.mark.parametrize('first,second', [('combine', 'collect'), ('collect', 'combine')])
    @pytest.mark.unit
    def test_rehold(self, first, second, caplog):
        d = document.Document()
        with caplog.at_level(logging.WARN):
            d.hold(first)
            assert caplog.text == ""
            assert len(caplog.records) == 0

            d.hold(first)
            assert caplog.text == ""
            assert len(caplog.records) == 0

            d.hold(second)
            assert caplog.text.strip().endswith("hold already active with '%s', ignoring '%s'" % (first, second))
            assert len(caplog.records) == 1

            d.unhold()

            d.hold(second)
            assert len(caplog.records) == 1

    @pytest.mark.parametrize('policy', document.HoldPolicy)
    @pytest.mark.unit
    def test_unhold(self, policy):
        d = document.Document()
        assert d._hold == None
        assert d._held_events == []

        d.hold(policy)
        assert d._hold == policy
        d.unhold()
        assert d._hold == None

    @patch("bokeh.document.document.Document._trigger_on_change")
    def test_unhold_triggers_events(self, mock_trigger):
        d = document.Document()
        d.hold('collect')
        d._held_events = [1,2,3]
        d.unhold()
        assert mock_trigger.call_count == 3
        assert mock_trigger.call_args[0] == (3,)
        assert mock_trigger.call_args[1] == {}

extra = []

class Test_Document_delete_modules(object):

    def test_basic(self):
        d = document.Document()
        assert not d.roots
        class FakeMod(object):
            __name__ = 'junkjunkjunk'
        mod = FakeMod()
        import sys
        assert 'junkjunkjunk' not in sys.modules
        sys.modules['junkjunkjunk'] = mod
        d._modules.append(mod)
        assert 'junkjunkjunk' in sys.modules
        d.delete_modules()
        assert 'junkjunkjunk' not in sys.modules
        assert d._modules is None

    def test_extra_referrer_error(self, caplog):
        d = document.Document()
        assert not d.roots
        class FakeMod(object):
            __name__ = 'junkjunkjunk'
        mod = FakeMod()
        import sys
        assert 'junkjunkjunk' not in sys.modules
        sys.modules['junkjunkjunk'] = mod
        d._modules.append(mod)
        assert 'junkjunkjunk' in sys.modules

        # add an extra referrer for delete_modules to complain about
        extra.append(mod)
        import gc
        assert len(gc.get_referrers(mod)) == 4

        with caplog.at_level(logging.ERROR):
            d.delete_modules()
            assert "Module %r has extra unexpected referrers! This could indicate a serious memory leak. Extra referrers:" % mod in caplog.text
            assert len(caplog.records) == 1
<commit_msg>account for get_referrers change in python 3.7 (#8222)<commit_after>from __future__ import absolute_import, print_function

import pytest

from mock import patch

import logging

from copy import copy

import bokeh.document.document as document

from bokeh.io.doc import curdoc
from bokeh.models import ColumnDataSource
from bokeh.document.events import (ColumnsPatchedEvent, ColumnsStreamedEvent, ModelChangedEvent, RootAddedEvent,
                                   RootRemovedEvent, SessionCallbackAdded, SessionCallbackRemoved, TitleChangedEvent)
from bokeh.protocol.messages.patch_doc import process_document_events
from bokeh.util.logconfig import basicConfig

from .setup import AnotherModelInTestDocument, SomeModelInTestDocument, ModelThatOverridesName, ModelWithSpecInTestDocument

# needed for caplog tests to function
basicConfig()

class TestDocumentHold(object):

    @pytest.mark.parametrize('policy', document.HoldPolicy)
    @pytest.mark.unit
    def test_hold(self, policy):
        d = document.Document()
        assert d._hold == None
        assert d._held_events == []

        d.hold(policy)
        assert d._hold == policy

    def test_hold_bad_policy(self):
        d = document.Document()
        with pytest.raises(ValueError):
            d.hold("junk")

    @pytest.mark.parametrize('first,second', [('combine', 'collect'), ('collect', 'combine')])
    @pytest.mark.unit
    def test_rehold(self, first, second, caplog):
        d = document.Document()
        with caplog.at_level(logging.WARN):
            d.hold(first)
            assert caplog.text == ""
            assert len(caplog.records) == 0

            d.hold(first)
            assert caplog.text == ""
            assert len(caplog.records) == 0

            d.hold(second)
            assert caplog.text.strip().endswith("hold already active with '%s', ignoring '%s'" % (first, second))
            assert len(caplog.records) == 1

            d.unhold()

            d.hold(second)
            assert len(caplog.records) == 1

    @pytest.mark.parametrize('policy', document.HoldPolicy)
    @pytest.mark.unit
    def test_unhold(self, policy):
        d = document.Document()
        assert d._hold == None
        assert d._held_events == []

        d.hold(policy)
        assert d._hold == policy
        d.unhold()
        assert d._hold == None

    @patch("bokeh.document.document.Document._trigger_on_change")
    def test_unhold_triggers_events(self, mock_trigger):
        d = document.Document()
        d.hold('collect')
        d._held_events = [1,2,3]
        d.unhold()
        assert mock_trigger.call_count == 3
        assert mock_trigger.call_args[0] == (3,)
        assert mock_trigger.call_args[1] == {}

extra = []

class Test_Document_delete_modules(object):

    def test_basic(self):
        d = document.Document()
        assert not d.roots
        class FakeMod(object):
            __name__ = 'junkjunkjunk'
        mod = FakeMod()
        import sys
        assert 'junkjunkjunk' not in sys.modules
        sys.modules['junkjunkjunk'] = mod
        d._modules.append(mod)
        assert 'junkjunkjunk' in sys.modules
        d.delete_modules()
        assert 'junkjunkjunk' not in sys.modules
        assert d._modules is None

    def test_extra_referrer_error(self, caplog):
        d = document.Document()
        assert not d.roots
        class FakeMod(object):
            __name__ = 'junkjunkjunk'
        mod = FakeMod()
        import sys
        assert 'junkjunkjunk' not in sys.modules
        sys.modules['junkjunkjunk'] = mod
        d._modules.append(mod)
        assert 'junkjunkjunk' in sys.modules

        # add an extra referrer for delete_modules to complain about
        extra.append(mod)
        import gc

        # get_referrers behavior changed in Python 3.7, see https://github.com/bokeh/bokeh/issues/8221
        assert len(gc.get_referrers(mod)) in (3,4)

        with caplog.at_level(logging.ERROR):
            d.delete_modules()
            assert "Module %r has extra unexpected referrers! This could indicate a serious memory leak. Extra referrers:" % mod in caplog.text
            assert len(caplog.records) == 1

{'fraction_non_alphanumeric': 0.09820884610698184, 'fraction_numerical': 0.0047520409406604115, 'mean_word_length': 2.5333620318553596, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2748439', 'n_tokens_mistral': 2471, 'n_tokens_neox': 2446, 'n_words': 578}