GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-127787: refactor helpers for `PyUnicodeErrorObject` internal interface by picnixz · Pull Request #127789 · python/cpython

Conversation

@picnixz

@picnixz picnixz commented Dec 10, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member
  • Unify get_unicode and get_string in a single function.

  • Allow to retrieve the underlying object attribute, its size and its start and end indices in one round.

  • Use a common implementation for the following functions:

    • PyUnicode{Decode,Encode}Error_GetEncoding
    • PyUnicode{Decode,Encode,Translate}Error_GetObject
    • PyUnicode{Decode,Encode,Translate}Error_{Get,Set}Reason
    • PyUnicode{Decode,Encode,Translate}Error_{Get,Set}{Start,End}

Note that there are some cosmetic changes here and there (in the naming of parameters) but these are essentially in prevision of #127694 in order to reduce the conflicts I'll need to solve (there will be conflicts probably but ideally, I want them to be minimal).

I've moved all helpers before the public API. I could move them inbetween but I felt that it's cleaner that way (it also allowed me to put double blank lines between functions a bit more easily).

  • Issue: Refactor PyUnicodeError internal C helpers #127787

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
picnixz added 3 commits December 10, 2024 12:57
@picnixz
Refactor helpers for PyUnicodeErrorObject.
0cc7bc7
- Unify `get_unicode` and `get_string` in a single function.
- Allow to retrieve the underlying `object` attribute and its
  size in one round.
- Use a common implementation for the following functions:

  - `PyUnicode{Decode,Encode}Error_GetEncoding`
  - `PyUnicode{Decode,Encode,Translate}Error_GetObject`
  - `PyUnicode{Decode,Encode,Translate}Error_{Get,Set}Reason`
  - `PyUnicode{Decode,Encode,Translate}Error_{Get,Set}{Start,End}`
@picnixz
put comment section headers
32a199d
@picnixz
add comments
2583095
@picnixz
picnixz requested a review from encukou December 10, 2024 12:08
@picnixz
picnixz requested a review from iritkatriel as a code owner December 10, 2024 12:08
@bedevere-app bedevere-app Bot added the awaiting review label Dec 10, 2024
@bedevere-app bedevere-app Bot mentioned this pull request Dec 10, 2024
Refactor PyUnicodeError internal C helpers #127787
Closed
@picnixz picnixz added the skip news label Dec 10, 2024
@picnixz
picnixz marked this pull request as draft December 10, 2024 12:14
@bedevere-app bedevere-app Bot removed the awaiting review label Dec 10, 2024
picnixz added 2 commits December 10, 2024 13:25
@picnixz
simpler checks
f0893b7
@picnixz
fix tests
a4b01f0
@picnixz
picnixz marked this pull request as ready for review December 10, 2024 12:27
@bedevere-app bedevere-app Bot added the awaiting review label Dec 10, 2024
@picnixz
unify even more the interface using a generic getter
01b5f22
@picnixz

picnixz commented Dec 10, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

@encukou I've designed a _PyUnicodeError_GetParams which allows to retrieve object, size, start, end and check whether start and end are consistent or not as well. This could help in the codecs handlers (but I just need to check whether I need < or <=).

NVM: just removing the parameter. It's easier to make the check start < end outside.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

picnixz added 3 commits December 10, 2024 14:16
@picnixz
remove useless consistent parameter
be982a0
@picnixz
Simplify call
d4dc9a6
@picnixz
Merge branch 'main' into feat/exc/unicode-error-refactor-127787
3078f23
@picnixz
picnixz marked this pull request as draft December 13, 2024 16:41
@bedevere-app bedevere-app Bot removed the awaiting review label Dec 13, 2024
@picnixz

picnixz commented Dec 13, 2024

Copy link
Copy Markdown
Member Author

@encukou A little implementation question. Do you think it's preferrable to have

PyObject *
PyUnicodeEncodeError_GetEncoding(PyObject *self)
{
    int rc = check_unicode_error_type(self, "UnicodeEncodeError");
    return rc < 0 ? NULL : unicode_error_get_encoding_impl(self);
}

with unicode_error_get_encoding_impl working on generic UnicodeError objects (just assertion casts) or do you prefer unicode_error_get_encoding_impl to actually be the one performing the following check with an additional expect_type parameter:

int rc = check_unicode_error_type(self, expect_type);

Unless I use generating maocrs, I'll end up either duplicating the expect_type strings, or by duplicating int rc = .... Personally, today I feel that it reads better as it is now, but tomorrow maybe I may prefer a "short" implementation of the public API itself.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

picnixz added 2 commits December 13, 2024 17:47
@picnixz
remove unused function
94800fd
@picnixz
remove un-necessary macros
e5709fa
@picnixz
picnixz marked this pull request as ready for review December 13, 2024 16:48
@bedevere-app bedevere-app Bot added the awaiting review label Dec 13, 2024
@encukou

