Opened 6 years ago

Closed 4 years ago

#28911 closed Cleanup/optimization (invalid)

Add support for the Msft time zone required on Windows Subsystem for Linux running openSUSE

Reported by: El'endia Starman Owned by: Sergey Fedoseev
Component: Utilities Version: 1.11
Severity: Normal Keywords: timezone
Cc: Sergey Fedoseev, Stephen James Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Stephen James)

Under Windows Subsystem for Linux, the only available time zone on openSUSE is Msft, which uses settings that are set on the Windows side. This is not a valid time zone in pytz. In the process of reporting an error thrown by a bug in my code, Django tried to normalize the time zone provided in the project settings by passing it through pytz. pytz then complains that the time zone is unknown. Somewhat amusingly, this error is also caught by Django and goes through the same code path, quickly hitting the recursion limit.

See below for a significant part of the stack trace. My temporary solution was to change

return pytz.timezone(settings.TIME_ZONE)

to

return pytz.timezone(settings.TIME_ZONE if settings.TIME_ZONE in pytz.all_timezones else 'UTC')

---

pytz.exceptions.UnknownTimeZoneError: 'Msft'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/utils/deprecation.py", line 140, in __call__
    response = self.get_response(request)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/handlers/exception.py", line 43, in inner
    response = response_for_exception(request, exc)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/handlers/exception.py", line 93, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/handlers/exception.py", line 139, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/views/debug.py", line 84, in technical_500_response
    html = reporter.get_traceback_html()
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/views/debug.py", line 328, in get_traceback_html
    return t.render(c)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 207, in render
    return self._render(context)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 199, in _render
    return self.nodelist.render(context)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 1040, in render
    output = self.filter_expression.resolve(context)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 732, in resolve
    obj = template_localtime(obj, context.use_tz)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/utils/timezone.py", line 195, in template_localtime
    return localtime(value) if should_convert else value
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/utils/timezone.py", line 213, in localtime
    timezone = get_current_timezone()
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/utils/timezone.py", line 97, in get_current_timezone
    return getattr(_active, "value", get_default_timezone())
  File "/home/elendiastarman/.virtualenvs/django/lib64/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/utils/timezone.py", line 79, in get_default_timezone
    return pytz.timezone(settings.TIME_ZONE)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/pytz/__init__.py", line 191, in timezone
    raise UnknownTimeZoneError(zone)
pytz.exceptions.UnknownTimeZoneError: 'Msft'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib64/python3.4/wsgiref/handlers.py", line 137, in run
    self.result = application(self.environ, self.start_response)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/contrib/staticfiles/handlers.py", line 63, in __call__
    return self.application(environ, start_response)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/handlers/wsgi.py", line 157, in __call__
    response = self.get_response(request)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/handlers/base.py", line 124, in get_response
    response = self._middleware_chain(request)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/handlers/exception.py", line 43, in inner
    response = response_for_exception(request, exc)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/handlers/exception.py", line 93, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/handlers/exception.py", line 139, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/views/debug.py", line 84, in technical_500_response
    html = reporter.get_traceback_html()
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/views/debug.py", line 328, in get_traceback_html
    return t.render(c)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 207, in render
    return self._render(context)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 199, in _render
    return self.nodelist.render(context)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 1040, in render
    output = self.filter_expression.resolve(context)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/template/base.py", line 732, in resolve
    obj = template_localtime(obj, context.use_tz)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/utils/timezone.py", line 195, in template_localtime
    return localtime(value) if should_convert else value
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/utils/timezone.py", line 213, in localtime
    timezone = get_current_timezone()
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/utils/timezone.py", line 97, in get_current_timezone
    return getattr(_active, "value", get_default_timezone())
  File "/home/elendiastarman/.virtualenvs/django/lib64/python3.4/functools.py", line 472, in wrapper
    result = user_function(*args, **kwds)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/utils/timezone.py", line 79, in get_default_timezone
    return pytz.timezone(settings.TIME_ZONE)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/pytz/__init__.py", line 191, in timezone
    raise UnknownTimeZoneError(zone)
pytz.exceptions.UnknownTimeZoneError: 'Msft'

Change History (11)

comment:1 by Tim Graham, 6 years ago

Component: Error reportingUtilities
Easy pickings: unset
Owner: set to nobody

I don't understand the reasoning behind your proposed patch. It seems that will make Django silently ignore an invalid time zone and use UTC instead. Can you clarify? Is your use case not solved with TIME_ZONE = 'UTC'?

comment:2 by Sergey Fedoseev, 6 years ago

Cc: Sergey Fedoseev added

in reply to:  1 comment:3 by El'endia Starman, 6 years ago

Replying to Tim Graham:

I don't understand the reasoning behind your proposed patch. It seems that will make Django silently ignore an invalid time zone and use UTC instead. Can you clarify? Is your use case not solved with TIME_ZONE = 'UTC'?

This is what happens with TIME_ZONE = 'UTC':

➜  IdeaGrapher git:(master) ✗ cat IdeaGrapher/settings.py | grep TIME_ZONE
TIME_ZONE = 'UTC'
➜  IdeaGrapher git:(master) ✗ workon django
(django)➜  IdeaGrapher git:(master) ✗ python manage.py runserver
Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/management/__init__.py", line 364, in execute_from_command_line
    utility.execute()
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/core/management/__init__.py", line 308, in execute
    settings.INSTALLED_APPS
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/conf/__init__.py", line 56, in __getattr__
    self._setup(name)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/conf/__init__.py", line 41, in _setup
    self._wrapped = Settings(settings_module)
  File "/home/elendiastarman/.virtualenvs/django/lib/python3.4/site-packages/django/conf/__init__.py", line 137, in __init__
    raise ValueError("Incorrect timezone setting: %s" % self.TIME_ZONE)
ValueError: Incorrect timezone setting: UTC
(django)➜  IdeaGrapher git:(master) ✗ ls /usr/share/zoneinfo
Msft

Msft is the only valid time zone when working in the Windows Subsystem for Linux. Inconveniently, pytz does not recognize it. Hence, I just defaulted the time zone that pytz sees to UTC.

comment:4 by Tim Graham, 6 years ago

Summary: Django dependency pytz does not recognize Msft time zone within Windows Subsystem for LinuxAdd support for the Msft time zone required on Windows Subsystem for Linux
Triage Stage: UnreviewedAccepted
Type: BugCleanup/optimization

I guess the problem is real. I'm still not sure that the proposed solution is appropriate for the reason I mentioned earlier.

in reply to:  4 comment:5 by El'endia Starman, 6 years ago

Replying to Tim Graham:

I guess the problem is real. I'm still not sure that the proposed solution is appropriate for the reason I mentioned earlier.

I agree my quick get-this-working-asap hack is most likely not the ideal solution. I was going to suggest somehow getting time info and figuring out a pytz-compatible timezone from there, but this GitHub issue does not give me confidence that this can be done.

Perhaps it would be okay to change return pytz.timezone(settings.TIME_ZONE) to return pytz.timezone('UTC' if settings.TIME_ZONE == 'Msft' else settings.TIME_ZONE) instead? Maybe also print out a warning on startup.

comment:6 by Sergey Fedoseev, 6 years ago

Probably the problem can be solved by setting environment variable PYTZ_TZDATADIR=/usr/share/zoneinfo with pytz>=2017.3.

comment:7 by Stephen James, 6 years ago

Cc: Stephen James added
Description: modified (diff)
Summary: Add support for the Msft time zone required on Windows Subsystem for LinuxAdd support for the Msft time zone required on Windows Subsystem for Linux running openSUSE

The three Linux distributions available for WSL at present are Ubuntu 16.04, openSUSE 42.3, and SUSE Linux Enterprise Server 12. Having tested on all three, the issue is only present on WSL when running openSUSE (i.e. there doesn't seem to be any issues on Ubuntu and SLES).

On openSUSE only:

$ ls /usr/share/zoneinfo
Msft

Msft is in all, but it is the only thing in openSUSE.

here is where Django tries to verify the timezone and would raise a ValueError if /usr/share/zoneinfo exists, but doesn't contain anything for the specified timezone.

Upon further investigation, I stumbled across this, specifically:

Apparently, /usr/share/zoneinfo is missing from a (minimal) openSUSE installation...

I assume this is why none of the other timezones are there (Microsoft seemingly still adds theirs regardless, hence why /usr/share/zoneinfo/Msft and hence /usr/share/zoneinfo would still exist).

Installing the timezone package (zypper install timezone), as the aforementioned link suggests, will add them, which would allow Django to not fail on other time zones. I would suggest using that as a fix for the reporter and anyone else with a similar issue.

If there is any desire to make any changes to Django itself for this issue, then I'd suggest changing the validation attempts to further determine if that folder can be relied on.

comment:8 by Sergey Fedoseev, 6 years ago

Owner: changed from nobody to Sergey Fedoseev
Status: newassigned

comment:9 by Matt Johnson, 5 years ago

I logged a bug for this in WSL here:
https://github.com/Microsoft/WSL/issues/3747

comment:10 by David Smith, 4 years ago

Hi All,

Since this ticket was opened the versions of openSUSE available for WSL have changed. Currently openSUSE Leap 15.1 and 15.2 are available in the store. The example above showed that only msft was available. In the same folder now there is a greater variety of options:

david@LAPTOP-HTRGKVO7:/usr/share/zoneinfo> ls
Africa      Brazil   Egypt    GB         Hongkong     Jamaica    MST7MDT   posix       Singapore  W-SU
America     Canada   Eire     GB-Eire    HST          Japan      Navajo    posixrules  Turkey     zone1970.tab
Antarctica  CET      EST      GMT        Iceland      Kwajalein  NZ        PRC         UCT        zone.tab
Arctic      Chile    EST5EDT  GMT0       Indian       Libya      NZ-CHAT   PST8PDT     Universal  Zulu
Asia        CST6CDT  Etc      GMT-0      Iran         MET        Pacific   right       US
Atlantic    Cuba     Europe   GMT+0      iso3166.tab  Mexico     Poland    ROC         UTC
Australia   EET      Factory  Greenwich  Israel       MST        Portugal  ROK         WET

This means that the example in the original ticket now works.

>>> settings.TIME_ZONE
'America/Chicago'
>>> import pytz
>>> pytz.timezone(settings.TIME_ZONE)
<DstTzInfo 'America/Chicago' LMT-1 day, 18:09:00 STD>
>>>

On this basis can we now close this ticket (worksforme?)

comment:11 by Mariusz Felisiak, 4 years ago

Resolution: invalid
Status: assignedclosed

David, Thanks for checking this.

Note: See TracTickets for help on using tickets.
Back to Top