Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pristan/components/plugins_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def _pop_group(self, requested_name: str) -> List[Plugin[PluginResult]]:
raise KeyError(requested_name)

removed_plugins = self.plugins_by_requested_names.pop(requested_name)
self.plugins = [plugin for plugin in self.plugins if plugin.requested_name != requested_name]
self.plugins[:] = [plugin for plugin in self.plugins if plugin.requested_name != requested_name]
return removed_plugins

def _pop_exact_plugin(self, key: str) -> List[Plugin[PluginResult]]:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "pristan"
version = "0.0.14"
version = "0.0.15"
authors = [{ name = "Evgeniy Blinov", email = "zheni-b@yandex.ru" }]
description = "Function-based plugin system with respect to typing"
readme = "README.md"
Expand Down
19 changes: 19 additions & 0 deletions tests/units/components/test_plugins_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,21 +248,29 @@ def test_getitem_good_key():

def test_pop_by_base_name(group_with_named_duplicates):
group, plugins = group_with_named_duplicates
plugins_reference = group.plugins

removed_plugins = group.pop('name')

assert removed_plugins == plugins[:3]
assert group.plugins is plugins_reference
assert group.plugins == [plugins[3]]
assert plugins_reference == [plugins[3]]
assert group.plugins_by_requested_names == {
'name2': [plugins[3]],
}


def test_pop_first_plugin_by_name_1(group_with_named_duplicates):
group, plugins = group_with_named_duplicates
plugins_reference = group.plugins

removed_plugins = group.pop('name-1')

