Skip to content

quopri uses conditional binascii import, when it is always available #133896

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
sobolevn opened this issue May 11, 2025 · 2 comments
Open

quopri uses conditional binascii import, when it is always available #133896

sobolevn opened this issue May 11, 2025 · 2 comments
Assignees
Labels
stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@sobolevn
Copy link
Member

sobolevn commented May 11, 2025

Feature or enhancement

This module is quite old, it uses a conditional import of binascii since times when it was possible to not have it when zlib was missing:

cpython/Lib/quopri.py

Lines 12 to 17 in 13cb8ca

try:
from binascii import a2b_qp, b2a_qp
except ImportError:
a2b_qp = None
b2a_qp = None

However, right now it is always available under all python implementations (like RustPython and PyPy).

Image

So, we can simplify the implementation and remove a lot of duplicated code, example:

cpython/Lib/quopri.py

Lines 51 to 99 in 13cb8ca

if b2a_qp is not None:
data = input.read()
odata = b2a_qp(data, quotetabs=quotetabs, header=header)
output.write(odata)
return
def write(s, output=output, lineEnd=b'\n'):
# RFC 1521 requires that the line ending in a space or tab must have
# that trailing character encoded.
if s and s[-1:] in b' \t':
output.write(s[:-1] + quote(s[-1:]) + lineEnd)
elif s == b'.':
output.write(quote(s) + lineEnd)
else:
output.write(s + lineEnd)
prevline = None
while line := input.readline():
outline = []
# Strip off any readline induced trailing newline
stripped = b''
if line[-1:] == b'\n':
line = line[:-1]
stripped = b'\n'
# Calculate the un-length-limited encoded line
for c in line:
c = bytes((c,))
if needsquoting(c, quotetabs, header):
c = quote(c)
if header and c == b' ':
outline.append(b'_')
else:
outline.append(c)
# First, write out the previous line
if prevline is not None:
write(prevline)
# Now see if we need any soft line breaks because of RFC-imposed
# length limitations. Then do the thisline->prevline dance.
thisline = EMPTYSTRING.join(outline)
while len(thisline) > MAXLINESIZE:
# Don't forget to include the soft line break `=' sign in the
# length calculation!
write(thisline[:MAXLINESIZE-1], lineEnd=b'=\n')
thisline = thisline[MAXLINESIZE-1:]
# Write out the current line
prevline = thisline
# Write out the last line, without a trailing newline
if prevline is not None:
write(prevline, lineEnd=stripped)

There are also several helper functions with public names, which are not in __all__ which will be unused after this. We can keep them and deprecate their use.

Since binascii is always available, python implementation is never used anyway.

So, the main pro:

  • We can remove some dead code

There are several cons to my proposal:

  • There are no real user reported problems
  • The module is old and stable
  • It does not require a lot of maintaince

I will open a draft PR, so people can see the amount of changes and decide better with that.

Should we do this?

Linked PRs

@sobolevn sobolevn self-assigned this May 11, 2025
@sobolevn sobolevn added type-feature A feature request or enhancement stdlib Python modules in the Lib dir labels May 11, 2025
sobolevn added a commit to sobolevn/cpython that referenced this issue May 11, 2025
@serhiy-storchaka
Copy link
Member

Not so fast. First we need to solve #62222.

@sobolevn
Copy link
Member Author

sobolevn commented May 12, 2025

@serhiy-storchaka there's no behavior change, unless you explicitly forbid to import binascii somehow with your own hacks / tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

2 participants