Skip to content

Conversation

@Eddy114514
Copy link
Collaborator

add warning for random.random() that in python 3 its string representation is longer (~18 digit) than python 2 (~14 digit).

as following:
image
image
image

@ltratt
Copy link
Member

ltratt commented Oct 22, 2025

Please force push a rebase against master before review.

@Eddy114514 Eddy114514 enabled auto-merge October 22, 2025 14:29
@Eddy114514 Eddy114514 disabled auto-merge October 22, 2025 14:29
@Eddy114514
Copy link
Collaborator Author

Please force push a rebase against master before review.

@ltratt , resolved, thanks for pointing out.

@ltratt
Copy link
Member

ltratt commented Oct 23, 2025

Please squash.

@ltratt
Copy link
Member

ltratt commented Oct 23, 2025

Hmm, actually, maybe I'm wrong.

Isn't this warning going to be annoying? Even if someone has updated their code, they're still going to get the "change your code" warning AFAICS?

@Eddy114514
Copy link
Collaborator Author

Hmm, actually, maybe I'm wrong.

Isn't this warning going to be annoying? Even if someone has updated their code, they're still going to get the "change your code" warning AFAICS?

@ltratt I think you are right about the warning behavior of my implementation. I think it is generally hard to detect whether user change their code within the warning.

Since the warning is about length of random.random(), maybe I should put warning inside of len() or __str__ method of random.random (if there is one) such that it is less frequent. But I think it still can't detect whether user change their code or not.

@ltratt
Copy link
Member

ltratt commented Oct 23, 2025

What one would need to do is track the string output by random.random and then see if someone does something "bad" on it (e.g. len). There are various ways one could do this.

For example, @nanjekyejoannah can fill you in on the bstate idea we've long been working towards. A variant of that would work here: one could (say) add a bool to PyStr that is true if the string was produced by random.random. This is pretty heavy-weight, admittedly.

Another way would be to return a "special" string-like object from random and intercept calls to it. I'm not sure how hard that might be.

@Eddy114514
Copy link
Collaborator Author

What one would need to do is track the string output by random.random and then see if someone does something "bad" on it (e.g. len). There are various ways one could do this.

For example, @nanjekyejoannah can fill you in on the bstate idea we've long been working towards. A variant of that would work here: one could (say) add a bool to PyStr that is true if the string was produced by random.random. This is pretty heavy-weight, admittedly.

Another way would be to return a "special" string-like object from random and intercept calls to it. I'm not sure how hard that might be.

@ltratt Thank you for your suggestions on improving my implementation, I will try to work on either ways and figure out which one is more suitable. Thanks again!

@Eddy114514
Copy link
Collaborator Author

@ltratt
After discussed and get help from @nanjekyejoannah about bstate yesterday, I choose to return a special float-like object (subclass of float object) from random.random. And since random.random return float object, I move check from len of string object to __str__ of float-like object (I called it pg_float).

I avoid putting a new filed inside of float object since change size of struct might cause some chain reaction.

@ltratt
Copy link
Member

ltratt commented Oct 30, 2025

This looks interesting but dumb question: doesn't this still mean that everyone who does len(random.random()) gets the warning i.e. there's no way to silence it?

@Eddy114514
Copy link
Collaborator Author

This looks interesting but dumb question: doesn't this still mean that everyone who does len(random.random()) gets the warning i.e. there's no way to silence it?

@ltratt it seems that len(random.random()) won't run because float objects doesn't have such method. As picture shown below Screenshot_20251030_042311_Chrome.jpg

@ltratt
Copy link
Member

ltratt commented Oct 30, 2025

Sorry, I meant len(str(random.random())).

@Eddy114514
Copy link
Collaborator Author

@ltratt I think since we are intended to warn user about the length change of str(random.random()), so user should get warning by directly calling len() on it. And when user change their code, for code like if (len(str(random.random())) == 14 (length of random.random() in python2), their could be 2 way:

  • if(len(str(random.random())[:14]) == 14
  • if(len(str(random.random())) == 18

We could avoid warning in first case that we also store the extra information about whether generated from random in string-object and check in len() method that whether it is from random and with length of 18. But for second case, unless we also store the information inside of integer return by len(), we might can't avoid false positive.

We could maybe also maintain a global dictionary with key be location of warning (code line number, etc) and value be a bool of whether user change their code when user run pygrate3 on their code that we assume user's change is correct and mark bool at that location to be true and avoid throw warning to user in next check. But if we assume user's change is correct then 1 run of pygrate3 is enough such that we don't even need to worry about silence problem.

@nanjekyejoannah
Copy link
Collaborator

@Eddy114514 lets first find a justification for duplicate C code on floats to avoid duplication.

return PyFloat_FromDouble((a*67108864.0+b)*(1.0/9007199254740992.0));
double x = (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
if (Py_Py2xWarningFlag){
return _PyFloat_FromDoubleWithFlags(x,0x01);
Copy link
Collaborator

Choose a reason for hiding this comment

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

small style issue


if (Py_Py2xWarningFlag && ((v->ob_pg_flags & 0x01) != 0) && PyErr_WarnEx(
PyExc_Py2xWarning,
"String repr of random.random() is longer in 3.x, change code accordingly",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Make fix more specific, @ltratt ideas?

@ltratt
Copy link
Member

ltratt commented Nov 18, 2025

If we want to move this PR forwards I think we need two passing tests:

  1. A test that the warning for len on the string produced by random produces a warning.
  2. A test that strings produced in other ways don't produce a warning.

@Eddy114514
Copy link
Collaborator Author

Eddy114514 commented Nov 18, 2025

If we want to move this PR forwards I think we need two passing tests:

  1. A test that the warning for len on the string produced by random produces a warning.
  2. A test that strings produced in other ways don't produce a warning.

@ltratt
Thanks for the idea!
image
I believe my current implementation and updated test address such requirement.
I also encountered some difficulties in squashing commits that because there are some PR passed during the process of this PR, if I squash all commits from random, it will include those that doesn't belong to this PR.

@ltratt
Copy link
Member

ltratt commented Nov 20, 2025

Please squash.

@Eddy114514
Copy link
Collaborator Author

Please squash.

@ltratt squashed

@ltratt ltratt added this pull request to the merge queue Nov 21, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Nov 21, 2025
@Eddy114514
Copy link
Collaborator Author

@ltratt the test logs suggest that I need to remove or configure some test cases for changed struct of float and unicode object, will do.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants