Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-104400: pygettext: use an AST parser instead of a tokenizer#104402

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
serhiy-storchaka merged 40 commits intopython:mainfromtomasr8:better-pygettext
Feb 11, 2025

Conversation

@tomasr8
Copy link
Member

@tomasr8tomasr8 commentedMay 11, 2023
edited
Loading

This PR replaces the token-based message extraction with one that uses the AST parser instead.
See theissue or theforum discussion for more info.

This change fixes some issues just by virtue of using AST instead of working directly with tokens:

  • docstrings with leading blank lines are extracted correctly
  • dosctrings like"""Hello, {}!""".format('world') are no longer extracted
  • docstrings are cleaned withinspect.cleandoc() viaast.get_docstring()
  • This is now correctly extracted:
deftest(x=_('param')):pass

I added a CLI argument--charset (same as in pybabel and--from-code in xgettext) to force a file encoding, e.g.--charset=utf-8 will open the source files withutf-8 encoding. This is useful because currently we are relying on the system default which is error-prone. For example on Windows,open() in my locale defaults tocp1250 which mangles uputf-8 files and vice versa (with someUnicodeDecoreErrors in between).

  • Let'd do this in a separate PR in order to keep the diff as small as possible here (this is also not needed when running python with-Xutf8)

This PR has lots more tests to make sure we don't regress on anything. The tests now compare the script output to a.po file rather than just comparing themsgids (basically snapshot tests). This ensures that we also catch issues with formatting, line locations or anything else.

@warsaw if you feel like having a look (or anyone else ;))

vasily-v-ryabov, Wulian233, and m-aciek reacted with thumbs up emoji
@tomasr8
Copy link
MemberAuthor

@ambv This is what I talked to you about at EuroPython. If you have time I'd be very happy if you could have a look :)

The TL;DR is pygettext has a couple of bugs which stem from it using a tokenizer-based extraction (and overall the code needs modernizing). I fix those bugs in this PR by switching to a parser. Otherwise I try to keep the functionality as close as possible. I also added lots more tests which compare the entire output and not just the messages as it was previously.

There are also lots of features missing in pygettext - handling ngettext, pgettext and others, format flags, etc..
Once this is done, I will submit patches for those missing features as well - I didn't want to put everything in one giant PR as it's already pretty big.

Thank you!

@AA-Turner
Copy link
Member

@tomasr8 would it be possible to break this PR up into several chunks / stages? You may have more luck with reviewers & progress -- I'm happy to help if wanted.

A

erlend-aasland reacted with thumbs up emoji

@tomasr8
Copy link
MemberAuthor

@tomasr8 would it be possible to break this PR up into several chunks / stages? You may have more luck with reviewers & progress -- I'm happy to help if wanted.

I can definitely give it a try! I think it'll be difficult to separate the actual change from tokens to AST, since that's kind of an all-or-nothing change but I could start with improving the tests first in a separate PR. That should be an added value regardless of whether the rest gets merged or not. I'll see if I can get a separate PR for the tests in the coming days.

Any help/review is greatly appreciated of course! :)

AA-Turner reacted with thumbs up emoji

@tomasr8
Copy link
MemberAuthor

@AA-Turner I opened a separatePR just adding extra tests, if you wanna have a look ;)

@Wulian233
Copy link
Contributor

There was a recent issue in support of f-string#113604 , that mentioned this. AST makes this feature easier to add

https://github.com/python/cpython/pull/108173/files already contains the required tests, can you remove them in this PR, so that the diff will be smaller and easier to review

@tomasr8
Copy link
MemberAuthor

There was a recent issue in support of f-string#113604 , that mentioned this. AST makes this feature easier to add

https://github.com/python/cpython/pull/108173/files already contains the required tests, can you remove them in this PR, so that the diff will be smaller and easier to review

Don't waste your time reviewing this PR just yet, we should get the tests merged before moving on with this :) Actually, it's been a while since I opened the tests PR, it might need updating first..

@bedevere-app
Copy link

Thanks for making the requested changes!

@AA-Turner: please review the changes made to this pull request.

Copy link
Member

@AA-TurnerAA-Turner left a comment

Choose a reason for hiding this comment

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

I'm not an amazing fan of reusing the same visitor for every file. There's not massive performance benefits, and it means we have tricks with resetting the filename, etc.

However, if you'd prefer to keep the current design, could we add awalkabout orinitiate_visit or etc method that takes the node tree and filename, to conceptually keep the two together during tree traversal?

ifttype==tokenize.NAMEandtstringin ('class','def'):
self.__state=self.__ignorenext
classGettextVisitor(ast.NodeVisitor):
def__init__(self,options,filename=None):
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def__init__(self,options,filename=None):
def__init__(self,options):

def__init__(self,options,filename=None):
super().__init__()
self.options=options
self.filename=filename
Copy link
Member

Choose a reason for hiding this comment

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

The filename argument is never used

Suggested change
self.filename=filename
self.filename:str=''

Copy link
Member

@serhiy-storchakaserhiy-storchaka left a comment

Choose a reason for hiding this comment

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

Great! It is now much simpler. And it works more correctly!

There are still some issues with var-positional arguments. Since we cannot determine the argument position in such case, it should be rejected.

@tomasr8
Copy link
MemberAuthor

I'm not an amazing fan of reusing the same visitor for every file. There's not massive performance benefits, and it means we have tricks with resetting the filename, etc.

I didn't really do this for performance but so that I don't need to pass themessages dictionary. If I create a new visitor for each file, I still need to pass the messages to it. I thought that passing the filename was simpler, so I did it this way, but if you prefer it the other way, just tell me and I'll change it 🙂 For now, I addedGettextVisitor.visit_file(module_tree, filename) which sets the filename before extracting the messages.

serhiy-storchaka reacted with thumbs up emoji

@tomasr8
Copy link
MemberAuthor

(The Windows failure is some unrelated build failure)

@serhiy-storchakaserhiy-storchaka merged commit374abde intopython:mainFeb 11, 2025
42 of 43 checks passed
@tomasr8
Copy link
MemberAuthor

Woohoo! 🎉🎉 it took almost two years but we got there :) Thanks@serhiy-storchaka and@AA-Turner for your patience and help!

m-aciek, AA-Turner, and srinivasreddy reacted with hooray emoji

@AA-Turner
Copy link
Member

Congratulations on getting this through, it's a great improvement!

A

@tomasr8tomasr8 deleted the better-pygettext branchFebruary 11, 2025 13:48
@serhiy-storchaka
Copy link
Member

I think pushing other changes (tests, etc.) before this helped with that.

tomasr8 reacted with thumbs up emoji

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@arhadthedevarhadthedevarhadthedev left review comments

@serhiy-storchakaserhiy-storchakaserhiy-storchaka approved these changes

@AA-TurnerAA-TurnerAwaiting requested review from AA-Turner

+1 more reviewer

@m-aciekm-aciekm-aciek left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

7 participants

@tomasr8@AA-Turner@Wulian233@serhiy-storchaka@arhadthedev@m-aciek@bedevere-bot

[8]ページ先頭

©2009-2025 Movatter.jp