assert removed_plugins == [plugins[0]]
assert group.plugins is plugins_reference
assert [x.name for x in group.plugins] == ['name', 'name-2', 'name2']
assert [x.name for x in plugins_reference] == ['name', 'name-2', 'name2']
assert group.plugins_by_requested_names == {
'name': [plugins[1], plugins[2]],
'name2': [plugins[3]],
Expand All @@ -271,10 +279,14 @@ def test_pop_first_plugin_by_name_1(group_with_named_duplicates):

def test_pop_middle_plugin_renumbers_remaining_duplicates(group_with_named_duplicates):
group, plugins = group_with_named_duplicates
plugins_reference = group.plugins

removed_plugins = group.pop('name-2')

assert removed_plugins == [plugins[1]]
assert group.plugins is plugins_reference
assert [x.name for x in group.plugins] == ['name', 'name-2', 'name2']
assert [x.name for x in plugins_reference] == ['name', 'name-2', 'name2']
assert group.plugins_by_requested_names == {
'name': [plugins[0], plugins[2]],
'name2': [plugins[3]],
Expand All @@ -283,10 +295,14 @@ def test_pop_middle_plugin_renumbers_remaining_duplicates(group_with_named_dupli

def test_pop_last_plugin_keeps_compact_numbering(group_with_named_duplicates):
group, plugins = group_with_named_duplicates
plugins_reference = group.plugins

removed_plugins = group.pop('name-3')

assert removed_plugins == [plugins[2]]
assert group.plugins is plugins_reference
assert [x.name for x in group.plugins] == ['name', 'name-2', 'name2']
assert [x.name for x in plugins_reference] == ['name', 'name-2', 'name2']
assert group.plugins_by_requested_names == {
'name': [plugins[0], plugins[1]],
'name2': [plugins[3]],
Expand All @@ -295,11 +311,14 @@ def test_pop_last_plugin_keeps_compact_numbering(group_with_named_duplicates):

def test_pop_only_plugin_by_name_1_removes_requested_name_bucket(group_with_named_duplicates):
group, plugins = group_with_named_duplicates
plugins_reference = group.plugins

removed_plugins = group.pop('name2-1')

assert removed_plugins == [plugins[3]]
assert group.plugins is plugins_reference
assert group.plugins == plugins[:3]
assert plugins_reference == plugins[:3]
assert group.plugins_by_requested_names == {
'name': plugins[:3],
}
Expand Down
226 changes: 219 additions & 7 deletions tests/units/decorators/test_slot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1081,21 +1081,23 @@ def plugin(): # noqa: F811


def test_delitem_removes_plugins_from_slot(folder_slot, folder_plugin):
bread_crumbs = []

@folder_slot(slot)
def some_slot():
...
bread_crumbs.append('slot')

@folder_plugin(some_slot)
def plugin():
...
bread_crumbs.append('plugin_1')

@folder_plugin(some_slot)
def plugin(): # noqa: F811
...
bread_crumbs.append('plugin_2')

@folder_plugin(some_slot)
def plugin2():
...
bread_crumbs.append('plugin2')

del some_slot['plugin']

Expand All @@ -1107,6 +1109,10 @@ def plugin2():
assert len(some_slot) == 1
assert 'plugin' not in some_slot

some_slot()

assert bread_crumbs == ['plugin2']


def test_pop_removes_plugin_and_returns_detached_selection(folder_slot):
bread_crumbs = []
Expand Down Expand Up @@ -1137,6 +1143,194 @@ def plugin_3(a):

assert bread_crumbs == ['plugin_2_1']

bread_crumbs.clear()

some_slot(1)

assert bread_crumbs == ['plugin_1_1', 'plugin_3_1']


def test_delitem_by_base_name_last_list_plugin_falls_back_to_slot_body(folder_slot, subscribable_list_type):
body_calls = []

@folder_slot(slot)
def some_slot(a) -> subscribable_list_type[int]:
body_calls.append(a)
return []

@some_slot.plugin('plugin')
def plugin_1(a):
return a

assert some_slot(1) == [1]
assert body_calls == []

del some_slot['plugin']

assert some_slot.keys() == ()
assert len(some_slot) == 0
assert 'plugin' not in some_slot
assert 'plugin-1' not in some_slot
assert [x.name for x in some_slot] == []
assert some_slot(1) == []
assert body_calls == [1]


def test_pop_by_base_name_last_list_plugin_falls_back_to_slot_body(folder_slot, subscribable_list_type):
body_calls = []

@folder_slot(slot)
def some_slot(a) -> subscribable_list_type[int]:
body_calls.append(a)
return []

@some_slot.plugin('plugin')
def plugin_1(a):
return a

assert some_slot(1) == [1]
assert body_calls == []

removed_plugins = some_slot.pop('plugin')

assert [x.name for x in removed_plugins] == ['plugin']
assert removed_plugins(2) == [2]
assert some_slot.keys() == ()
assert len(some_slot) == 0
assert 'plugin' not in some_slot
assert 'plugin-1' not in some_slot
assert [x.name for x in some_slot] == []
assert some_slot(2) == []
assert body_calls == [2]


def test_delitem_by_base_name_removes_group_from_list_slot_call(folder_slot, subscribable_list_type):
@folder_slot(slot)
def some_slot(a) -> subscribable_list_type[int]: # noqa: ARG001
return []

@some_slot.plugin('plugin')
def plugin_1(a):
return a

@some_slot.plugin('plugin')
def plugin_2(a):
return a + 1

@some_slot.plugin('other')
def other(a):
return a + 2

assert some_slot(1) == [1, 2, 3]

del some_slot['plugin']

assert some_slot.keys() == ('other',)
assert len(some_slot) == 1
assert 'plugin' not in some_slot
assert 'plugin-1' not in some_slot
assert 'plugin-2' not in some_slot
assert 'other' in some_slot
assert [x.name for x in some_slot] == ['other']
assert some_slot(1) == [3]


def test_pop_by_base_name_returns_detached_group_and_keeps_survivors_in_list_slot_call(folder_slot, subscribable_list_type):
@folder_slot(slot)
def some_slot(a) -> subscribable_list_type[int]: # noqa: ARG001
return []

@some_slot.plugin('plugin')
def plugin_1(a):
return a

@some_slot.plugin('plugin')
def plugin_2(a):
return a + 1

@some_slot.plugin('other')
def other(a):
return a + 2

assert some_slot(1) == [1, 2, 3]

removed_plugins = some_slot.pop('plugin')

assert [x.name for x in removed_plugins] == ['plugin', 'plugin-2']
assert removed_plugins(1) == [1, 2]
assert some_slot.keys() == ('other',)
assert len(some_slot) == 1
assert 'plugin' not in some_slot
assert 'plugin-1' not in some_slot
assert 'plugin-2' not in some_slot
assert 'other' in some_slot
assert [x.name for x in some_slot] == ['other']
assert some_slot(1) == [3]


def test_delitem_by_base_name_removes_group_from_dict_slot_call(folder_slot, subscribable_dict_type):
@folder_slot(slot)
def some_slot(a) -> subscribable_dict_type[str, int]: # noqa: ARG001
return {}

@some_slot.plugin('plugin')
def plugin_1(a):
return a

@some_slot.plugin('plugin')
def plugin_2(a):
return a + 1

@some_slot.plugin('other')
def other(a):
return a + 2

assert some_slot(1) == {'plugin': 1, 'plugin-2': 2, 'other': 3}

del some_slot['plugin']

assert some_slot.keys() == ('other',)
assert len(some_slot) == 1
assert 'plugin' not in some_slot
assert 'plugin-1' not in some_slot
assert 'plugin-2' not in some_slot
assert 'other' in some_slot
assert [x.name for x in some_slot] == ['other']
assert some_slot(1) == {'other': 3}


def test_pop_by_base_name_returns_detached_group_and_keeps_survivors_in_dict_slot_call(folder_slot, subscribable_dict_type):
@folder_slot(slot)
def some_slot(a) -> subscribable_dict_type[str, int]: # noqa: ARG001
return {}

@some_slot.plugin('plugin')
def plugin_1(a):
return a

@some_slot.plugin('plugin')
def plugin_2(a):
return a + 1

@some_slot.plugin('other')
def other(a):
return a + 2

assert some_slot(1) == {'plugin': 1, 'plugin-2': 2, 'other': 3}

removed_plugins = some_slot.pop('plugin')

assert [x.name for x in removed_plugins] == ['plugin', 'plugin-2']
assert removed_plugins(1) == {'plugin': 1, 'plugin-2': 2}
assert some_slot.keys() == ('other',)
assert len(some_slot) == 1
assert 'plugin' not in some_slot
assert 'plugin-1' not in some_slot
assert 'plugin-2' not in some_slot
assert 'other' in some_slot
assert [x.name for x in some_slot] == ['other']
assert some_slot(1) == {'other': 3}


def test_pop_returns_default_for_missing_key(folder_slot):
@folder_slot(slot)
Expand Down Expand Up @@ -1199,31 +1393,49 @@ def plugin_3(a, b=6):


def test_delitem_and_pop_support_exact_duplicate_keys(folder_slot):
bread_crumbs = []

@folder_slot(slot)
def some_slot():
...

@some_slot.plugin('plugin')
def plugin_1():
...
bread_crumbs.append('plugin_1')

@some_slot.plugin('plugin')
def plugin_2():
...
bread_crumbs.append('plugin_2')

@some_slot.plugin('plugin')
def plugin_3():
...
bread_crumbs.append('plugin_3')

del some_slot['plugin-1']

assert [x.name for x in some_slot.plugins.plugins] == ['plugin', 'plugin-2']

some_slot()

assert bread_crumbs == ['plugin_2', 'plugin_3']

bread_crumbs.clear()

removed_plugins = some_slot.pop('plugin-2')

assert [x.name for x in removed_plugins] == ['plugin-2']
assert [x.name for x in some_slot.plugins.plugins] == ['plugin']

removed_plugins()

assert bread_crumbs == ['plugin_3']

bread_crumbs.clear()

some_slot()

assert bread_crumbs == ['plugin_2']


def test_delitem_with_name_1_removes_first_plugin(folder_slot):
bread_crumbs = []
Expand Down
Loading