From 58ab35d1cbe1f8f5810a44c28c39a3b35262ba42 Mon Sep 17 00:00:00 2001 From: Aleksei Kovura <3616242+alex3kov@users.noreply.github.com> Date: Sun, 5 Nov 2017 17:59:23 +0300 Subject: [PATCH 1/7] First draft of libsecret support. --- youtube_dl/__init__.py | 29 ++++++++++++++++++++++++++++- youtube_dl/options.py | 4 ++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index ba684a075..8f20a7ecc 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -11,6 +11,10 @@ import os import random import sys +import gi +gi.require_version('Secret', '1') +from gi.repository import Secret +from .compat import compat_urllib_parse from .options import ( parseOpts, @@ -46,6 +50,14 @@ from .YoutubeDL import YoutubeDL def _real_main(argv=None): + LIBSECRET_SCHEMA = Secret.Schema.new("io.github.rg3.youtube-dl.Store", + Secret.SchemaFlags.DONT_MATCH_NAME, + { + "user-name": Secret.SchemaAttributeType.STRING, + "domain-name": Secret.SchemaAttributeType.STRING + } + ) + # Compatibility fixes for Windows if sys.platform == 'win32': # https://github.com/rg3/youtube-dl/issues/820 @@ -141,7 +153,22 @@ def _real_main(argv=None): parser.error('auto number start must be positive or 0') if opts.usetitle and opts.useid: parser.error('using title conflicts with using video ID') - if opts.username is not None and opts.password is None: + if opts.username is not None and opts.password is None and opts.password_from_keyring is True: + # extract domain names, check if all videos are from the same domain. + all_domains = set(map(lambda url: compat_urllib_parse.urlparse(url).netloc, all_urls)) + if len(all_domains) > 1: + parser.error('You passed URLs from more than one domain - supplying credentials from command line is not supported in this case.') + domain_name = all_domains.pop() + password = Secret.password_lookup_sync(LIBSECRET_SCHEMA, { "user-name": opts.username, "domain-name": domain_name }, None) + if password is None: + print("Password for domain " + domain_name + " and user name " + opts.username + " not found in the keyring.") + supplied_password = compat_getpass('Type account password and press [Return]: ') + attributes = { "user-name": opts.username, "domain-name": domain_name } + label = "Youtube-dl: " + domain_name + " password" + Secret.password_store_sync(LIBSECRET_SCHEMA, attributes, Secret.COLLECTION_DEFAULT, label, supplied_password, None) + password = Secret.password_lookup_sync(LIBSECRET_SCHEMA, { "user-name": opts.username, "domain-name": domain_name }, None) + opts.password = password + if opts.username is not None and opts.password is None and opts.password_from_keyring is False: opts.password = compat_getpass('Type account password and press [Return]: ') if opts.ap_username is not None and opts.ap_password is None: opts.ap_password = compat_getpass('Type TV provider account password and press [Return]: ') diff --git a/youtube_dl/options.py b/youtube_dl/options.py index 4c0455044..eb15ae3bd 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -366,6 +366,10 @@ def parseOpts(overrideArguments=None): '--video-password', dest='videopassword', metavar='PASSWORD', help='Video password (vimeo, smotri, youku)') + authentication.add_option( + '--password-from-keyring', + action='store_true', dest='password_from_keyring', default=False, + help='Retrieve/store password from keyring. Experimental.') adobe_pass = optparse.OptionGroup(parser, 'Adobe Pass Options') adobe_pass.add_option( From a2cfa8019833ff971afb69972038c045625502c5 Mon Sep 17 00:00:00 2001 From: Aleksei Kovura <3616242+alex3kov@users.noreply.github.com> Date: Sun, 5 Nov 2017 18:12:39 +0300 Subject: [PATCH 2/7] First draft of libsecret support (fixed formatting). --- youtube_dl/__init__.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 8f20a7ecc..bba15db35 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -50,14 +50,8 @@ from .YoutubeDL import YoutubeDL def _real_main(argv=None): - LIBSECRET_SCHEMA = Secret.Schema.new("io.github.rg3.youtube-dl.Store", - Secret.SchemaFlags.DONT_MATCH_NAME, - { - "user-name": Secret.SchemaAttributeType.STRING, - "domain-name": Secret.SchemaAttributeType.STRING - } - ) - + LIBSECRET_SCHEMA = Secret.Schema.new("io.github.rg3.youtube-dl.Store", Secret.SchemaFlags.DONT_MATCH_NAME, {"user-name": Secret.SchemaAttributeType.STRING, "domain-name": Secret.SchemaAttributeType.STRING}) + # Compatibility fixes for Windows if sys.platform == 'win32': # https://github.com/rg3/youtube-dl/issues/820 @@ -159,14 +153,14 @@ def _real_main(argv=None): if len(all_domains) > 1: parser.error('You passed URLs from more than one domain - supplying credentials from command line is not supported in this case.') domain_name = all_domains.pop() - password = Secret.password_lookup_sync(LIBSECRET_SCHEMA, { "user-name": opts.username, "domain-name": domain_name }, None) + password = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"user-name": opts.username, "domain-name": domain_name}, None) if password is None: print("Password for domain " + domain_name + " and user name " + opts.username + " not found in the keyring.") supplied_password = compat_getpass('Type account password and press [Return]: ') - attributes = { "user-name": opts.username, "domain-name": domain_name } + attributes = {"user-name": opts.username, "domain-name": domain_name} label = "Youtube-dl: " + domain_name + " password" Secret.password_store_sync(LIBSECRET_SCHEMA, attributes, Secret.COLLECTION_DEFAULT, label, supplied_password, None) - password = Secret.password_lookup_sync(LIBSECRET_SCHEMA, { "user-name": opts.username, "domain-name": domain_name }, None) + password = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"user-name": opts.username, "domain-name": domain_name}, None) opts.password = password if opts.username is not None and opts.password is None and opts.password_from_keyring is False: opts.password = compat_getpass('Type account password and press [Return]: ') From ce0148424a15bda20fb46f67db5346a2ac836b36 Mon Sep 17 00:00:00 2001 From: Aleksei Kovura <3616242+alex3kov@users.noreply.github.com> Date: Mon, 6 Nov 2017 10:42:07 +0300 Subject: [PATCH 3/7] Renamed libsecret option from "--password-from-keyring" to "--keyring". --- youtube_dl/__init__.py | 4 ++-- youtube_dl/options.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index bba15db35..fba9621d3 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -147,7 +147,7 @@ def _real_main(argv=None): parser.error('auto number start must be positive or 0') if opts.usetitle and opts.useid: parser.error('using title conflicts with using video ID') - if opts.username is not None and opts.password is None and opts.password_from_keyring is True: + if opts.username is not None and opts.password is None and opts.keyring is True: # extract domain names, check if all videos are from the same domain. all_domains = set(map(lambda url: compat_urllib_parse.urlparse(url).netloc, all_urls)) if len(all_domains) > 1: @@ -162,7 +162,7 @@ def _real_main(argv=None): Secret.password_store_sync(LIBSECRET_SCHEMA, attributes, Secret.COLLECTION_DEFAULT, label, supplied_password, None) password = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"user-name": opts.username, "domain-name": domain_name}, None) opts.password = password - if opts.username is not None and opts.password is None and opts.password_from_keyring is False: + if opts.username is not None and opts.password is None and opts.keyring is False: opts.password = compat_getpass('Type account password and press [Return]: ') if opts.ap_username is not None and opts.ap_password is None: opts.ap_password = compat_getpass('Type TV provider account password and press [Return]: ') diff --git a/youtube_dl/options.py b/youtube_dl/options.py index eb15ae3bd..18f6ce4e8 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -367,9 +367,9 @@ def parseOpts(overrideArguments=None): dest='videopassword', metavar='PASSWORD', help='Video password (vimeo, smotri, youku)') authentication.add_option( - '--password-from-keyring', - action='store_true', dest='password_from_keyring', default=False, - help='Retrieve/store password from keyring. Experimental.') + '--keyring', + action='store_true', dest='keyring', default=False, + help='Retrieve password from keyring. Experimental.') adobe_pass = optparse.OptionGroup(parser, 'Adobe Pass Options') adobe_pass.add_option( From 5b295effdd8ff980f319c975a9ec4b69879d5358 Mon Sep 17 00:00:00 2001 From: Aleksei Kovura <3616242+alex3kov@users.noreply.github.com> Date: Mon, 6 Nov 2017 11:12:35 +0300 Subject: [PATCH 4/7] If password was not found in keyring - don't ask for it, just fail with error. --- youtube_dl/__init__.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index fba9621d3..4338d5ed1 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -155,13 +155,7 @@ def _real_main(argv=None): domain_name = all_domains.pop() password = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"user-name": opts.username, "domain-name": domain_name}, None) if password is None: - print("Password for domain " + domain_name + " and user name " + opts.username + " not found in the keyring.") - supplied_password = compat_getpass('Type account password and press [Return]: ') - attributes = {"user-name": opts.username, "domain-name": domain_name} - label = "Youtube-dl: " + domain_name + " password" - Secret.password_store_sync(LIBSECRET_SCHEMA, attributes, Secret.COLLECTION_DEFAULT, label, supplied_password, None) - password = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"user-name": opts.username, "domain-name": domain_name}, None) - opts.password = password + parser.error('Password not found in keyring/wallet') if opts.username is not None and opts.password is None and opts.keyring is False: opts.password = compat_getpass('Type account password and press [Return]: ') if opts.ap_username is not None and opts.ap_password is None: From 1579fd3889dd975fe967404d017c108cbc87c250 Mon Sep 17 00:00:00 2001 From: Aleksei Kovura <3616242+alex3kov@users.noreply.github.com> Date: Fri, 10 Nov 2017 18:17:52 +0300 Subject: [PATCH 5/7] libsecret stuff moved to extractor/common.py, reworked --- youtube_dl/__init__.py | 22 ++++++---------------- youtube_dl/extractor/common.py | 20 +++++++++++++++++++- youtube_dl/options.py | 2 +- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 4338d5ed1..c5fcf2744 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -11,10 +11,6 @@ import os import random import sys -import gi -gi.require_version('Secret', '1') -from gi.repository import Secret -from .compat import compat_urllib_parse from .options import ( parseOpts, @@ -50,8 +46,6 @@ from .YoutubeDL import YoutubeDL def _real_main(argv=None): - LIBSECRET_SCHEMA = Secret.Schema.new("io.github.rg3.youtube-dl.Store", Secret.SchemaFlags.DONT_MATCH_NAME, {"user-name": Secret.SchemaAttributeType.STRING, "domain-name": Secret.SchemaAttributeType.STRING}) - # Compatibility fixes for Windows if sys.platform == 'win32': # https://github.com/rg3/youtube-dl/issues/820 @@ -133,6 +127,10 @@ def _real_main(argv=None): # Conflicting, missing and erroneous options if opts.usenetrc and (opts.username is not None or opts.password is not None): parser.error('using .netrc conflicts with giving username/password') + if opts.usekeyring and (opts.username is not None or opts.password is not None): + parser.error('using keyring conflicts with giving username/password') + if opts.usekeyring and opts.usenetrc: + parser.error('using keyring conflicts with using .netrc') if opts.password is not None and opts.username is None: parser.error('account username missing\n') if opts.ap_password is not None and opts.ap_username is None: @@ -147,16 +145,7 @@ def _real_main(argv=None): parser.error('auto number start must be positive or 0') if opts.usetitle and opts.useid: parser.error('using title conflicts with using video ID') - if opts.username is not None and opts.password is None and opts.keyring is True: - # extract domain names, check if all videos are from the same domain. - all_domains = set(map(lambda url: compat_urllib_parse.urlparse(url).netloc, all_urls)) - if len(all_domains) > 1: - parser.error('You passed URLs from more than one domain - supplying credentials from command line is not supported in this case.') - domain_name = all_domains.pop() - password = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"user-name": opts.username, "domain-name": domain_name}, None) - if password is None: - parser.error('Password not found in keyring/wallet') - if opts.username is not None and opts.password is None and opts.keyring is False: + if opts.username is not None and opts.password is None: opts.password = compat_getpass('Type account password and press [Return]: ') if opts.ap_username is not None and opts.ap_password is None: opts.ap_password = compat_getpass('Type TV provider account password and press [Return]: ') @@ -324,6 +313,7 @@ def _real_main(argv=None): ydl_opts = { 'usenetrc': opts.usenetrc, + 'usekeyring': opts.usekeyring, 'username': opts.username, 'password': opts.password, 'twofactor': opts.twofactor, diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index a67ac4411..dde09939c 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -826,6 +826,24 @@ class InfoExtractor(object): except (IOError, netrc.NetrcParseError) as err: self._downloader.report_warning( 'parsing .netrc: %s' % error_to_compat_str(err)) + + if self._downloader.params.get('usekeyring', False): + try: + import gi + gi.require_version('Secret', '1') + from gi.repository import Secret + LIBSECRET_SCHEMA = Secret.Schema.new("io.github.rg3.youtube-dl.Store",Secret.SchemaFlags.DONT_MATCH_NAME,{"extractor": Secret.SchemaAttributeType.STRING,"app": Secret.SchemaAttributeType.STRING}) + secret = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"extractor": "json", "app": "youtube-dl"}, None) + if secret is None: + raise netrc.NetrcParseError('Can\'t find credentials in keyring for "' + netrc_machine + '"') + print(str(secret)) + secret_dict = json.loads(secret) + print('JSON Parsed: ' + str(secret_json)) + print('JSON User: ' + secret_json['u']) + print('JSON Password: ' + secret_json['p']) + except (IOError, netrc.NetrcParseError) as err: + self._downloader.report_warning( + 'Libsecret: %s' % error_to_compat_str(err)) return username, password @@ -843,7 +861,7 @@ class InfoExtractor(object): downloader_params = self._downloader.params - # Attempt to use provided username and password or .netrc data + # Attempt to use provided username and password or .netrc data or libsecret data if downloader_params.get(username_option) is not None: username = downloader_params[username_option] password = downloader_params[password_option] diff --git a/youtube_dl/options.py b/youtube_dl/options.py index 18f6ce4e8..901687e38 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -368,7 +368,7 @@ def parseOpts(overrideArguments=None): help='Video password (vimeo, smotri, youku)') authentication.add_option( '--keyring', - action='store_true', dest='keyring', default=False, + action='store_true', dest='usekeyring', default=False, help='Retrieve password from keyring. Experimental.') adobe_pass = optparse.OptionGroup(parser, 'Adobe Pass Options') From 3be4a1db6b6e144390cb337888daba6c4b52c852 Mon Sep 17 00:00:00 2001 From: Aleksei Kovura <3616242+alex3kov@users.noreply.github.com> Date: Fri, 10 Nov 2017 20:54:59 +0300 Subject: [PATCH 6/7] Handling additional exceptions, fixed formatting, minor edits. --- README.md | 24 ++++++++++++++++++++++++ youtube_dl/YoutubeDL.py | 1 + youtube_dl/extractor/common.py | 26 +++++++++++++++++--------- youtube_dl/options.py | 2 +- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index ea321d536..4a476adfa 100644 --- a/README.md +++ b/README.md @@ -362,6 +362,7 @@ Alternatively, refer to the [developer instructions](#developer-instructions) fo out, youtube-dl will ask interactively. -2, --twofactor TWOFACTOR Two-factor authentication code -n, --netrc Use .netrc authentication data + --keyring Retrieve authentication data from keyring. Experimental. --video-password PASSWORD Video password (vimeo, smotri, youku) ## Adobe Pass Options: @@ -481,6 +482,29 @@ On Windows you may also need to setup the `%HOME%` environment variable manually set HOME=%USERPROFILE% ``` +### Authentication with keyring + +This option retrieves credentials for an extractor from keyring (typically gnome-keyring or kwallet) using libsecret. +Check that you have python-gobject and libsecret installed. +After that you can add credentials for an extractor to the keyring like this, where *extractor* is the name of the extractor in lowercase: +``` +secret-tool store --label="Youtube-dl: password" extractor "" app "youtube-dl" +``` +For example: +``` +secret-tool store --label="Youtube-dl: youtube password" extractor "youtube" app "youtube-dl" +``` +Both username and password need to be put into password prompt of the above command in JSON format as follows. There are 2 characters that need to be escaped with a backslash: " (double quote" and \ (backslash). +``` +{"user":"","pass":""} +``` +For example, given that login is john.doe@gmail.com and password is Pass"wor\d : +``` +{"user":"john.doe@gmail.com","pass":"Pass\"wor\\d"} +``` +To activate authentication with keyring you should pass `--keyring` to youtube-dl or place it in the [configuration file](#configuration). + + # OUTPUT TEMPLATE The `-o` option allows users to indicate a template for the output file names. diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 342d6b47c..8a80e9ecb 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -144,6 +144,7 @@ class YoutubeDL(object): ap_username: Multiple-system operator account username. ap_password: Multiple-system operator account password. usenetrc: Use netrc for authentication instead. + usekeyring: Use keyring for authentication instead. verbose: Print additional info to stdout. quiet: Do not print messages to stdout. no_warnings: Do not print out anything for warnings. diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index dde09939c..f1a075d6d 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -826,24 +826,32 @@ class InfoExtractor(object): except (IOError, netrc.NetrcParseError) as err: self._downloader.report_warning( 'parsing .netrc: %s' % error_to_compat_str(err)) - + if self._downloader.params.get('usekeyring', False): try: import gi gi.require_version('Secret', '1') from gi.repository import Secret - LIBSECRET_SCHEMA = Secret.Schema.new("io.github.rg3.youtube-dl.Store",Secret.SchemaFlags.DONT_MATCH_NAME,{"extractor": Secret.SchemaAttributeType.STRING,"app": Secret.SchemaAttributeType.STRING}) - secret = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"extractor": "json", "app": "youtube-dl"}, None) + LIBSECRET_SCHEMA = Secret.Schema.new("io.github.rg3.youtube-dl.Store", + Secret.SchemaFlags.DONT_MATCH_NAME, + { + "extractor": Secret.SchemaAttributeType.STRING, + "app": Secret.SchemaAttributeType.STRING + }) + secret = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"extractor": netrc_machine, "app": "youtube-dl"}, None) if secret is None: - raise netrc.NetrcParseError('Can\'t find credentials in keyring for "' + netrc_machine + '"') - print(str(secret)) + raise KeyError('Cannot find credentials in keyring for "' + netrc_machine + '"') secret_dict = json.loads(secret) - print('JSON Parsed: ' + str(secret_json)) - print('JSON User: ' + secret_json['u']) - print('JSON Password: ' + secret_json['p']) - except (IOError, netrc.NetrcParseError) as err: + username = secret_dict['user'] + password = secret_dict['pass'] + except KeyError as err: self._downloader.report_warning( 'Libsecret: %s' % error_to_compat_str(err)) + except json.decoder.JSONDecodeError: + self._downloader.report_warning( + 'JSON error, your JSON string in keyring is likely malformed') + except ImportError: + raise ImportError('Cannot import gi module. Check that you have python-gobject installed.') return username, password diff --git a/youtube_dl/options.py b/youtube_dl/options.py index 901687e38..10978d8a5 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -369,7 +369,7 @@ def parseOpts(overrideArguments=None): authentication.add_option( '--keyring', action='store_true', dest='usekeyring', default=False, - help='Retrieve password from keyring. Experimental.') + help='Retrieve authentication data from keyring. Experimental.') adobe_pass = optparse.OptionGroup(parser, 'Adobe Pass Options') adobe_pass.add_option( From b74f9c04d4540e06bd84b9d3b244ad3765809684 Mon Sep 17 00:00:00 2001 From: Aleksei Kovura <3616242+alex3kov@users.noreply.github.com> Date: Sun, 12 Nov 2017 13:25:40 +0300 Subject: [PATCH 7/7] More libsecret exceptions handling. --- youtube_dl/extractor/common.py | 53 ++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index f1a075d6d..c94bef798 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -830,28 +830,39 @@ class InfoExtractor(object): if self._downloader.params.get('usekeyring', False): try: import gi - gi.require_version('Secret', '1') - from gi.repository import Secret - LIBSECRET_SCHEMA = Secret.Schema.new("io.github.rg3.youtube-dl.Store", - Secret.SchemaFlags.DONT_MATCH_NAME, - { - "extractor": Secret.SchemaAttributeType.STRING, - "app": Secret.SchemaAttributeType.STRING - }) - secret = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"extractor": netrc_machine, "app": "youtube-dl"}, None) - if secret is None: - raise KeyError('Cannot find credentials in keyring for "' + netrc_machine + '"') - secret_dict = json.loads(secret) - username = secret_dict['user'] - password = secret_dict['pass'] - except KeyError as err: - self._downloader.report_warning( - 'Libsecret: %s' % error_to_compat_str(err)) - except json.decoder.JSONDecodeError: - self._downloader.report_warning( - 'JSON error, your JSON string in keyring is likely malformed') + can_use_gi = True except ImportError: - raise ImportError('Cannot import gi module. Check that you have python-gobject installed.') + self._downloader.report_warning( + 'Problem while processing --keyring option: cannot import gi module. Check that you have python-gobject installed.') + can_use_gi = False + if can_use_gi: + try: + gi.require_version('Secret', '1') + from gi.repository import Secret + LIBSECRET_SCHEMA = Secret.Schema.new("io.github.rg3.youtube-dl.Store", + Secret.SchemaFlags.DONT_MATCH_NAME, + { + "extractor": Secret.SchemaAttributeType.STRING, + "app": Secret.SchemaAttributeType.STRING + }) + secret = Secret.password_lookup_sync(LIBSECRET_SCHEMA, {"extractor": netrc_machine, "app": "youtube-dl"}, None) + if secret is None: + raise KeyError('Cannot find credentials in keyring for "' + netrc_machine + '"') + secret_dict = json.loads(secret) + username = secret_dict['user'] + password = secret_dict['pass'] + except ValueError as err: + self._downloader.report_warning( + 'Looks like libsecret is not installed. Error: %s:' % error_to_compat_str(err)) + except gi.repository.GLib.GError as err: + self._downloader.report_warning( + 'Something went wrong when invoking libsecret. Error: %s' % error_to_compat_str(err)) + except KeyError as err: + self._downloader.report_warning( + 'Libsecret: %s' % error_to_compat_str(err)) + except json.decoder.JSONDecodeError: + self._downloader.report_warning( + 'JSON error, your JSON string in keyring is likely malformed') return username, password