diff --git a/Pipfile b/Pipfile index 579d61263..98e9e2f75 100644 --- a/Pipfile +++ b/Pipfile @@ -26,7 +26,6 @@ wheel = "*" [packages] pycairo = "1.20.0" PyGObject = "3.38.0" -events = "0.4" argparse = "1.4.0" rx = "~=3.2" more-itertools = "~=7.2" diff --git a/Pipfile.lock b/Pipfile.lock index 444c87375..05f7cc528 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "bf6b40e37ac055327ede1ff942a50f66fb6f50ea2f875e56e5f6366c73b77a47" + "sha256": "9b36de1fcafb41ae1bc1fd84c2f55e12349f11e42a72267f7f310add0623ee9c" }, "pipfile-spec": 6, "requires": { @@ -40,13 +40,6 @@ "index": "pypi", "version": "==0.6" }, - "events": { - "hashes": [ - "sha256:a7286af378ba3e46640ac9825156c93bdba7502174dd696090fdfcd4d80a1abd" - ], - "index": "pypi", - "version": "==0.5" - }, "importlib-metadata": { "hashes": [ "sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26", diff --git a/fapolicy-analyzer.spec b/fapolicy-analyzer.spec index 0e15ba81c..01cbd4a61 100644 --- a/fapolicy-analyzer.spec +++ b/fapolicy-analyzer.spec @@ -61,7 +61,6 @@ Summary: File Access Policy Analyzer GUI Requires: python3 Requires: python3-gobject -Requires: python3-events Requires: python3-configargparse Requires: python3-more-itertools Requires: python3-rx diff --git a/fapolicy_analyzer/events/__init__.py b/fapolicy_analyzer/events/__init__.py new file mode 100644 index 000000000..07a62a48c --- /dev/null +++ b/fapolicy_analyzer/events/__init__.py @@ -0,0 +1,25 @@ +# Copyright (c) 2017 by Nicola Iarocci and contributors. +# Copyright Concurrent Technologies Corporation 2024 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- +from .events import Events, EventsException + +__version__ = '0.4' + +__all__ = [ + Events.__name__, + EventsException.__name__, +] diff --git a/fapolicy_analyzer/events/events.py b/fapolicy_analyzer/events/events.py new file mode 100644 index 000000000..49969987f --- /dev/null +++ b/fapolicy_analyzer/events/events.py @@ -0,0 +1,133 @@ +# Copyright (c) 2017 by Nicola Iarocci and contributors. +# Copyright Concurrent Technologies Corporation 2024 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -*- coding: utf-8 -*- + +""" + Events + ~~~~~~ + + Implements C#-Style Events. + + Derived from the original work by Zoran Isailovski: + http://code.activestate.com/recipes/410686/ - Copyright (c) 2005 + + :copyright: (c) 2014-2017 by Nicola Iarocci. + :license: BSD, see LICENSE for more details. +""" + + +class _EventSlot: + def __init__(self, name): + self.targets = [] + self.__name__ = name + + def __repr__(self): + return "event '%s'" % self.__name__ + + def __call__(self, *a, **kw): + for f in tuple(self.targets): + f(*a, **kw) + + def __iadd__(self, f): + self.targets.append(f) + return self + + def __isub__(self, f): + while f in self.targets: + self.targets.remove(f) + return self + + def __len__(self): + return len(self.targets) + + def __iter__(self): + def gen(): + for target in self.targets: + yield target + return gen() + + def __getitem__(self, key): + return self.targets[key] + + +class EventsException(Exception): + pass + + +class Events: + """ + Encapsulates the core to event subscription and event firing, and feels + like a "natural" part of the language. + + The class Events is there mainly for 3 reasons: + + - Events (Slots) are added automatically, so there is no need to + declare/create them separately. This is great for prototyping. (Note + that `__events__` is optional and should primarilly help detect + misspelled event names.) + - To provide (and encapsulate) some level of introspection. + - To "steel the name" and hereby remove unneeded redundancy in a call + like: + + xxx.OnChange = event('OnChange') + """ + def __init__(self, events=None, event_slot_cls=_EventSlot): + self.__event_slot_cls__ = event_slot_cls + + if events is not None: + + try: + for _ in events: + break + except: + raise AttributeError("type object %s is not iterable" % + (type(events))) + else: + self.__events__ = events + + def __getattr__(self, name): + if name.startswith('__'): + raise AttributeError("type object '%s' has no attribute '%s'" % + (self.__class__.__name__, name)) + + if hasattr(self, '__events__'): + if name not in self.__events__: + raise EventsException("Event '%s' is not declared" % name) + + elif hasattr(self.__class__, '__events__'): + if name not in self.__class__.__events__: + raise EventsException("Event '%s' is not declared" % name) + + self.__dict__[name] = ev = self.__event_slot_cls__(name) + return ev + + def __repr__(self): + return '<%s.%s object at %s>' % (self.__class__.__module__, + self.__class__.__name__, + hex(id(self))) + + __str__ = __repr__ + + def __len__(self): + return len(list(self.__iter__())) + + def __iter__(self): + def gen(dictitems=self.__dict__.items()): + for attr, val in dictitems: + if isinstance(val, self.__event_slot_cls__): + yield val + return gen() diff --git a/fapolicy_analyzer/ui/add_file_button.py b/fapolicy_analyzer/ui/add_file_button.py index 0d6a0f777..cb11e6283 100644 --- a/fapolicy_analyzer/ui/add_file_button.py +++ b/fapolicy_analyzer/ui/add_file_button.py @@ -18,7 +18,7 @@ from os import path import gi -from events import Events +from fapolicy_analyzer.events import Events from fapolicy_analyzer.ui import strings from fapolicy_analyzer.ui.file_chooser_dialog import FileChooserDialog diff --git a/fapolicy_analyzer/ui/editable_text_view.py b/fapolicy_analyzer/ui/editable_text_view.py index d8c3b2a65..42633e504 100644 --- a/fapolicy_analyzer/ui/editable_text_view.py +++ b/fapolicy_analyzer/ui/editable_text_view.py @@ -26,7 +26,7 @@ except ImportError: import importlib_resources as resources -from events import Events +from fapolicy_analyzer.events import Events from fapolicy_analyzer.ui.ui_widget import UIBuilderWidget gi.require_version("GtkSource", "3.0") diff --git a/fapolicy_analyzer/ui/object_list.py b/fapolicy_analyzer/ui/object_list.py index e9f05bafe..ba53af898 100644 --- a/fapolicy_analyzer/ui/object_list.py +++ b/fapolicy_analyzer/ui/object_list.py @@ -14,7 +14,7 @@ # along with this program. If not, see . import gi -from events import Events +from fapolicy_analyzer.events import Events from fapolicy_analyzer.ui.strings import ( FILE_LIST_RULE_ID_HEADER, diff --git a/fapolicy_analyzer/ui/policy_rules_admin_page.py b/fapolicy_analyzer/ui/policy_rules_admin_page.py index 6fc42ef64..22fbf55ae 100644 --- a/fapolicy_analyzer/ui/policy_rules_admin_page.py +++ b/fapolicy_analyzer/ui/policy_rules_admin_page.py @@ -18,7 +18,7 @@ from typing import Optional, Sequence import gi -from events import Events +from fapolicy_analyzer.events import Events from fapolicy_analyzer import EventLog, Group, Trust, User from fapolicy_analyzer.ui.acl_list import ACLList diff --git a/fapolicy_analyzer/ui/profiler_page.py b/fapolicy_analyzer/ui/profiler_page.py index 9c9c88d6e..8fad34094 100644 --- a/fapolicy_analyzer/ui/profiler_page.py +++ b/fapolicy_analyzer/ui/profiler_page.py @@ -27,7 +27,7 @@ import fapolicy_analyzer.ui.strings as s import gi -from events import Events +from fapolicy_analyzer.events import Events from fapolicy_analyzer.ui.actions import ( clear_profiler_state, start_profiling, diff --git a/fapolicy_analyzer/ui/rules/rules_admin_page.py b/fapolicy_analyzer/ui/rules/rules_admin_page.py index 47b81d8fb..3d48180e4 100644 --- a/fapolicy_analyzer/ui/rules/rules_admin_page.py +++ b/fapolicy_analyzer/ui/rules/rules_admin_page.py @@ -17,7 +17,7 @@ import logging from typing import Any, Optional, Sequence, Tuple -from events import Events +from fapolicy_analyzer.events import Events from fapolicy_analyzer import Rule, System, reload_profiler_rules from fapolicy_analyzer.ui.actions import ( diff --git a/fapolicy_analyzer/ui/searchable_list.py b/fapolicy_analyzer/ui/searchable_list.py index c0750712a..9f64cb2e4 100644 --- a/fapolicy_analyzer/ui/searchable_list.py +++ b/fapolicy_analyzer/ui/searchable_list.py @@ -20,7 +20,7 @@ from fapolicy_analyzer.ui.strings import FILTERING_DISABLED_DURING_LOADING_MESSAGE gi.require_version("Gtk", "3.0") -from events import Events +from fapolicy_analyzer.events import Events from gi.repository import Gtk from fapolicy_analyzer.ui.loader import Loader diff --git a/fapolicy_analyzer/ui/stats/stats_view_page.py b/fapolicy_analyzer/ui/stats/stats_view_page.py index 6fbeca905..87dcf7bc5 100644 --- a/fapolicy_analyzer/ui/stats/stats_view_page.py +++ b/fapolicy_analyzer/ui/stats/stats_view_page.py @@ -15,7 +15,7 @@ import gi -from events import Events +from fapolicy_analyzer.events import Events from fapolicy_analyzer.ui.reducers.stats_reducer import StatsStreamState from fapolicy_analyzer.ui.actions import ( diff --git a/fapolicy_analyzer/ui/system_trust_database_admin.py b/fapolicy_analyzer/ui/system_trust_database_admin.py index 548952ceb..7854bdabb 100644 --- a/fapolicy_analyzer/ui/system_trust_database_admin.py +++ b/fapolicy_analyzer/ui/system_trust_database_admin.py @@ -16,7 +16,7 @@ import logging from locale import gettext as _ -from events import Events +from fapolicy_analyzer.events import Events import fapolicy_analyzer.ui.strings as strings from fapolicy_analyzer.ui.actions import ( diff --git a/scripts/srpm/fapolicy-analyzer.el9.spec b/scripts/srpm/fapolicy-analyzer.el9.spec index 74baf6651..448aad0f1 100644 --- a/scripts/srpm/fapolicy-analyzer.el9.spec +++ b/scripts/srpm/fapolicy-analyzer.el9.spec @@ -134,7 +134,6 @@ Summary: File Access Policy Analyzer GUI Requires: python3 Requires: python3-gobject -Requires: python3-events Requires: python3-configargparse Requires: python3-more-itertools Requires: python3-rx diff --git a/setup.py b/setup.py index e44ad867c..388edb60e 100644 --- a/setup.py +++ b/setup.py @@ -60,6 +60,7 @@ def get_features(): include=[ "fapolicy_analyzer", "fapolicy_analyzer.css", + "fapolicy_analyzer.events*", "fapolicy_analyzer.glade", "fapolicy_analayzer.locale*", "fapolicy_analyzer.redux*",