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
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ jobs:
contents: read
security-events: write # Required to upload results to the Security tab.
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- uses: github/codeql-action/init@6f5948dfacef28e207b48d0905cf90c03365536d # v3
- uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
languages: python
# Scoped to real package source -- excludes vendored/generated
Expand All @@ -35,6 +35,6 @@ jobs:
**/data/**
**/*.json

- uses: github/codeql-action/analyze@6f5948dfacef28e207b48d0905cf90c03365536d # v3
- uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
category: "/language:python"
10 changes: 5 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
permissions:
contents: read # Only checks out and reads the repo -- no write access needed.
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install uv
uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
- name: Set up Python
# Pinned explicitly: a bare `uv python install` grabs whatever's
# newest at run time. Confirmed 2026-08-19: it silently picked up
Expand Down Expand Up @@ -56,12 +56,12 @@ jobs:
id-token: write # Required for OIDC trusted publishing
contents: write # Required to create GitHub Release
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

- name: Install uv
uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1

- name: Build package
run: uv build
Expand All @@ -77,7 +77,7 @@ jobs:
# write above) -- no extra input needed for Signed-Releases.

- name: Create GitHub Release
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
files: dist/*
generate_release_notes: true
Expand Down
308 changes: 308 additions & 0 deletions PYEGERIA_ISSUES.md

Large diffs are not rendered by default.

22 changes: 2 additions & 20 deletions my_egeria/my_egeria/DemoCode/My_Profile/AddToElementsScreens.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,6 @@ def compose(self) -> ComposeResult:
Input("Description of Todo", id="todo_description"),
Input("Priority of Todo", id="todo_priority"),
Static("Status will be automatically set to 'REQUESTED'"),
Horizontal(
Static("Link Todo to your profile? True or False, Default = True"),
Switch(value=True, id="link_todo_to_profile")
),
Horizontal(
Button("Add Todo", id="add_todo_button", variant="primary"),
Button("Quit", id="quit_button", variant="warning")
Expand All @@ -95,17 +91,8 @@ def action_add_new_todo(self):
priority=self.todo_priority,
activity_status="REQUESTED"
)
self.log(f"Created ToDo assigned to the current user: {todo_guid}")
if self.link_todo_to_profile is True:
try:
self.todo_link_guid = tclient.link_todo_to_profile(
todo_guid=todo_guid,
profile_guid=self.user_guid
)
self.notify(f"Linked ToDo to profile: {self.todo_link_guid}", timeout=10, severity="information")
except PyegeriaException as e:
self.log(f"Link todo to profile failed with return: {e}")
self.notify(f"Link todo to profile failed with return: {e}", timeout=10, severity="error")
self.log(f"Created ToDo: {todo_guid}")

except PyegeriaException as e:
self.notify(f"Add todo failed with return: {e}", timeout=10, severity="error")
finally:
Expand Down Expand Up @@ -516,7 +503,6 @@ def action_add_new_blog(self):
self.query_one("#blog_entry_name", Input).clear()
self.query_one("#blog_entry_text", Input).clear()
self.query_one("#blog_entry_situation", Input).clear()
self.query_one("#blog_entry_guid", Input).clear()
self.query_one("#blog_entry_container", ScrollableContainer).refresh()
return

Expand All @@ -529,10 +515,6 @@ def handle_input_changed(self, event: Input.Changed):
if event.input.id == "blog_entry_situation":
self.blog_entry_situation = event.input.value

# @on(Switch.Changed, "#link_blog_entry_to_profile")
# def handle_link_blog_entry_to_profile_changed(self, event: Switch.Changed):
# self.link_blog_entry_to_profile = event.switch.value

def action_quit(self):
self.dismiss(200)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ class CreateSubscriptionRequestScreen(ModalScreen):

CSS_PATH = "my_profile.tcss"

def __init__(self, *args, **kwargs):
def __init__(self, selected_item: str = "", *args, **kwargs):
super().__init__(*args, **kwargs)
self.selected_item = selected_item
self.display_name = ""
self.description = ""
self.status = "DRAFT"
self.identifier = ""
self.response = {}
self.valid_status = ["DRAFT",
"PROPOSED",
"ACTIVE",
Expand All @@ -42,6 +48,10 @@ def compose(self) -> ComposeResult:
Static(f"Please provide the following input as appropriate:"),
Static("Display Name should be short but descriptive, it will also be used to create the Qualified Name as well"),
Input("Display Name for the subscription", id = "sub_display_name"),
Static(f"Description of this Subscription"),
Input(placeholder="Please enter a description", id="sub_description"),
Static(f"A short identifier for the subscription, e..g. MySub1"),
Input(placeholder="Please enter an identifier", id="sub_ID"),
Static("By default the user defined status for this subscription will be set to DRAFT, you can override"),
Input("User defined Status - optional", id = "sub_status"),
Static("When all input is completed please click the 'Create Subscription' (c) key"),
Expand All @@ -66,12 +76,27 @@ def handle_subscription_status_change(self, event):
if self.status not in self.valid_status:
self.status = "DRAFT"

@on(Input.Changed, "#sub_description")
def handle_description_change(self, event):
self.description = event.value or ""

@on(Input.Changed, "#sub_ID")
def handle_subscription_id_change(self, event):
self.identifier = event.value

def action_create_subscription(self):
self.log("Creating subscription request")
self.response = []
if self.display_name and self.display_name != None and self.display_name != "":
self.response.append(self.display_name)
if self.status and self.status != None and self.status != "":
self.response.append(f"Status: {self.status}")
self.response: dict = {}
if self.selected_item:
self.response["externalSourceGUID"] = self.selected_item
self.response["guid"] = self.selected_item
if self.display_name:
self.response["displayName"] = self.display_name
if self.status:
self.response["Status"] = self.status
if self.description:
self.response["description"] = self.description
if self.identifier:
self.response["identifier"] = self.identifier
self.dismiss(self.response)
return self.response
112 changes: 89 additions & 23 deletions my_egeria/my_egeria/DemoCode/My_Profile/MainScreen.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
This file provides a set of report specification related functions for my_egeria.

"""
import pwd
from typing import Any
from textual import events, on
from textual.app import ComposeResult
from textual.containers import ScrollableContainer
from textual.screen import Screen
Expand All @@ -18,8 +19,9 @@ class MainScreen(Screen):

BINDINGS = [
("q", "app.quit", "Quit"),
("ctrl+e", "edit_table", "Edit Selected Table"),
("ctrl+b", "bookmarks", "Manage Bookmarks"),
("ctrl+s", "show_comments", "Show Comments for Selected Row"),
("ctrl+t", "edit_table", "Edit Selected Table"),
]

CSS_PATH = "my_profile.tcss"
Expand Down Expand Up @@ -55,7 +57,7 @@ def compose(self) -> ComposeResult:
Option("Edit Profile"),
Option("Subscriptions"),
Option("Technology Types"),
Option("User Bookmarks", disabled=True),
Option("User Bookmarks"),
id="other_function_list"
),
id="other_function_container"
Expand Down Expand Up @@ -88,31 +90,94 @@ def compose(self) -> ComposeResult:

yield Footer(id="main_footer")

def on_descendant_focus(self, event: events.DescendantFocus) -> None:
"""Track which DataTable is currently focused when clicking or navigating into it."""
if isinstance(event.widget, DataTable):
self.selected_table = event.widget.id
if event.widget.row_count > 0 and 0 <= event.widget.cursor_row < event.widget.row_count:
try:
self.selected_row = event.widget.coordinate_to_cell_key(event.widget.cursor_coordinate).row_key
except Exception:
self.selected_row = None
else:
self.selected_row = None
self.log(f"Focused Table: {self.selected_table}, Row: {self.selected_row}")

@on(DataTable.RowHighlighted)
def on_data_table_row_highlighted(self, event: DataTable.RowHighlighted):
""" Collect row and table when the user highlights a row in a table """
self.selected_row = event.row_key
self.selected_table = event.data_table.id
self.log(f"Highlighted Table: {self.selected_table}, Row: {self.selected_row}")

@on(DataTable.RowSelected)
def on_data_table_row_selected(self, event: DataTable.RowSelected):
""" Collect row and table when the user selects a row in a table """
self.selected_row = event.row_key
self.selected_table = event.data_table.id
self.log(f"Selected Table: {self.selected_table}, Row: {self.selected_row}")

@on(DataTable.CellHighlighted)
def on_data_table_cell_highlighted(self, event: DataTable.CellHighlighted):
""" Collect row and table when a cell is highlighted in a table """
self.selected_row = event.cell_key.row_key
self.selected_table = event.data_table.id
self.log(f"Cell Highlighted Table: {self.selected_table}, Row: {self.selected_row}")

@on(DataTable.CellSelected)
def on_data_table_cell_selected(self, event: DataTable.CellSelected):
""" Collect row and table when a cell is selected in a table """
self.selected_row = event.cell_key.row_key
self.selected_table = event.data_table.id
self.log(f"Cell Selected Table: {self.selected_table}, Row: {self.selected_row}")

@on(DataTable.HeaderSelected)
def on_data_table_header_selected(self, event: DataTable.HeaderSelected):
""" Collect table when header is selected in a table """
self.selected_table = event.data_table.id
self.log(f"Header Selected Table: {self.selected_table}")

def get_focused_table(self) -> DataTable | None:
focused_widget = self.screen.focused

# Check if the focused widget is a DataTable
if isinstance(focused_widget, DataTable):
return focused_widget

return None

async def action_edit_table(self):
def get_current_table_and_row(self) -> tuple[str | None, Any]:
"""Return the currently focused or selected table id and row key."""
focused_table = self.get_focused_table()
if focused_table is not None:
table_id = focused_table.id
row_key = None
if focused_table.row_count > 0 and 0 <= focused_table.cursor_row < focused_table.row_count:
try:
row_key = focused_table.coordinate_to_cell_key(focused_table.cursor_coordinate).row_key
except Exception:
row_key = None
return table_id, row_key
return self.selected_table, self.selected_row

def action_edit_table(self):
""" Edit the selected table """
if self.selected_table and self.selected_row:
await self.app.edit_tables(self.selected_table, self.selected_row)
table_name, row_k = self.get_current_table_and_row()
if table_name:
self.selected_table = table_name
self.selected_row = row_k
self.log(f"Editing Table: {table_name}, Row: {row_k}")
self.app.edit_tables(table_name, row_k)
else:
active_table = self.get_focused_table()
if active_table:
await self.app.add_to_tables(active_table, "0")
else:
self.notify("Please select at least a table, or a table and row to edit.", timeout=5, severity="warning")
self.notify("Please select at least a table, or a table and row to edit.", timeout=5, severity="warning")

async def action_show_comments(self):
""" Show comments for the selected table """
if self.selected_table and self.selected_row:
self.app.show_comments(self.selected_table, self.selected_row)
table_name, row_k = self.get_current_table_and_row()
if table_name and row_k:
self.selected_table = table_name
self.selected_row = row_k
self.app.show_comments(table_name, row_k)
else:
self.notify("Please select a row and table to show comments.", timeout=5, severity="warning")

Expand All @@ -122,17 +187,18 @@ async def action_add_to_table(self):
Kept as a generic entry point; adding a row is normally reached from
within the per-table edit screen (Edit Selected Table -> Add Row).
"""
if self.selected_table:
await self.app.add_to_tables(self.selected_table, self.selected_row)
table_name, row_k = self.get_current_table_and_row()
if table_name:
self.selected_table = table_name
self.selected_row = row_k
await self.app.add_to_tables(table_name, row_k)
else:
self.notify("Please select a table to add to.", timeout=5, severity="warning")

def get_focused_table(self) -> DataTable | None:
focused_widget = self.screen.focused

# Check if the focused widget is a DataTable
if isinstance(focused_widget, DataTable):
return focused_widget

return None
def action_bookmarks(self):
""" Manages BookMarks for the currently logged in user
Note - to add a new bookmark you must first have found and copied
the GUID of the item you want to bookmark to the clipboard
as you will need to know it during the add processing"""
self.app.show_my_bookmarks()

Loading
Loading