Hi Luke, Thanks for the review! I've updated the branch with your suggestions.
Here are a few comments -- when I have something to say other than "fixed, thanks". 2011/11/8 Luke Plant <l.plant...@cantab.net>: > == django/contrib/admin/util.py == > >> elif isinstance(field, models.DateField): >> return formats.localize(timezone.aslocaltime(value)) >> elif isinstance(field, models.DateField) or isinstance(field, > models.TimeField): >> return formats.localize(value) > > Isn't the first clause in the second elif rendered useless by the > previous elif? It's a bug: the first elif should test for models.DateTimeField. The problem didn't appear in the tests because DateTimeField is a subclass of DateField. > == django/db/backends/mysql/base.py == > >> # Finally, MySQLdb always returns naive datetime objects. > > Is it possible that a future version of MySQLdb could change this? If > so, would it be better to not make this assumption, and future proof the > code? We could perhaps just add an assertion for the assumption we make, > so that we don't end up silently corrupting data with a future version > of MySQLdb that acts differently, because at the moment the function > datetime_or_None_with_timezone_support just wipes out any existing > tzinfo field. I'm now checking if the value is naive before overwriting its tzinfo. If the database adapter returns an aware datetime (in a future version), it's passed through unchanged. > There is a similar issue in the Oracle backend I think. The issue existed in SQLite, MySQL and Oracle. >> raise ValueError("MySQL backend does not support timezone-aware > datetimes.") > > This seems to be misleading - shouldn't the message add the caveat "if > USE_TZ == False" or something? I've updated the message for SQLite, MySQL and Oracle. > == django/db/backends/sqlite3/base.py == > >> supports_timezones = False > > What exactly is meant by this? The timezone support in the sqlite > backend appears to be very similar to that in MySQL. > > If SQLite genuinely does not support time zones in some important way, > this should probably be noted in the release notes, and definitely in > docs/ref/databases.txt All backends but PostgreSQL have supports_timezones = False. It means that the database engine (SQLite, MySQL) or its adapter (cx_Oracle) doesn't support timezones. This flag existed before my branch, and it was True for SQLite. I switched it to False because SQLite doesn't actually support timezones. This shouldn't affect anything besides Django's own test suite -- database features aren't part of the public API (AFAIK). I've added a paragraph about this change to the release notes. > == django/utils/timezone.py == > >> import time as _time > > There doesn't seem to be any clash to avoid, so I don't see the need for > importing like this. This code is taken straight from Python's docs, and I wanted to keep it as close as possible to the original for clarity and ease of maintenance -- see #16899 for example. I can't use the original code as is, because the timezone isn't known at compile time, only after the settings have been loaded. But I still think it's worth minimizing the diff. > However, my biggest question is about the LocalTimezone class. We now > have two implementations of this, one in django.utils.tzinfo, which > seems to have more extensive tests, and a new one in > django.utils.timezone. The old one is still in use, both by old code > e.g. in django/contrib/syndication/views.py and new code e.g. > django/utils/dateformat.py under DateFormat.__init__ > > The new one is used in other places. Yes. I spent a lot of time on this problem, and I eventually decided to add a second implementation of the LocalTimezone, because there are too many issues in the "old" implementation to build more code upon it. The "new" implementation focuses on correctness and simplicity. Here are the problems of the "old" implementation. Its __init__ method takes an argument, which is problematic for pickling and deepcopying. From Python's docs: > Special requirement for pickling: A tzinfo subclass must have an __init__() > method that can be called with no arguments, else it can be pickled but > possibly not unpickled again. This is a technical requirement that may be > relaxed in the future. Adding a __getinitargs__ method resolved this problem, but it's magic, and we're still doing something that's officially discouraged. Also, I don't like the hack in the "old" implementation to support post-2037 dates. Sure, it doesn't crash, but it can return wrong data, because DST doesn't apply during the same period every year. So much for refusing the temptation to guess in the face of ambiguity :) This inaccuracy is irrelevant for syndication (dates are in the past) and acceptable for display purposes in dateformat (naturaltime will return "in X years", an offset of 1 hour doesn't matter). But when we're saving data in the database, we can't take the risk to corrupt it. > Perhaps we just need to combine the two LocalTimezone implementations in > tzinfo.py? If we can't do that for some backward compatibility reasons, > can we have some explanation, and preferably a deprecation path for the > older code? Finally, do we need to address code that uses the old > LocalTimezone in some way - should it be unconditionally using our own > LocalTimezone instead of something from pytz when available? There are two problems in deprecating the "old" implementation: - the output of self.tzname() would change — it depends on the argument taken by __init__; - post-2037 dates would no longer be supported. To sum up: - the "old" implementation isn't suitable for the needs of my branch; - there's a lot of history, and we can't deprecate it without creating regressions: https://code.djangoproject.com/log/django/trunk/django/utils/tzinfo.py > There is no explanation of the need for these two, or when they should > be used, which to me seems like a minimum requirement. I've added a comment. >> - It includes the time zone for aware datetime objects. It raises >> an exception for aware time objects. > > First instance of 'aware' should be 'naive'. Second sentence should end > 'aware datetime or time objects' for completeness. The current wording describes what my branch does: - naive datetime => output without TZ info - aware datetime => output with TZ info - naive time => output without TZ info - aware time => exception > == tests == > > I haven't actually reviewed any of the test code - I ran out of energy, > and test code is so dull, sorry! > > I did run coverage for the tests and found: > > - without pytz installed, the new LocalTimezone class You apparently ran out of energy mid-sentence :) Do you remember what you were going to say? Thanks again for the review! -- Aymeric. -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.