encukou commented Dec 19, 2024

Copy link
Copy Markdown
Member

I think it's fine to silently accept “wrong” subclasses of UnicodeError, especially if a strict check would be difficult to implement.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@picnixz

picnixz commented Dec 21, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

Maybe I wasn't clear but I wasn't talking about subclasses or not. Since I'm using PyObject_TypeCheck, I consider the check to be broad enough. What I wanted to ask is whether you want me to have something like:

static inline PyObject *
unicode_error_get_encoding_impl(PyObject *self)
{
    PyUnicodeErrorObject *exc = PyUnicodeError_CAST(self);
    return as_unicode_error_attribute(exc->encoding, "encoding", false);
}

PyObject *
PyUnicodeEncodeError_GetEncoding(PyObject *self)
{
    int rc = check_unicode_error_type(self, "UnicodeEncodeError");
    return rc < 0 ? NULL : unicode_error_get_encoding_impl(self);
}

or

static inline PyUnicodeErrorObject *
as_unicode_error(PyObject *self, const char *expect_type)
{
    int rc = check_unicode_error_type(self, expect_type);
    return rc < 0 ? NULL : _PyUnicodeError_CAST(self);
}

static inline PyObject *
unicode_error_get_encoding_impl(PyObject *self, const char *expect_type)
{
    PyUnicodeErrorObject *exc = as_unicode_error(self, expect_type);
    return as_unicode_error_attribute(exc->encoding, "encoding", false);
}


PyObject *
PyUnicodeEncodeError_GetEncoding(PyObject *self)
{
    return unicode_error_get_encoding_impl(self, "UnicodeEncodeError");
}

The first solution delegates type-checking and attribute retrieval to two different functions ( check_unicode_error_type and unicode_error_get_encoding_impl), while the second version assumes that unicode_error_get_encoding_impl is also responsible for the cast. However, I designed the functions so that internal ones do not need to do runtime (yet assert-only) checks so that they could possibly be used somewhere else.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

encukou
encukou reviewed Jan 2, 2025
View reviewed changes
Comment thread Objects/exceptions.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

encukou
encukou reviewed Jan 2, 2025
View reviewed changes
Comment thread Objects/exceptions.c Outdated
/*
* Return the underlying (str) 'encoding' attribute of a Unicode Error object.
*
* The caller is responsible to ensure that 'self' is a PyUnicodeErrorObject.

@encukou encukou Jan 2, 2025

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer an assert over a “The caller is responsible to ensure...” comment. To a human reader, they should be equivalent.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@picnixz picnixz Jan 2, 2025

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert is actually inside the _CAST macro. It's just to document that this function would crash otherwise. The alternative is to remove the assert inside the CAST macro and make it an explicit one though that would add lines.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

encukou reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@encukou

encukou commented Jan 2, 2025

Copy link
Copy Markdown
Member

That I wanted to ask is whether you want me to have something like: [...]

Hm, that looks like a style choice I can leave to you; they look similarly complex.

There's one more style you can consider for internal functions, “error pass-through”:

/* if self is NULL, return NULL; an exception must already be set */
static inline PyObject *
unicode_error_get_encoding_impl(PyObject *self) {
    if (!self) {
        return NULL,
    }
    PyUnicodeErrorObject *exc = PyUnicodeError_CAST(self);
    return as_unicode_error_attribute(exc->encoding, "encoding", false);
}

PyObject *
PyUnicodeEncodeError_GetEncoding(PyObject *self)
{
    PyObject *err = check_unicode_error_type(self, "UnicodeEncodeError");
    return unicode_error_get_encoding_impl(err);
}

Are you happy with the current iteration of the PR?
(Apologies, I'm now a bit lost about the state of your PRs; if there's one I should look at first, please let me know!)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@picnixz @encukou
Update Objects/exceptions.c
83eb24d
Co-authored-by: Petr Viktorin <[email protected]>
@picnixz

picnixz commented Jan 2, 2025

Copy link
Copy Markdown
Member Author

(Apologies, I'm now a bit lost about the state of your PRs; if there's one I should look at first, please let me know!)

No worries! I have a lot of PRs that are identical (namely UBSan ones) which you can just skip for now. Other PRs related to unicode error objects are those with codecs. I'm not on my dev session now and since it's a holidays period, I don't want to overwhelm you with review requests.

Are you happy with the current iteration of the PR?

I'll have a look again tomorrow to decide the final state of the PR. I'm pretty happy with the current implementation (namely no pass-through, and assertion in the CAST) but I can consider the pass-through approach. It looks nice and could reduce the number of overall lines. I can also make sure that an exception is set before returning NULL so it would at least suit what I wanted to do (it would also decouple the logic of checking and performing the actual operation in PyUnicodeEncodeError_{Get,Set}* functions so it's also fine).

I don't know how the exception class will evolve in the future, especially how we will decide to handle relative start/end indices (I think we're unfortunately stuck and won't really be able to change the behaviour since it's part of the stable ABI).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@picnixz

picnixz commented Jan 2, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

The merge plan I had in mind was:

  • This PR (so that I introduce the GetParams function)
  • The PRs for Incorrect handling of start and end values in codecs error handlers #126004 which could then use the GetParams function.

So until this one is merged, there is no need to review the others as the code will change a bit. Though, you can review them if you want to look at the logic only.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

picnixz added 5 commits January 3, 2025 10:24
@picnixz
style update
7c9fd99
@picnixz
use macro for repeated names to avoid typos
8219be9
@picnixz
specialize _PyUnicodeError_GetParams for start and end attributes
4a5e4e3
This is typically useful for future refactorization and to
be able to write lines below 80 characters. This also helps
avoiding having to remember where to place the NULL arguments.
@picnixz
update comments
f7a2efa
@picnixz
put 2 blank lines before sections
17367ff
@picnixz
picnixz requested a review from encukou January 3, 2025 10:06
@picnixz

picnixz commented Jan 3, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

I eventually decided to avoid a pass-through. While it would work, I feel that it's not right to expect the callee to eventually rely on the fact that an exception has been set.

However, do you want me to add NULL checks? (without those, the assertions would also crash)
EDIT: I've added them so that it's more robust.

encukou reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@picnixz
add NULL assertions to avoid obscure segmentation faults
c05f2ad
encukou
encukou reviewed Jan 3, 2025
View reviewed changes

@encukou encukou left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just a few comment nitpicks left.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Objects/exceptions.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/exceptions.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Objects/exceptions.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

picnixz added 3 commits January 3, 2025 12:24
@picnixz
update comments
6c07afc
@picnixz
fixup comment
ebf86c7
@picnixz
fixup comment
3fb81c2
@picnixz
picnixz requested a review from encukou January 3, 2025 11:36
encukou
encukou approved these changes Jan 3, 2025
View reviewed changes

@encukou encukou left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

picnixz reacted with heart emoji
All reactions
  • ❤️ 1 reaction
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting review labels Jan 3, 2025
@encukou
encukou merged commit fa985be into python:main Jan 3, 2025
@bedevere-app bedevere-app Bot removed the awaiting merge label Jan 3, 2025
@picnixz
picnixz deleted the feat/exc/unicode-error-refactor-127787 branch January 3, 2025 12:48
WolframAlph pushed a commit to WolframAlph/cpython that referenced this pull request Jan 4, 2025
@picnixz @WolframAlph
pythongh-127787: refactor helpers for PyUnicodeErrorObject internal…
b5bb8cc
… interface (pythonGH-127789)

- Unify `get_unicode` and `get_string` in a single function.

- Allow to retrieve the underlying `object` attribute, its
  size, and the adjusted 'start' and 'end', all at once.
  Add a new `_PyUnicodeError_GetParams` internal function for this.
  (In `exceptions.c`, it's somewhat common to not need all the attributes,
  but the compiler has opportunity to inline the function and optimize
  unneeded work away. Outside that file, we'll usually need all or
  most of them at once.)

- Use a common implementation for the following functions:

  - `PyUnicode{Decode,Encode}Error_GetEncoding`
  - `PyUnicode{Decode,Encode,Translate}Error_GetObject`
  - `PyUnicode{Decode,Encode,Translate}Error_{Get,Set}Reason`
  - `PyUnicode{Decode,Encode,Translate}Error_{Get,Set}{Start,End}`
srinivasreddy pushed a commit to srinivasreddy/cpython that referenced this pull request Jan 8, 2025
@picnixz @srinivasreddy
pythongh-127787: refactor helpers for PyUnicodeErrorObject internal…
02e0f80
… interface (pythonGH-127789)

- Unify `get_unicode` and `get_string` in a single function.

- Allow to retrieve the underlying `object` attribute, its
  size, and the adjusted 'start' and 'end', all at once.
  Add a new `_PyUnicodeError_GetParams` internal function for this.
  (In `exceptions.c`, it's somewhat common to not need all the attributes,
  but the compiler has opportunity to inline the function and optimize
  unneeded work away. Outside that file, we'll usually need all or
  most of them at once.)

- Use a common implementation for the following functions:

  - `PyUnicode{Decode,Encode}Error_GetEncoding`
  - `PyUnicode{Decode,Encode,Translate}Error_GetObject`
  - `PyUnicode{Decode,Encode,Translate}Error_{Get,Set}Reason`
  - `PyUnicode{Decode,Encode,Translate}Error_{Get,Set}{Start,End}`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@encukou encukou encukou approved these changes
@iritkatriel iritkatriel Awaiting requested review from iritkatriel iritkatriel is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

skip news

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@picnixz @encukou
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.