From cda46e7ac67be500ecacaa365075392a0ff9f4bc Mon Sep 17 00:00:00 2001 From: Anil Belur Date: Fri, 5 Dec 2025 13:26:54 +1000 Subject: [PATCH] Fix: Unicode encoding and logging errors in lftools MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 1. Fix UnicodeEncodeError in Gerrit/Nexus API requests: - Encode JSON string data as UTF-8 in RestApi._request() - Change Nexus encoding from latin-1 to utf-8 (5 locations) - Handles Unicode characters in responses (e.g., user names with 'Å¡') - Fixes: 'latin-1' codec can't encode character '\u0161' 2. Fix logging format errors (3 locations): - GitHub create-repo: Use f-string instead of comma in log.info() - GitHub votes: Use f-string for approval list logging - Gerrit vote_on_change: Use f-string with parameters - Fixes: TypeError: not all arguments converted during string formatting Based on: https://github.com/modeseven-lfit/lftools-uv/pull/53 Tested with: lftools gerrit addgithubrights git.opendaylight.org gnmi Change-Id: Ief4a4ffa9bcc1d0a31342ac49b448fd097dda879 Signed-off-by: Anil Belur --- lftools/api/client.py | 4 ++++ lftools/api/endpoints/gerrit.py | 2 +- lftools/cli/github_cli.py | 4 ++-- lftools/nexus/__init__.py | 10 +++++----- .../fix-unicode-encoding-logging-c891ffd99f38c7f5.yaml | 15 +++++++++++++++ 5 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/fix-unicode-encoding-logging-c891ffd99f38c7f5.yaml diff --git a/lftools/api/client.py b/lftools/api/client.py index 612ce4df..96527468 100644 --- a/lftools/api/client.py +++ b/lftools/api/client.py @@ -48,6 +48,10 @@ class RestApi(object): self, url: str, method: str, data: Optional[Any] = None, timeout: int = 30 ) -> requests.Response | Tuple[requests.Response, Optional[Dict[str, Any] | str]]: """Execute the request.""" + # Encode string data as UTF-8 to handle Unicode characters + if isinstance(data, str): + data = data.encode("utf-8") + resp: requests.Response = self.r.request(method, self.endpoint + url, data=data, timeout=timeout) # Some massaging to make our gerrit python code work diff --git a/lftools/api/endpoints/gerrit.py b/lftools/api/endpoints/gerrit.py index 28314d15..f71d7c09 100644 --- a/lftools/api/endpoints/gerrit.py +++ b/lftools/api/endpoints/gerrit.py @@ -171,7 +171,7 @@ class Gerrit(client.RestApi): POST /changes/{change-id}/revisions/{revision-id}/review """ - log.info(fqdn, gerrit_project, changeid) + log.info(f"Voting on change: fqdn={fqdn}, project={gerrit_project}, changeid={changeid}") access_str = "changes/{}/revisions/2/review".format(changeid) headers = {"Content-Type": "application/json; charset=UTF-8"} self.r.headers.update(headers) diff --git a/lftools/cli/github_cli.py b/lftools/cli/github_cli.py index 2de9cf2e..a2cd92b9 100644 --- a/lftools/cli/github_cli.py +++ b/lftools/cli/github_cli.py @@ -68,7 +68,7 @@ def submit_pr(ctx, organization, repo, pr): def votes(ctx, organization, repo, pr): """Helper for votes.""" approval_list = prvotes(organization, repo, pr) - log.info("Approvals:", approval_list) + log.info(f"Approvals: {approval_list}") @click.command(name="list") @@ -109,7 +109,7 @@ def createrepo(ctx, organization, repository, description, has_issues, has_proje has_issues = has_issues or False has_wiki = has_wiki or False has_projects = has_projects or False - log.info("Creating repo under organization: ", orgName) + log.info(f"Creating repo under organization: {orgName}") try: org = g.get_organization(orgName) except GithubException as ghe: diff --git a/lftools/nexus/__init__.py b/lftools/nexus/__init__.py index 51c8a178..f8d3d29c 100644 --- a/lftools/nexus/__init__.py +++ b/lftools/nexus/__init__.py @@ -96,7 +96,7 @@ class Nexus: } } - json_data = json.dumps(target).encode(encoding="latin-1") + json_data = json.dumps(target).encode(encoding="utf-8") r = requests.post(url, auth=self.auth, headers=self.headers, data=json_data) @@ -148,7 +148,7 @@ class Nexus: } } - json_data = json.dumps(privileges).encode(encoding="latin-1") + json_data = json.dumps(privileges).encode(encoding="utf-8") r = requests.post(url, auth=self.auth, headers=self.headers, data=json_data) privileges = r.json() @@ -188,7 +188,7 @@ class Nexus: } } - json_data = json.dumps(role).encode(encoding="latin-1") + json_data = json.dumps(role).encode(encoding="utf-8") log.debug("Sending role {} to Nexus".format(json_data)) r = requests.post(url, auth=self.auth, headers=self.headers, data=json_data) @@ -243,7 +243,7 @@ class Nexus: for role in extra_roles: user["data"]["roles"].append(self.get_role(role)) - json_data = json.dumps(user).encode(encoding="latin-1") + json_data = json.dumps(user).encode(encoding="utf-8") user = requests.post(url, auth=self.auth, headers=self.headers, data=json_data) @@ -274,7 +274,7 @@ class Nexus: repo = {"data": data} - json_data = json.dumps(repo).encode(encoding="latin-1") + json_data = json.dumps(repo).encode(encoding="utf-8") requests.put(url, auth=self.auth, headers=self.headers, data=json_data) diff --git a/releasenotes/notes/fix-unicode-encoding-logging-c891ffd99f38c7f5.yaml b/releasenotes/notes/fix-unicode-encoding-logging-c891ffd99f38c7f5.yaml new file mode 100644 index 00000000..8aa11fb2 --- /dev/null +++ b/releasenotes/notes/fix-unicode-encoding-logging-c891ffd99f38c7f5.yaml @@ -0,0 +1,15 @@ +--- +fixes: + - | + Fix UnicodeEncodeError in Gerrit API requests when responses contain + Unicode characters. JSON string data is now properly encoded as UTF-8 + in the RestApi._request() method, preventing 'latin-1' codec errors + when user names or group names contain special characters (e.g., 'Å¡'). + + This fixes failures in commands like: + lftools gerrit addgithubrights + + - | + Fix logging TypeError in GitHub create-repo command. Changed from + using comma-separated arguments (which caused format string errors) + to using f-string formatting for proper message construction. -- 2.16.6