-
Notifications
You must be signed in to change notification settings - Fork 715
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
Job's __unicode__ method leads to misleading representations #459
Comments
The |
Thanks for the response. When you say 'the proper way to find out what object you're dealing with', do you have any particular programming or Python guideline/mantra in mind that suggests such pattern? If I may, in my opinion this is a bad design that is bug prone, as it silently aliases one class for another. One improvement I can think of would be to return something like |
If in a REPL you typed |
I understand what you outline, but politely I'll stay with my opinion in that this is a bad design - I hope you can see that I'm merely trying to aid you in removing technical debt from the library. Once again, if you think this is in some way a standard way or 'proper way' to do this, then please share your resources so we all can understand the reasoning behind such decision. To support my argument let me bring a couple of pieces from the official Python documentation:
And just for clarity, let me repeat the highlighted segments:
I think it is pretty clearly outlined that both __str__ and __repr__ are meant to represent the object. Currently, Job.__str__ (and by extension Job.__unicode__ on which there is no documentation) does not return the “informal” or nicely printable string representation of an object, but a representation of an object (or function) that the Job is going to call. Given that APS currently supports __repr__'s definition, but breaks it for __str__ by aliasing the job object behind another object (or a function), I think it is fair to say that it goes against the official documentation and contains an incorrect implementation of the __str__ method. The fact that one could still call repr(job) to get the representation of the Job object does not change that. Does anything in APS actually rely on the current implementation of __str__ in a way that would make the suggested correction troublesome? |
APScheduler does have technical debt but this isn't technical debt, it's deliberate design. I honestly do not understand what you think makes this "bug prone". The string representation is only ever used for visual presentation, and its
They didn't define what "informal representation" means, so APScheduler isn't doing anything contrary to that. The current
Yes, |
It introduces confusion as it aliases one object behind another. Confusion is bug prone. Imagine someone developing using APS and needing to print or convert the job to a string. Without carefully analysing the print log or the Converting to string using Imagine I write a test that ensures the logging functionality of my app is correct. It may look as follows: with self.assertLogs(logging.getLogger('my_logger'), level='INFO') as cm:
self.assertTrue('Job([...]' in ';'.join(cm.output)) while my logging looks along the lines of: def my_target():
pass
aps_job = scheduler.add_job(my_target)
logging.getLogger('my_logger').info(aps_job) One would assume such a test to pass, given that we're passing a Job object directly to the logger. Unfortunately, quite contrarily, due to the aliasing in Job.__str__ the logger will output
Unless you're referring to another version of APS, I just went over the print(u' %s' % job, file=out) Both of which would not break if the __str__() / __unicode__() were to change. Could you elaborable on that?
Sorry, but I don't think you're being correct by taking these words out of context. The sentence is the “informal” or nicely printable string representation of an object. Yes, the 'informal' is not specified, but it is specific that the representation should be of the object, not of another object or function. APS indeed does that, it returns a representation that is not of the object itself. Imagine there is a red bicycle and a green car parked on a street. Mark asks Ben: "Hey Ben, what vehicles are parked on the street?", to which Ben replies: "A red bicycle and a green bicycle". I think it's clear this is a wrong answer. Even though the properties were given correctly (as it would in APS's case), the representation is incorrect due to name aliasing. Being 'informal' does not mean that Ben can change the meaning of the information he's trying to convey. |
In my 15 years of using Python (and 12 years of maintaining APScheduler) I've yet to hear a complaint about the difference between
Why do you think they're separate methods, if not to allow arbitrary output on
You're wrong about that. The class Foo:
def __str__(self):
return 'This is __str__() of Foo %s' % id(self)
def __repr__(self):
return 'Foo()'
print('%s' % Foo()) What is printed on the console?
Again, you are treating If it helps, APScheduler 4.0 does not have a separate |
I wish this was your first response to this issue! If I'm not mistaken you're not really fixing 3.* anymore until 4.0 gets released. This would have saved us all this discussion. However, I think it's only fair if I respond to your points:
Let's be honest, you could say this about half of new issues, and quite frankly such speech doesn't entirely encourage APS's users to speak to you about new issues. To be fair - in my 12 years of using Python, I've never seen anyone aliasing objects like this either, so let's put the experience calling aside if you may.
By no means, and I don't think I've ever suggested such assumption in this thread. However, I believe the fact that they can be different does not mean that one could chose any arbitrary output for the
Am I wrong? Removing or changing Job.__str__ , would not break the
Now let's remove __str__: class Foo():
pass
print("%s", Foo())
>>> <__main__.Foo object at 0x000002C70C229808> Nothing breaks. Please elaborate how does
Again, at no point have I treated them as such. Remove the word 'formal' from this sentence and then I agree - I treat these two as the representation of the object - and the documentation indeed tells you that this should be the case.
Unless you can support this with some sources I'd say this is your own conjecture. The official documentation clearly states the opposite: the “informal” or nicely printable string representation of an object
Yet again, unless you can support this, that's your personal conjecture. Just about every result from the first page of googling 'python __str__' teaches to represent the object itself (not any arbitrary output), I can't find a single mention of name aliasing similar to APS's Job's, and about half of them outline that __str__ can indeed be used for debugging. (1, 2, 3, 4, 5, 6 to name a few)
Fantastic statement, now tell me: how does any of the following represent an object called 'Job': MagicMock (trigger:...)
myfunc(trigger:...)
download(trigger:...)
run(trigger:...)
whathaveyou(trigger:...) One would clearly see that all of these indeed are instances of an object called 'Job', wouldn't they? If this doesn't convince you, the zen of python has something to say on the topic too: Explicit is better than implicit. - The Job representation is implicit. Please, do bring any external sources outlining or explaining the pattern you've implemented, as I'm sure you're not just basing your arguments on personal opinion only. Lastly: I hope you're enjoying this convo as much as I am 😊 Even though I'm pointing out what I believe to be mistakes in your library I hope you're not taking any of it personally and that this doesn't hurt you in any way. If it isn't the case, then my apologies! |
A change there would not raise an exception, but the output would be drastically different from what it used to be. To fix that, I would have to move the string formatting to I think we'll just have to agree to disagree on the the semantics of I'll close this issue now since it doesn't exist in 4.0 and I won't make this change in 3.x. |
Cool, thanks for addressing the issue either way! Any idea on when could we expect 4.0? I remember you mentioned a public beta coming out in October last year, is that available somewhere? |
hey @agronholm just following up on these two questions I posted last time. Thanks |
Expected Behavior
When printing job or converting one to string, I'd expect to see an indication that it is the Job object I'm operating on.
Current Behavior
Job prints its name followed by parenthesis and some properties. If the name is misleading (eg. MagicMock), the job disguises itself as something else.
Steps to Reproduce
Context (Environment)
It is confusing and potentially error-prone when debugging or serialising Jobs.
Detailed Description
I suggest that Job should always print
Job
at the beginning when converting to unicode.The text was updated successfully, but these errors were encountered: