From 2af05732a2fe0eb36286a7e9cd9c3692f8f95990 Mon Sep 17 00:00:00 2001
From: Daniel Harding <dharding@living180.net>
Date: Fri, 26 Sep 2025 13:03:57 +0300
Subject: [PATCH] Replace deprecated urwid.connect_signal() user_arg

Use the new user_args keyword argument instead.
---
 requirements.txt  |  2 +-
 upass/__main__.py | 50 ++++++++++++++++++++++++++---------------------
 2 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/requirements.txt b/requirements.txt
index a1b919b..e72ebcd 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,2 @@
-urwid
+urwid >= 2.1.2
 pyclip
diff --git a/upass/__main__.py b/upass/__main__.py
index 34fdfe5..a68d790 100755
--- a/upass/__main__.py
+++ b/upass/__main__.py
@@ -43,6 +43,15 @@ else:
     casefold = str.casefold
 
 
+def connect_button_click(button, callback, *args):
+    urwid.connect_signal(
+        button,
+        'click',
+        lambda args, originator: callback(originator, *args),
+        user_args=(args,),
+    )
+
+
 class PasswordButton(urwid.Button):
 
     """A password button."""
@@ -51,7 +60,7 @@ class PasswordButton(urwid.Button):
         """Initialize a button."""
         super(PasswordButton, self).__init__("")
         self.caption = caption[:-len('.gpg')]
-        urwid.connect_signal(self, 'click', callback, self.caption)
+        connect_button_click(self, callback, self.caption)
         self._w = urwid.AttrMap(urwid.SelectableIcon(
             [u'├ ', self.caption], 0), 'button', 'button_reversed')
 
@@ -64,7 +73,7 @@ class DirectoryButton(urwid.Button):
         """Initialize a button."""
         super(DirectoryButton, self).__init__("")
         self.caption = caption
-        urwid.connect_signal(self, 'click', callback, self.caption)
+        connect_button_click(self, callback, self.caption)
         self._w = urwid.AttrMap(urwid.SelectableIcon(
             [u'├ ', self.caption, '/'], 0), 'button', 'button_reversed')
 
@@ -73,11 +82,11 @@ class ActionButton(urwid.Button):
 
     """An action button."""
 
-    def __init__(self, caption, callback, user_arg=None):
+    def __init__(self, caption, callback, *user_args):
         """Initialize a button."""
         super(ActionButton, self).__init__("")
         self.caption = caption
-        urwid.connect_signal(self, 'click', callback, user_arg)
+        connect_button_click(self, callback, *user_args)
         self._w = urwid.AttrMap(urwid.SelectableIcon(
             [u'> ', self.caption], 0), 'button', 'button_reversed')
 
@@ -90,7 +99,7 @@ class BackButton(urwid.Button):
         """Initialize a button."""
         super(BackButton, self).__init__("")
         self.caption = caption
-        urwid.connect_signal(self, 'click', callback, user_arg)
+        connect_button_click(self, callback, user_arg)
         self._w = urwid.AttrMap(urwid.SelectableIcon(
             [u'< ', self.caption], 0), 'button', 'button_reversed')
         app.back_callback = callback
@@ -283,20 +292,17 @@ class App(object):
         """Display the currently selected password."""
         path, pathg = self.get_selected_password(originator)
         if pathg in self.passwords:
-            self.call_pass(originator, (path, False, None))
+            self.call_pass(originator, path, False, None)
 
     def copy_selected(self, originator):
         """Copy the currently selected password."""
         path, pathg = self.get_selected_password(originator)
         if pathg in self.passwords:
-            self.call_pass(originator, (path, True, False))
+            self.call_pass(originator, path, True, False)
 
-    def generate_password(self, originator, args=None):
+    def generate_password(self, originator, path='', length=16, symbols=True,
+                          force=False):
         self.mode = 'generate'
-        if args:
-            path, length, symbols, force = args
-        else:
-            path, length, symbols, force = '', 16, True, False
         if not path and self.current != '.':
             path = self.current + '/'
         self.set_header('GENERATE PASSWORD')
@@ -365,7 +371,7 @@ class App(object):
         if self._store_key_exists(path):
             self.box.body.append(ActionButton('LOAD PASSWORD', self.pass_load, path))
         self.box.body.append(ActionButton('GENERATE NEW PASSWORD', self.generate_password,
-                                          (path, length, symbols, force)))
+                                          path, length, symbols, force))
         self.box.body.append(BackButton('BACK TO DIRECTORY', self.dir_load,
                                         os.path.dirname(path) or '.', self))
         self.box.set_focus(focus_position)
@@ -476,17 +482,17 @@ class App(object):
         prevdir = os.path.dirname(path) or '.'
         self.box.body.append(BackButton('BACK', self.dir_load, prevdir, self))
         self.box.body.append(ActionButton('DISPLAY', self.call_pass,
-                                          (path, False, None)))
+                                          path, False, None))
         self.box.body.append(ActionButton('COPY FIRST LINE', self.call_pass,
-                                          (path, True, False)))
+                                          path, True, False))
         self.box.body.append(ActionButton('COPY EVERYTHING', self.call_pass,
-                                          (path, True, True)))
-        self.box.body.append(ActionButton('GENERATE NEW PASSWORD', self.generate_password, (path, 16, True, True)))
+                                          path, True, True))
+        self.box.body.append(ActionButton('GENERATE NEW PASSWORD', self.generate_password, path, 16, True, True))
         self.box.body.append(urwid.Text("More copy options are available after displaying the password."))
 
-    def call_pass(self, originator, args):
+    def call_pass(self, originator, path, copy, copy_key):
         """Call pass to get a password."""
-        self.current, copy, copy_key = args
+        self.current = path
         self.set_header(self.current)
         pargs = ['pass', self.current]
         copymsg = ' and copying output afterwards' if copy else ''
@@ -534,13 +540,13 @@ class App(object):
                 self.box.body.append(urwid.Text(text.strip()))
 
             self.box.body.append(ActionButton('COPY FIRST LINE', self.call_pass,
-                                              (self.current, True, False)))
+                                              self.current, True, False))
             self.box.body.append(ActionButton('COPY EVERYTHING', self.call_pass,
-                                              (self.current, True, True)))
+                                              self.current, True, True))
 
             for k in copiable_keys:
                 self.box.body.append(ActionButton('COPY {0}'.format(k), self.call_pass,
-                                                  (self.current, True, k)))
+                                                  self.current, True, k))
         else:
             self.box.body.append(urwid.Text(('error', 'ERROR')))
             self.box.body.append(
-- 
2.49.1

