Skip to content

Commit

Permalink
Merge pull request #374 from livMatS/2024-12-01-tests-withpygobject-3-50
Browse files Browse the repository at this point in the history
Tests with pygobject 3.50
  • Loading branch information
jotelha authored Dec 2, 2024
2 parents 8597426 + 0d731f4 commit edf2436
Show file tree
Hide file tree
Showing 14 changed files with 1,178 additions and 631 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
# run in virtual X server, see https://github.com/pygobject/pygobject-travis-ci-docker-examples
- name: Test with pytest
run: |
xvfb-run pytest --log-cli-level=DEBUG
xvfb-run pytest -n $(python maintenance/collect_number_of_tests.py) --log-cli-level=DEBUG
- name: setup pages
uses: actions/configure-pages@v5
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
# run in virtual X server, see https://github.com/pygobject/pygobject-travis-ci-docker-examples
- name: Test with pytest
run: |
xvfb-run pytest --log-cli-level=DEBUG
xvfb-run pytest -n $(python maintenance/collect_number_of_tests.py) --log-cli-level=DEBUG
- name: Lint with flake8
run: |
Expand Down
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ unpublished
-----------

- Login window
- Pagination
- Sorting
- Pagination for dserver lookup results
- Sorting for dserver lookup results
- Add/delete tags in GUI
- Add annotations in GUI (key - value pairs)

0.6.2 (02Nov22)
---------------
Expand Down
79 changes: 67 additions & 12 deletions dtool_lookup_gui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@
from gi.repository import GLib, GObject, Gio, Gtk, GtkSource, GdkPixbuf
from gi.events import GLibEventLoopPolicy

asyncio.set_event_loop_policy(GLibEventLoopPolicy())

from .models.settings import settings

from .views.main_window import MainWindow
Expand All @@ -65,32 +63,62 @@

from . import __version__

appid = f'de.uni-freiburg.dtool-lookup-gui.{__version__}'
# APP_ID = f'de.uni-freiburg.dtool-lookup-gui.{__version__}'
APP_ID = 'de.uni-freiburg.dtool-lookup-gui'

# Windows taskbar icons fix
try:
from ctypes import windll # Only exists on Windows.
windll.shell32.SetCurrentProcessExplicitAppUserModelID(appid)
windll.shell32.SetCurrentProcessExplicitAppUserModelID(APP_ID)
except ImportError:
pass


# adapted from https://python-gtk-3-tutorial.readthedocs.io/en/latest/popover.html#menu-popover
class Application(Gtk.Application):
__gsignals__ = {
'dtool-config-changed': (GObject.SIGNAL_RUN_FIRST, None, ())
'dtool-config-changed': (GObject.SignalFlags.RUN_FIRST, None, ()),
'token-renewed': (GObject.SignalFlags.RUN_FIRST, None, ()),
'startup-done': (GObject.SignalFlags.RUN_FIRST, None, ()),
'activation-done': (GObject.SignalFlags.RUN_FIRST, None, ())
}

def __init__(self, *args, loop=None, **kwargs):
def __init__(self, *args, loop=None,
application_id=APP_ID,
flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE, **kwargs):
print("Launch with application_id %s" % application_id)
super().__init__(*args,
application_id='de.uni-freiburg.dtool-lookup-gui',
flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE, **kwargs)
application_id=application_id,
flags=flags, **kwargs)
self.loop = loop
self.args = None

def on_window_delete(self, window, event):
self._startup_done = asyncio.Event()
self._activation_done = asyncio.Event()
self._shutdown_done = asyncio.Event()

async def shutdown(self):
# Perform any cleanup tasks here
for window in self.get_windows():
window.close()
self.quit()
self._shutdown_done.set()

def on_window_destroy(self, window):
self.quit()
return False
# return False

def on_startup_done(self, app):
logger.debug("Received startup-done signal in on_startup_done signal handler.")
self._startup_done.set()

def on_activation_done(self, app):
logger.debug("Received activation-done signal in on_activation_done signal handler.")
self._activation_done.set()

def on_shutdown(self, app):
logger.debug("Received shutdown signal in on_shutdown signal handler.")
self._shutdown_done.set()

def do_activate(self):
logger.debug("do_activate")
Expand Down Expand Up @@ -118,11 +146,12 @@ def do_activate(self):
logger.debug("%s", icon_file_list)
else:
logger.warning("Could not load app icons.")
win.connect("delete-event", self.on_window_delete)
win.connect("destroy", self.on_window_destroy)
self.loop.call_soon(win.refresh) # Populate widgets after event loop starts

logger.debug("Present main window.")
win.present()
self.emit('activation-done')

# adapted from http://fedorarules.blogspot.com/2013/09/how-to-handle-command-line-options-in.html
# and https://python-gtk-3-tutorial.readthedocs.io/en/latest/application.html#example
Expand Down Expand Up @@ -194,6 +223,11 @@ def do_startup(self):

string_variant = GLib.Variant.new_string("dummy")

# connect signals and signal handlers
self.connect('startup-done', self.on_startup_done)
self.connect('activation-done', self.on_activation_done)
self.connect('shutdown', self.on_shutdown)

# toggle-logging
toggle_logging_variant = GLib.Variant.new_boolean(True)
toggle_logging_action = Gio.SimpleAction.new_stateful(
Expand Down Expand Up @@ -240,6 +274,9 @@ def do_startup(self):

Gtk.Application.do_startup(self)

self.emit('startup-done')


# custom application-scoped actions
def do_toggle_logging(self, action, value):
action.set_state(value)
Expand Down Expand Up @@ -328,15 +365,18 @@ def do_renew_token(self, action, value):
username, password, auth_url = value.unpack()

logger.debug("look for certificates in %s", ssl.get_default_verify_paths())

async def retrieve_token(auth_url, username, password):
try:
async with ConfigurationBasedLookupClient(auth_url=auth_url, username=username, password=password) as lookup_client:
async with ConfigurationBasedLookupClient(
auth_url=auth_url, username=username, password=password) as lookup_client:
token = await lookup_client.authenticate()
except Exception as e:
logger.error(str(e))
return

dtool_lookup_api.core.config.Config.token = token
self.emit("token-renewed")
self.emit('dtool-config-changed')

asyncio.create_task(retrieve_token(
Expand All @@ -345,9 +385,24 @@ async def retrieve_token(auth_url, username, password):
password))


async def wait_for_activation(self):
logger.debug("Waiting for activation-done signal.")
await self._activation_done.wait()

async def wait_for_startup(self):
logger.debug("Waiting for startup-done signal.")
await self._startup_done.wait()

async def wait_for_shutdown(self):
logger.debug("Waiting for shutdown signal.")
await self._shutdown_done.wait()


def run_gui():
GObject.type_register(GtkSource.View)

asyncio.set_event_loop_policy(GLibEventLoopPolicy())

loop = asyncio.get_event_loop()
app = Application(loop=loop)

Expand Down
48 changes: 48 additions & 0 deletions dtool_lookup_gui/models/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ def _info(dataset):
info['scheme'] = p.scheme
info['base_uri'] = p.path if p.netloc is None else p.netloc

info['tags'] = dataset.list_tags()
annotation_names = dataset.list_annotation_names()
info['annotations'] = {annotation_name: dataset.get_annotation(annotation_name)
for annotation_name in annotation_names}
return info


Expand Down Expand Up @@ -347,8 +351,34 @@ def put_readme(self, text):
self.readme_content = text
return _load_dataset(str(self)).put_readme(text)

def put_tag(self, tag):
_load_dataset(str(self)).put_tag(tag)
if 'tags' not in self._dataset_info:
self._dataset_info['tags'] = []
self._dataset_info['tags'].append(tag)

def put_annotation(self, annotation_name, annotation):
_load_dataset(str(self)).put_annotation(annotation_name, annotation)
if 'annotations' not in self._dataset_info:
self._dataset_info['annotations'] = {}
self._dataset_info['annotations'].update({annotation_name : annotation})

def delete_tag(self,tag):
_load_dataset(str(self)).delete_tag(tag)
if 'tags' in self._dataset_info:
self._dataset_info['tags'].remove(tag)

# delete annotation is not implemented in dtoolcore
# def delete_annotation(self,annotation_name , annotation):
# print("delete_annotation",annotation_name,annotation)
# _load_dataset(str(self)).delete_annotation(annotation_name, annotation)
# if 'annotations' in self._dataset_info:
# self._dataset_info['annotations'].remove(annotation_name)

async def get_readme(self):
if 'readme_content' in self._dataset_info:
logger.debug("%s", dir(self._dataset_info))
logger.debug("%s", dict(self._dataset_info))
logger.debug("README.yml cached.")
return self._dataset_info['readme_content']

Expand All @@ -368,6 +398,24 @@ async def get_manifest(self):
self._dataset_info['manifest'] = _mangle_lookup_manifest(manifest_dict)
return self._dataset_info['manifest']

async def get_tags(self):
if 'tags' in self._dataset_info:
return self._dataset_info['tags']

async with ConfigurationBasedLookupClient() as lookup:
tags_list = await lookup.get_tags(self.uri)
self._dataset_info['tags'] = tags_list
return tags_list

async def get_annotations(self):
if 'annotations' in self._dataset_info:
return self._dataset_info['annotations']

async with ConfigurationBasedLookupClient() as lookup:
annotations_dict = await lookup.get_annotations(self.uri)
self._dataset_info['annotations'] = annotations_dict
return annotations_dict

async def get_item(self, item_uuid):
"""Get item from dataset by item UUID"""
if not self.is_frozen:
Expand Down
Loading

0 comments on commit edf2436

Please sign in to comment.