diff --git a/python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/PKG-INFO b/python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/PKG-INFO similarity index 58% rename from python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/PKG-INFO rename to python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/PKG-INFO index 1c79c9de946c..12aa93e3e284 100644 --- a/python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/PKG-INFO +++ b/python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: MarkupSafe -Version: 0.18 +Version: 0.23 Summary: Implements a XML/HTML/XHTML Markup safe string for Python Home-page: http://github.com/mitsuhiko/markupsafe Author: Armin Ronacher @@ -29,6 +29,9 @@ Description: MarkupSafe >>> soft_unicode(Markup('foo')) Markup(u'foo') + HTML Representations + -------------------- + Objects can customize their HTML markup equivalent by overriding the `__html__` function: @@ -41,6 +44,9 @@ Description: MarkupSafe >>> Markup(Foo()) Markup(u'Nice') + Silent Escapes + -------------- + Since MarkupSafe 0.10 there is now also a separate escape function called `escape_silent` that returns an empty string for `None` for consistency with other systems that return empty strings for `None` @@ -58,6 +64,48 @@ Description: MarkupSafe def escape(cls, s): return cls(escape(s)) + New-Style String Formatting + --------------------------- + + Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and + 3.x are now fully supported. Previously the escape behavior of those + functions was spotty at best. The new implementations operates under the + following algorithm: + + 1. if an object has an ``__html_format__`` method it is called as + replacement for ``__format__`` with the format specifier. It either + has to return a string or markup object. + 2. if an object has an ``__html__`` method it is called. + 3. otherwise the default format system of Python kicks in and the result + is HTML escaped. + + Here is how you can implement your own formatting:: + + class User(object): + + def __init__(self, id, username): + self.id = id + self.username = username + + def __html_format__(self, format_spec): + if format_spec == 'link': + return Markup('{1}').format( + self.id, + self.__html__(), + ) + elif format_spec: + raise ValueError('Invalid format spec') + return self.__html__() + + def __html__(self): + return Markup('{0}').format(self.username) + + And to format that user: + + >>> user = User(1, 'foo') + >>> Markup('

User: {0:link}').format(user) + Markup(u'

User: foo') + Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment diff --git a/python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/SOURCES.txt b/python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/SOURCES.txt similarity index 100% rename from python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/SOURCES.txt rename to python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/SOURCES.txt diff --git a/python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/dependency_links.txt b/python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/dependency_links.txt similarity index 100% rename from python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/dependency_links.txt rename to python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/dependency_links.txt diff --git a/python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/installed-files.txt b/python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/installed-files.txt similarity index 100% rename from python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/installed-files.txt rename to python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/installed-files.txt diff --git a/python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/not-zip-safe b/python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/not-zip-safe similarity index 100% rename from python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/not-zip-safe rename to python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/not-zip-safe diff --git a/python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/top_level.txt b/python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/top_level.txt similarity index 100% rename from python/ext-libs/MarkupSafe-0.18-py2.7.egg-info/top_level.txt rename to python/ext-libs/MarkupSafe-0.23-py2.7.egg-info/top_level.txt diff --git a/python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/PKG-INFO b/python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/PKG-INFO similarity index 92% rename from python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/PKG-INFO rename to python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/PKG-INFO index 0deccb48b7cc..f938617c0500 100644 --- a/python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/PKG-INFO +++ b/python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: OWSLib -Version: 0.8.6 +Version: 0.8.8 Summary: OGC Web Service utility library Home-page: https://geopython.github.io/OWSLib Author: Tom Kralidis @@ -97,6 +97,18 @@ Description: OWSLib Service for the Web (CSW), Web Processing Service (WPS), and Web Map Tile Service (WMTS). Some of those are beta quality. + + Logging + ------- + OWSLib logs messages to the 'owslib' named python logger. You may + configure your application to use the log messages like so: + + >>> import logging + >>> owslib_log = logging.getLogger('owslib') + >>> # Add formatting and handlers as needed + >>> owslib_log.setLevel(logging.DEBUG) + + Support ------- diff --git a/python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/SOURCES.txt b/python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/SOURCES.txt similarity index 95% rename from python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/SOURCES.txt rename to python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/SOURCES.txt index 67c3295d1679..ea58bb7945f3 100644 --- a/python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/SOURCES.txt +++ b/python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/SOURCES.txt @@ -8,6 +8,7 @@ LICENSE.txt MANIFEST.in README.txt VERSION.txt +requirements-2.6.txt requirements-dev.txt requirements.txt setup.cfg @@ -56,6 +57,4 @@ owslib/swe/sensor/sml.py owslib/waterml/__init__.py owslib/waterml/wml.py owslib/waterml/wml10.py -owslib/waterml/wml11.py -tests/__init__.py -tests/utils.py \ No newline at end of file +owslib/waterml/wml11.py \ No newline at end of file diff --git a/python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/dependency_links.txt b/python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/dependency_links.txt similarity index 100% rename from python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/dependency_links.txt rename to python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/dependency_links.txt diff --git a/python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/installed-files.txt b/python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/installed-files.txt similarity index 96% rename from python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/installed-files.txt rename to python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/installed-files.txt index da9df2ede4f7..19f407adc28b 100644 --- a/python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/installed-files.txt +++ b/python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/installed-files.txt @@ -1,5 +1,3 @@ -../tests/utils.py -../tests/__init__.py ../owslib/sos.py ../owslib/etree.py ../owslib/wms.py @@ -40,8 +38,6 @@ ../owslib/swe/observation/sos200.py ../owslib/swe/observation/sos100.py ../owslib/swe/observation/__init__.py -../tests/utils.pyc -../tests/__init__.pyc ../owslib/sos.pyc ../owslib/etree.pyc ../owslib/wms.pyc diff --git a/python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/requires.txt b/python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/requires.txt similarity index 100% rename from python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/requires.txt rename to python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/requires.txt diff --git a/python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/top_level.txt b/python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/top_level.txt similarity index 53% rename from python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/top_level.txt rename to python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/top_level.txt index aecd71bdeb18..3908eeb1eb24 100644 --- a/python/ext-libs/OWSLib-0.8.6-py2.7.egg-info/top_level.txt +++ b/python/ext-libs/OWSLib-0.8.8-py2.7.egg-info/top_level.txt @@ -1,2 +1 @@ -tests owslib diff --git a/python/ext-libs/markupsafe/__init__.py b/python/ext-libs/markupsafe/__init__.py index 25f00d3a4f27..275540154ea5 100644 --- a/python/ext-libs/markupsafe/__init__.py +++ b/python/ext-libs/markupsafe/__init__.py @@ -9,8 +9,10 @@ :license: BSD, see LICENSE for more details. """ import re +import string +from collections import Mapping from markupsafe._compat import text_type, string_types, int_types, \ - unichr, PY2 + unichr, iteritems, PY2 __all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent'] @@ -41,7 +43,7 @@ class Markup(text_type): >>> class Foo(object): ... def __html__(self): ... return 'foo' - ... + ... >>> Markup(Foo()) Markup(u'foo') @@ -117,7 +119,8 @@ def rsplit(self, *args, **kwargs): rsplit.__doc__ = text_type.rsplit.__doc__ def splitlines(self, *args, **kwargs): - return list(map(self.__class__, text_type.splitlines(self, *args, **kwargs))) + return list(map(self.__class__, text_type.splitlines( + self, *args, **kwargs))) splitlines.__doc__ = text_type.splitlines.__doc__ def unescape(self): @@ -164,11 +167,11 @@ def escape(cls, s): return cls(rv) return rv - def make_wrapper(name): + def make_simple_escaping_wrapper(name): orig = getattr(text_type, name) def func(self, *args, **kwargs): args = _escape_argspec(list(args), enumerate(args), self.escape) - #_escape_argspec(kwargs, kwargs.iteritems(), None) + _escape_argspec(kwargs, iteritems(kwargs), self.escape) return self.__class__(orig(self, *args, **kwargs)) func.__name__ = orig.__name__ func.__doc__ = orig.__doc__ @@ -178,7 +181,7 @@ def func(self, *args, **kwargs): 'title', 'lower', 'upper', 'replace', 'ljust', \ 'rjust', 'lstrip', 'rstrip', 'center', 'strip', \ 'translate', 'expandtabs', 'swapcase', 'zfill': - locals()[method] = make_wrapper(method) + locals()[method] = make_simple_escaping_wrapper(method) # new in python 2.5 if hasattr(text_type, 'partition'): @@ -191,13 +194,74 @@ def rpartition(self, sep): # new in python 2.6 if hasattr(text_type, 'format'): - format = make_wrapper('format') + def format(*args, **kwargs): + self, args = args[0], args[1:] + formatter = EscapeFormatter(self.escape) + kwargs = _MagicFormatMapping(args, kwargs) + return self.__class__(formatter.vformat(self, args, kwargs)) + + def __html_format__(self, format_spec): + if format_spec: + raise ValueError('Unsupported format specification ' + 'for Markup.') + return self # not in python 3 if hasattr(text_type, '__getslice__'): - __getslice__ = make_wrapper('__getslice__') + __getslice__ = make_simple_escaping_wrapper('__getslice__') - del method, make_wrapper + del method, make_simple_escaping_wrapper + + +class _MagicFormatMapping(Mapping): + """This class implements a dummy wrapper to fix a bug in the Python + standard library for string formatting. + + See http://bugs.python.org/issue13598 for information about why + this is necessary. + """ + + def __init__(self, args, kwargs): + self._args = args + self._kwargs = kwargs + self._last_index = 0 + + def __getitem__(self, key): + if key == '': + idx = self._last_index + self._last_index += 1 + try: + return self._args[idx] + except LookupError: + pass + key = str(idx) + return self._kwargs[key] + + def __iter__(self): + return iter(self._kwargs) + + def __len__(self): + return len(self._kwargs) + + +if hasattr(text_type, 'format'): + class EscapeFormatter(string.Formatter): + + def __init__(self, escape): + self.escape = escape + + def format_field(self, value, format_spec): + if hasattr(value, '__html_format__'): + rv = value.__html_format__(format_spec) + elif hasattr(value, '__html__'): + if format_spec: + raise ValueError('No format specification allowed ' + 'when formatting an object with ' + 'its __html__ method.') + rv = value.__html__() + else: + rv = string.Formatter.format_field(self, value, format_spec) + return text_type(self.escape(rv)) def _escape_argspec(obj, iterable, escape): diff --git a/python/ext-libs/markupsafe/_compat.py b/python/ext-libs/markupsafe/_compat.py index 29e4a3dac13f..62e5632ad8fd 100644 --- a/python/ext-libs/markupsafe/_compat.py +++ b/python/ext-libs/markupsafe/_compat.py @@ -17,8 +17,10 @@ string_types = (str,) unichr = chr int_types = (int,) + iteritems = lambda x: iter(x.items()) else: text_type = unicode string_types = (str, unicode) unichr = unichr int_types = (int, long) + iteritems = lambda x: x.iteritems() diff --git a/python/ext-libs/markupsafe/_speedups.so b/python/ext-libs/markupsafe/_speedups.so new file mode 100755 index 000000000000..b30d0f95decf Binary files /dev/null and b/python/ext-libs/markupsafe/_speedups.so differ diff --git a/python/ext-libs/markupsafe/tests.py b/python/ext-libs/markupsafe/tests.py index b34cc6ee0209..6369936296e2 100644 --- a/python/ext-libs/markupsafe/tests.py +++ b/python/ext-libs/markupsafe/tests.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import gc +import sys import unittest from markupsafe import Markup, escape, escape_silent from markupsafe._compat import text_type @@ -42,7 +43,7 @@ def __unicode__(self): __str__ = __unicode__ assert Markup(Foo()) == 'awesome' assert Markup('%s') % Foo() == \ - 'awesome' + 'awesome' def test_tuple_interpol(self): self.assertEqual(Markup('%s:%s') % ( @@ -65,6 +66,60 @@ def test_escaping(self): assert Markup("Foo & Bar").striptags() == "Foo & Bar" assert Markup("<test>").unescape() == "" + def test_formatting(self): + for actual, expected in ( + (Markup('%i') % 3.14, '3'), + (Markup('%.2f') % 3.14159, '3.14'), + (Markup('%s %s %s') % ('<', 123, '>'), '< 123 >'), + (Markup('{awesome}').format(awesome=''), + '<awesome>'), + (Markup('{0[1][bar]}').format([0, {'bar': ''}]), + '<bar/>'), + (Markup('{0[1][bar]}').format([0, {'bar': Markup('')}]), + '')): + assert actual == expected, "%r should be %r!" % (actual, expected) + + # This is new in 2.7 + if sys.version_info >= (2, 7): + def test_formatting_empty(self): + formatted = Markup('{}').format(0) + assert formatted == Markup('0') + + def test_custom_formatting(self): + class HasHTMLOnly(object): + def __html__(self): + return Markup('') + + class HasHTMLAndFormat(object): + def __html__(self): + return Markup('') + def __html_format__(self, spec): + return Markup('') + + assert Markup('{0}').format(HasHTMLOnly()) == Markup('') + assert Markup('{0}').format(HasHTMLAndFormat()) == Markup('') + + def test_complex_custom_formatting(self): + class User(object): + def __init__(self, id, username): + self.id = id + self.username = username + def __html_format__(self, format_spec): + if format_spec == 'link': + return Markup('{1}').format( + self.id, + self.__html__(), + ) + elif format_spec: + raise ValueError('Invalid format spec') + return self.__html__() + def __html__(self): + return Markup('{0}').format(self.username) + + user = User(1, 'foo') + assert Markup('

User: {0:link}').format(user) == \ + Markup('

User: foo') + def test_all_set(self): import markupsafe as markup for item in markup.__all__: diff --git a/python/ext-libs/owslib/__init__.py b/python/ext-libs/owslib/__init__.py index 37e9d6dd54d3..a02276f750fe 100644 --- a/python/ext-libs/owslib/__init__.py +++ b/python/ext-libs/owslib/__init__.py @@ -1 +1 @@ -__version__ = '0.8.6' +__version__ = '0.8.8' diff --git a/python/ext-libs/owslib/coverage/wcs100.py b/python/ext-libs/owslib/coverage/wcs100.py index 0a4de3658870..d54da2159d13 100644 --- a/python/ext-libs/owslib/coverage/wcs100.py +++ b/python/ext-libs/owslib/coverage/wcs100.py @@ -16,6 +16,9 @@ from owslib.crs import Crs import os, errno +import logging +from owslib.util import log + # function to save writing out WCS namespace in full each time def ns(tag): return '{http://www.opengis.net/wcs}'+tag @@ -105,12 +108,16 @@ def getCoverage(self, identifier=None, bbox=None, time=None, format = None, crs http://myhost/mywcs?SERVICE=WCS&REQUEST=GetCoverage&IDENTIFIER=TuMYrRQ4&VERSION=1.1.0&BOUNDINGBOX=-180,-90,180,90&TIME=2792-06-01T00:00:00.0&FORMAT=cf-netcdf """ - - self.log.debug('WCS 1.0.0 DEBUG: Parameters passed to GetCoverage: identifier=%s, bbox=%s, time=%s, format=%s, crs=%s, width=%s, height=%s, resx=%s, resy=%s, resz=%s, parameter=%s, method=%s, other_arguments=%s'%(identifier, bbox, time, format, crs, width, height, resx, resy, resz, parameter, method, str(kwargs))) + if log.isEnabledFor(logging.DEBUG): + log.debug('WCS 1.0.0 DEBUG: Parameters passed to GetCoverage: identifier=%s, bbox=%s, time=%s, format=%s, crs=%s, width=%s, height=%s, resx=%s, resy=%s, resz=%s, parameter=%s, method=%s, other_arguments=%s'%(identifier, bbox, time, format, crs, width, height, resx, resy, resz, parameter, method, str(kwargs))) - base_url = self.getOperationByName('GetCoverage').methods[method]['url'] + try: + base_url = next((m.get('url') for m in self.getOperationByName('GetCoverage').methods if m.get('type').lower() == method.lower())) + except StopIteration: + base_url = self.url - self.log.debug('WCS 1.0.0 DEBUG: base url of server: %s'%base_url) + if log.isEnabledFor(logging.DEBUG): + log.debug('WCS 1.0.0 DEBUG: base url of server: %s'%base_url) #process kwargs request = {'version': self.version, 'request': 'GetCoverage', 'service':'WCS'} @@ -144,7 +151,8 @@ def getCoverage(self, identifier=None, bbox=None, time=None, format = None, crs #encode and request data = urlencode(request) - self.log.debug('WCS 1.0.0 DEBUG: Second part of URL: %s'%data) + if log.isEnabledFor(logging.DEBUG): + log.debug('WCS 1.0.0 DEBUG: Second part of URL: %s'%data) u=openURL(base_url, data, method, self.cookies) @@ -159,7 +167,8 @@ def getOperationByName(self, name): if item.name == name: return item raise KeyError, "No operation named %s" % name - + + class OperationMetadata(object): """Abstraction for WCS metadata. Implements IMetadata. @@ -169,15 +178,15 @@ def __init__(self, elem): self.name = elem.tag.split('}')[1] #self.formatOptions = [f.text for f in elem.findall('{http://www.opengis.net/wcs/1.1/ows}Parameter/{http://www.opengis.net/wcs/1.1/ows}AllowedValues/{http://www.opengis.net/wcs/1.1/ows}Value')] - methods = [] + self.methods = [] for resource in elem.findall(ns('DCPType/')+ns('HTTP/')+ns('Get/')+ns('OnlineResource')): url = resource.attrib['{http://www.w3.org/1999/xlink}href'] - methods.append(('Get', {'url': url})) + self.methods.append({'type': 'Get', 'url': url}) for resource in elem.findall(ns('DCPType/')+ns('HTTP/')+ns('Post/')+ns('OnlineResource')): url = resource.attrib['{http://www.w3.org/1999/xlink}href'] - methods.append(('Post', {'url': url})) - self.methods = dict(methods) - + self.methods.append({'type': 'Post', 'url': url}) + + class ServiceIdentification(object): """ Abstraction for ServiceIdentification metadata """ def __init__(self,elem): @@ -186,7 +195,7 @@ def __init__(self,elem): self.version='1.0.0' self.service = testXMLValue(elem.find(ns('name'))) self.abstract = testXMLValue(elem.find(ns('description'))) - self.title = testXMLValue(elem.find(ns('name'))) + self.title = testXMLValue(elem.find(ns('label'))) self.keywords = [f.text for f in elem.findall(ns('keywords')+'/'+ns('keyword'))] #note: differs from 'rights' in interface self.fees=elem.find(ns('fees')).text diff --git a/python/ext-libs/owslib/coverage/wcs110.py b/python/ext-libs/owslib/coverage/wcs110.py index 7a7422fb1af5..39022f0ca482 100644 --- a/python/ext-libs/owslib/coverage/wcs110.py +++ b/python/ext-libs/owslib/coverage/wcs110.py @@ -20,6 +20,9 @@ from owslib.coverage import wcsdecoder from owslib.crs import Crs +import logging +from owslib.util import log + def ns(tag): return '{http://www.opengis.net/wcs/1.1}'+tag @@ -132,12 +135,15 @@ def getCoverage(self, identifier=None, bbox=None, time=None, format = None, stor if store = true, returns a coverages XML file if store = false, returns a multipart mime """ - self.log.debug('WCS 1.1.0 DEBUG: Parameters passed to GetCoverage: identifier=%s, bbox=%s, time=%s, format=%s, rangesubset=%s, gridbaseCRS=%s, gridtype=%s, gridCS=%s, gridorigin=%s, gridoffsets=%s, method=%s, other_arguments=%s'%(identifier, bbox, time, format, rangesubset, gridbaseCRS, gridtype, gridCS, gridorigin, gridoffsets, method, str(kwargs))) - + if log.isEnabledFor(logging.DEBUG): + log.debug('WCS 1.1.0 DEBUG: Parameters passed to GetCoverage: identifier=%s, bbox=%s, time=%s, format=%s, rangesubset=%s, gridbaseCRS=%s, gridtype=%s, gridCS=%s, gridorigin=%s, gridoffsets=%s, method=%s, other_arguments=%s'%(identifier, bbox, time, format, rangesubset, gridbaseCRS, gridtype, gridCS, gridorigin, gridoffsets, method, str(kwargs))) if method == 'Get': method='{http://www.opengis.net/wcs/1.1/ows}Get' - base_url = self.getOperationByName('GetCoverage').methods[method]['url'] + try: + base_url = next((m.get('url') for m in self.getOperationByName('GetCoverage').methods if m.get('type').lower() == method.lower())) + except StopIteration: + base_url = self.url #process kwargs diff --git a/python/ext-libs/owslib/coverage/wcsBase.py b/python/ext-libs/owslib/coverage/wcsBase.py index 81eb6cbb0641..8debc4610ae3 100644 --- a/python/ext-libs/owslib/coverage/wcsBase.py +++ b/python/ext-libs/owslib/coverage/wcsBase.py @@ -15,9 +15,6 @@ import cgi from StringIO import StringIO -#!/usr/bin/env python - -import logging class ServiceException(Exception): """WCS ServiceException @@ -48,9 +45,6 @@ def __new__(self,url, xml, cookies): obj=object.__new__(self) obj.__init__(url, xml, cookies) self.cookies=cookies - self.log = logging.getLogger(__name__) - consoleh = logging.StreamHandler() - self.log.addHandler(consoleh) self._describeCoverage = {} #cache for DescribeCoverage responses return obj @@ -64,19 +58,6 @@ def getDescribeCoverage(self, identifier): self._describeCoverage[identifier] = reader.read(self.url) return self._describeCoverage[identifier] - - def setLogLevel(self, level='CRITICAL'): - #accepts level = DEBUG, INFO, WARNING, ERROR, CRITICAL - if level=='DEBUG': - self.log.setLevel(logging.DEBUG) - elif level=='INFO': - self.log.setLevel(logging.INFO) - elif level=='WARNING': - self.log.setLevel(logging.WARNING) - elif level=='ERROR': - self.log.setLevel(logging.ERROR) - elif level=='CRITICAL': - self.log.setLevel(logging.CRITICAL) class WCSCapabilitiesReader(object): """Read and parses WCS capabilities document into a lxml.etree infoset @@ -114,7 +95,7 @@ def capabilities_url(self, service_url): urlqs = urlencode(tuple(qs)) return service_url.split('?')[0] + '?' + urlqs - def read(self, service_url): + def read(self, service_url, timeout=30): """Get and parse a WCS capabilities document, returning an elementtree tree @@ -128,7 +109,7 @@ def read(self, service_url): req = Request(request) if self.cookies is not None: req.add_header('Cookie', self.cookies) - u = urlopen(req) + u = urlopen(req, timeout=timeout) return etree.fromstring(u.read()) def readString(self, st): @@ -187,7 +168,7 @@ def descCov_url(self, service_url): urlqs = urlencode(tuple(qs)) return service_url.split('?')[0] + '?' + urlqs - def read(self, service_url): + def read(self, service_url, timeout=30): """Get and parse a Describe Coverage document, returning an elementtree tree @@ -201,7 +182,7 @@ def read(self, service_url): req = Request(request) if self.cookies is not None: req.add_header('Cookie', self.cookies) - u = urlopen(req) + u = urlopen(req, timeout=timeout) return etree.fromstring(u.read()) diff --git a/python/ext-libs/owslib/crs.py b/python/ext-libs/owslib/crs.py index 28f2e8ce0229..bda0de3aff64 100644 --- a/python/ext-libs/owslib/crs.py +++ b/python/ext-libs/owslib/crs.py @@ -1812,3 +1812,12 @@ def getcodeurn(self): (self.authority or ""), (self.version or ""), (self.code or "")) + + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.getcodeurn() == other.getcodeurn() + else: + return False + + def __repr__(self): + return self.getcodeurn() diff --git a/python/ext-libs/owslib/csw.py b/python/ext-libs/owslib/csw.py index ce2f4bcca40f..80ec92534a8d 100644 --- a/python/ext-libs/owslib/csw.py +++ b/python/ext-libs/owslib/csw.py @@ -14,6 +14,9 @@ import random from urllib import urlencode from urllib2 import urlopen + +from owslib.util import OrderedDict + from owslib.etree import etree from owslib import fes from owslib import util @@ -22,7 +25,7 @@ from owslib.fgdc import Metadata from owslib.dif import DIF from owslib.namespaces import Namespaces -from owslib.util import cleanup_namespaces, bind_url +from owslib.util import cleanup_namespaces, bind_url, add_namespaces # default variables outputformat = 'application/xml' @@ -234,7 +237,7 @@ def getrecords(self, qtype=None, keywords=[], typenames='csw:Record', propertyna self.results['nextrecord'] = int(util.testXMLValue(val, True)) # process list of matching records - self.records = {} + self.records = OrderedDict() self._parserecords(outputschema, esn) @@ -253,7 +256,7 @@ def getrecordbyid(self, id=[], esn='full', outputschema=namespaces['csw'], forma """ - # construct request + # construct request data = { 'service': self.service, 'version': self.version, @@ -261,16 +264,16 @@ def getrecordbyid(self, id=[], esn='full', outputschema=namespaces['csw'], forma 'outputFormat': format, 'outputSchema': outputschema, 'elementsetname': esn, - 'id': '', + 'id': ','.join(id), } - self.request = '%s%s%s' % (bind_url(self.url), urlencode(data), ','.join(id)) + self.request = '%s%s' % (bind_url(self.url), urlencode(data)) self._invoke() - + if self.exceptionreport is None: self.results = {} - self.records = {} + self.records = OrderedDict() self._parserecords(outputschema, esn) def getrecords2(self, constraints=[], sortby=None, typenames='csw:Record', esn='summary', outputschema=namespaces['csw'], format=outputformat, startposition=0, maxrecords=10, cql=None, xml=None, resulttype='results'): @@ -359,7 +362,7 @@ def getrecords2(self, constraints=[], sortby=None, typenames='csw:Record', esn=' self.results['nextrecord'] = None # process list of matching records - self.records = {} + self.records = OrderedDict() self._parserecords(outputschema, esn) @@ -472,6 +475,13 @@ def harvest(self, source, resourcetype, resourceformat=None, harvestinterval=Non self._parsetransactionsummary() self._parseinsertresult() + def get_operation_by_name(self, name): + """Return a named operation""" + for item in self.operations: + if item.name.lower() == name.lower(): + return item + raise KeyError, "No operation named %s" % name + def getService_urls(self, service_string=None): """ @@ -576,10 +586,37 @@ def _invoke(self): if isinstance(self.request, basestring): # GET KVP self.response = urlopen(self.request, timeout=self.timeout).read() else: + xml_post_url = self.url + # Get correct POST URL based on Operation list. + # If skip_caps=True, then self.operations has not been set, so use + # default URL. + if hasattr(self, 'operations'): + for op in self.operations: + post_verbs = filter(lambda x: x.get('type').lower() == 'post', op.methods) + if len(post_verbs) > 1: + # Filter by constraints. We must match a PostEncoding of "XML" + try: + xml_post_url = next(x for x in filter(list, ([pv.get('url') for const in pv.get('constraints') if const.name.lower() == "postencoding" and 'xml' in map(lambda x: x.lower(), const.values)] for pv in post_verbs)))[0] + except StopIteration: + # Well, just use the first one. + xml_post_url = post_verbs[0].get('url') + elif len(post_verbs) == 1: + xml_post_url = post_verbs[0].get('url') + self.request = cleanup_namespaces(self.request) - self.request = util.xml2string(etree.tostring(self.request)) + # Add any namespaces used in the "typeNames" attribute of the + # csw:Query element to the query's xml namespaces. + for query in self.request.findall(util.nspath_eval('csw:Query', namespaces)): + ns = query.get("typeNames", None) + if ns is not None: + # Pull out "gmd" from something like "gmd:MD_Metadata" from the list + # of typenames + ns_keys = [x.split(':')[0] for x in ns.split(' ')] + self.request = add_namespaces(self.request, ns_keys) + + self.request = util.element_to_string(self.request, encoding='utf-8') - self.response = util.http_post(self.url, self.request, self.lang, self.timeout) + self.response = util.http_post(xml_post_url, self.request, self.lang, self.timeout) # parse result see if it's XML self._exml = etree.parse(StringIO.StringIO(self.response)) @@ -664,7 +701,7 @@ def __init__(self, record): val = record.find(util.nspath_eval('dc:relation', namespaces)) self.relation = util.testXMLValue(val) - val = record.find(util.nspath_eval('dc:temporal', namespaces)) + val = record.find(util.nspath_eval('dct:temporal', namespaces)) self.temporal = util.testXMLValue(val) self.uris = [] # list of dicts diff --git a/python/ext-libs/owslib/feature/__init__.py b/python/ext-libs/owslib/feature/__init__.py index 5f4f5a3c0ba6..5a9b224b8b11 100644 --- a/python/ext-libs/owslib/feature/__init__.py +++ b/python/ext-libs/owslib/feature/__init__.py @@ -9,19 +9,7 @@ from urllib import urlencode import logging - -try: - hdlr = logging.FileHandler('/tmp/owslibwfs.log') -except: - import tempfile - f=tempfile.NamedTemporaryFile(prefix='owslib.wfs-', delete=False) - hdlr = logging.FileHandler(f.name) - -log = logging.getLogger(__name__) -formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') -hdlr.setFormatter(formatter) -log.addHandler(hdlr) -log.setLevel(logging.DEBUG) +from owslib.util import log class WebFeatureService_: """Base class for WebFeatureService implementations""" @@ -31,14 +19,14 @@ def getBBOXKVP (self,bbox,typename): @param bbox: (minx,miny,maxx,maxy[,srs]) @type bbox: List - @param typename: feature name + @param typename: feature name @type typename: String @returns: String properly formated according to version and coordinate reference system """ srs = None - # srs of the bbox is specified in the bbox as fifth parameter + # srs of the bbox is specified in the bbox as fifth paramter if len(bbox) == 5: srs = self.getSRS(bbox[4],typename[0]) # take default srs @@ -64,41 +52,36 @@ def getBBOXKVP (self,bbox,typename): return "%s,%s,%s,%s,%s" % \ (bbox[0],bbox[1],bbox[2],bbox[3],srs.getcode()) - def getSRS(self,srsname,typename): + def getSRS(self, srsname, typename): """Returns None or Crs object for given name - @param typename: feature name + @param typename: feature name @type typename: String """ - if type(srsname) == type(""): + if not isinstance(srsname, Crs): srs = Crs(srsname) else: srs = srsname - srss = map(lambda crs: crs.getcodeurn(), - self.contents[typename].crsOptions) - - for s in srss: - s = Crs(s) - if srs.authority == s.authority and\ - srs.code == s.code: - if s.version and srs.version: - if s.version == srs.version: - idx = srss.index(s.getcodeurn()) - return self.contents[typename].crsOptions[idx] - else: - idx = srss.index(s.getcodeurn()) - return self.contents[typename].crsOptions[idx] - return None + try: + index = self.contents[typename].crsOptions.index(srs) + # Return the Crs string that was pulled directly from the + # GetCaps document (the 'id' attribute in the Crs object). + return self.contents[typename].crsOptions[index] + except ValueError: + options = ", ".join(map(lambda x: x.id, self.contents[typename].crsOptions)) + log.warning("Requested srsName '%s' not available for requested typename '%s'. \ + Options are: %s. " % (srs.getcode(), typename, options)) + return None def getGETGetFeatureRequest(self, typename=None, filter=None, bbox=None, featureid=None, featureversion=None, propertyname=None, maxfeatures=None,storedQueryID=None, storedQueryParams={}, - method='Get'): + outputFormat=None, method='Get'): """Formulate proper GetFeature request using KVP encoding ---------- typename : list List of typenames (string) - filter : string + filter : string XML-encoded OGC filter expression. bbox : tuple (left, bottom, right, top) in the feature type's coordinates == (minx, miny, maxx, maxy) @@ -112,6 +95,8 @@ def getGETGetFeatureRequest(self, typename=None, filter=None, bbox=None, feature Maximum number of features to be returned. method : string Qualified name of the HTTP DCP method to use. + outputFormat: string (optional) + Requested response format of the request. There are 3 different modes of use @@ -120,11 +105,11 @@ def getGETGetFeatureRequest(self, typename=None, filter=None, bbox=None, feature 3) featureid (direct access to known features) """ - base_url = self.getOperationByName('GetFeature').methods[method]['url'] + base_url = next((m.get('url') for m in self.getOperationByName('GetFeature').methods if m.get('type').lower() == method.lower())) base_url = base_url if base_url.endswith("?") else base_url+"?" - + request = {'service': 'WFS', 'version': self.version, 'request': 'GetFeature'} - + # check featureid if featureid: request['featureid'] = ','.join(featureid) @@ -135,16 +120,18 @@ def getGETGetFeatureRequest(self, typename=None, filter=None, bbox=None, feature if typename: typename = [typename] if type(typename) == type("") else typename request['typename'] = ','.join(typename) - if propertyname: + if propertyname: request['propertyname'] = ','.join(propertyname) - if featureversion: + if featureversion: request['featureversion'] = str(featureversion) - if maxfeatures: + if maxfeatures: request['maxfeatures'] = str(maxfeatures) - if storedQueryID: + if storedQueryID: request['storedQuery_id']=str(storedQueryID) for param in storedQueryParams: request[param]=storedQueryParams[param] + if outputFormat is not None: + request["outputFormat"] = outputFormat data = urlencode(request) diff --git a/python/ext-libs/owslib/feature/wfs100.py b/python/ext-libs/owslib/feature/wfs100.py index 30f5f67dfcde..9fb25e540c3a 100644 --- a/python/ext-libs/owslib/feature/wfs100.py +++ b/python/ext-libs/owslib/feature/wfs100.py @@ -10,13 +10,13 @@ from cStringIO import StringIO from urllib import urlencode from urllib2 import urlopen -import logging -from owslib.util import openURL, testXMLValue, extract_xml_list +from owslib.util import openURL, testXMLValue, extract_xml_list, ServiceException, xmltag_split from owslib.etree import etree from owslib.fgdc import Metadata from owslib.iso import MD_Metadata from owslib.crs import Crs from owslib.namespaces import Namespaces +from owslib.util import log n = Namespaces() WFS_NAMESPACE = n.get_namespace("wfs") @@ -44,10 +44,6 @@ def nspath(path, ns=WFS_NAMESPACE): return "/".join(components) -class ServiceException(Exception): - pass - - class WebFeatureService_1_0_0(object): """Abstraction for OGC Web Feature Service (WFS). @@ -66,9 +62,6 @@ def __new__(self,url, version, xml, parse_remote_metadata=False): """ obj=object.__new__(self) obj.__init__(url, version, xml, parse_remote_metadata) - self.log = logging.getLogger() - consoleh = logging.StreamHandler() - self.log.addHandler(consoleh) return obj def __getitem__(self,name): @@ -120,12 +113,12 @@ def _buildMetadata(self, parse_remote_metadata=False): self.exceptions = [f.text for f \ in self._capabilities.findall('Capability/Exception/Format')] - def getcapabilities(self): + def getcapabilities(self, timeout=30): """Request and return capabilities document from the WFS as a file-like object. NOTE: this is effectively redundant now""" reader = WFSCapabilitiesReader(self.version) - return urlopen(reader.capabilities_url(self.url)) + return urlopen(reader.capabilities_url(self.url), timeout=timeout) def items(self): '''supports dict-like items() access''' @@ -136,7 +129,7 @@ def items(self): def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, featureversion=None, propertyname=['*'], maxfeatures=None, - srsname=None, method='{http://www.opengis.net/wfs}Get'): + srsname=None, outputFormat=None, method='{http://www.opengis.net/wfs}Get'): """Request and return feature data as a file-like object. Parameters @@ -159,6 +152,9 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, Qualified name of the HTTP DCP method to use. srsname: string EPSG code to request the data in + outputFormat: string (optional) + Requested response format of the request. + There are 3 different modes of use @@ -166,9 +162,12 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, 2) typename and filter (more expressive) 3) featureid (direct access to known features) """ - base_url = self.getOperationByName('{http://www.opengis.net/wfs}GetFeature').methods[method]['url'] + try: + base_url = next((m.get('url') for m in self.getOperationByName('GetFeature').methods if m.get('type').lower() == method.lower())) + except StopIteration: + base_url = self.url request = {'service': 'WFS', 'version': self.version, 'request': 'GetFeature'} - + # check featureid if featureid: request['featureid'] = ','.join(featureid) @@ -188,13 +187,18 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, if featureversion: request['featureversion'] = str(featureversion) if maxfeatures: request['maxfeatures'] = str(maxfeatures) + if outputFormat is not None: + request["outputFormat"] = outputFormat + data = urlencode(request) + log.debug("Making request: %s?%s" % (base_url, data)) u = openURL(base_url, data, method) # check for service exceptions, rewrap, and return # We're going to assume that anything with a content-length > 32k # is data. We'll check anything smaller. + try: length = int(u.info()['Content-Length']) have_read = False @@ -206,12 +210,18 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, if length < 32000: if not have_read: data = u.read() - tree = etree.fromstring(data) - if tree.tag == "{%s}ServiceExceptionReport" % OGC_NAMESPACE: - se = tree.find(nspath('ServiceException', OGC_NAMESPACE)) - raise ServiceException, str(se.text).strip() - return StringIO(data) + try: + tree = etree.fromstring(data) + except BaseException: + # Not XML + return StringIO(data) + else: + if tree.tag == "{%s}ServiceExceptionReport" % OGC_NAMESPACE: + se = tree.find(nspath('ServiceException', OGC_NAMESPACE)) + raise ServiceException(str(se.text).strip()) + else: + return StringIO(data) else: if have_read: return StringIO(data) @@ -251,7 +261,7 @@ class ContentMetadata: Implements IMetadata. """ - def __init__(self, elem, parent, parse_remote_metadata=False): + def __init__(self, elem, parent, parse_remote_metadata=False, timeout=30): """.""" self.id = testXMLValue(elem.find(nspath('Name'))) self.title = testXMLValue(elem.find(nspath('Title'))) @@ -298,7 +308,7 @@ def __init__(self, elem, parent, parse_remote_metadata=False): if metadataUrl['url'] is not None and parse_remote_metadata: # download URL try: - content = urlopen(metadataUrl['url']) + content = urlopen(metadataUrl['url'], timeout=timeout) doc = etree.parse(content) if metadataUrl['type'] is not None: if metadataUrl['type'] == 'FGDC': @@ -310,6 +320,7 @@ def __init__(self, elem, parent, parse_remote_metadata=False): self.metadataUrls.append(metadataUrl) + class OperationMetadata: """Abstraction for WFS metadata. @@ -317,14 +328,13 @@ class OperationMetadata: """ def __init__(self, elem): """.""" - self.name = elem.tag + self.name = xmltag_split(elem.tag) # formatOptions self.formatOptions = [f.tag for f in elem.findall(nspath('ResultFormat/*'))] - methods = [] + self.methods = [] for verb in elem.findall(nspath('DCPType/HTTP/*')): url = verb.attrib['onlineResource'] - methods.append((verb.tag, {'url': url})) - self.methods = dict(methods) + self.methods.append({'type' : xmltag_split(verb.tag), 'url': url}) class WFSCapabilitiesReader(object): @@ -355,7 +365,7 @@ def capabilities_url(self, service_url): urlqs = urlencode(tuple(qs)) return service_url.split('?')[0] + '?' + urlqs - def read(self, url): + def read(self, url, timeout=30): """Get and parse a WFS capabilities document, returning an instance of WFSCapabilitiesInfoset @@ -363,9 +373,11 @@ def read(self, url): ---------- url : string The URL to the WFS capabilities document. + timeout : number + A timeout value (in seconds) for the request. """ request = self.capabilities_url(url) - u = urlopen(request) + u = urlopen(request, timeout=timeout) return etree.fromstring(u.read()) def readString(self, st): diff --git a/python/ext-libs/owslib/feature/wfs110.py b/python/ext-libs/owslib/feature/wfs110.py index 97f15896af52..590a8da444c7 100644 --- a/python/ext-libs/owslib/feature/wfs110.py +++ b/python/ext-libs/owslib/feature/wfs110.py @@ -11,7 +11,6 @@ from cStringIO import StringIO from urllib import urlencode from urllib2 import urlopen -import logging from owslib.util import openURL, testXMLValue, nspath_eval, ServiceException from owslib.etree import etree from owslib.fgdc import Metadata @@ -21,6 +20,7 @@ from owslib.crs import Crs from owslib.feature import WebFeatureService_ from owslib.namespaces import Namespaces +from owslib.util import log def get_namespaces(): n = Namespaces() @@ -33,8 +33,8 @@ class WebFeatureService_1_1_0(WebFeatureService_): Implements IWebFeatureService. """ def __new__(self,url, version, xml, parse_remote_metadata=False): - """ overridden __new__ method - + """ overridden __new__ method + @type url: string @param url: url of WFS capabilities document @type xml: string @@ -45,19 +45,16 @@ def __new__(self,url, version, xml, parse_remote_metadata=False): """ obj=object.__new__(self) obj.__init__(url, version, xml, parse_remote_metadata) - self.log = logging.getLogger() - consoleh = logging.StreamHandler() - self.log.addHandler(consoleh) return obj - + def __getitem__(self,name): ''' check contents dictionary to allow dict like access to service layers''' if name in self.__getattribute__('contents').keys(): return self.__getattribute__('contents')[name] else: raise KeyError, "No content named %s" % name - - + + def __init__(self, url, version, xml=None, parse_remote_metadata=False): """Initialize.""" self.url = url @@ -70,7 +67,7 @@ def __init__(self, url, version, xml=None, parse_remote_metadata=False): else: self._capabilities = reader.read(self.url) self._buildMetadata(parse_remote_metadata) - + def _buildMetadata(self, parse_remote_metadata=False): '''set up capabilities metadata objects: ''' @@ -89,43 +86,43 @@ def _buildMetadata(self, parse_remote_metadata=False): val = self._capabilities.find(util.nspath_eval('ogc:Filter_Capabilities', namespaces)) self.filters=FilterCapabilities(val) - #serviceContents metadata: our assumption is that services use a top-level - #layer as a metadata organizer, nothing more. - - self.contents={} + #serviceContents metadata: our assumption is that services use a top-level + #layer as a metadata organizer, nothing more. + + self.contents={} features = self._capabilities.findall(nspath_eval('wfs:FeatureTypeList/wfs:FeatureType', namespaces)) for feature in features: cm=ContentMetadata(feature, parse_remote_metadata) - self.contents[cm.id]=cm - + self.contents[cm.id]=cm + #exceptions self.exceptions = [f.text for f \ in self._capabilities.findall('Capability/Exception/Format')] - - def getcapabilities(self): - """Request and return capabilities document from the WFS as a + + def getcapabilities(self, timeout=30): + """Request and return capabilities document from the WFS as a file-like object. NOTE: this is effectively redundant now""" reader = WFSCapabilitiesReader(self.version) - return urlopen(reader.capabilities_url(self.url)) - + return urlopen(reader.capabilities_url(self.url), timeout=timeout) + def items(self): '''supports dict-like items() access''' items=[] for item in self.contents: items.append((item,self.contents[item])) return items - + def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, featureversion=None, propertyname=['*'], maxfeatures=None, - srsname=None, method='Get'): + srsname=None, outputFormat=None, method='Get'): """Request and return feature data as a file-like object. - + Parameters ---------- typename : list List of typenames (string) - filter : string + filter : string XML-encoded OGC filter expression. bbox : tuple (left, bottom, right, top) in the feature type's coordinates. @@ -141,7 +138,9 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, Qualified name of the HTTP DCP method to use. srsname: string EPSG code to request the data in - + outputFormat: string (optional) + Requested response format of the request. + There are 3 different modes of use 1) typename and bbox (simple spatial query). It is assumed, that @@ -149,27 +148,25 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, 2) typename and filter (more expressive) 3) featureid (direct access to known features) """ - base_url = self.getOperationByName('GetFeature').methods[method]['url'] + try: + base_url = next((m.get('url') for m in self.getOperationByName('GetFeature').methods if m.get('type').lower() == method.lower())) + except StopIteration: + base_url = self.url request = {'service': 'WFS', 'version': self.version, 'request': 'GetFeature'} - srs_func = None - - if type(typename) == type(""): - typename=[typename] - - if srsname: - # check, if desired SRS is supported by the service - if typename: - - # convert srsname string to Crs object - srsnameobj = self.getSRS(srsname,typename[0]) - - if srsname: - # set the srsname string with propper function - # (getcode or getcodeurn) - request['srsname'] = srsnameobj.encoding == "urn" and\ - srsnameobj.getcodeurn() or srsnameobj.getcode() + + if not isinstance(typename, list): + typename = [typename] + + if srsname is not None: + # check, if desired SRS is supported by the service for this typename + if typename is not None: + # convert srsname string to Crs object found in GetCaps + srsnameobj = self.getSRS(srsname, typename[0]) + if srsnameobj is not None: + request['srsname'] = srsnameobj.id else: - raise util.ServiceException, "SRSNAME %s not supported" % srsname + options = ", ".join(map(lambda x: x.id, self.contents[typename[0]].crsOptions)) + raise ServiceException("SRSNAME %s not supported. Options: %s" % (srsname, options)) else: request['srsname'] = str(srsname) @@ -179,25 +176,31 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, # bbox elif bbox and typename: - - request["bbox"] = self.getBBOXKVP(bbox,typename) + request["bbox"] = self.getBBOXKVP(bbox, typename) # or filter elif filter and typename: request['filter'] = str(filter) - - + assert len(typename) > 0 request['typename'] = ','.join(typename) - - if propertyname: + + if propertyname is not None: + if not isinstance(propertyname, list): + propertyname = [propertyname] request['propertyname'] = ','.join(propertyname) - if featureversion: request['featureversion'] = str(featureversion) - if maxfeatures: request['maxfeatures'] = str(maxfeatures) + + if featureversion is not None: + request['featureversion'] = str(featureversion) + if maxfeatures is not None: + request['maxfeatures'] = str(maxfeatures) + if outputFormat is not None: + request["outputFormat"] = outputFormat data = urlencode(request) + log.debug("Making request: %s?%s" % (base_url, data)) u = openURL(base_url, data, method) - + # check for service exceptions, rewrap, and return # We're going to assume that anything with a content-length > 32k # is data. We'll check anything smaller. @@ -208,16 +211,22 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, data = u.read() have_read = True length = len(data) - + if length < 32000: if not have_read: data = u.read() - tree = etree.fromstring(data) - if tree.tag == "{%s}ServiceExceptionReport" % namespaces["ogc"]: - se = tree.find(nspath_eval('ServiceException', namespaces["ogc"])) - raise util.ServiceException, str(se.text).strip() - return StringIO(data) + try: + tree = etree.fromstring(data) + except BaseException: + # Not XML + return StringIO(data) + else: + if tree.tag == "{%s}ServiceExceptionReport" % namespaces["ogc"]: + se = tree.find(nspath_eval('ServiceException', namespaces["ogc"])) + raise ServiceException(str(se.text).strip()) + else: + return StringIO(data) else: if have_read: return StringIO(data) @@ -234,11 +243,11 @@ def getOperationByName(self, name): class ContentMetadata: """Abstraction for WFS metadata. - + Implements IMetadata. """ - def __init__(self, elem, parse_remote_metadata=False): + def __init__(self, elem, parse_remote_metadata=False, timeout=30): """.""" self.id = testXMLValue(elem.find(nspath_eval('wfs:Name', namespaces))) self.title = testXMLValue(elem.find(nspath_eval('wfs:Title', namespaces))) @@ -263,7 +272,7 @@ def __init__(self, elem, parse_remote_metadata=False): self.verbOptions = [op.text for op in elem.findall(nspath_eval('wfs:Operations/wfs:Operation', namespaces))] # output formats - self.verbOptions = [op.text for op in elem.findall(nspath_eval('wfs:OutputFormats/wfs:Format', namespaces))] + self.outputFormats = [op.text for op in elem.findall(nspath_eval('wfs:OutputFormats/wfs:Format', namespaces))] # MetadataURLs self.metadataUrls = [] @@ -276,7 +285,7 @@ def __init__(self, elem, parse_remote_metadata=False): if metadataUrl['url'] is not None and parse_remote_metadata: # download URL try: - content = urlopen(metadataUrl['url']) + content = urlopen(metadataUrl['url'], timeout=timeout) doc = etree.parse(content) if metadataUrl['type'] is not None: if metadataUrl['type'] == 'FGDC': @@ -321,7 +330,7 @@ def capabilities_url(self, service_url): urlqs = urlencode(tuple(qs)) return service_url.split('?')[0] + '?' + urlqs - def read(self, url): + def read(self, url, timeout=30): """Get and parse a WFS capabilities document, returning an instance of WFSCapabilitiesInfoset @@ -329,9 +338,11 @@ def read(self, url): ---------- url : string The URL to the WFS capabilities document. + timeout : number + A timeout value (in seconds) for the request. """ request = self.capabilities_url(url) - u = urlopen(request) + u = urlopen(request, timeout=timeout) return etree.fromstring(u.read()) def readString(self, st): @@ -343,4 +354,4 @@ def readString(self, st): if not isinstance(st, str): raise ValueError("String must be of type string, not %s" % type(st)) return etree.fromstring(st) - + diff --git a/python/ext-libs/owslib/feature/wfs200.py b/python/ext-libs/owslib/feature/wfs200.py index 9d57c4107186..d805ded9680f 100644 --- a/python/ext-libs/owslib/feature/wfs200.py +++ b/python/ext-libs/owslib/feature/wfs200.py @@ -21,19 +21,7 @@ from urllib2 import urlopen import logging - -try: - hdlr = logging.FileHandler('/tmp/owslibwfs.log') -except: - import tempfile - f=tempfile.NamedTemporaryFile(prefix='owslib.wfs-', delete=False) - hdlr = logging.FileHandler(f.name) - -log = logging.getLogger(__name__) -formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') -hdlr.setFormatter(formatter) -log.addHandler(hdlr) -log.setLevel(logging.DEBUG) +from owslib.util import log n = Namespaces() WFS_NAMESPACE = n.get_namespace("wfs20") @@ -65,9 +53,6 @@ def __new__(self,url, version, xml, parse_remote_metadata=False): """ obj=object.__new__(self) obj.__init__(url, version, xml, parse_remote_metadata) - self.log = logging.getLogger() - consoleh = logging.StreamHandler() - self.log.addHandler(consoleh) return obj def __getitem__(self,name): @@ -80,7 +65,8 @@ def __getitem__(self,name): def __init__(self, url, version, xml=None, parse_remote_metadata=False): """Initialize.""" - log.debug('building WFS %s'%url) + if log.isEnabledFor(logging.DEBUG): + log.debug('building WFS %s'%url) self.url = url self.version = version self._capabilities = None @@ -133,12 +119,12 @@ def _buildMetadata(self, parse_remote_metadata=False): self.exceptions = [f.text for f \ in self._capabilities.findall('Capability/Exception/Format')] - def getcapabilities(self): + def getcapabilities(self, timeout=30): """Request and return capabilities document from the WFS as a file-like object. NOTE: this is effectively redundant now""" reader = WFSCapabilitiesReader(self.version) - return urlopen(reader.capabilities_url(self.url)) + return urlopen(reader.capabilities_url(self.url), timeout=timeout) def items(self): '''supports dict-like items() access''' @@ -149,7 +135,7 @@ def items(self): def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, featureversion=None, propertyname=None, maxfeatures=None,storedQueryID=None, storedQueryParams={}, - method='Get'): + method='Get', timeout=30, outputFormat=None): """Request and return feature data as a file-like object. #TODO: NOTE: have changed property name from ['*'] to None - check the use of this in WFS 2.0 Parameters @@ -170,6 +156,10 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, Maximum number of features to be returned. method : string Qualified name of the HTTP DCP method to use. + timeout : number + A timeout value (in seconds) for the request. + outputFormat: string (optional) + Requested response format of the request. There are 3 different modes of use @@ -182,18 +172,18 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, if typename and type(typename) == type(""): typename = [typename] if method.upper() == "GET": - (url) = self.getGETGetFeatureRequest(typename, filter, bbox, featureid, - featureversion, propertyname, maxfeatures,storedQueryID, storedQueryParams) - log.debug('GetFeature WFS GET url %s'% url) + (url) = self.getGETGetFeatureRequest(typename, filter, bbox, featureid, + featureversion, propertyname, + maxfeatures, storedQueryID, + storedQueryParams, outputFormat) + if log.isEnabledFor(logging.DEBUG): + log.debug('GetFeature WFS GET url %s'% url) else: (url,data) = self.getPOSTGetFeatureRequest() - - if method == 'Post': - u = urlopen(base_url, data=data) - else: - u = urlopen(url) + # If method is 'Post', data will be None here + u = urlopen(url, data, timeout) # check for service exceptions, rewrap, and return # We're going to assume that anything with a content-length > 32k @@ -209,12 +199,18 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, if length < 32000: if not have_read: data = u.read() - tree = etree.fromstring(data) - if tree.tag == "{%s}ServiceExceptionReport" % OGC_NAMESPACE: - se = tree.find(nspath('ServiceException', OGC_NAMESPACE)) - raise ServiceException, str(se.text).strip() - return StringIO(data) + try: + tree = etree.fromstring(data) + except BaseException: + # Not XML + return StringIO(data) + else: + if tree.tag == "{%s}ServiceExceptionReport" % OGC_NAMESPACE: + se = tree.find(nspath('ServiceException', OGC_NAMESPACE)) + raise ServiceException(str(se.text).strip()) + else: + return StringIO(data) else: if have_read: return StringIO(data) @@ -222,8 +218,11 @@ def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, def getpropertyvalue(self, query=None, storedquery_id=None, valuereference=None, typename=None, method=nspath('Get'),**kwargs): - ''' the WFS GetPropertyValue method''' - base_url = self.getOperationByName('GetPropertyValue').methods[method]['url'] + ''' the WFS GetPropertyValue method''' + try: + base_url = next((m.get('url') for m in self.getOperationByName('GetPropertyValue').methods if m.get('type').lower() == method.lower())) + except StopIteration: + base_url = self.url request = {'service': 'WFS', 'version': self.version, 'request': 'GetPropertyValue'} if query: request['query'] = str(query) @@ -236,12 +235,12 @@ def getpropertyvalue(self, query=None, storedquery_id=None, valuereference=None, if kwargs: for kw in kwargs.keys(): request[kw]=str(kwargs[kw]) - data=urlencode(request) - u = urlopen(base_url + data) + encoded_request=urlencode(request) + u = urlopen(base_url + encoded_request) return u.read() - def _getStoredQueries(self): + def _getStoredQueries(self, timeout=30): ''' gets descriptions of the stored queries available on the server ''' sqs=[] #This method makes two calls to the WFS - one ListStoredQueries, and one DescribeStoredQueries. The information is then @@ -249,12 +248,15 @@ def _getStoredQueries(self): method=nspath('Get') #first make the ListStoredQueries response and save the results in a dictionary if form {storedqueryid:(title, returnfeaturetype)} - base_url = self.getOperationByName('ListStoredQueries').methods[method]['url'] + try: + base_url = next((m.get('url') for m in self.getOperationByName('ListStoredQueries').methods if m.get('type').lower() == method.lower())) + except StopIteration: + base_url = self.url + request = {'service': 'WFS', 'version': self.version, 'request': 'ListStoredQueries'} - data = urlencode(request) - u = urlopen(base_url + data) + encoded_request = urlencode(request) + u = urlopen(base_url + encoded_request, timeout=timeout) tree=etree.fromstring(u.read()) - base_url = self.getOperationByName('ListStoredQueries').methods[method]['url'] tempdict={} for sqelem in tree[:]: title=rft=id=None @@ -267,10 +269,13 @@ def _getStoredQueries(self): tempdict[id]=(title,rft) #store in temporary dictionary #then make the DescribeStoredQueries request and get the rest of the information about the stored queries - base_url = self.getOperationByName('DescribeStoredQueries').methods[method]['url'] + try: + base_url = next((m.get('url') for m in self.getOperationByName('DescribeStoredQueries').methods if m.get('type').lower() == method.lower())) + except StopIteration: + base_url = self.url request = {'service': 'WFS', 'version': self.version, 'request': 'DescribeStoredQueries'} - data = urlencode(request) - u = urlopen(base_url + data) + encoded_request = urlencode(request) + u = urlopen(base_url + encoded_request, timeout=timeout) tree=etree.fromstring(u.read()) tempdict2={} for sqelem in tree[:]: @@ -320,7 +325,7 @@ class ContentMetadata: Implements IMetadata. """ - def __init__(self, elem, parent, parse_remote_metadata=False): + def __init__(self, elem, parent, parse_remote_metadata=False, timeout=30): """.""" self.id = elem.find(nspath('Name',ns=WFS_NAMESPACE)).text self.title = elem.find(nspath('Title',ns=WFS_NAMESPACE)).text @@ -378,7 +383,7 @@ def __init__(self, elem, parent, parse_remote_metadata=False): if metadataUrl['url'] is not None and parse_remote_metadata: # download URL try: - content = urllib2.urlopen(metadataUrl['url']) + content = urllib2.urlopen(metadataUrl['url'], timeout=timeout) doc = etree.parse(content) try: # FGDC metadataUrl['metadata'] = Metadata(doc) @@ -418,7 +423,7 @@ def capabilities_url(self, service_url): urlqs = urlencode(tuple(qs)) return service_url.split('?')[0] + '?' + urlqs - def read(self, url): + def read(self, url, timeout=30): """Get and parse a WFS capabilities document, returning an instance of WFSCapabilitiesInfoset @@ -426,9 +431,11 @@ def read(self, url): ---------- url : string The URL to the WFS capabilities document. + timeout : number + A timeout value (in seconds) for the request. """ request = self.capabilities_url(url) - u = urlopen(request) + u = urlopen(request, timeout=timeout) return etree.fromstring(u.read()) def readString(self, st): diff --git a/python/ext-libs/owslib/fes.py b/python/ext-libs/owslib/fes.py index b9c4a641d947..5fb981630694 100644 --- a/python/ext-libs/owslib/fes.py +++ b/python/ext-libs/owslib/fes.py @@ -258,7 +258,7 @@ def __init__(self, propertyoperator, propertyname, literal, matchcase=True): self.matchcase = matchcase def toXML(self): node0 = etree.Element(util.nspath_eval(self.propertyoperator, namespaces)) - if self.matchcase is False: + if not self.matchcase: node0.set('matchCase', 'false') etree.SubElement(node0, util.nspath_eval('ogc:PropertyName', namespaces)).text = self.propertyname etree.SubElement(node0, util.nspath_eval('ogc:Literal', namespaces)).text = self.literal @@ -296,17 +296,20 @@ def __init__(self, propertyname, literal, matchcase=True): class PropertyIsLike(OgcExpression): """PropertyIsLike class""" - def __init__(self, propertyname, literal, escapeChar='\\', singleChar='_', wildCard='%'): + def __init__(self, propertyname, literal, escapeChar='\\', singleChar='_', wildCard='%', matchCase=True): self.propertyname = propertyname self.literal = literal self.escapeChar = escapeChar self.singleChar = singleChar self.wildCard = wildCard + self.matchCase = matchCase def toXML(self): node0 = etree.Element(util.nspath_eval('ogc:PropertyIsLike', namespaces)) node0.set('wildCard', self.wildCard) node0.set('singleChar', self.singleChar) node0.set('escapeChar', self.escapeChar) + if not self.matchCase: + node0.set('matchCase', 'false') etree.SubElement(node0, util.nspath_eval('ogc:PropertyName', namespaces)).text = self.propertyname etree.SubElement(node0, util.nspath_eval('ogc:Literal', namespaces)).text = self.literal return node0 diff --git a/python/ext-libs/owslib/iso.py b/python/ext-libs/owslib/iso.py index cf7fb1b0bce8..9c693255ed41 100644 --- a/python/ext-libs/owslib/iso.py +++ b/python/ext-libs/owslib/iso.py @@ -25,492 +25,629 @@ def get_namespaces(): class MD_Metadata(object): """ Process gmd:MD_Metadata """ - def __init__(self, md): - - if hasattr(md, 'getroot'): # standalone document - self.xml = etree.tostring(md.getroot()) - else: # part of a larger document - self.xml = etree.tostring(md) - - val = md.find(util.nspath_eval('gmd:fileIdentifier/gco:CharacterString', namespaces)) - self.identifier = util.testXMLValue(val) + def __init__(self, md=None): + + if md is None: + self.xml = None + self.identifier = None + self.parentidentifier = None + self.language = None + self.dataseturi = None + self.languagecode = None + self.datestamp = None + self.charset = None + self.hierarchy = None + self.contact = [] + self.datetimestamp = None + self.stdname = None + self.stdver = None + self.referencesystem = None + self.identification = None + self.serviceidentification = None + self.identificationinfo = [] + self.distribution = None + self.dataquality = None + else: + if hasattr(md, 'getroot'): # standalone document + self.xml = etree.tostring(md.getroot()) + else: # part of a larger document + self.xml = etree.tostring(md) - val = md.find(util.nspath_eval('gmd:parentIdentifier/gco:CharacterString', namespaces)) - self.parentidentifier = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:fileIdentifier/gco:CharacterString', namespaces)) + self.identifier = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:language/gco:CharacterString', namespaces)) - self.language = util.testXMLValue(val) - - val = md.find(util.nspath_eval('gmd:dataSetURI/gco:CharacterString', namespaces)) - self.dataseturi = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:parentIdentifier/gco:CharacterString', namespaces)) + self.parentidentifier = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:language/gmd:LanguageCode', namespaces)) - self.languagecode = util.testXMLValue(val) - - val = md.find(util.nspath_eval('gmd:dateStamp/gco:Date', namespaces)) - self.datestamp = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:language/gco:CharacterString', namespaces)) + self.language = util.testXMLValue(val) + + val = md.find(util.nspath_eval('gmd:dataSetURI/gco:CharacterString', namespaces)) + self.dataseturi = util.testXMLValue(val) - if not self.datestamp: - val = md.find(util.nspath_eval('gmd:dateStamp/gco:DateTime', namespaces)) + val = md.find(util.nspath_eval('gmd:language/gmd:LanguageCode', namespaces)) + self.languagecode = util.testXMLValue(val) + + val = md.find(util.nspath_eval('gmd:dateStamp/gco:Date', namespaces)) self.datestamp = util.testXMLValue(val) - self.charset = _testCodeListValue(md.find(util.nspath_eval('gmd:characterSet/gmd:MD_CharacterSetCode', namespaces))) - - self.hierarchy = _testCodeListValue(md.find(util.nspath_eval('gmd:hierarchyLevel/gmd:MD_ScopeCode', namespaces))) - - self.contact = [] - for i in md.findall(util.nspath_eval('gmd:contact/gmd:CI_ResponsibleParty', namespaces)): - o = CI_ResponsibleParty(i) - self.contact.append(o) - - val = md.find(util.nspath_eval('gmd:dateStamp/gco:DateTime', namespaces)) - self.datetimestamp = util.testXMLValue(val) - - val = md.find(util.nspath_eval('gmd:metadataStandardName/gco:CharacterString', namespaces)) - self.stdname = util.testXMLValue(val) + if not self.datestamp: + val = md.find(util.nspath_eval('gmd:dateStamp/gco:DateTime', namespaces)) + self.datestamp = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:metadataStandardVersion/gco:CharacterString', namespaces)) - self.stdver = util.testXMLValue(val) + self.charset = _testCodeListValue(md.find(util.nspath_eval('gmd:characterSet/gmd:MD_CharacterSetCode', namespaces))) + + self.hierarchy = _testCodeListValue(md.find(util.nspath_eval('gmd:hierarchyLevel/gmd:MD_ScopeCode', namespaces))) - val = md.find(util.nspath_eval('gmd:referenceSystemInfo/gmd:MD_ReferenceSystem', namespaces)) - if val is not None: - self.referencesystem = MD_ReferenceSystem(val) - else: - self.referencesystem = None + self.contact = [] + for i in md.findall(util.nspath_eval('gmd:contact/gmd:CI_ResponsibleParty', namespaces)): + o = CI_ResponsibleParty(i) + self.contact.append(o) + + val = md.find(util.nspath_eval('gmd:dateStamp/gco:DateTime', namespaces)) + self.datetimestamp = util.testXMLValue(val) + + val = md.find(util.nspath_eval('gmd:metadataStandardName/gco:CharacterString', namespaces)) + self.stdname = util.testXMLValue(val) - # TODO: merge .identificationinfo into .identification - #warnings.warn( - # 'the .identification and .serviceidentification properties will merge into ' - # '.identification being a list of properties. This is currently implemented ' - # 'in .identificationinfo. ' - # 'Please see https://github.com/geopython/OWSLib/issues/38 for more information', - # FutureWarning) + val = md.find(util.nspath_eval('gmd:metadataStandardVersion/gco:CharacterString', namespaces)) + self.stdver = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:identificationInfo/gmd:MD_DataIdentification', namespaces)) - val2 = md.find(util.nspath_eval('gmd:identificationInfo/srv:SV_ServiceIdentification', namespaces)) + val = md.find(util.nspath_eval('gmd:referenceSystemInfo/gmd:MD_ReferenceSystem', namespaces)) + if val is not None: + self.referencesystem = MD_ReferenceSystem(val) + else: + self.referencesystem = None - if val is not None: - self.identification = MD_DataIdentification(val, 'dataset') - self.serviceidentification = None - elif val2 is not None: - self.identification = MD_DataIdentification(val2, 'service') - self.serviceidentification = SV_ServiceIdentification(val2) - else: - self.identification = None - self.serviceidentification = None + # TODO: merge .identificationinfo into .identification + #warnings.warn( + # 'the .identification and .serviceidentification properties will merge into ' + # '.identification being a list of properties. This is currently implemented ' + # 'in .identificationinfo. ' + # 'Please see https://github.com/geopython/OWSLib/issues/38 for more information', + # FutureWarning) - self.identificationinfo = [] - for idinfo in md.findall(util.nspath_eval('gmd:identificationInfo', namespaces)): - val = list(idinfo)[0] - tagval = util.xmltag_split(val.tag) - if tagval == 'MD_DataIdentification': - self.identificationinfo.append(MD_DataIdentification(val, 'dataset')) - elif tagval == 'MD_ServiceIdentification': - self.identificationinfo.append(MD_DataIdentification(val, 'service')) - elif tagval == 'SV_ServiceIdentification': - self.identificationinfo.append(SV_ServiceIdentification(val)) + val = md.find(util.nspath_eval('gmd:identificationInfo/gmd:MD_DataIdentification', namespaces)) + val2 = md.find(util.nspath_eval('gmd:identificationInfo/srv:SV_ServiceIdentification', namespaces)) - val = md.find(util.nspath_eval('gmd:distributionInfo/gmd:MD_Distribution', namespaces)) + if val is not None: + self.identification = MD_DataIdentification(val, 'dataset') + self.serviceidentification = None + elif val2 is not None: + self.identification = MD_DataIdentification(val2, 'service') + self.serviceidentification = SV_ServiceIdentification(val2) + else: + self.identification = None + self.serviceidentification = None + + self.identificationinfo = [] + for idinfo in md.findall(util.nspath_eval('gmd:identificationInfo', namespaces)): + val = list(idinfo)[0] + tagval = util.xmltag_split(val.tag) + if tagval == 'MD_DataIdentification': + self.identificationinfo.append(MD_DataIdentification(val, 'dataset')) + elif tagval == 'MD_ServiceIdentification': + self.identificationinfo.append(MD_DataIdentification(val, 'service')) + elif tagval == 'SV_ServiceIdentification': + self.identificationinfo.append(SV_ServiceIdentification(val)) + + val = md.find(util.nspath_eval('gmd:distributionInfo/gmd:MD_Distribution', namespaces)) - if val is not None: - self.distribution = MD_Distribution(val) - else: - self.distribution = None - - val = md.find(util.nspath_eval('gmd:dataQualityInfo/gmd:DQ_DataQuality', namespaces)) - if val is not None: - self.dataquality = DQ_DataQuality(val) - else: - self.dataquality = None + if val is not None: + self.distribution = MD_Distribution(val) + else: + self.distribution = None + + val = md.find(util.nspath_eval('gmd:dataQualityInfo/gmd:DQ_DataQuality', namespaces)) + if val is not None: + self.dataquality = DQ_DataQuality(val) + else: + self.dataquality = None class CI_Date(object): """ process CI_Date """ - def __init__(self, md): - val = md.find(util.nspath_eval('gmd:date/gco:Date', namespaces)) - if val is not None: - self.date = util.testXMLValue(val) + def __init__(self, md=None): + if md is None: + self.date = None + self.type = None else: - val = md.find(util.nspath_eval('gmd:date/gco:DateTime', namespaces)) + val = md.find(util.nspath_eval('gmd:date/gco:Date', namespaces)) if val is not None: self.date = util.testXMLValue(val) else: - self.date = None + val = md.find(util.nspath_eval('gmd:date/gco:DateTime', namespaces)) + if val is not None: + self.date = util.testXMLValue(val) + else: + self.date = None - val = md.find(util.nspath_eval('gmd:dateType/gmd:CI_DateTypeCode', namespaces)) - self.type = _testCodeListValue(val) + val = md.find(util.nspath_eval('gmd:dateType/gmd:CI_DateTypeCode', namespaces)) + self.type = _testCodeListValue(val) class CI_ResponsibleParty(object): """ process CI_ResponsibleParty """ - def __init__(self, md): - val = md.find(util.nspath_eval('gmd:individualName/gco:CharacterString', namespaces)) - self.name = util.testXMLValue(val) + def __init__(self, md=None): + + if md is None: + self.name = None + self.organization = None + self.position = None + self.phone = None + self.fax = None + self.address = None + self.city = None + self.region = None + self.postcode = None + self.country = None + self.email = None + self.onlineresource = None + self.role = None + else: + val = md.find(util.nspath_eval('gmd:individualName/gco:CharacterString', namespaces)) + self.name = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:organisationName/gco:CharacterString', namespaces)) - self.organization = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:organisationName/gco:CharacterString', namespaces)) + self.organization = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:positionName/gco:CharacterString', namespaces)) - self.position = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:positionName/gco:CharacterString', namespaces)) + self.position = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:phone/gmd:CI_Telephone/gmd:voice/gco:CharacterString', namespaces)) + val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:phone/gmd:CI_Telephone/gmd:voice/gco:CharacterString', namespaces)) - self.phone = util.testXMLValue(val) + self.phone = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:phone/gmd:CI_Telephone/gmd:facsimile/gco:CharacterString', namespaces)) - self.fax = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:phone/gmd:CI_Telephone/gmd:facsimile/gco:CharacterString', namespaces)) + self.fax = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:deliveryPoint/gco:CharacterString', namespaces)) - self.address = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:deliveryPoint/gco:CharacterString', namespaces)) + self.address = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:city/gco:CharacterString', namespaces)) - self.city = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:city/gco:CharacterString', namespaces)) + self.city = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:administrativeArea/gco:CharacterString', namespaces)) - self.region = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:administrativeArea/gco:CharacterString', namespaces)) + self.region = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:postalCode/gco:CharacterString', namespaces)) - self.postcode = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:postalCode/gco:CharacterString', namespaces)) + self.postcode = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:country/gco:CharacterString', namespaces)) - self.country = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:country/gco:CharacterString', namespaces)) + self.country = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:electronicMailAddress/gco:CharacterString', namespaces)) - self.email = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:address/gmd:CI_Address/gmd:electronicMailAddress/gco:CharacterString', namespaces)) + self.email = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:onlineResource/gmd:CI_OnlineResource', namespaces)) - if val is not None: - self.onlineresource = CI_OnlineResource(val) - else: - self.onlineresource = None - - self.role = _testCodeListValue(md.find(util.nspath_eval('gmd:role/gmd:CI_RoleCode', namespaces))) + val = md.find(util.nspath_eval('gmd:contactInfo/gmd:CI_Contact/gmd:onlineResource/gmd:CI_OnlineResource', namespaces)) + if val is not None: + self.onlineresource = CI_OnlineResource(val) + else: + self.onlineresource = None + + self.role = _testCodeListValue(md.find(util.nspath_eval('gmd:role/gmd:CI_RoleCode', namespaces))) class MD_DataIdentification(object): """ process MD_DataIdentification """ - def __init__(self, md, identtype): - self.identtype = identtype - val = md.find(util.nspath_eval('gmd:citation/gmd:CI_Citation/gmd:title/gco:CharacterString', namespaces)) - self.title = util.testXMLValue(val) - - val = md.find(util.nspath_eval('gmd:citation/gmd:CI_Citation/gmd:alternateTitle/gco:CharacterString', namespaces)) - self.alternatetitle = util.testXMLValue(val) + def __init__(self, md=None, identtype=None): + if md is None: + self.identtype = None + self.title = None + self.alternatetitle = None + self.aggregationinfo = None + self.uricode = [] + self.uricodespace = [] + self.date = [] + self.datetype = [] + self.uselimitation = [] + self.accessconstraints = [] + self.classification = [] + self.otherconstraints = [] + self.securityconstraints = [] + self.useconstraints = [] + self.denominators = [] + self.distance = [] + self.uom = [] + self.resourcelanguage = [] + self.creator = None + self.publisher = None + self.originator = None + self.edition = None + self.abstract = None + self.purpose = None + self.status = None + self.contact = [] + self.keywords = [] + self.topiccategory = [] + self.supplementalinformation = None + self.extent = None + self.bbox = None + self.temporalextent_start = None + self.temporalextent_end = None + else: + self.identtype = identtype + val = md.find(util.nspath_eval('gmd:citation/gmd:CI_Citation/gmd:title/gco:CharacterString', namespaces)) + self.title = util.testXMLValue(val) + + val = md.find(util.nspath_eval('gmd:citation/gmd:CI_Citation/gmd:alternateTitle/gco:CharacterString', namespaces)) + self.alternatetitle = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:aggregationInfo', namespaces)) - self.aggregationinfo = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:aggregationInfo', namespaces)) + self.aggregationinfo = util.testXMLValue(val) - self.date = [] - self.datetype = [] - - for i in md.findall(util.nspath_eval('gmd:citation/gmd:CI_Citation/gmd:date/gmd:CI_Date', namespaces)): - self.date.append(CI_Date(i)) - - self.uselimitation = [] - for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_Constraints/gmd:useLimitation/gco:CharacterString', namespaces)): - val = util.testXMLValue(i) - if val is not None: - self.uselimitation.append(val) - - self.accessconstraints = [] - for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_LegalConstraints/gmd:accessConstraints/gmd:MD_RestrictionCode', namespaces)): - val = _testCodeListValue(i) - if val is not None: - self.accessconstraints.append(val) - - self.classification = [] - for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_LegalConstraints/gmd:accessConstraints/gmd:MD_ClassificationCode', namespaces)): - val = _testCodeListValue(i) - if val is not None: - self.classification.append(val) - - self.otherconstraints = [] - for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_LegalConstraints/gmd:otherConstraints/gco:CharacterString', namespaces)): - val = util.testXMLValue(i) - if val is not None: - self.otherconstraints.append(val) + self.uricode = [] + for i in md.findall(util.nspath_eval('gmd:citation/gmd:CI_Citation/gmd:identifier/gmd:RS_Identifier/gmd:code/gco:CharacterString', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.uricode.append(val) - self.securityconstraints = [] - for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_SecurityConstraints/gmd:useLimitation', namespaces)): - val = util.testXMLValue(i) - if val is not None: - self.securityconstraints.append(val) + self.uricodespace = [] + for i in md.findall(util.nspath_eval('gmd:citation/gmd:CI_Citation/gmd:identifier/gmd:RS_Identifier/gmd:codeSpace/gco:CharacterString', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.uricodespace.append(val) - self.useconstraints = [] - for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_LegalConstraints/gmd:useConstraints/gmd:MD_RestrictionCode', namespaces)): - val = _testCodeListValue(i) - if val is not None: - self.useconstraints.append(val) - - self.denominators = [] - for i in md.findall(util.nspath_eval('gmd:spatialResolution/gmd:MD_Resolution/gmd:equivalentScale/gmd:MD_RepresentativeFraction/gmd:denominator/gco:Integer', namespaces)): - val = util.testXMLValue(i) - if val is not None: - self.denominators.append(val) - - self.distance = [] - self.uom = [] - for i in md.findall(util.nspath_eval('gmd:spatialResolution/gmd:MD_Resolution/gmd:distance/gco:Distance', namespaces)): - val = util.testXMLValue(i) - if val is not None: - self.distance.append(val) - self.uom.append(i.get("uom")) - - self.resourcelanguage = [] - for i in md.findall(util.nspath_eval('gmd:language/gmd:LanguageCode', namespaces)): - val = _testCodeListValue(i) - if val is not None: - self.resourcelanguage.append(val) + self.date = [] + self.datetype = [] + + for i in md.findall(util.nspath_eval('gmd:citation/gmd:CI_Citation/gmd:date/gmd:CI_Date', namespaces)): + self.date.append(CI_Date(i)) + + self.uselimitation = [] + for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_Constraints/gmd:useLimitation/gco:CharacterString', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.uselimitation.append(val) + + self.accessconstraints = [] + for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_LegalConstraints/gmd:accessConstraints/gmd:MD_RestrictionCode', namespaces)): + val = _testCodeListValue(i) + if val is not None: + self.accessconstraints.append(val) + + self.classification = [] + for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_LegalConstraints/gmd:accessConstraints/gmd:MD_ClassificationCode', namespaces)): + val = _testCodeListValue(i) + if val is not None: + self.classification.append(val) + + self.otherconstraints = [] + for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_LegalConstraints/gmd:otherConstraints/gco:CharacterString', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.otherconstraints.append(val) - val = md.find(util.nspath_eval('gmd:pointOfContact/gmd:CI_ResponsibleParty/gmd:organisationName', namespaces)) - if val is not None: - val2 = val.find(util.nspath_eval('gmd:role/gmd:CI_RoleCode', namespaces)) - if val2 is not None: - clv = _testCodeListValue(val) - if clv == 'originator': - self.creator = util.testXMLValue(val) - elif clv == 'publisher': - self.publisher = util.testXMLValue(val) - elif clv == 'contributor': - self.originator = util.testXMLValue(val) - - val = md.find(util.nspath_eval('gmd:edition/gco:CharacterString', namespaces)) - self.edition = util.testXMLValue(val) - - val = md.find(util.nspath_eval('gmd:abstract/gco:CharacterString', namespaces)) - self.abstract = util.testXMLValue(val) - - val = md.find(util.nspath_eval('gmd:purpose/gco:CharacterString', namespaces)) - self.purpose = util.testXMLValue(val) - - self.status = _testCodeListValue(md.find(util.nspath_eval('gmd:status/gmd:MD_ProgressCode', namespaces))) - - self.contact = [] - for i in md.findall(util.nspath_eval('gmd:pointOfContact/gmd:CI_ResponsibleParty', namespaces)): - o = CI_ResponsibleParty(i) - self.contact.append(o) - - self.keywords = [] + self.securityconstraints = [] + for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_SecurityConstraints/gmd:useLimitation', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.securityconstraints.append(val) - for i in md.findall(util.nspath_eval('gmd:descriptiveKeywords', namespaces)): - mdkw = {} - mdkw['type'] = _testCodeListValue(i.find(util.nspath_eval('gmd:MD_Keywords/gmd:type/gmd:MD_KeywordTypeCode', namespaces))) + self.useconstraints = [] + for i in md.findall(util.nspath_eval('gmd:resourceConstraints/gmd:MD_LegalConstraints/gmd:useConstraints/gmd:MD_RestrictionCode', namespaces)): + val = _testCodeListValue(i) + if val is not None: + self.useconstraints.append(val) + + self.denominators = [] + for i in md.findall(util.nspath_eval('gmd:spatialResolution/gmd:MD_Resolution/gmd:equivalentScale/gmd:MD_RepresentativeFraction/gmd:denominator/gco:Integer', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.denominators.append(val) + + self.distance = [] + self.uom = [] + for i in md.findall(util.nspath_eval('gmd:spatialResolution/gmd:MD_Resolution/gmd:distance/gco:Distance', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.distance.append(val) + self.uom.append(i.get("uom")) + + self.resourcelanguage = [] + for i in md.findall(util.nspath_eval('gmd:language/gmd:LanguageCode', namespaces)): + val = _testCodeListValue(i) + if val is not None: + self.resourcelanguage.append(val) - mdkw['thesaurus'] = {} + val = md.find(util.nspath_eval('gmd:pointOfContact/gmd:CI_ResponsibleParty/gmd:organisationName', namespaces)) + if val is not None: + val2 = val.find(util.nspath_eval('gmd:role/gmd:CI_RoleCode', namespaces)) + if val2 is not None: + clv = _testCodeListValue(val) + if clv == 'originator': + self.creator = util.testXMLValue(val) + elif clv == 'publisher': + self.publisher = util.testXMLValue(val) + elif clv == 'contributor': + self.originator = util.testXMLValue(val) + + val = md.find(util.nspath_eval('gmd:edition/gco:CharacterString', namespaces)) + self.edition = util.testXMLValue(val) + + val = md.find(util.nspath_eval('gmd:abstract/gco:CharacterString', namespaces)) + self.abstract = util.testXMLValue(val) + + val = md.find(util.nspath_eval('gmd:purpose/gco:CharacterString', namespaces)) + self.purpose = util.testXMLValue(val) + + self.status = _testCodeListValue(md.find(util.nspath_eval('gmd:status/gmd:MD_ProgressCode', namespaces))) + + self.contact = [] + for i in md.findall(util.nspath_eval('gmd:pointOfContact/gmd:CI_ResponsibleParty', namespaces)): + o = CI_ResponsibleParty(i) + self.contact.append(o) + + self.keywords = [] - val = i.find(util.nspath_eval('gmd:thesaurusName/gmd:CI_Citation/gmd:title/gco:CharacterString', namespaces)) - mdkw['thesaurus']['title'] = util.testXMLValue(val) + for i in md.findall(util.nspath_eval('gmd:descriptiveKeywords', namespaces)): + mdkw = {} + mdkw['type'] = _testCodeListValue(i.find(util.nspath_eval('gmd:MD_Keywords/gmd:type/gmd:MD_KeywordTypeCode', namespaces))) - val = i.find(util.nspath_eval('gmd:thesaurusName/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:date/gco:Date', namespaces)) - mdkw['thesaurus']['date'] = util.testXMLValue(val) + mdkw['thesaurus'] = {} - val = i.find(util.nspath_eval('gmd:thesaurusName/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:dateType/gmd:CI_DateTypeCode', namespaces)) - mdkw['thesaurus']['datetype'] = util.testXMLValue(val) + val = i.find(util.nspath_eval('gmd:MD_Keywords/gmd:thesaurusName/gmd:CI_Citation/gmd:title/gco:CharacterString', namespaces)) + mdkw['thesaurus']['title'] = util.testXMLValue(val) - mdkw['keywords'] = [] + val = i.find(util.nspath_eval('gmd:MD_Keywords/gmd:thesaurusName/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:date/gco:Date', namespaces)) + mdkw['thesaurus']['date'] = util.testXMLValue(val) - for k in i.findall(util.nspath_eval('gmd:MD_Keywords/gmd:keyword', namespaces)): - val = k.find(util.nspath_eval('gco:CharacterString', namespaces)) - if val is not None: - val2 = util.testXMLValue(val) - if val2 is not None: - mdkw['keywords'].append(val2) + val = i.find(util.nspath_eval('gmd:MD_Keywords/gmd:thesaurusName/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:dateType/gmd:CI_DateTypeCode', namespaces)) + mdkw['thesaurus']['datetype'] = util.testXMLValue(val) - self.keywords.append(mdkw) + mdkw['keywords'] = [] - self.topiccategory = [] - for i in md.findall(util.nspath_eval('gmd:topicCategory/gmd:MD_TopicCategoryCode', namespaces)): - val = util.testXMLValue(i) - if val is not None: - self.topiccategory.append(val) - - val = md.find(util.nspath_eval('gmd:supplementalInformation/gco:CharacterString', namespaces)) - self.supplementalinformation = util.testXMLValue(val) - - # There may be multiple geographicElement, create an extent - # from the one containing either an EX_GeographicBoundingBox or EX_BoundingPolygon. - # The schema also specifies an EX_GeographicDescription. This is not implemented yet. - val = None - val2 = None - val3 = None - extents = md.findall(util.nspath_eval('gmd:extent', namespaces)) - extents.extend(md.findall(util.nspath_eval('srv:extent', namespaces))) - for extent in extents: - if val is None: - for e in extent.findall(util.nspath_eval('gmd:EX_Extent/gmd:geographicElement', namespaces)): - if e.find(util.nspath_eval('gmd:EX_GeographicBoundingBox', namespaces)) is not None or e.find(util.nspath_eval('gmd:EX_BoundingPolygon', namespaces)) is not None: - val = e - break - self.extent = EX_Extent(val) - self.bbox = self.extent.boundingBox # for backwards compatibility - - if val2 is None: - val2 = extent.find(util.nspath_eval('gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod/gml:beginPosition', namespaces)) - self.temporalextent_start = util.testXMLValue(val2) - - if val3 is None: - self.temporalextent_end = [] - val3 = extent.find(util.nspath_eval('gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod/gml:endPosition', namespaces)) - self.temporalextent_end = util.testXMLValue(val3) + for k in i.findall(util.nspath_eval('gmd:MD_Keywords/gmd:keyword', namespaces)): + val = k.find(util.nspath_eval('gco:CharacterString', namespaces)) + if val is not None: + val2 = util.testXMLValue(val) + if val2 is not None: + mdkw['keywords'].append(val2) + + self.keywords.append(mdkw) + + self.topiccategory = [] + for i in md.findall(util.nspath_eval('gmd:topicCategory/gmd:MD_TopicCategoryCode', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.topiccategory.append(val) + + val = md.find(util.nspath_eval('gmd:supplementalInformation/gco:CharacterString', namespaces)) + self.supplementalinformation = util.testXMLValue(val) + + # There may be multiple geographicElement, create an extent + # from the one containing either an EX_GeographicBoundingBox or EX_BoundingPolygon. + # The schema also specifies an EX_GeographicDescription. This is not implemented yet. + val = None + val2 = None + val3 = None + extents = md.findall(util.nspath_eval('gmd:extent', namespaces)) + extents.extend(md.findall(util.nspath_eval('srv:extent', namespaces))) + for extent in extents: + if val is None: + for e in extent.findall(util.nspath_eval('gmd:EX_Extent/gmd:geographicElement', namespaces)): + if e.find(util.nspath_eval('gmd:EX_GeographicBoundingBox', namespaces)) is not None or e.find(util.nspath_eval('gmd:EX_BoundingPolygon', namespaces)) is not None: + val = e + break + self.extent = EX_Extent(val) + self.bbox = self.extent.boundingBox # for backwards compatibility + + if val2 is None: + val2 = extent.find(util.nspath_eval('gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod/gml:beginPosition', namespaces)) + if val2 is None: + val2 = extent.find(util.nspath_eval('gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml32:TimePeriod/gml32:beginPosition', namespaces)) + self.temporalextent_start = util.testXMLValue(val2) + + if val3 is None: + val3 = extent.find(util.nspath_eval('gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod/gml:endPosition', namespaces)) + if val3 is None: + val3 = extent.find(util.nspath_eval('gmd:EX_Extent/gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml32:TimePeriod/gml32:endPosition', namespaces)) + self.temporalextent_end = util.testXMLValue(val3) class MD_Distributor(object): """ process MD_Distributor """ - def __init__(self, md): - self.contact = None - val = md.find(util.nspath_eval('gmd:MD_Distributor/gmd:distributorContact/gmd:CI_ResponsibleParty', namespaces)) - if val is not None: - self.contact = CI_ResponsibleParty(val) + def __init__(self, md=None): + if md is None: + self.contact = None + self.online = [] + else: + self.contact = None + val = md.find(util.nspath_eval('gmd:MD_Distributor/gmd:distributorContact/gmd:CI_ResponsibleParty', namespaces)) + if val is not None: + self.contact = CI_ResponsibleParty(val) - self.online = [] + self.online = [] - for ol in md.findall(util.nspath_eval('gmd:MD_Distributor/gmd:distributorTransferOptions/gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource', namespaces)): - self.online.append(CI_OnlineResource(ol)) + for ol in md.findall(util.nspath_eval('gmd:MD_Distributor/gmd:distributorTransferOptions/gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource', namespaces)): + self.online.append(CI_OnlineResource(ol)) class MD_Distribution(object): """ process MD_Distribution """ - def __init__(self, md): - val = md.find(util.nspath_eval('gmd:distributionFormat/gmd:MD_Format/gmd:name/gco:CharacterString', namespaces)) - self.format = util.testXMLValue(val) + def __init__(self, md=None): + if md is None: + self.format = None + self.version = None + self.distributor = [] + self.online = [] + pass + else: + val = md.find(util.nspath_eval('gmd:distributionFormat/gmd:MD_Format/gmd:name/gco:CharacterString', namespaces)) + self.format = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:distributionFormat/gmd:MD_Format/gmd:version/gco:CharacterString', namespaces)) - self.version = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:distributionFormat/gmd:MD_Format/gmd:version/gco:CharacterString', namespaces)) + self.version = util.testXMLValue(val) - self.distributor = [] - for dist in md.findall(util.nspath_eval('gmd:distributor', namespaces)): - self.distributor.append(MD_Distributor(dist)) + self.distributor = [] + for dist in md.findall(util.nspath_eval('gmd:distributor', namespaces)): + self.distributor.append(MD_Distributor(dist)) - self.online = [] + self.online = [] - for ol in md.findall(util.nspath_eval('gmd:transferOptions/gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource', namespaces)): - self.online.append(CI_OnlineResource(ol)) + for ol in md.findall(util.nspath_eval('gmd:transferOptions/gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource', namespaces)): + self.online.append(CI_OnlineResource(ol)) class DQ_DataQuality(object): ''' process DQ_DataQuality''' - def __init__(self, md): - - self.conformancetitle = [] - for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:title/gco:CharacterString', namespaces)): - val = util.testXMLValue(i) - if val is not None: - self.conformancetitle.append(val) - - self.conformancedate = [] - for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:date/gco:Date', namespaces)): - val = util.testXMLValue(i) - if val is not None: - self.conformancedate.append(val) - - self.conformancedatetype = [] - for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:dateType/gmd:CI_DateTypeCode', namespaces)): - val = _testCodeListValue(i) - if val is not None: - self.conformancedatetype.append(val) - - self.conformancedegree = [] - for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:pass/gco:Boolean', namespaces)): - val = util.testXMLValue(i) - if val is not None: - self.conformancedegree.append(val) - - val = md.find(util.nspath_eval('gmd:lineage/gmd:LI_Lineage/gmd:statement/gco:CharacterString', namespaces)) - self.lineage = util.testXMLValue(val) + def __init__(self, md=None): + if md is None: + self.conformancetitle = [] + self.conformancedate = [] + self.conformancedatetype = [] + self.conformancedegree = [] + self.lineage = None + self.specificationtitle = None + self.specificationdate = [] + else: + self.conformancetitle = [] + for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:title/gco:CharacterString', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.conformancetitle.append(val) + + self.conformancedate = [] + for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:date/gco:Date', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.conformancedate.append(val) + + self.conformancedatetype = [] + for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:dateType/gmd:CI_DateTypeCode', namespaces)): + val = _testCodeListValue(i) + if val is not None: + self.conformancedatetype.append(val) + + self.conformancedegree = [] + for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:pass/gco:Boolean', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.conformancedegree.append(val) + + val = md.find(util.nspath_eval('gmd:lineage/gmd:LI_Lineage/gmd:statement/gco:CharacterString', namespaces)) + self.lineage = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:title/gco:CharacterString', namespaces)) - self.specificationtitle = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:title/gco:CharacterString', namespaces)) + self.specificationtitle = util.testXMLValue(val) - self.specificationdate = [] - for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:date/gmd:CI_Date', namespaces)): - val = util.testXMLValue(i) - if val is not None: - self.specificationdate.append(val) + self.specificationdate = [] + for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:date/gmd:CI_Date', namespaces)): + val = util.testXMLValue(i) + if val is not None: + self.specificationdate.append(val) class SV_ServiceIdentification(object): """ process SV_ServiceIdentification """ - def __init__(self, md): - self.identtype = 'service' - val = md.find(util.nspath_eval('srv:serviceType/gco:LocalName', namespaces)) - self.type = util.testXMLValue(val) - - val = md.find(util.nspath_eval('srv:serviceTypeVersion/gco:CharacterString', namespaces)) - self.version = util.testXMLValue(val) + def __init__(self, md=None): + if md is None: + self.identtype = 'service' + self.type = None + self.version = None + self.fees = None + self.bbox = None + self.couplingtype + self.operations = [] + self.operateson = [] + else: + self.identtype = 'service' + val = md.find(util.nspath_eval('srv:serviceType/gco:LocalName', namespaces)) + self.type = util.testXMLValue(val) + + val = md.find(util.nspath_eval('srv:serviceTypeVersion/gco:CharacterString', namespaces)) + self.version = util.testXMLValue(val) - val = md.find(util.nspath_eval('srv:accessProperties/gmd:MD_StandardOrderProcess/gmd:fees/gco:CharacterString', namespaces)) - self.fees = util.testXMLValue(val) + val = md.find(util.nspath_eval('srv:accessProperties/gmd:MD_StandardOrderProcess/gmd:fees/gco:CharacterString', namespaces)) + self.fees = util.testXMLValue(val) - val = md.find(util.nspath_eval('srv:extent/gmd:EX_Extent', namespaces)) + val = md.find(util.nspath_eval('srv:extent/gmd:EX_Extent', namespaces)) - if val is not None: - self.bbox = EX_Extent(val) - else: - self.bbox = None - - self.couplingtype = _testCodeListValue(md.find(util.nspath_eval('gmd:couplingType/gmd:SV_CouplingType', namespaces))) - - self.operations = [] - - for i in md.findall(util.nspath_eval('srv:containsOperations', namespaces)): - tmp = {} - val = i.find(util.nspath_eval('srv:SV_OperationMetadata/srv:operationName/gco:CharacterString', namespaces)) - tmp['name'] = util.testXMLValue(val) - tmp['dcplist'] = [] - for d in i.findall(util.nspath_eval('srv:SV_OperationMetadata/srv:DCP', namespaces)): - tmp2 = _testCodeListValue(d.find(util.nspath_eval('srv:DCPList', namespaces))) - tmp['dcplist'].append(tmp2) - - tmp['connectpoint'] = [] - - for d in i.findall(util.nspath_eval('srv:SV_OperationMetadata/srv:connectPoint', namespaces)): - tmp3 = d.find(util.nspath_eval('gmd:CI_OnlineResource', namespaces)) - tmp['connectpoint'].append(CI_OnlineResource(tmp3)) - self.operations.append(tmp) - - self.operateson = [] - - for i in md.findall(util.nspath_eval('srv:operatesOn', namespaces)): - tmp = {} - tmp['uuidref'] = i.attrib.get('uuidref') - tmp['href'] = i.attrib.get(util.nspath_eval('xlink:href', namespaces)) - tmp['title'] = i.attrib.get(util.nspath_eval('xlink:title', namespaces)) - self.operateson.append(tmp) + if val is not None: + self.bbox = EX_Extent(val) + else: + self.bbox = None + + self.couplingtype = _testCodeListValue(md.find(util.nspath_eval('gmd:couplingType/gmd:SV_CouplingType', namespaces))) + + self.operations = [] + + for i in md.findall(util.nspath_eval('srv:containsOperations', namespaces)): + tmp = {} + val = i.find(util.nspath_eval('srv:SV_OperationMetadata/srv:operationName/gco:CharacterString', namespaces)) + tmp['name'] = util.testXMLValue(val) + tmp['dcplist'] = [] + for d in i.findall(util.nspath_eval('srv:SV_OperationMetadata/srv:DCP', namespaces)): + tmp2 = _testCodeListValue(d.find(util.nspath_eval('srv:DCPList', namespaces))) + tmp['dcplist'].append(tmp2) + + tmp['connectpoint'] = [] + + for d in i.findall(util.nspath_eval('srv:SV_OperationMetadata/srv:connectPoint', namespaces)): + tmp3 = d.find(util.nspath_eval('gmd:CI_OnlineResource', namespaces)) + tmp['connectpoint'].append(CI_OnlineResource(tmp3)) + self.operations.append(tmp) + + self.operateson = [] + + for i in md.findall(util.nspath_eval('srv:operatesOn', namespaces)): + tmp = {} + tmp['uuidref'] = i.attrib.get('uuidref') + tmp['href'] = i.attrib.get(util.nspath_eval('xlink:href', namespaces)) + tmp['title'] = i.attrib.get(util.nspath_eval('xlink:title', namespaces)) + self.operateson.append(tmp) class CI_OnlineResource(object): """ process CI_OnlineResource """ - def __init__(self,md): - val = md.find(util.nspath_eval('gmd:linkage/gmd:URL', namespaces)) - self.url = util.testXMLValue(val) + def __init__(self,md=None): + if md is None: + self.url = None + self.protocol = None + self.name = None + self.description = None + self.function = None + else: + val = md.find(util.nspath_eval('gmd:linkage/gmd:URL', namespaces)) + self.url = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:protocol/gco:CharacterString', namespaces)) - self.protocol = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:protocol/gco:CharacterString', namespaces)) + self.protocol = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:name/gco:CharacterString', namespaces)) - self.name = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:name/gco:CharacterString', namespaces)) + self.name = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:description/gco:CharacterString', namespaces)) - self.description = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:description/gco:CharacterString', namespaces)) + self.description = util.testXMLValue(val) - self.function = _testCodeListValue(md.find(util.nspath_eval('gmd:function/gmd:CI_OnLineFunctionCode', namespaces))) + self.function = _testCodeListValue(md.find(util.nspath_eval('gmd:function/gmd:CI_OnLineFunctionCode', namespaces))) class EX_GeographicBoundingBox(object): - def __init__(self, md): - val = md.find(util.nspath_eval('gmd:westBoundLongitude/gco:Decimal', namespaces)) - self.minx = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:eastBoundLongitude/gco:Decimal', namespaces)) - self.maxx = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:southBoundLatitude/gco:Decimal', namespaces)) - self.miny = util.testXMLValue(val) - val = md.find(util.nspath_eval('gmd:northBoundLatitude/gco:Decimal', namespaces)) - self.maxy = util.testXMLValue(val) + def __init__(self, md=None): + if md is None: + self.minx = None + self.maxx = None + self.miny = None + self.maxy = None + else: + val = md.find(util.nspath_eval('gmd:westBoundLongitude/gco:Decimal', namespaces)) + self.minx = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:eastBoundLongitude/gco:Decimal', namespaces)) + self.maxx = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:southBoundLatitude/gco:Decimal', namespaces)) + self.miny = util.testXMLValue(val) + val = md.find(util.nspath_eval('gmd:northBoundLatitude/gco:Decimal', namespaces)) + self.maxy = util.testXMLValue(val) class EX_Polygon(object): - def __init__(self, md): - linear_ring = md.find(util.nspath_eval('gml32:Polygon/gml32:exterior/gml32:LinearRing', namespaces)) - if linear_ring is not None: - self.exterior_ring = self._coordinates_for_ring(linear_ring) - - interior_ring_elements = md.findall(util.nspath_eval('gml32:Polygon/gml32:interior', namespaces)) - self.interior_rings = [] - for iring_element in interior_ring_elements: - linear_ring = iring_element.find(util.nspath_eval('gml32:LinearRing', namespaces)) - self.interior_rings.append(self._coordinates_for_ring(linear_ring)) + def __init__(self, md=None): + if md is None: + self.exterior_ring = None + self.interior_rings = [] + else: + linear_ring = md.find(util.nspath_eval('gml32:Polygon/gml32:exterior/gml32:LinearRing', namespaces)) + if linear_ring is not None: + self.exterior_ring = self._coordinates_for_ring(linear_ring) + + interior_ring_elements = md.findall(util.nspath_eval('gml32:Polygon/gml32:interior', namespaces)) + self.interior_rings = [] + for iring_element in interior_ring_elements: + linear_ring = iring_element.find(util.nspath_eval('gml32:LinearRing', namespaces)) + self.interior_rings.append(self._coordinates_for_ring(linear_ring)) def _coordinates_for_ring(self, linear_ring): coordinates = [] @@ -522,39 +659,51 @@ def _coordinates_for_ring(self, linear_ring): return coordinates class EX_GeographicBoundingPolygon(object): - def __init__(self, md): - val = md.find(util.nspath_eval('gmd:extentTypeCode', namespaces)) - self.is_extent = util.testXMLValue(val) - - md_polygons = md.findall(util.nspath_eval('gmd:polygon', namespaces)) - - self.polygons = [] - for val in md_polygons: - self.polygons.append(EX_Polygon(val)) + def __init__(self, md=None): + if md is None: + self.is_extent + self.polygons = [] + else: + val = md.find(util.nspath_eval('gmd:extentTypeCode', namespaces)) + self.is_extent = util.testXMLValue(val) + + md_polygons = md.findall(util.nspath_eval('gmd:polygon', namespaces)) + self.polygons = [] + for val in md_polygons: + self.polygons.append(EX_Polygon(val)) + class EX_Extent(object): """ process EX_Extent """ - def __init__(self, md): - self.boundingBox = None - self.boundingPolygon = None + def __init__(self, md=None): + if md is None: + self.boundingBox = None + self.boundingPolygon = None + self.description_code = None + else: + self.boundingBox = None + self.boundingPolygon = None - if md is not None: - bboxElement = md.find(util.nspath_eval('gmd:EX_GeographicBoundingBox', namespaces)) - if bboxElement is not None: - self.boundingBox = EX_GeographicBoundingBox(bboxElement) - - polygonElement = md.find(util.nspath_eval('gmd:EX_BoundingPolygon', namespaces)) - if polygonElement is not None: - self.boundingPolygon = EX_GeographicBoundingPolygon(polygonElement) - - val = md.find(util.nspath_eval('gmd:EX_GeographicDescription/gmd:geographicIdentifier/gmd:MD_Identifier/gmd:code/gco:CharacterString', namespaces)) - self.description_code = util.testXMLValue(val) + if md is not None: + bboxElement = md.find(util.nspath_eval('gmd:EX_GeographicBoundingBox', namespaces)) + if bboxElement is not None: + self.boundingBox = EX_GeographicBoundingBox(bboxElement) + + polygonElement = md.find(util.nspath_eval('gmd:EX_BoundingPolygon', namespaces)) + if polygonElement is not None: + self.boundingPolygon = EX_GeographicBoundingPolygon(polygonElement) + + val = md.find(util.nspath_eval('gmd:EX_GeographicDescription/gmd:geographicIdentifier/gmd:MD_Identifier/gmd:code/gco:CharacterString', namespaces)) + self.description_code = util.testXMLValue(val) class MD_ReferenceSystem(object): """ process MD_ReferenceSystem """ def __init__(self, md): - val = md.find(util.nspath_eval('gmd:referenceSystemIdentifier/gmd:RS_Identifier/gmd:code/gco:CharacterString', namespaces)) - self.code = util.testXMLValue(val) + if md is None: + pass + else: + val = md.find(util.nspath_eval('gmd:referenceSystemIdentifier/gmd:RS_Identifier/gmd:code/gco:CharacterString', namespaces)) + self.code = util.testXMLValue(val) def _testCodeListValue(elpath): """ get gco:CodeListValue_Type attribute, else get text content """ diff --git a/python/ext-libs/owslib/namespaces.py b/python/ext-libs/owslib/namespaces.py index 6037cdfc1ff8..cbf5a4df9216 100644 --- a/python/ext-libs/owslib/namespaces.py +++ b/python/ext-libs/owslib/namespaces.py @@ -114,10 +114,12 @@ def get_namespaces(self, keys=None): Example: -------- >>> ns = Namespaces() - >>> ns.get_namespaces(['csw','gmd']) - { 'csw' : http://www.opengis.net/cat/csw/2.0.2', 'gmd' : 'http://www.isotc211.org/2005/gmd' } - >>> ns.get_namespaces('csw') - { 'csw' : http://www.opengis.net/cat/csw/2.0.2' } + >>> x = ns.get_namespaces(['csw','gmd']) + >>> x == {'csw': 'http://www.opengis.net/cat/csw/2.0.2', 'gmd': 'http://www.isotc211.org/2005/gmd'} + True + >>> x = ns.get_namespaces('csw') + >>> x == {'csw': 'http://www.opengis.net/cat/csw/2.0.2'} + True >>> ns.get_namespaces() {...} """ @@ -130,7 +132,12 @@ def get_namespaces(self, keys=None): retval = {} for key in keys: - if key in self.namespace_dict.keys(): - retval[key] = self.namespace_dict[key] + retval[key] = self.get_namespace(key) - return retval \ No newline at end of file + return retval + + def get_namespace_from_url(self, url): + for k, v in self.namespace_dict.items(): + if v == url: + return k + return None diff --git a/python/ext-libs/owslib/ows.py b/python/ext-libs/owslib/ows.py index 318aadba3868..cb5ade533b5a 100644 --- a/python/ext-libs/owslib/ows.py +++ b/python/ext-libs/owslib/ows.py @@ -145,18 +145,34 @@ def __init__(self, infoset,namespace=DEFAULT_OWS_NAMESPACE): val = self._root.find(util.nspath('ServiceContact/ContactInfo/ContactInstructions', namespace)) self.instructions = util.testXMLValue(val) + +class Constraint(object): + def __init__(self, elem, namespace=DEFAULT_OWS_NAMESPACE): + self.name = elem.attrib.get('name') + self.values = [i.text for i in elem.findall(util.nspath('Value', namespace))] + self.values += [i.text for i in elem.findall(util.nspath('AllowedValues/Value', namespace))] + + def __repr__(self): + if self.values: + return "Constraint: %s - %s" % (self.name, self.values) + else: + return "Constraint: %s" % self.name + + class OperationsMetadata(object): """Initialize an OWS OperationMetadata construct""" - def __init__(self,elem,namespace=DEFAULT_OWS_NAMESPACE): + def __init__(self, elem, namespace=DEFAULT_OWS_NAMESPACE): self.name = elem.attrib['name'] self.formatOptions = ['text/xml'] - methods = [] parameters = [] - constraints = [] + self.methods = [] + self.constraints = [] for verb in elem.findall(util.nspath('DCP/HTTP/*', namespace)): - methods.append((util.xmltag_split(verb.tag), {'url': verb.attrib[util.nspath('href', XLINK_NAMESPACE)]})) - self.methods = dict(methods) + url = util.testXMLAttribute(verb, util.nspath('href', XLINK_NAMESPACE)) + if url is not None: + verb_constraints = [Constraint(conts, namespace) for conts in verb.findall(util.nspath('Constraint', namespace))] + self.methods.append({'constraints' : verb_constraints, 'type' : util.xmltag_split(verb.tag), 'url': url}) for parameter in elem.findall(util.nspath('Parameter', namespace)): if namespace == OWS_NAMESPACE_1_1_0: @@ -166,8 +182,8 @@ def __init__(self,elem,namespace=DEFAULT_OWS_NAMESPACE): self.parameters = dict(parameters) for constraint in elem.findall(util.nspath('Constraint', namespace)): - constraints.append((constraint.attrib['name'], {'values': [i.text for i in constraint.findall(util.nspath('Value', namespace))]})) - self.constraints = dict(constraints) + self.constraints.append(Constraint(constraint, namespace)) + class BoundingBox(object): """Initialize an OWS BoundingBox construct""" diff --git a/python/ext-libs/owslib/swe/common.py b/python/ext-libs/owslib/swe/common.py index b912b7014bb7..6f7df8d55fdd 100644 --- a/python/ext-libs/owslib/swe/common.py +++ b/python/ext-libs/owslib/swe/common.py @@ -83,7 +83,7 @@ def __init__(self, element): self.id = testXMLAttribute(element,"id") # string, optional # Elements - self.extension = [] # anyType, min=0, max=X + self.extention = [] # anyType, min=0, max=X class AbstractSWEIdentifiable(AbstractSWE): def __init__(self, element): @@ -407,4 +407,4 @@ def __init__(self, element): class BinaryEncoding(AbstractEncoding): def __init__(self, element): - raise NotImplementedError + raise NotImplementedError \ No newline at end of file diff --git a/python/ext-libs/owslib/swe/observation/sos100.py b/python/ext-libs/owslib/swe/observation/sos100.py index 3fcf66f7035a..776ca58fd24f 100644 --- a/python/ext-libs/owslib/swe/observation/sos100.py +++ b/python/ext-libs/owslib/swe/observation/sos100.py @@ -53,13 +53,19 @@ def __init__(self, url, version='1.0.0', xml=None, username=None, password=None) self._capabilities = reader.read(self.url) # Avoid building metadata if the response is an Exception - se = self._capabilities.find(nspath_eval('ows:ExceptionReport', namespaces)) - if se is not None: - raise ows.ExceptionReport(se) + if self._capabilities.tag == nspath_eval("ows:ExceptionReport", namespaces): + raise ows.ExceptionReport(self._capabilities) # build metadata objects self._build_metadata() + def getOperationByName(self, name): + """Return a named content item.""" + for item in self.operations: + if item.name == name: + return item + raise KeyError("No operation named %s" % name) + def _build_metadata(self): """ Set up capabilities metadata objects @@ -97,7 +103,10 @@ def describe_sensor(self, outputFormat=None, method='Get', **kwargs): - base_url = self.get_operation_by_name('DescribeSensor').methods[method]['url'] + try: + base_url = next((m.get('url') for m in self.getOperationByName('DescribeSensor').methods if m.get('type').lower() == method.lower())) + except StopIteration: + base_url = self.url request = {'service': 'SOS', 'version': self.version, 'request': 'DescribeSensor'} # Required Fields @@ -138,8 +147,11 @@ def get_observation(self, responseFormat=None, **kwargs : extra arguments anything else e.g. vendor specific parameters """ + try: + base_url = next((m.get('url') for m in self.getOperationByName('GetObservation').methods if m.get('type').lower() == method.lower())) + except StopIteration: + base_url = self.url - base_url = self.get_operation_by_name('GetObservation').methods[method]['url'] request = {'service': 'SOS', 'version': self.version, 'request': 'GetObservation'} # Required Fields diff --git a/python/ext-libs/owslib/swe/observation/sos200.py b/python/ext-libs/owslib/swe/observation/sos200.py index 131980837fb8..08ab1410bf17 100644 --- a/python/ext-libs/owslib/swe/observation/sos200.py +++ b/python/ext-libs/owslib/swe/observation/sos200.py @@ -62,6 +62,13 @@ def __init__(self, url, version='2.0.0', xml=None, username=None, password=None) # build metadata objects self._build_metadata() + def getOperationByName(self, name): + """Return a named content item.""" + for item in self.operations: + if item.name == name: + return item + raise KeyError("No operation named %s" % name) + def _build_metadata(self): """ Set up capabilities metadata objects @@ -100,8 +107,8 @@ def describe_sensor(self, outputFormat=None, **kwargs): try: - base_url = self.get_operation_by_name('DescribeSensor').methods[method]['url'] - except: + base_url = next((m.get('url') for m in self.getOperationByName('DescribeSensor').methods if m.get('type').lower() == method.lower())) + except StopIteration: base_url = self.url request = {'service': 'SOS', 'version': self.version, 'request': 'DescribeSensor'} diff --git a/python/ext-libs/owslib/swe/sensor/sml.py b/python/ext-libs/owslib/swe/sensor/sml.py index 135d3b2f734d..f220aceeb0cc 100644 --- a/python/ext-libs/owslib/swe/sensor/sml.py +++ b/python/ext-libs/owslib/swe/sensor/sml.py @@ -45,12 +45,14 @@ def __init__(self, element): self.capabilities = {} for cap in element.findall(nsp('sml:capabilities')): name = testXMLAttribute(cap, "name") - self.capabilities[name] = cap[0] + if name is not None: + self.capabilities[name] = cap[0] self.characteristics = {} for cha in element.findall(nsp('sml:characteristics')): name = testXMLAttribute(cha, "name") - self.characteristics[name] = cha[0] + if name is not None: + self.characteristics[name] = cha[0] def get_capabilities_by_name(self, name): """ @@ -314,4 +316,4 @@ def __init__(self, element): class ArrayLink(object): def __init__(self, element): - raise NotImplementedError("ArrayLink is not implemented in OWSLib (yet)") \ No newline at end of file + raise NotImplementedError("ArrayLink is not implemented in OWSLib (yet)") diff --git a/python/ext-libs/owslib/util.py b/python/ext-libs/owslib/util.py index 94ebfc8dae96..cbcfb2b7252f 100644 --- a/python/ext-libs/owslib/util.py +++ b/python/ext-libs/owslib/util.py @@ -12,6 +12,7 @@ from datetime import datetime import pytz from owslib.etree import etree +from owslib.namespaces import Namespaces import urlparse, urllib2 from urllib2 import urlopen, HTTPError, Request from urllib2 import HTTPPasswordMgrWithDefaultRealm @@ -20,6 +21,8 @@ import cgi from urllib import urlencode import re +from copy import deepcopy +import warnings """ @@ -30,14 +33,14 @@ class RereadableURL(StringIO,object): """ Class that acts like a combination of StringIO and url - has seek method and url headers etc """ def __init__(self, u): #get url headers etc from url - self.headers = u.headers + self.headers = u.headers #get file like seek, read methods from StringIO content=u.read() super(RereadableURL, self).__init__(content) class ServiceException(Exception): - #TODO: this should go in ows common module when refactored. + #TODO: this should go in ows common module when refactored. pass # http://stackoverflow.com/questions/6256183/combine-two-dictionaries-of-dictionaries-python @@ -91,7 +94,7 @@ def xml_to_dict(root, prefix=None, depth=1, diction=None): Return ======= Dictionary of (key,value); where key is the element tag stripped of namespace and cleaned up to be pep8 and - value is the inner-text of the element. Note that duplicate elements will be replaced by the last element of the + value is the inner-text of the element. Note that duplicate elements will be replaced by the last element of the same tag in the tree. """ ret = diction if diction is not None else dict() @@ -114,19 +117,19 @@ def xml_to_dict(root, prefix=None, depth=1, diction=None): return ret -def openURL(url_base, data, method='Get', cookies=None, username=None, password=None): +def openURL(url_base, data, method='Get', cookies=None, username=None, password=None, timeout=30): ''' function to open urls - wrapper around urllib2.urlopen but with additional checks for OGC service exceptions and url formatting, also handles cookies and simple user password authentication''' - url_base.strip() + url_base.strip() lastchar = url_base[-1] if lastchar not in ['?', '&']: if url_base.find('?') == -1: url_base = url_base + '?' else: url_base = url_base + '&' - + if username and password: # Provide login information in order to use the WMS server - # Create an OpenerDirector with support for Basic HTTP + # Create an OpenerDirector with support for Basic HTTP # Authentication... passman = HTTPPasswordMgrWithDefaultRealm() passman.add_password(None, url_base, username, password) @@ -138,7 +141,7 @@ def openURL(url_base, data, method='Get', cookies=None, username=None, password= #opener = urllib2.build_opener(urllib2.HTTPHandler(debuglevel=0)) #openit = opener.open openit = urlopen - + try: if method == 'Post': req = Request(url_base, data) @@ -152,17 +155,17 @@ def openURL(url_base, data, method='Get', cookies=None, username=None, password= req=Request(url_base + data) if cookies is not None: req.add_header('Cookie', cookies) - u = openit(req) + u = openit(req, timeout=timeout) except HTTPError, e: #Some servers may set the http header to 400 if returning an OGC service exception or 401 if unauthorised. if e.code in [400, 401]: raise ServiceException, e.read() else: raise e # check for service exceptions without the http header set - if u.info()['Content-Type'] in ['text/xml', 'application/xml']: + if ((u.info().has_key('Content-Type')) and (u.info()['Content-Type'] in ['text/xml', 'application/xml'])): #just in case 400 headers were not set, going to have to read the xml to see if it's an exception report. #wrap the url stram in a extended StringIO object so it's re-readable - u=RereadableURL(u) + u=RereadableURL(u) se_xml= u.read() se_tree = etree.fromstring(se_xml) serviceException=se_tree.find('{http://www.opengis.net/ows}Exception') @@ -171,7 +174,7 @@ def openURL(url_base, data, method='Get', cookies=None, username=None, password= if serviceException is not None: raise ServiceException, \ str(serviceException.text).strip() - u.seek(0) #return cursor to start of u + u.seek(0) #return cursor to start of u return u #default namespace for nspath is OWS common @@ -181,7 +184,7 @@ def nspath(path, ns=OWS_NAMESPACE): """ Prefix the given path with the given namespace identifier. - + Parameters ---------- @@ -216,6 +219,66 @@ def cleanup_namespaces(element): else: return etree.fromstring(etree.tostring(element)) + +def add_namespaces(root, ns_keys): + if isinstance(ns_keys, basestring): + ns_keys = [ns_keys] + + namespaces = Namespaces() + + ns_keys = map(lambda x: (x, namespaces.get_namespace(x)), ns_keys) + + if etree.__name__ != 'lxml.etree': + # We can just add more namespaces when not using lxml. + # We can't re-add an existing namespaces. Get a list of current + # namespaces in use + existing_namespaces = set() + for elem in root.getiterator(): + if elem.tag[0] == "{": + uri, tag = elem.tag[1:].split("}") + existing_namespaces.add(namespaces.get_namespace_from_url(uri)) + for key, link in ns_keys: + if link is not None and key not in existing_namespaces: + root.set("xmlns:%s" % key, link) + return root + else: + # lxml does not support setting xmlns attributes + # Update the elements nsmap with new namespaces + new_map = root.nsmap + for key, link in ns_keys: + if link is not None: + new_map[key] = link + # Recreate the root element with updated nsmap + new_root = etree.Element(root.tag, nsmap=new_map) + # Carry over attributes + for a, v in root.items(): + new_root.set(a, v) + # Carry over children + for child in root: + new_root.append(deepcopy(child)) + return new_root + + +def getXMLInteger(elem, tag): + """ + Return the text within the named tag as an integer. + + Raises an exception if the tag cannot be found or if its textual + value cannot be converted to an integer. + + Parameters + ---------- + + - elem: the element to search within + - tag: the name of the tag to look for + + """ + e = elem.find(tag) + if e is None: + raise ValueError('Missing %s in %s' % (tag, elem)) + return int(e.text.strip()) + + def testXMLValue(val, attrib=False): """ @@ -231,10 +294,10 @@ def testXMLValue(val, attrib=False): if val is not None: if attrib: return val.strip() - elif val.text: + elif val.text: return val.text.strip() else: - return None + return None else: return None @@ -258,7 +321,7 @@ def testXMLAttribute(element, attribute): def http_post(url=None, request=None, lang='en-US', timeout=10): """ - Invoke an HTTP POST request + Invoke an HTTP POST request Parameters ---------- @@ -302,6 +365,31 @@ def http_post(url=None, request=None, lang='en-US', timeout=10): return response + +def element_to_string(element, encoding=None): + """ + Returns a string from a XML object + + Parameters + ---------- + - xml: etree Element + - encoding (optional): encoding in string form. 'utf-8', 'ISO-8859-1', etc. + + """ + if encoding is None: + encoding = "ISO-8859-1" + + if etree.__name__ == 'lxml.etree': + if encoding in ['unicode', 'utf-8']: + return '\n%s' % \ + etree.tostring(element, encoding='unicode') + else: + return etree.tostring(element, encoding=encoding, xml_declaration=True) + else: + return '\n%s' % (encoding, + etree.tostring(element, encoding=encoding)) + + def xml2string(xml): """ @@ -313,6 +401,8 @@ def xml2string(xml): - xml: xml string """ + warnings.warn("DEPRECIATION WARNING! You should now use the 'element_to_string' method \ + The 'xml2string' method will be removed in a future version of OWSLib.") return '\n' + xml def xmlvalid(xml, xsd): @@ -350,7 +440,7 @@ def getNamespace(element): def build_get_url(base_url, params): ''' Utility function to build a full HTTP GET URL from the service base URL and a dictionary of HTTP parameters. ''' - + qs = [] if base_url.find('?') != -1: qs = cgi.parse_qsl(base_url.split('?')[1]) @@ -366,12 +456,12 @@ def build_get_url(base_url, params): def dump(obj, prefix=''): '''Utility function to print to standard output a generic object with all its attributes.''' - + print "%s %s : %s" % (prefix, obj.__class__, obj.__dict__) - + def getTypedValue(type, value): ''' Utility function to cast a string value to the appropriate XSD type. ''' - + if type=='boolean': return bool(value) elif type=='integer': @@ -414,7 +504,7 @@ def extract_time(element): def extract_xml_list(elements): """ -Some people don't have separate tags for their keywords and separate them with +Some people don't have seperate tags for their keywords and seperate them with a newline. This will extract out all of the keywords correctly. """ keywords = [re.split(r'[\n\r]+',f.text) for f in elements if f.text] @@ -442,3 +532,23 @@ def bind_url(url): elif url.find('&', -1) == -1: # like http://host/wms?foo=bar binder = '&' return '%s%s' % (url, binder) + +import logging +# Null logging handler +try: + # Python 2.7 + NullHandler = logging.NullHandler +except AttributeError: + # Python < 2.7 + class NullHandler(logging.Handler): + def emit(self, record): + pass +log = logging.getLogger('owslib') +log.addHandler(NullHandler()) + +# OrderedDict +try: # 2.7 + from collections import OrderedDict +except: # 2.6 + from ordereddict import OrderedDict + diff --git a/python/ext-libs/owslib/wcs.py b/python/ext-libs/owslib/wcs.py index fec1dbca9e4e..634c056a1292 100644 --- a/python/ext-libs/owslib/wcs.py +++ b/python/ext-libs/owslib/wcs.py @@ -18,7 +18,7 @@ import etree from coverage import wcs100, wcs110, wcsBase -def WebCoverageService(url, version=None, xml=None, cookies=None): +def WebCoverageService(url, version=None, xml=None, cookies=None, timeout=30): ''' wcs factory function, returns a version specific WebCoverageService object ''' if version is None: @@ -26,11 +26,11 @@ def WebCoverageService(url, version=None, xml=None, cookies=None): reader = wcsBase.WCSCapabilitiesReader() request = reader.capabilities_url(url) if cookies is None: - xml = urllib2.urlopen(request).read() + xml = urllib2.urlopen(request, timeout=timeout).read() else: req = urllib2.Request(request) req.add_header('Cookie', cookies) - xml=urllib2.urlopen(req) + xml=urllib2.urlopen(req, timeout=timeout) capabilities = etree.etree.fromstring(xml) version = capabilities.get('version') del capabilities diff --git a/python/ext-libs/owslib/wms.py b/python/ext-libs/owslib/wms.py index 0e5d1504ef6a..045c3880f1eb 100644 --- a/python/ext-libs/owslib/wms.py +++ b/python/ext-libs/owslib/wms.py @@ -20,7 +20,7 @@ from urllib import urlencode import warnings from etree import etree -from .util import openURL, testXMLValue, extract_xml_list +from .util import openURL, testXMLValue, extract_xml_list, xmltag_split from fgdc import Metadata from iso import MD_Metadata @@ -189,20 +189,23 @@ def getmap(self, layers=None, styles=None, srs=None, bbox=None, Example ------- - >>> img = wms.getmap(layers=['global_mosaic'], - ... styles=['visual'], - ... srs='EPSG:4326', - ... bbox=(-112,36,-106,41), - ... format='image/jpeg', - ... size=(300,250), - ... transparent=True, - ... ) - >>> out = open('example.jpg', 'wb') + >>> wms = WebMapService('http://giswebservices.massgis.state.ma.us/geoserver/wms', version='1.1.1') + >>> img = wms.getmap(layers=['massgis:GISDATA.SHORELINES_ARC'],\ + styles=[''],\ + srs='EPSG:4326',\ + bbox=(-70.8, 42, -70, 42.8),\ + size=(300, 300),\ + format='image/jpeg',\ + transparent=True) + >>> out = open('example.jpg.jpg', 'wb') >>> out.write(img.read()) >>> out.close() """ - base_url = self.getOperationByName('GetMap').methods[method]['url'] + try: + base_url = next((m.get('url') for m in self.getOperationByName('GetMap').methods if m.get('type').lower() == method.lower())) + except StopIteration: + base_url = self.url request = {'version': self.version, 'request': 'GetMap'} # check layers and styles @@ -312,7 +315,7 @@ class ContentMetadata: Implements IContentMetadata. """ - def __init__(self, elem, parent=None, index=0, parse_remote_metadata=False): + def __init__(self, elem, parent=None, index=0, parse_remote_metadata=False, timeout=30): if elem.tag != 'Layer': raise ValueError('%s should be a Layer' % (elem,)) @@ -474,7 +477,7 @@ def __init__(self, elem, parent=None, index=0, parse_remote_metadata=False): if metadataUrl['url'] is not None and parse_remote_metadata: # download URL try: - content = urllib2.urlopen(metadataUrl['url']) + content = urllib2.urlopen(metadataUrl['url'], timeout=timeout) doc = etree.parse(content) if metadataUrl['type'] is not None: if metadataUrl['type'] == 'FGDC': @@ -510,14 +513,14 @@ class OperationMetadata: """ def __init__(self, elem): """.""" - self.name = elem.tag + self.name = xmltag_split(elem.tag) # formatOptions self.formatOptions = [f.text for f in elem.findall('Format')] - methods = [] + self.methods = [] for verb in elem.findall('DCPType/HTTP/*'): url = verb.find('OnlineResource').attrib['{http://www.w3.org/1999/xlink}href'] - methods.append((verb.tag, {'url': url})) - self.methods = dict(methods) + self.methods.append({'type' : xmltag_split(verb.tag), 'url': url}) + class ContactMetadata: """Abstraction for contact details advertised in GetCapabilities. diff --git a/python/ext-libs/owslib/wmts.py b/python/ext-libs/owslib/wmts.py index ce2768d6d50f..a40233419563 100644 --- a/python/ext-libs/owslib/wmts.py +++ b/python/ext-libs/owslib/wmts.py @@ -26,15 +26,29 @@ """ -import cgi +import warnings +import urlparse import urllib2 from urllib import urlencode from etree import etree -from .util import openURL, testXMLValue +from .util import openURL, testXMLValue, getXMLInteger from fgdc import Metadata from iso import MD_Metadata from ows import ServiceProvider, ServiceIdentification, OperationsMetadata + +_WMTS_NS = '{http://www.opengis.net/wmts/1.0}' +_TILE_MATRIX_SET_LINK_TAG = _WMTS_NS + 'TileMatrixSetLink' +_TILE_MATRIX_SET_TAG = _WMTS_NS + 'TileMatrixSet' +_TILE_MATRIX_SET_LIMITS_TAG = _WMTS_NS + 'TileMatrixSetLimits' +_TILE_MATRIX_LIMITS_TAG = _WMTS_NS + 'TileMatrixLimits' +_TILE_MATRIX_TAG = _WMTS_NS + 'TileMatrix' +_MIN_TILE_ROW_TAG = _WMTS_NS + 'MinTileRow' +_MAX_TILE_ROW_TAG = _WMTS_NS + 'MaxTileRow' +_MIN_TILE_COL_TAG = _WMTS_NS + 'MinTileCol' +_MAX_TILE_COL_TAG = _WMTS_NS + 'MaxTileCol' + + class ServiceException(Exception): """WMTS ServiceException @@ -167,7 +181,46 @@ def items(self): items.append((item,self.contents[item])) return items - def buildTileRequest(self, layer=None, style=None, format=None, tilematrixset=None, tilematrix=None, row=None, column=None): + def buildTileRequest(self, layer=None, style=None, format=None, tilematrixset=None, tilematrix=None, row=None, column=None, **kwargs): + """Return the URL-encoded parameters for a GetTile request. + + Parameters + ---------- + layer : string + Content layer name. + style : string + Optional style name. Defaults to the first style defined for + the relevant layer in the GetCapabilities response. + format : string + Optional output image format, such as 'image/jpeg'. + Defaults to the first format defined for the relevant layer + in the GetCapabilities response. + tilematrixset : string + Optional name of tile matrix set to use. + Defaults to the first tile matrix set defined for the + relevant layer in the GetCapabilities response. + tilematrix : string + Name of the tile matrix to use. + row : integer + Row index of tile to request. + column : integer + Column index of tile to request. + **kwargs : extra arguments + anything else e.g. vendor specific parameters + + Example + ------- + >>> url = 'http://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi' + >>> wmts = WebMapTileService(url) + >>> wmts.buildTileRequest(layer='VIIRS_CityLights_2012', + ... tilematrixset='EPSG4326_500m', + ... tilematrix='6', + ... row=4, column=4) + 'SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&\ +LAYER=VIIRS_CityLights_2012&STYLE=default&TILEMATRIXSET=EPSG4326_500m&\ +TILEMATRIX=6&TILEROW=4&TILECOL=4&FORMAT=image%2Fjpeg' + + """ request = {'version': self.version, 'request': 'GetTile'} if (layer is None): @@ -177,9 +230,10 @@ def buildTileRequest(self, layer=None, style=None, format=None, tilematrixset=No if format is None: format = self[layer].formats[0] if tilematrixset is None: - tilematrixset = self[layer].tilematrixsets[0] + tilematrixset = sorted(self[layer].tilematrixsetlinks.keys())[0] if tilematrix is None: - raise ValueError("tilematrix (zoom level) is mandatory (cannot be None)") + msg = 'tilematrix (zoom level) is mandatory (cannot be None)' + raise ValueError(msg) if row is None: raise ValueError("row is mandatory (cannot be None)") if column is None: @@ -197,25 +251,80 @@ def buildTileRequest(self, layer=None, style=None, format=None, tilematrixset=No request.append(('TILECOL', str(column))) request.append(('FORMAT', format)) + for key, value in kwargs.iteritems(): + request.append(key, value) + data = urlencode(request, True) return data + def gettile(self, base_url=None, layer=None, style=None, format=None, tilematrixset=None, tilematrix=None, row=None, column=None, **kwargs): + """Return a tile from the WMTS. + + Returns the tile image as a file-like object. + + Parameters + ---------- + base_url : string + Optional URL for request submission. Defaults to the URL of + the GetTile operation as declared in the GetCapabilities + response. + layer : string + Content layer name. + style : string + Optional style name. Defaults to the first style defined for + the relevant layer in the GetCapabilities response. + format : string + Optional output image format, such as 'image/jpeg'. + Defaults to the first format defined for the relevant layer + in the GetCapabilities response. + tilematrixset : string + Optional name of tile matrix set to use. + Defaults to the first tile matrix set defined for the + relevant layer in the GetCapabilities response. + tilematrix : string + Name of the tile matrix to use. + row : integer + Row index of tile to request. + column : integer + Column index of tile to request. + **kwargs : extra arguments + anything else e.g. vendor specific parameters + + Example + ------- + >>> url = 'http://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi' + >>> wmts = WebMapTileService(url) + >>> img = wmts.gettile(layer='VIIRS_CityLights_2012',\ + tilematrixset='EPSG4326_500m',\ + tilematrix='6',\ + row=4, column=4) + >>> out = open('tile.jpg', 'wb') + >>> out.write(img.read()) + >>> out.close() - def gettile(self, base_url=None, layer=None, style=None, format=None, tilematrixset=None, tilematrix=None, row=None, column=None): - """Request a tile from a WMTS server """ - data = self.buildTileRequest(layer, style, format, tilematrixset, tilematrix, row, column) + data = self.buildTileRequest(layer, style, format, tilematrixset, tilematrix, row, column, **kwargs) if base_url is None: - base_url = self.getOperationByName('GetTile').methods['Get']['url'] - u = openURL(base_url, data, username = self.username, password = self.password) + base_url = self.url + try: + get_verbs = filter(lambda x: x.get('type').lower() == 'get', self.getOperationByName('GetTile').methods) + if len(get_verbs) > 1: + # Filter by constraints + base_url = next(x for x in filter(list, ([pv.get('url') for const in pv.get('constraints') if 'kvp' in map(lambda x: x.lower(), const.values)] for pv in get_verbs if pv.get('constraints'))))[0] + elif len(get_verbs) == 1: + base_url = get_verbs[0].get('url') + except StopIteration: + pass + u = openURL(base_url, data, username=self.username, + password=self.password) # check for service exceptions, and return if u.info()['Content-Type'] == 'application/vnd.ogc.se_xml': se_xml = u.read() se_tree = etree.fromstring(se_xml) - err_message = unicode(se_tree.find('ServiceException').text).strip() - raise ServiceException(err_message, se_xml) + err_message = unicode(se_tree.find('ServiceException').text) + raise ServiceException(err_message.strip(), se_xml) return u def getServiceXML(self): @@ -304,6 +413,93 @@ def __init__(self, elem): if layerRef.text is not None: self.layerRefs.append(layerRef.text) + +class TileMatrixLimits(object): + """ + Represents a WMTS TileMatrixLimits element. + + """ + def __init__(self, elem): + if elem.tag != _TILE_MATRIX_LIMITS_TAG: + raise ValueError('%s should be a TileMatrixLimits' % elem) + + tm = elem.find(_TILE_MATRIX_TAG) + if tm is None: + raise ValueError('Missing TileMatrix in %s' % elem) + self.tilematrix = tm.text.strip() + + self.mintilerow = getXMLInteger(elem, _MIN_TILE_ROW_TAG) + self.maxtilerow = getXMLInteger(elem, _MAX_TILE_ROW_TAG) + self.mintilecol = getXMLInteger(elem, _MIN_TILE_COL_TAG) + self.maxtilecol = getXMLInteger(elem, _MAX_TILE_COL_TAG) + + def __repr__(self): + fmt = ('') + return fmt.format(self=self) + + +class TileMatrixSetLink(object): + """ + Represents a WMTS TileMatrixSetLink element. + + """ + @staticmethod + def from_elements(link_elements): + """ + Return a list of TileMatrixSetLink instances derived from the + given list of XML elements. + + """ + # NB. The WMTS spec is contradictory re. the multiplicity + # relationships between Layer and TileMatrixSetLink, and + # TileMatrixSetLink and tileMatrixSet (URI). + # Try to figure out which model has been used by the server. + links = [] + for link_element in link_elements: + matrix_set_elements = link_element.findall(_TILE_MATRIX_SET_TAG) + if len(matrix_set_elements) == 0: + raise ValueError('Missing TileMatrixSet in %s' % link_element) + elif len(matrix_set_elements) > 1: + set_limits_elements = link_element.findall( + _TILE_MATRIX_SET_LIMITS_TAG) + if set_limits_elements: + raise ValueError('Multiple instances of TileMatrixSet' + ' plus TileMatrixSetLimits in %s' % + link_element) + for matrix_set_element in matrix_set_elements: + uri = matrix_set_element.text.strip() + links.append(TileMatrixSetLink(uri)) + else: + uri = matrix_set_elements[0].text.strip() + + tilematrixlimits = {} + path = '%s/%s' % (_TILE_MATRIX_SET_LIMITS_TAG, _TILE_MATRIX_LIMITS_TAG) + for limits_element in link_element.findall(path): + tml = TileMatrixLimits(limits_element) + if tml.tilematrix: + if tml.tilematrix in tilematrixlimits: + raise KeyError('TileMatrixLimits with tileMatrix "%s" already exists' % tml.tilematrix) + tilematrixlimits[tml.tilematrix] = tml + + links.append(TileMatrixSetLink(uri, tilematrixlimits)) + return links + + def __init__(self, tilematrixset, tilematrixlimits=None): + self.tilematrixset = tilematrixset + + if tilematrixlimits is None: + self.tilematrixlimits = {} + else: + self.tilematrixlimits = tilematrixlimits + + def __repr__(self): + fmt = ('') + return fmt.format(self=self) + + class ContentMetadata: """ Abstraction for WMTS layer metadata. @@ -340,7 +536,20 @@ def __init__(self, elem, parent=None, index=0, parse_remote_metadata=False): self.boundingBoxWGS84 = (ll[0],ll[1],ur[0],ur[1]) # TODO: there is probably some more logic here, and it should probably be shared code - self.tilematrixsets = [f.text.strip() for f in elem.findall('{http://www.opengis.net/wmts/1.0}TileMatrixSetLink/{http://www.opengis.net/wmts/1.0}TileMatrixSet')] + self._tilematrixsets = [f.text.strip() for f in + elem.findall(_TILE_MATRIX_SET_LINK_TAG + '/' + + _TILE_MATRIX_SET_TAG)] + + link_elements = elem.findall(_TILE_MATRIX_SET_LINK_TAG) + tile_matrix_set_links = TileMatrixSetLink.from_elements(link_elements) + self.tilematrixsetlinks = {} + for tmsl in tile_matrix_set_links: + if tmsl.tilematrixset: + if tmsl.tilematrixset in self.tilematrixsetlinks: + raise KeyError('TileMatrixSetLink with tilematrixset "%s"' + ' already exists' % + tmsl.tilematrixset) + self.tilematrixsetlinks[tmsl.tilematrixset] = tmsl self.resourceURLs = [] for resourceURL in elem.findall('{http://www.opengis.net/wmts/1.0}ResourceURL'): @@ -371,34 +580,20 @@ def __init__(self, elem, parent=None, index=0, parse_remote_metadata=False): for child in elem.findall('{http://www.opengis.net/wmts/1.0}Layer'): self.layers.append(ContentMetadata(child, self)) + @property + def tilematrixsets(self): + # NB. This attribute has been superseeded by the + # `tilematrixsetlinks` attribute defined below, but is included + # for now to provide continuity. + warnings.warn("The 'tilematrixsets' attribute has been deprecated" + " and will be removed in a future version of OWSLib." + " Please use 'tilematrixsetlinks' instead.") + return self._tilematrixsets + def __str__(self): return 'Layer Name: %s Title: %s' % (self.name, self.title) -class OperationsMetadata: - """Abstraction for WMTS OperationsMetadata. - - Implements IOperationMetadata. - """ - def __init__(self, elem): - """.""" - self.name = elem.attrib['name'] - # formatOptions - self.formatOptions = [f.text for f in elem.findall('{http://www.opengis.net/ows/1.1}Format')] - methods = [] - for verb in elem.findall('{http://www.opengis.net/ows/1.1}DCP/{http://www.opengis.net/ows/1.1}HTTP'): - url = verb.find('{http://www.opengis.net/ows/1.1}Get').attrib['{http://www.w3.org/1999/xlink}href'] - encodings = [] - constraints = verb.findall('{http://www.opengis.net/ows/1.1}Get/{http://www.opengis.net/ows/1.1}Constraint') - for constraint in constraints: - if constraint.attrib['name'] == "GetEncoding": - for encoding in constraint.findall('{http://www.opengis.net/ows/1.1}AllowedValues/{http://www.opengis.net/ows/1.1}Value'): - encodings.append(encoding.text) - if len(encodings) < 1: # KVP is only a SHOULD requirement, and SFS doesn't provide it. - encodings = ['KVP'] - methods.append(('Get', {'url': url, 'encodings': encodings})) - self.methods = dict(methods) - class WMTSCapabilitiesReader: """Read and parse capabilities document into a lxml.etree infoset """ @@ -416,7 +611,7 @@ def capabilities_url(self, service_url): """ qs = [] if service_url.find('?') != -1: - qs = cgi.parse_qsl(service_url.split('?')[1]) + qs = urlparse.parse_qsl(service_url.split('?')[1]) params = [x[0] for x in qs] diff --git a/python/ext-libs/owslib/wps.py b/python/ext-libs/owslib/wps.py index 0dc435ac6791..fb16ea62058b 100644 --- a/python/ext-libs/owslib/wps.py +++ b/python/ext-libs/owslib/wps.py @@ -20,25 +20,25 @@ Usage ----- -The module can be used to execute three types of requests versus a remote WPS endpoint: +The module can be used to execute three types of requests versus a remote WPS endpoint: -a) "GetCapabilities" +a) "GetCapabilities" - use the method wps.getcapabilities(xml=None) - the optional keyword argument "xml" may be used to avoid a real live request, and instead read the WPS capabilities document from a cached XML file - + b) "DescribeProcess" - use the method wps.describeprocess(identifier, xml=None) - identifier is the process identifier, retrieved from the list obtained from a previous "GetCapabilities" invocation - the optional keyword argument "xml" may be used to avoid a real live request, and instead read the WPS process description document from a cached XML file - + c) "Execute" - - use the method wps.execute(identifier, inputs, output=None, request=None, response=None), - which submits the job to the remote WPS server and returns a WPSExecution object that can be used to periodically check the job status until completion + - use the method wps.execute(identifier, inputs, output=None, request=None, response=None), + which submits the job to the remote WPS server and returns a WPSExecution object that can be used to periodically check the job status until completion (or error) - - - the optional keyword argument "request" may be used to avoid re-building the request XML from input arguments, and instead submit a request from a + + - the optional keyword argument "request" may be used to avoid re-building the request XML from input arguments, and instead submit a request from a pre-made XML file - + - alternatively, an "Execute" request can be built from input arguments by supplying the "identifier", "inputs" and "output" arguments to the execute() method. - "identifier" is the mandatory process identifier - "inputs" is a dictionary of (key,value) pairs where: @@ -48,31 +48,31 @@ - "WFSFeatureCollection" can be used in conjunction with "WFSQuery" to define a FEATURE_COLLECTION retrieved from a live WFS server. - "GMLMultiPolygonFeatureCollection" can be used to define one or more polygons of (latitude, longitude) points. - "output" is an optional output identifier to be included in the ResponseForm section of the request. - + - the optional keyword argument "response" mey be used to avoid submitting a real live request, and instead reading the WPS execution response document from a cached XML file (for debugging or testing purposes) - the convenience module function monitorExecution() can be used to periodically check the status of a remote running job, and eventually download the output either to a named file, or to a file specified by the server. - - + + Examples -------- -The files examples/wps-usgs-script.py, examples/wps-pml-script-1.py and examples/wps-pml-script-2.py contain real-world usage examples -that submits a "GetCapabilities", "DescribeProcess" and "Execute" requests to the live USGS and PML servers. To run: +The files examples/wps-usgs-script.py, examples/wps-pml-script-1.py and examples/wps-pml-script-2.py contain real-world usage examples +that submits a "GetCapabilities", "DescribeProcess" and "Execute" requests to the live USGS and PML servers. To run: cd examples python wps-usgs-script.py python wps-pml-script-1.py python wps-pml-script-2.py - + The file wps-client.py contains a command-line client that can be used to submit a "GetCapabilities", "DescribeProcess" or "Execute" request to an arbitratry WPS server. For example, you can run it as follows: cd examples To prints out usage and example invocations: wps-client -help - To execute a (fake) WPS invocation: + To execute a (fake) WPS invocation: wps-client.py -v -u http://cida.usgs.gov/climate/gdp/process/WebProcessingService -r GetCapabilities -x ../tests/USGSCapabilities.xml - -The directory tests/ includes several doctest-style files wps_*.txt that show how to interactively submit a + +The directory tests/ includes several doctest-style files wps_*.txt that show how to interactively submit a "GetCapabilities", "DescribeProcess" or "Execute" request, without making a live request but rather parsing the response of cached XML response documents. To run: cd tests python -m doctest wps_*.txt @@ -87,8 +87,8 @@ from owslib.etree import etree from owslib.ows import DEFAULT_OWS_NAMESPACE, ServiceIdentification, ServiceProvider, OperationsMetadata from time import sleep -from owslib.util import (testXMLValue, build_get_url, dump, getTypedValue, - getNamespace, xml2string, nspath, openURL, nspath_eval) +from owslib.util import (testXMLValue, build_get_url, dump, getTypedValue, + getNamespace, element_to_string, nspath, openURL, nspath_eval) from xml.dom.minidom import parseString from owslib.namespaces import Namespaces @@ -119,21 +119,21 @@ class IWebProcessingService(): """ Abstract interface for an OGC Web Processing Service (WPS). """ - + url = property("""URL for the remote WPS server (string).""") - + def getcapabilities(**kw): """ Makes a GetCapabilities request to the remote WPS server, returns an XML document wrapped in a python file-like object. """ - + def describeprocess(**kw): """ Makes a DescribeProcess request to the remote WPS server, returns a Process object containing all the process metadata. """ - + def execute(**kw): """ Submits an Execute request to the remote WPS server, @@ -144,34 +144,34 @@ class IComplexData(): """ Abstract interface representing complex input object for a WPS request. """ - + def getXml(self): """ - Method that returns the object data as an XML snippet, + Method that returns the object data as an XML snippet, to be inserted into the WPS request document sent to the server. - """ - + """ + class WebProcessingService(object): """ Class that contains client-side functionality for invoking an OGC Web Processing Service (WPS). - + Implements IWebProcessingService. """ - + def __init__(self, url, version=WPS_DEFAULT_VERSION, username=None, password=None, verbose=False, skip_caps=False): """ Initialization method resets the object status. - By default it will execute a GetCapabilities invocation to the remote service, + By default it will execute a GetCapabilities invocation to the remote service, which can be skipped by using skip_caps=True. """ - + # fields passed in from object initializer self.url = url self.username = username self.password = password self.version = version self.verbose = verbose - + # fields populated by method invocations self._capabilities = None self.identification = None @@ -181,13 +181,13 @@ def __init__(self, url, version=WPS_DEFAULT_VERSION, username=None, password=Non if not skip_caps: self.getcapabilities() - + def getcapabilities(self, xml=None): """ Method that requests a capabilities document from the remote WPS server and populates this object's metadata. keyword argument xml: local XML GetCapabilities document, prevents actual HTTP invocation. """ - + # read capabilities document reader = WPSCapabilitiesReader(version=self.version, verbose=self.verbose) if xml: @@ -195,19 +195,19 @@ def getcapabilities(self, xml=None): self._capabilities = reader.readFromString(xml) else: self._capabilities = reader.readFromUrl(self.url, username=self.username, password=self.password) - + if self.verbose==True: - print xml2string(etree.tostring(self._capabilities)) + print element_to_string(self._capabilities) # populate the capabilities metadata obects from the XML tree self._parseCapabilitiesMetadata(self._capabilities) - + def describeprocess(self, identifier, xml=None): """ Requests a process document from a WPS service and populates the process metadata. Returns the process object. """ - + # read capabilities document reader = WPSDescribeProcessReader(version=self.version, verbose=self.verbose) if xml: @@ -216,59 +216,59 @@ def describeprocess(self, identifier, xml=None): else: # read from server rootElement = reader.readFromUrl(self.url, identifier) - + if self.verbose==True: - print xml2string(etree.tostring(rootElement)) + print element_to_string(rootElement) # build metadata objects return self._parseProcessMetadata(rootElement) - + def execute(self, identifier, inputs, output=None, request=None, response=None): """ - Submits a WPS process execution request. + Submits a WPS process execution request. Returns a WPSExecution object, which can be used to monitor the status of the job, and ultimately retrieve the result. - + identifier: the requested process identifier inputs: list of process inputs as (key, value) tuples (where value is either a string for LiteralData, or an object for ComplexData) output: optional identifier for process output reference (if not provided, output will be embedded in the response) request: optional pre-built XML request document, prevents building of request from other arguments response: optional pre-built XML response document, prevents submission of request to live WPS server """ - + # instantiate a WPSExecution object print 'Executing WPS request...' execution = WPSExecution(version=self.version, url=self.url, username=self.username, password=self.password, verbose=self.verbose) - # build XML request from parameters + # build XML request from parameters if request is None: requestElement = execution.buildRequest(identifier, inputs, output) - request = etree.tostring( requestElement ) + request = etree.tostring( requestElement ) if self.verbose==True: print request - + # submit the request to the live server - if response is None: + if response is None: response = execution.submitRequest(request) else: response = etree.fromstring(response) - + if self.verbose==True: print etree.tostring(response) - + # parse response execution.parseResponse(response) - + return execution - - + + def _parseProcessMetadata(self, rootElement): """ Method to parse a XML element and returned the constructed Process object """ - + processDescriptionElement = rootElement.find( 'ProcessDescription' ) process = Process(processDescriptionElement, verbose=self.verbose) - + # override existing processes in object metadata, if existing already found = False for n, p in enumerate(self.processes): @@ -278,34 +278,34 @@ def _parseProcessMetadata(self, rootElement): # otherwise add it if not found: self.processes.append(process) - + return process - - - def _parseCapabilitiesMetadata(self, root): + + + def _parseCapabilitiesMetadata(self, root): ''' Sets up capabilities metadata objects ''' - + # use the WPS namespace defined in the document root wpsns = getNamespace(root) - + # loop over children WITHOUT requiring a specific namespace for element in root: - + # thie element's namespace ns = getNamespace(element) - + # metadata if element.tag.endswith('ServiceIdentification'): self.identification=ServiceIdentification(element, namespace=ns) if self.verbose==True: dump(self.identification) - + # metadata elif element.tag.endswith('ServiceProvider'): - self.provider=ServiceProvider(element, namespace=ns) + self.provider=ServiceProvider(element, namespace=ns) if self.verbose==True: dump(self.provider) - + # # # @@ -321,7 +321,7 @@ def _parseCapabilitiesMetadata(self, root): self.operations.append( OperationsMetadata(child, namespace=ns) ) if self.verbose==True: dump(self.operations[-1]) - + # # # gov.usgs.cida.gdp.wps.algorithm.filemanagement.ReceiveFiles @@ -336,17 +336,17 @@ def _parseCapabilitiesMetadata(self, root): if self.verbose==True: dump(self.processes[-1]) - - + + class WPSReader(object): """ Superclass for reading a WPS document into a lxml.etree infoset. """ - def __init__(self, version=WPS_DEFAULT_VERSION, verbose=False): + def __init__(self, version=WPS_DEFAULT_VERSION, verbose=False): self.version = version self.verbose = verbose - + def _readFromUrl(self, url, data, method='Get', username=None, password=None): """ Method to get and parse a WPS document, returning an elementtree instance. @@ -354,54 +354,54 @@ def _readFromUrl(self, url, data, method='Get', username=None, password=None): data: GET: dictionary of HTTP (key, value) parameter pairs, POST: XML document to post username, password: optional user credentials """ - + if method == 'Get': # full HTTP request url request_url = build_get_url(url, data) if self.verbose==True: print request_url - + # split URL into base url and query string to use utility function spliturl=request_url.split('?') u = openURL(spliturl[0], spliturl[1], method='Get', username=username, password=password) return etree.fromstring(u.read()) - + elif method == 'Post': u = openURL(url, data, method='Post', username = username, password = password) return etree.fromstring(u.read()) - + else: raise Exception("Unrecognized HTTP method: %s" % method) - - + + def readFromString(self, string): """ Method to read a WPS GetCapabilities document from an XML string. """ - + if not isinstance(string, str): raise ValueError("Input must be of type string, not %s" % type(string)) - return etree.fromstring(string) + return etree.fromstring(string) class WPSCapabilitiesReader(WPSReader): """ Utility class that reads and parses a WPS GetCapabilities document into a lxml.etree infoset. """ - + def __init__(self, version=WPS_DEFAULT_VERSION, verbose=False): # superclass initializer super(WPSCapabilitiesReader,self).__init__(version=version, verbose=verbose) - + def readFromUrl(self, url, username=None, password=None): """ Method to get and parse a WPS capabilities document, returning an elementtree instance. url: WPS service base url, to which is appended the HTTP parameters: service, version, and request. username, password: optional user credentials """ - return self._readFromUrl(url, - {'service':'WPS', 'request':'GetCapabilities', 'version':self.version}, + return self._readFromUrl(url, + {'service':'WPS', 'request':'GetCapabilities', 'version':self.version}, username=username, password=password) - + class WPSDescribeProcessReader(WPSReader): """ Class that reads and parses a WPS DescribeProcess document into a etree infoset @@ -411,17 +411,17 @@ def __init__(self, version=WPS_DEFAULT_VERSION, verbose=False): # superclass initializer super(WPSDescribeProcessReader,self).__init__(version=version, verbose=verbose) - + def readFromUrl(self, url, identifier, username=None, password=None): """ Reads a WPS DescribeProcess document from a remote service and returns the XML etree object url: WPS service base url, to which is appended the HTTP parameters: 'service', 'version', and 'request', and 'identifier'. """ - - return self._readFromUrl(url, - {'service':'WPS', 'request':'DescribeProcess', 'version':self.version, 'identifier':identifier}, + + return self._readFromUrl(url, + {'service':'WPS', 'request':'DescribeProcess', 'version':self.version, 'identifier':identifier}, username=username, password=password) - + class WPSExecuteReader(WPSReader): """ Class that reads and parses a WPS Execute response document into a etree infoset @@ -429,36 +429,36 @@ class WPSExecuteReader(WPSReader): def __init__(self, verbose=False): # superclass initializer super(WPSExecuteReader,self).__init__(verbose=verbose) - + def readFromUrl(self, url, data={}, method='Get', username=None, password=None): """ Reads a WPS status document from a remote service and returns the XML etree object. url: the URL to submit the GET/POST request to. """ - + return self._readFromUrl(url, data, method, username=username, password=password) - + class WPSExecution(): """ Class that represents a single WPS process executed on a remote WPS service. """ - + def __init__(self, version=WPS_DEFAULT_VERSION, url=None, username=None, password=None, verbose=False): - + # initialize fields self.url = url self.version = version self.username = username self.password = password self.verbose = verbose - + # request document self.request = None - + # last response document self.response = None - + # status fields retrieved from the response documents self.process = None self.serviceInstance = None @@ -469,8 +469,8 @@ def __init__(self, version=WPS_DEFAULT_VERSION, url=None, username=None, passwor self.statusLocation = None self.dataInputs=[] self.processOutputs=[] - - + + def buildRequest(self, identifier, inputs=[], output=None): """ Method to build a WPS process request. @@ -481,32 +481,32 @@ def buildRequest(self, identifier, inputs=[], output=None): and the object must contain a 'getXml()' method that returns an XML infoset to be included in the WPS request output: optional identifier if process output is to be returned as a hyperlink reference """ - - # + + # root = etree.Element(nspath_eval('wps:Execute', namespaces)) root.set('service', 'WPS') root.set('version', WPS_DEFAULT_VERSION) root.set(nspath_eval('xsi:schemaLocation', namespaces), '%s %s' % (namespaces['wps'], WPS_DEFAULT_SCHEMA_LOCATION) ) - + # gov.usgs.cida.gdp.wps.algorithm.FeatureWeightedGridStatisticsAlgorithm identifierElement = etree.SubElement(root, nspath_eval('ows:Identifier', namespaces)) identifierElement.text = identifier - + # dataInputsElement = etree.SubElement(root, nspath_eval('wps:DataInputs', namespaces)) - + for (key,val) in inputs: inputElement = etree.SubElement(dataInputsElement, nspath_eval('wps:Input', namespaces)) identifierElement = etree.SubElement(inputElement, nspath_eval('ows:Identifier', namespaces)) identifierElement.text = key - + # Literal data # # DATASET_URI @@ -518,7 +518,7 @@ def buildRequest(self, identifier, inputs=[], output=None): dataElement = etree.SubElement(inputElement, nspath_eval('wps:Data', namespaces)) literalDataElement = etree.SubElement(dataElement, nspath_eval('wps:LiteralData', namespaces)) literalDataElement.text = val - + # Complex data # # FEATURE_COLLECTION @@ -538,7 +538,7 @@ def buildRequest(self, identifier, inputs=[], output=None): # else: inputElement.append( val.getXml() ) - + # # # @@ -548,7 +548,7 @@ def buildRequest(self, identifier, inputs=[], output=None): # if output is not None: responseFormElement = etree.SubElement(root, nspath_eval('wps:ResponseForm', namespaces)) - responseDocumentElement = etree.SubElement(responseFormElement, nspath_eval('wps:ResponseDocument', namespaces), + responseDocumentElement = etree.SubElement(responseFormElement, nspath_eval('wps:ResponseDocument', namespaces), attrib={'storeExecuteResponse':'true', 'status':'true'} ) if isinstance(output, str): self._add_output(responseDocumentElement, output, asReference=True) @@ -560,22 +560,22 @@ def buildRequest(self, identifier, inputs=[], output=None): return root def _add_output(self, element, identifier, asReference=False): - outputElement = etree.SubElement(element, nspath_eval('wps:Output', namespaces), + outputElement = etree.SubElement(element, nspath_eval('wps:Output', namespaces), attrib={'asReference':str(asReference).lower()} ) outputIdentifierElement = etree.SubElement(outputElement, nspath_eval('ows:Identifier', namespaces)).text = identifier - - + + # wait for 60 seconds by default def checkStatus(self, url=None, response=None, sleepSecs=60): """ Method to check the status of a job execution. In the process, this method will upadte the object 'response' attribute. - + url: optional 'statusLocation' URL retrieved from a previous WPS Execute response document. If not provided, the current 'statusLocation' URL will be used. sleepSecs: number of seconds to sleep before returning control to the caller. """ - + reader = WPSExecuteReader(verbose=self.verbose) if response is None: # override status location @@ -585,23 +585,23 @@ def checkStatus(self, url=None, response=None, sleepSecs=60): response = reader.readFromUrl(self.statusLocation, username=self.username, password=self.password) else: response = reader.readFromString(response) - + # store latest response self.response = etree.tostring(response) if self.verbose==True: print self.response self.parseResponse(response) - + # sleep given number of seconds if self.isComplete()==False: print 'Sleeping %d seconds...' % sleepSecs sleep(sleepSecs) - + def getStatus(self): return self.status - + def isComplete(self): if (self.status=='ProcessSucceeded' or self.status=='ProcessFailed' or self.status=='Exception'): return True @@ -611,108 +611,97 @@ def isComplete(self): return False else: raise Exception('Unknown process execution status: %s' % self.status) - + def isSucceded(self): if self.status=='ProcessSucceeded': return True else: return False - + def isNotComplete(self): return not self.isComplete() - + def getOutput(self, filepath=None): """ - Method to write the output of a WPS process to a file: - either retrieve the referenced file from the server, or write out the content of response embedded output. - - filepath: optional path to the output file, otherwise a file will be created in the local directory with the name assigned by the server, + Method to write the outputs of a WPS process to a file: + either retrieves the referenced files from the server, or writes out the content of response embedded output. + + filepath: optional path to the output file, otherwise a file will be created in the local directory with the name assigned by the server, or default name 'wps.out' for embedded output. """ - + if self.isSucceded(): content = '' for output in self.processOutputs: - + + output_content = output.retrieveData(self.username, self.password) + # ExecuteResponse contains reference to server-side output - if output.reference is not None: - # a) 'http://cida.usgs.gov/climate/gdp/process/RetrieveResultServlet?id=1318528582026OUTPUT.601bb3d0-547f-4eab-8642-7c7d2834459e' - # b) 'http://rsg.pml.ac.uk/wps/wpsoutputs/outputImage-11294Bd6l2a.tif' - url = output.reference - print 'Output URL=%s' % url - if '?' in url: - spliturl=url.split('?') - u = openURL(spliturl[0], spliturl[1], method='Get', username = self.username, password = self.password) - # extract output filepath from URL query string - if filepath is None: - filepath = spliturl[1].split('=')[1] - else: - u = openURL(url, '', method='Get', username = self.username, password = self.password) - # extract output filepath from base URL - if filepath is None: - filepath = url.split('/')[-1] - content = content + u.read() - - # ExecuteResponse contain embedded output + if output_content is not "": + content = content + output_content + if filepath is None: + filepath = output.fileName + + # ExecuteResponse contain embedded output if len(output.data)>0: if filepath is None: filepath = 'wps.out' for data in output.data: content = content + data - + # write out content if content is not '': out = open(filepath, 'wb') out.write(content) out.close() print 'Output written to file: %s' %filepath - + else: raise Exception("Execution not successfully completed: status=%s" % self.status) - + def submitRequest(self, request): """ Submits a WPS Execute document to a remote service, returns the XML response document from the server. This method will save the request document and the first returned response document. - + request: the XML request document to be submitted as POST to the server. - """ - + """ + self.request = request reader = WPSExecuteReader(verbose=self.verbose) response = reader.readFromUrl(self.url, request, method='Post', username=self.username, password=self.password) self.response = response return response - - ''' + + ''' if response is None: # override status location if url is not None: self.statusLocation = url - + else: response = reader.readFromString(response) - + ''' - + def parseResponse(self, response): """ Method to parse a WPS response document """ - + rootTag = response.tag.split('}')[1] # if rootTag == 'ExecuteResponse': self._parseExecuteResponse(response) - + # elif rootTag == 'ExceptionReport': self._parseExceptionReport(response) - + else: print 'Unknown Response' - + # print status, errors print 'Execution status=%s' % self.status print 'Percent completed=%s' % self.percentCompleted @@ -720,7 +709,7 @@ def parseResponse(self, response): for error in self.errors: dump(error) - + def _parseExceptionReport(self, root): """ Method to parse a WPS ExceptionReport document and populate this object's metadata. @@ -728,22 +717,22 @@ def _parseExceptionReport(self, root): # set exception status, unless set already if self.status is None: self.status = "Exception" - + for exceptionEl in root.findall( nspath('Exception', ns=namespaces['ows']) ): self.errors.append( WPSException(exceptionEl) ) - def _parseExecuteResponse(self, root): + def _parseExecuteResponse(self, root): """ Method to parse a WPS ExecuteResponse response document and populate this object's metadata. """ - + # retrieve WPS namespace directly from root element wpsns = getNamespace(root) self.serviceInstance = root.get( 'serviceInstance' ) self.statusLocation = root.get( 'statusLocation' ) - + # # PyWPS Process v.net.path successfully calculated # @@ -773,26 +762,26 @@ def _parseExecuteResponse(self, root): self._parseExceptionReport(element) self.process = Process(root.find(nspath('Process', ns=wpsns)), verbose=self.verbose) - + # for inputElement in root.findall( nspath('DataInputs/Input', ns=wpsns) ): self.dataInputs.append( Input(inputElement) ) if self.verbose==True: dump(self.dataInputs[-1]) - + # - # xmlns:ns="http://www.opengis.net/wps/1.0.0" + # xmlns:ns="http://www.opengis.net/wps/1.0.0" for outputElement in root.findall( nspath('ProcessOutputs/Output', ns=wpsns) ): self.processOutputs.append( Output(outputElement) ) if self.verbose==True: dump(self.processOutputs[-1]) - + class ComplexData(object): """ Class that represents a ComplexData element in a WPS document """ - + def __init__(self, mimeType=None, encoding=None, schema=None): self.mimeType = mimeType self.encoding = encoding @@ -802,12 +791,12 @@ class InputOutput(object): """ Superclass of a WPS input or output data object. """ - + def __init__(self, element): - + # loop over sub-elements without requiring a specific namespace for subElement in element: - + # SUMMARIZE_TIMESTEP if subElement.tag.endswith('Identifier'): self.identifier = testXMLValue( subElement ) @@ -815,36 +804,36 @@ def __init__(self, element): # Summarize Timestep elif subElement.tag.endswith('Title'): self.title = testXMLValue( subElement ) - + # If selected, processing output will include columns with summarized statistics for all feature attribute values for each timestep elif subElement.tag.endswith('Abstract'): self.abstract = testXMLValue( subElement ) - + self.allowedValues = [] self.supportedValues = [] self.defaultValue = None self.dataType = None - + def _parseData(self, element): """ Method to parse a "Data" element """ - + # # - # 7504912.93758151 -764109.175074507,7750849.82379226 -22141.8611641468,8561828.42371234 -897195.923493867,7724946.16844165 -602984.014261927 + # 7504912.93758151 -764109.175074507,7750849.82379226 -22141.8611641468,8561828.42371234 -897195.923493867,7724946.16844165 -602984.014261927 # # #nspath('Data', ns=WPS_NAMESPACE) complexDataElement = element.find( nspath('ComplexData', ns=getNamespace(element)) ) if complexDataElement is not None: self.dataType = "ComplexData" - + def _parseLiteralData(self, element, literalElementName): """ Method to parse the LiteralData element. """ - + # # # @@ -854,7 +843,7 @@ def _parseLiteralData(self, element, literalElementName): # # COMMA # - + # # # @@ -873,13 +862,13 @@ def _parseLiteralData(self, element, literalElementName): self.defaultValue = getTypedValue(self.dataType, subElement.text) elif subElement.tag.endswith('AnyValue'): self.allowedValues.append( getTypedValue(self.dataType, 'AnyValue') ) - + def _parseComplexData(self, element, complexDataElementName): """ Method to parse a ComplexData or ComplexOutput element. """ - + # # # @@ -909,43 +898,43 @@ def _parseComplexData(self, element, complexDataElementName): # NONE # # - + complexDataElement = element.find( complexDataElementName ) if complexDataElement is not None: self.dataType = "ComplexData" - + for supportedComlexDataElement in complexDataElement.findall( 'SupportedComplexData' ): self.supportedValues.append( ComplexData( mimeType=testXMLValue( supportedComlexDataElement.find( 'Format' ) ), encoding=testXMLValue( supportedComlexDataElement.find( 'Encoding' ) ), - schema=testXMLValue( supportedComlexDataElement.find( 'Schema' ) ) - ) + schema=testXMLValue( supportedComlexDataElement.find( 'Schema' ) ) + ) ) - + for formatElement in complexDataElement.findall( 'Supported/Format'): self.supportedValues.append( ComplexData( mimeType=testXMLValue( formatElement.find( 'MimeType' ) ), encoding=testXMLValue( formatElement.find( 'Encoding' ) ), - schema=testXMLValue( formatElement.find( 'Schema' ) ) - ) + schema=testXMLValue( formatElement.find( 'Schema' ) ) + ) ) - - defaultFormatElement = complexDataElement.find( 'Default/Format' ) + + defaultFormatElement = complexDataElement.find( 'Default/Format' ) if defaultFormatElement is not None: self.defaultValue = ComplexData( mimeType=testXMLValue( defaultFormatElement.find( 'MimeType' ) ), encoding=testXMLValue( defaultFormatElement.find( 'Encoding' ) ), - schema=testXMLValue( defaultFormatElement.find( 'Schema' ) ) - ) + schema=testXMLValue( defaultFormatElement.find( 'Schema' ) ) + ) class Input(InputOutput): """ Class that represents a WPS process input. """ - + def __init__(self, inputElement): - + # superclass initializer super(Input,self).__init__(inputElement) - + # # OR # 1 @@ -953,54 +942,56 @@ def __init__(self, inputElement): if inputElement.get("minOccurs") is not None: self.minOccurs = int( inputElement.get("minOccurs") ) if inputElement.find('MinimumOccurs') is not None: - self.minOccurs = int( testXMLValue( inputElement.find('MinimumOccurs') ) ) + self.minOccurs = int( testXMLValue( inputElement.find('MinimumOccurs') ) ) self.maxOccurs = -1 if inputElement.get("maxOccurs") is not None: self.maxOccurs = int( inputElement.get("maxOccurs") ) if inputElement.find('MaximumOccurs') is not None: - self.maxOccurs = int( testXMLValue( inputElement.find('MaximumOccurs') ) ) - + self.maxOccurs = int( testXMLValue( inputElement.find('MaximumOccurs') ) ) + # self._parseLiteralData(inputElement, 'LiteralData') - + # self._parseComplexData(inputElement, 'ComplexData') - - + + class Output(InputOutput): """ Class that represents a WPS process output. """ - + def __init__(self, outputElement): - + # superclass initializer super(Output,self).__init__(outputElement) - + self.reference = None self.mimeType = None self.data = [] - + self.fileName = None + self.filePath = None + # extract wps namespace from outputElement itself wpsns = getNamespace(outputElement) - + # referenceElement = outputElement.find( nspath('Reference', ns=wpsns) ) if referenceElement is not None: self.reference = referenceElement.get('href') self.mimeType = referenceElement.get('mimeType') - + # self._parseLiteralData(outputElement, 'LiteralOutput') - + # or self._parseComplexData(outputElement, 'ComplexOutput') - - # + + # # # - # 7504912.93758151 -764109.175074507,7750849.82379226 -22141.8611641468,8561828.42371234 -897195.923493867,7724946.16844165 -602984.014261927 + # 7504912.93758151 -764109.175074507,7750849.82379226 -22141.8611641468,8561828.42371234 -897195.923493867,7724946.16844165 -602984.014261927 # # # OR: @@ -1012,7 +1003,7 @@ def __init__(self, outputElement): # -960123.14218016264665723.56559387 # -101288.65106088225108200.011823481 # - # + # # # # -960123.142180162365548,4665723.565593870356679,0 -960123.142180162365548,4665723.565593870356679,0 -960123.142180162598379,4665723.565593870356679,0 -960123.142180162598379,4665723.565593870356679,0 -711230.141176006174646,4710278.48552671354264,0 -711230.141176006174646,4710278.48552671354264,0 -623656.677859728806652,4848552.374973464757204,0 -623656.677859728806652,4848552.374973464757204,0 -410100.337491964863148,4923834.82589447684586,0 -410100.337491964863148,4923834.82589447684586,0 -101288.651060882242746,5108200.011823480948806,0 -101288.651060882242746,5108200.011823480948806,0 -101288.651060882257298,5108200.011823480948806,0 -101288.651060882257298,5108200.011823480948806,0 @@ -1029,7 +1020,7 @@ def __init__(self, outputElement): # # # - dataElement = outputElement.find( nspath('Data', ns=wpsns) ) + dataElement = outputElement.find( nspath('Data', ns=wpsns) ) if dataElement is not None: complexDataElement = dataElement.find( nspath('ComplexData', ns=wpsns) ) if complexDataElement is not None: @@ -1045,13 +1036,69 @@ def __init__(self, outputElement): self.dataType = literalDataElement.get('dataType') if literalDataElement.text is not None and literalDataElement.text.strip() is not '': self.data.append(literalDataElement.text.strip()) - - + + def retrieveData(self, username=None, password=None): + """ + Method to retrieve data from server-side reference: + returns "" if the reference is not known. + + username, password: credentials to access the remote WPS server + """ + + url = self.reference + if url is None: + return "" + + # a) 'http://cida.usgs.gov/climate/gdp/process/RetrieveResultServlet?id=1318528582026OUTPUT.601bb3d0-547f-4eab-8642-7c7d2834459e' + # b) 'http://rsg.pml.ac.uk/wps/wpsoutputs/outputImage-11294Bd6l2a.tif' + print 'Output URL=%s' % url + if '?' in url: + spliturl=url.split('?') + u = openURL(spliturl[0], spliturl[1], method='Get', username = username, password = password) + # extract output filepath from URL query string + self.fileName = spliturl[1].split('=')[1] + else: + u = openURL(url, '', method='Get', username = username, password = password) + # extract output filepath from base URL + self.fileName = url.split('/')[-1] + + return u.read() + + + def writeToDisk(self, path=None, username=None, password=None): + """ + Method to write an output of a WPS process to disk: + it either retrieves the referenced file from the server, or write out the content of response embedded output. + + filepath: optional path to the output file, otherwise a file will be created in the local directory with the name assigned by the server, + username, password: credentials to access the remote WPS server + """ + + # Check if ExecuteResponse contains reference to server-side output + content = self.retrieveData(username, password) + + # ExecuteResponse contain embedded output + if content is "" and len(self.data)>0: + self.fileName = self.identifier + for data in self.data: + content = content + data + + # write out content + if content is not "": + if self.fileName == "": + self.fileName = self.identifier + self.filePath = path + self.fileName + out = open(self.filePath, 'wb') + out.write(content) + out.close() + print 'Output written to file: %s' %self.filePath + + class WPSException: """ Class representing an exception raised by a WPS. """ - + def __init__(self, root): self.code = root.attrib.get("exceptionCode", None) self.locator = root.attrib.get("locator", None) @@ -1065,81 +1112,81 @@ class Process(object): """ Class that represents a WPS process. """ - + def __init__(self, elem, verbose=False): """ Initialization method extracts all available metadata from an XML document (passed in as etree object) """ - - # # OR: # self._root = elem self.verbose = verbose - + wpsns = getNamespace(elem) - + # self.processVersion = elem.get( nspath('processVersion', ns=wpsns) ) self.statusSupported = bool( elem.get( "statusSupported" ) ) self.storeSupported = bool( elem.get( "storeSupported" ) ) - + for child in elem: - + # this element's namespace ns = getNamespace(child) - + # gov.usgs.cida.gdp.wps.algorithm.FeatureWeightedGridStatisticsAlgorithm if child.tag.endswith('Identifier'): self.identifier = testXMLValue( child ) - + # Feature Weighted Grid Statistics elif child.tag.endswith('Title'): self.title = testXMLValue( child ) - + # This algorithm generates area weighted statistics of a gridded dataset for a set of vector polygon features. Using the bounding-box that encloses the feature data and the time range, if provided, a subset of the gridded dataset is requested from the remote gridded data server. Polygon representations are generated for cells in the retrieved grid. The polygon grid-cell representations are then projected to the feature data coordinate reference system. The grid-cells are used to calculate per grid-cell feature coverage fractions. Area-weighted statistics are then calculated for each feature using the grid values and fractions as weights. If the gridded dataset has a time range the last step is repeated for each time step within the time range or all time steps if a time range was not supplied. elif child.tag.endswith('Abstract'): self.abstract = testXMLValue( child ) - + if self.verbose==True: dump(self) - + # self.dataInputs = [] for inputElement in elem.findall( 'DataInputs/Input' ): self.dataInputs.append( Input(inputElement) ) if self.verbose==True: dump(self.dataInputs[-1], prefix='\tInput: ') - + # self.processOutputs = [] for outputElement in elem.findall( 'ProcessOutputs/Output' ): self.processOutputs.append( Output(outputElement) ) if self.verbose==True: dump(self.processOutputs[-1], prefix='\tOutput: ') - - + + class FeatureCollection(): ''' Base class to represent a Feature Collection used as input to a WPS request. The method getXml() is invoked by the WPS execute() method to build the WPS request. All subclasses must implement the getXml() method to provide their specific XML. - + Implements IComplexData. ''' - + def __init__(self): pass - + def getXml(self): raise NotImplementedError - + class WFSFeatureCollection(FeatureCollection): ''' FeatureCollection specified by a WFS query. All subclasses must implement the getQuery() method to provide the specific query portion of the XML. ''' - + def __init__(self, wfsUrl, wfsQuery): ''' wfsUrl: the WFS service URL @@ -1148,7 +1195,7 @@ def __init__(self, wfsUrl, wfsQuery): ''' self.url = wfsUrl self.query = wfsQuery - + # # # @@ -1157,7 +1204,7 @@ def __init__(self, wfsUrl, wfsQuery): # # def getXml(self): - + root = etree.Element(nspath_eval('wps:Reference', namespaces), attrib = { nspath_eval("xlink:href",namespaces) : self.url} ) bodyElement = etree.SubElement(root, nspath_eval('wps:Body', namespaces)) getFeatureElement = etree.SubElement(bodyElement, nspath_eval('wfs:GetFeature', namespaces), @@ -1165,7 +1212,7 @@ def getXml(self): "version":"1.1.0", "outputFormat":"text/xml; subtype=gml/3.1.1", nspath_eval("xsi:schemaLocation",namespaces):"%s %s" % (namespaces['wfs'], '../wfs/1.1.0/WFS.xsd')}) - + # # the_geom # STATE @@ -1174,23 +1221,23 @@ def getXml(self): # # getFeatureElement.append( self.query.getXml() ) - + return root - + class WFSQuery(): ''' Class representing a WFS query, for insertion into a WFSFeatureCollection instance. - + Implements IComplexData. ''' - + def __init__(self, typeName, propertyNames=[], filters=[]): self.typeName = typeName self.propertyNames = propertyNames self.filters = filters - + def getXml(self): - + # # the_geom # STATE @@ -1198,7 +1245,7 @@ def getXml(self): # # # - + queryElement = etree.Element(nspath_eval('wfs:Query', namespaces), attrib = { "typeName":self.typeName }) for propertyName in self.propertyNames: propertyNameElement = etree.SubElement(queryElement, nspath_eval('wfs:PropertyName', namespaces)) @@ -1206,15 +1253,15 @@ def getXml(self): if len(self.filters)>0: filterElement = etree.SubElement(queryElement, nspath_eval('ogc:Filter', namespaces)) for filter in self.filters: - gmlObjectIdElement = etree.SubElement(filterElement, nspath_eval('ogc:GmlObjectId', namespaces), + gmlObjectIdElement = etree.SubElement(filterElement, nspath_eval('ogc:GmlObjectId', namespaces), attrib={nspath_eval('gml:id', namespaces):filter}) return queryElement - + class GMLMultiPolygonFeatureCollection(FeatureCollection): ''' Class that represents a FeatureCollection defined as a GML multi-polygon. ''' - + def __init__(self, polygons): ''' Initializer accepts an array of polygons, where each polygon is an array of (lat,lon) tuples. @@ -1222,7 +1269,7 @@ def __init__(self, polygons): [(-92.8184, 39.5273), (-92.8184, 37.418), (-91.2363, 37.418), (-91.2363, 39.5273), (-92.8184, 39.5273)] ] ''' self.polygons = polygons - + def getXml(self): ''' @@ -1270,32 +1317,32 @@ def getXml(self): linearRingElement = etree.SubElement(exteriorElement, nspath_eval('gml:LinearRing', namespaces)) posListElement = etree.SubElement(linearRingElement, nspath_eval('gml:posList', namespaces)) posListElement.text = ' '.join(["%s %s" % (x, y) for x, y in polygon[:] ]) - + idElement = etree.SubElement(boxElement, nspath_eval('gml:ID', namespaces)) idElement.text = "0" return dataElement - + def monitorExecution(execution, sleepSecs=3, download=False, filepath=None): ''' - Convenience method to monitor the status of a WPS execution till it completes (successfully or not), - and write the output to file after a successful job completion. - + Convenience method to monitor the status of a WPS execution till it completes (succesfully or not), + and write the output to file after a succesfull job completion. + execution: WPSExecution instance sleepSecs: number of seconds to sleep in between check status invocations download: True to download the output when the process terminates, False otherwise filepath: optional path to output file (if downloaded=True), otherwise filepath will be inferred from response document - + ''' - + while execution.isComplete()==False: execution.checkStatus(sleepSecs=sleepSecs) print 'Execution status: %s' % execution.status - + if execution.isSucceded(): if download: execution.getOutput(filepath=filepath) else: - for output in execution.processOutputs: + for output in execution.processOutputs: if output.reference is not None: print 'Output URL=%s' % output.reference else: @@ -1306,7 +1353,7 @@ def printValue(value): ''' Utility method to format a value for printing. ''' - + # ComplexData type if isinstance(value, ComplexData): return "mimeType=%s, encoding=%s, schema=%s" % (value.mimeType, value.encoding, value.schema) @@ -1326,11 +1373,11 @@ def printInputOutput(value, indent=''): for val in value.supportedValues: print '%s Supported Value: %s' % (indent, printValue(val)) print '%s Default Value: %s ' % (indent, printValue(value.defaultValue)) - + # Input fields if isinstance(value, Input): print '%s minOccurs=%d, maxOccurs=%d' % (indent, value.minOccurs, value.maxOccurs) - + # Output fields if isinstance(value, Output): print '%s reference=%s, mimeType=%s' % (indent, value.reference, value.mimeType) diff --git a/python/ext-libs/pytz-2013.9-py2.7.egg-info/PKG-INFO b/python/ext-libs/pytz-2014.7-py2.7.egg-info/PKG-INFO similarity index 91% rename from python/ext-libs/pytz-2013.9-py2.7.egg-info/PKG-INFO rename to python/ext-libs/pytz-2014.7-py2.7.egg-info/PKG-INFO index a99f49793e67..3df625f640fb 100644 --- a/python/ext-libs/pytz-2013.9-py2.7.egg-info/PKG-INFO +++ b/python/ext-libs/pytz-2014.7-py2.7.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: pytz -Version: 2013.9 +Version: 2014.7 Summary: World timezone definitions, modern and historical Home-page: http://pythonhosted.org/pytz Author: Stuart Bishop @@ -18,7 +18,7 @@ Description: pytz - World Timezone Definitions for Python pytz brings the Olson tz database into Python. This library allows accurate and cross platform timezone calculations using Python 2.4 or higher. It also solves the issue of ambiguous times at the end - of daylight savings, which you can read more about in the Python + of daylight saving time, which you can read more about in the Python Library Reference (``datetime.tzinfo``). Almost all of the Olson timezones are supported. @@ -97,9 +97,9 @@ Description: pytz - World Timezone Definitions for Python constructors ''does not work'' with pytz for many timezones. >>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=amsterdam).strftime(fmt) - '2002-10-27 12:00:00 AMT+0020' + '2002-10-27 12:00:00 LMT+0020' - It is safe for timezones without daylight savings trasitions though, such + It is safe for timezones without daylight saving transitions though, such as UTC: >>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=pytz.utc).strftime(fmt) @@ -116,9 +116,9 @@ Description: pytz - World Timezone Definitions for Python This library also allows you to do date arithmetic using local times, although it is more complicated than working in UTC as you - need to use the ``normalize()`` method to handle daylight savings time + need to use the ``normalize()`` method to handle daylight saving time and other timezone transitions. In this example, ``loc_dt`` is set - to the instant when daylight savings time ends in the US/Eastern + to the instant when daylight saving time ends in the US/Eastern timezone. >>> before = loc_dt - timedelta(minutes=10) @@ -152,14 +152,14 @@ Description: pytz - World Timezone Definitions for Python >>> au_tz = timezone('Australia/Sydney') >>> au_dt = au_tz.normalize(utc_dt.astimezone(au_tz)) >>> au_dt.strftime(fmt) - '2006-03-27 08:34:59 EST+1100' + '2006-03-27 08:34:59 AEDT+1100' >>> utc_dt2 = utc.normalize(au_dt.astimezone(utc)) >>> utc_dt2.strftime(fmt) '2006-03-26 21:34:59 UTC+0000' You can take shortcuts when dealing with the UTC side of timezone conversions. ``normalize()`` and ``localize()`` are not really - necessary when there are no daylight savings time transitions to + necessary when there are no daylight saving time transitions to deal with. >>> utc_dt = datetime.utcfromtimestamp(1143408899).replace(tzinfo=utc) @@ -168,7 +168,7 @@ Description: pytz - World Timezone Definitions for Python >>> au_tz = timezone('Australia/Sydney') >>> au_dt = au_tz.normalize(utc_dt.astimezone(au_tz)) >>> au_dt.strftime(fmt) - '2006-03-27 08:34:59 EST+1100' + '2006-03-27 08:34:59 AEDT+1100' >>> utc_dt2 = au_dt.astimezone(utc) >>> utc_dt2.strftime(fmt) '2006-03-26 21:34:59 UTC+0000' @@ -258,11 +258,12 @@ Description: pytz - World Timezone Definitions for Python and 01:00 happens again (this time 01:00 EST) In fact, every instant between 01:00 and 02:00 occurs twice. This means - that if you try and create a time in the 'US/Eastern' timezone using + that if you try and create a time in the 'US/Eastern' timezone the standard datetime syntax, there is no way to specify if you meant - before of after the end-of-daylight-savings-time transition. + before of after the end-of-daylight-saving-time transition. Using the + pytz custom syntax, the best you can do is make an educated guess: - >>> loc_dt = datetime(2002, 10, 27, 1, 30, 00, tzinfo=eastern) + >>> loc_dt = eastern.localize(datetime(2002, 10, 27, 1, 30, 00)) >>> loc_dt.strftime(fmt) '2002-10-27 01:30:00 EST-0500' @@ -297,12 +298,16 @@ Description: pytz - World Timezone Definitions for Python >>> pytz.utc is pytz.UTC is pytz.timezone('UTC') True - Note that this instance is not the same instance (or implementation) as - other timezones with the same meaning (GMT, Greenwich, Universal, etc.). + Note that some other timezones are commonly thought of as the same (GMT, + Greenwich, Universal, etc.). The definition of UTC is distinct from these + other timezones, and they are not equivalent. For this reason, they will + not compare the same in Python. - >>> utc is pytz.timezone('GMT') + >>> utc == pytz.timezone('GMT') False + See the section `What is UTC`_, below. + If you insist on working with local times, this library provides a facility for constructing them unambiguously: @@ -317,7 +322,7 @@ Description: pytz - World Timezone Definitions for Python times. For example, 1:30am on 27th Oct 2002 happened twice in the US/Eastern - timezone when the clocks where put back at the end of Daylight Savings + timezone when the clocks where put back at the end of Daylight Saving Time: >>> dt = datetime(2002, 10, 27, 1, 30, 00) @@ -348,13 +353,13 @@ Description: pytz - World Timezone Definitions for Python Although ``localize()`` handles many cases, it is still not possible to handle all. In cases where countries change their timezone definitions, - cases like the end-of-daylight-savings-time occur with no way of resolving + cases like the end-of-daylight-saving-time occur with no way of resolving the ambiguity. For example, in 1915 Warsaw switched from Warsaw time to Central European time. So at the stroke of midnight on August 5th 1915 the clocks were wound back 24 minutes creating an ambiguous time period that cannot be specified without referring to the timezone abbreviation or the actual UTC offset. In this case midnight happened twice, neither - time during a daylight savings time period: + time during a daylight saving time period: >>> warsaw = pytz.timezone('Europe/Warsaw') >>> loc_dt1 = warsaw.localize(datetime(1915, 8, 4, 23, 59, 59), is_dst=False) @@ -368,7 +373,7 @@ Description: pytz - World Timezone Definitions for Python The only way of creating a time during the missing 24 minutes is converting from another timezone - because neither of the timezones - involved where in daylight savings mode the API simply provides no way + involved where in daylight saving mode the API simply provides no way to express it: >>> utc_dt = datetime(1915, 8, 4, 22, 36, tzinfo=pytz.utc) @@ -424,13 +429,19 @@ Description: pytz - World Timezone Definitions for Python What is UTC ~~~~~~~~~~~ - 'UTC' is Universal Time, also known as Greenwich Mean Time or GMT - in the United Kingdom. All other timezones are given as offsets from - UTC. No daylight savings time occurs in UTC, making it a useful timezone - to perform date arithmetic without worrying about the confusion and - ambiguities caused by daylight savings time transitions, your country - changing its timezone, or mobile computers that move roam through - multiple timezones. + 'UTC' is `Coordinated Universal Time`_. It is a successor to, but distinct + from, Greenwich Mean Time (GMT) and the various definitions of Universal + Time. UTC is now the worldwide standard for regulating clocks and time + measurement. + + All other timezones are defined relative to UTC, and include offsets like + UTC+0800 - hours to add or subtract from UTC to derive the local time. No + daylight saving time occurs in UTC, making it a useful timezone to perform + date arithmetic without worrying about the confusion and ambiguities caused + by daylight saving time transitions, your country changing its timezone, or + mobile computers that roam through multiple timezones. + + .. _Coordinated Universal Time: https://en.wikipedia.org/wiki/Coordinated_Universal_Time Helpers @@ -567,7 +578,7 @@ Description: pytz - World Timezone Definitions for Python Keywords: timezone,tzinfo,datetime,olson,time -Platform: Independent +Platform: Independant Classifier: Development Status :: 6 - Mature Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License diff --git a/python/ext-libs/pytz-2013.9-py2.7.egg-info/SOURCES.txt b/python/ext-libs/pytz-2014.7-py2.7.egg-info/SOURCES.txt similarity index 99% rename from python/ext-libs/pytz-2013.9-py2.7.egg-info/SOURCES.txt rename to python/ext-libs/pytz-2014.7-py2.7.egg-info/SOURCES.txt index 9a35f51e7dbd..f13bdfecedca 100644 --- a/python/ext-libs/pytz-2013.9-py2.7.egg-info/SOURCES.txt +++ b/python/ext-libs/pytz-2014.7-py2.7.egg-info/SOURCES.txt @@ -67,6 +67,7 @@ pytz/zoneinfo/iso3166.tab pytz/zoneinfo/localtime pytz/zoneinfo/posixrules pytz/zoneinfo/zone.tab +pytz/zoneinfo/zone1970.tab pytz/zoneinfo/Africa/Abidjan pytz/zoneinfo/Africa/Accra pytz/zoneinfo/Africa/Addis_Ababa @@ -295,6 +296,7 @@ pytz/zoneinfo/Antarctica/Palmer pytz/zoneinfo/Antarctica/Rothera pytz/zoneinfo/Antarctica/South_Pole pytz/zoneinfo/Antarctica/Syowa +pytz/zoneinfo/Antarctica/Troll pytz/zoneinfo/Antarctica/Vostok pytz/zoneinfo/Arctic/Longyearbyen pytz/zoneinfo/Asia/Aden @@ -313,6 +315,7 @@ pytz/zoneinfo/Asia/Beirut pytz/zoneinfo/Asia/Bishkek pytz/zoneinfo/Asia/Brunei pytz/zoneinfo/Asia/Calcutta +pytz/zoneinfo/Asia/Chita pytz/zoneinfo/Asia/Choibalsan pytz/zoneinfo/Asia/Chongqing pytz/zoneinfo/Asia/Chungking @@ -370,6 +373,7 @@ pytz/zoneinfo/Asia/Samarkand pytz/zoneinfo/Asia/Seoul pytz/zoneinfo/Asia/Shanghai pytz/zoneinfo/Asia/Singapore +pytz/zoneinfo/Asia/Srednekolymsk pytz/zoneinfo/Asia/Taipei pytz/zoneinfo/Asia/Tashkent pytz/zoneinfo/Asia/Tbilisi diff --git a/python/ext-libs/pytz-2013.9-py2.7.egg-info/dependency_links.txt b/python/ext-libs/pytz-2014.7-py2.7.egg-info/dependency_links.txt similarity index 100% rename from python/ext-libs/pytz-2013.9-py2.7.egg-info/dependency_links.txt rename to python/ext-libs/pytz-2014.7-py2.7.egg-info/dependency_links.txt diff --git a/python/ext-libs/pytz-2013.9-py2.7.egg-info/installed-files.txt b/python/ext-libs/pytz-2014.7-py2.7.egg-info/installed-files.txt similarity index 99% rename from python/ext-libs/pytz-2013.9-py2.7.egg-info/installed-files.txt rename to python/ext-libs/pytz-2014.7-py2.7.egg-info/installed-files.txt index 4909fa50436c..643b5f568a65 100644 --- a/python/ext-libs/pytz-2013.9-py2.7.egg-info/installed-files.txt +++ b/python/ext-libs/pytz-2014.7-py2.7.egg-info/installed-files.txt @@ -51,6 +51,7 @@ ../pytz/zoneinfo/Egypt ../pytz/zoneinfo/zone.tab ../pytz/zoneinfo/MET +../pytz/zoneinfo/zone1970.tab ../pytz/zoneinfo/MST ../pytz/zoneinfo/NZ-CHAT ../pytz/zoneinfo/Europe/Gibraltar @@ -156,6 +157,7 @@ ../pytz/zoneinfo/Asia/Kathmandu ../pytz/zoneinfo/Asia/Damascus ../pytz/zoneinfo/Asia/Baku +../pytz/zoneinfo/Asia/Srednekolymsk ../pytz/zoneinfo/Asia/Anadyr ../pytz/zoneinfo/Asia/Baghdad ../pytz/zoneinfo/Asia/Kuala_Lumpur @@ -173,6 +175,7 @@ ../pytz/zoneinfo/Asia/Hebron ../pytz/zoneinfo/Asia/Tokyo ../pytz/zoneinfo/Asia/Novokuznetsk +../pytz/zoneinfo/Asia/Chita ../pytz/zoneinfo/Asia/Dushanbe ../pytz/zoneinfo/Asia/Aqtobe ../pytz/zoneinfo/Asia/Tel_Aviv @@ -277,6 +280,7 @@ ../pytz/zoneinfo/Antarctica/South_Pole ../pytz/zoneinfo/Antarctica/Davis ../pytz/zoneinfo/Antarctica/Palmer +../pytz/zoneinfo/Antarctica/Troll ../pytz/zoneinfo/Antarctica/Rothera ../pytz/zoneinfo/Antarctica/DumontDUrville ../pytz/zoneinfo/Antarctica/McMurdo diff --git a/python/ext-libs/pytz-2013.9-py2.7.egg-info/top_level.txt b/python/ext-libs/pytz-2014.7-py2.7.egg-info/top_level.txt similarity index 100% rename from python/ext-libs/pytz-2013.9-py2.7.egg-info/top_level.txt rename to python/ext-libs/pytz-2014.7-py2.7.egg-info/top_level.txt diff --git a/python/ext-libs/pytz-2013.9-py2.7.egg-info/zip-safe b/python/ext-libs/pytz-2014.7-py2.7.egg-info/zip-safe similarity index 100% rename from python/ext-libs/pytz-2013.9-py2.7.egg-info/zip-safe rename to python/ext-libs/pytz-2014.7-py2.7.egg-info/zip-safe diff --git a/python/ext-libs/pytz/__init__.py b/python/ext-libs/pytz/__init__.py index eed68c4bf718..da80e71097ee 100644 --- a/python/ext-libs/pytz/__init__.py +++ b/python/ext-libs/pytz/__init__.py @@ -9,8 +9,8 @@ ''' # The Olson database is updated several times a year. -OLSON_VERSION = '2013i' -VERSION = '2013.9' # Switching to pip compatible version numbering. +OLSON_VERSION = '2014g' +VERSION = '2014.7' # Switching to pip compatible version numbering. __version__ = VERSION OLSEN_VERSION = OLSON_VERSION # Old releases had this misspelling @@ -716,6 +716,7 @@ def _test(): 'Antarctica/Rothera', 'Antarctica/South_Pole', 'Antarctica/Syowa', + 'Antarctica/Troll', 'Antarctica/Vostok', 'Arctic/Longyearbyen', 'Asia/Aden', @@ -734,6 +735,7 @@ def _test(): 'Asia/Bishkek', 'Asia/Brunei', 'Asia/Calcutta', + 'Asia/Chita', 'Asia/Choibalsan', 'Asia/Chongqing', 'Asia/Chungking', @@ -791,6 +793,7 @@ def _test(): 'Asia/Seoul', 'Asia/Shanghai', 'Asia/Singapore', + 'Asia/Srednekolymsk', 'Asia/Taipei', 'Asia/Tashkent', 'Asia/Tbilisi', @@ -1279,6 +1282,7 @@ def _test(): 'Antarctica/Palmer', 'Antarctica/Rothera', 'Antarctica/Syowa', + 'Antarctica/Troll', 'Antarctica/Vostok', 'Arctic/Longyearbyen', 'Asia/Aden', @@ -1295,8 +1299,8 @@ def _test(): 'Asia/Beirut', 'Asia/Bishkek', 'Asia/Brunei', + 'Asia/Chita', 'Asia/Choibalsan', - 'Asia/Chongqing', 'Asia/Colombo', 'Asia/Damascus', 'Asia/Dhaka', @@ -1304,7 +1308,6 @@ def _test(): 'Asia/Dubai', 'Asia/Dushanbe', 'Asia/Gaza', - 'Asia/Harbin', 'Asia/Hebron', 'Asia/Ho_Chi_Minh', 'Asia/Hong_Kong', @@ -1316,7 +1319,6 @@ def _test(): 'Asia/Kabul', 'Asia/Kamchatka', 'Asia/Karachi', - 'Asia/Kashgar', 'Asia/Kathmandu', 'Asia/Khandyga', 'Asia/Kolkata', @@ -1346,6 +1348,7 @@ def _test(): 'Asia/Seoul', 'Asia/Shanghai', 'Asia/Singapore', + 'Asia/Srednekolymsk', 'Asia/Taipei', 'Asia/Tashkent', 'Asia/Tbilisi', diff --git a/python/ext-libs/pytz/tzinfo.py b/python/ext-libs/pytz/tzinfo.py index 459b88a8006d..d53e9ff172c0 100644 --- a/python/ext-libs/pytz/tzinfo.py +++ b/python/ext-libs/pytz/tzinfo.py @@ -142,14 +142,14 @@ def __repr__(self): def __reduce__(self): # Special pickle to zone remains a singleton and to cope with - # database changes. + # database changes. return pytz._p, (self.zone,) class DstTzInfo(BaseTzInfo): '''A timezone that has a variable offset from UTC - The offset might change if daylight savings time comes into effect, + The offset might change if daylight saving time comes into effect, or at a point in history when the region decides to change their timezone definition. ''' @@ -248,7 +248,7 @@ def localize(self, dt, is_dst=False): than passing a tzinfo argument to a datetime constructor. is_dst is used to determine the correct timezone in the ambigous - period at the end of daylight savings time. + period at the end of daylight saving time. >>> from pytz import timezone >>> fmt = '%Y-%m-%d %H:%M:%S %Z (%z)' @@ -264,7 +264,7 @@ def localize(self, dt, is_dst=False): '1:00:00' Use is_dst=None to raise an AmbiguousTimeError for ambiguous - times at the end of daylight savings + times at the end of daylight saving time >>> try: ... loc_dt1 = amdam.localize(dt, is_dst=None) @@ -278,7 +278,7 @@ def localize(self, dt, is_dst=False): True is_dst is also used to determine the correct timezone in the - wallclock times jumped over at the start of daylight savings time. + wallclock times jumped over at the start of daylight saving time. >>> pacific = timezone('US/Pacific') >>> dt = datetime(2008, 3, 9, 2, 0, 0) @@ -362,7 +362,7 @@ def localize(self, dt, is_dst=False): if len(filtered_possible_loc_dt) == 0: filtered_possible_loc_dt = list(possible_loc_dt) - # If we get this far, we have in a weird timezone transition + # If we get this far, we have in a wierd timezone transition # where the clocks have been wound back but is_dst is the same # in both (eg. Europe/Warsaw 1915 when they switched to CET). # At this point, we just have to guess unless we allow more diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Abidjan b/python/ext-libs/pytz/zoneinfo/Africa/Abidjan index 65d19ec2651a..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Abidjan and b/python/ext-libs/pytz/zoneinfo/Africa/Abidjan differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Accra b/python/ext-libs/pytz/zoneinfo/Africa/Accra index 8c473eda0b70..6ff8fb6b235d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Accra and b/python/ext-libs/pytz/zoneinfo/Africa/Accra differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Addis_Ababa b/python/ext-libs/pytz/zoneinfo/Africa/Addis_Ababa index 5a95ab66625c..4dfa06ab707b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Addis_Ababa and b/python/ext-libs/pytz/zoneinfo/Africa/Addis_Ababa differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Algiers b/python/ext-libs/pytz/zoneinfo/Africa/Algiers index c88883117117..2a25f3ac268f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Algiers and b/python/ext-libs/pytz/zoneinfo/Africa/Algiers differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Asmara b/python/ext-libs/pytz/zoneinfo/Africa/Asmara index d1e876e2ff93..0bc80c440007 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Asmara and b/python/ext-libs/pytz/zoneinfo/Africa/Asmara differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Asmera b/python/ext-libs/pytz/zoneinfo/Africa/Asmera index d1e876e2ff93..0bc80c440007 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Asmera and b/python/ext-libs/pytz/zoneinfo/Africa/Asmera differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Bamako b/python/ext-libs/pytz/zoneinfo/Africa/Bamako index da18d7137740..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Bamako and b/python/ext-libs/pytz/zoneinfo/Africa/Bamako differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Bangui b/python/ext-libs/pytz/zoneinfo/Africa/Bangui index 883e597eb0f3..b1c97cc5a77e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Bangui and b/python/ext-libs/pytz/zoneinfo/Africa/Bangui differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Banjul b/python/ext-libs/pytz/zoneinfo/Africa/Banjul index a85a7d87261f..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Banjul and b/python/ext-libs/pytz/zoneinfo/Africa/Banjul differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Bissau b/python/ext-libs/pytz/zoneinfo/Africa/Bissau index ab4a195a8804..0696667ce83f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Bissau and b/python/ext-libs/pytz/zoneinfo/Africa/Bissau differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Blantyre b/python/ext-libs/pytz/zoneinfo/Africa/Blantyre index 2972580dad6a..aebba5d95909 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Blantyre and b/python/ext-libs/pytz/zoneinfo/Africa/Blantyre differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Brazzaville b/python/ext-libs/pytz/zoneinfo/Africa/Brazzaville index abb0c08700a2..b1c97cc5a77e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Brazzaville and b/python/ext-libs/pytz/zoneinfo/Africa/Brazzaville differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Bujumbura b/python/ext-libs/pytz/zoneinfo/Africa/Bujumbura index cac565245744..fff46c52044a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Bujumbura and b/python/ext-libs/pytz/zoneinfo/Africa/Bujumbura differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Cairo b/python/ext-libs/pytz/zoneinfo/Africa/Cairo index 1c6a2fc8fa68..0eeed1138f28 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Cairo and b/python/ext-libs/pytz/zoneinfo/Africa/Cairo differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Casablanca b/python/ext-libs/pytz/zoneinfo/Africa/Casablanca index 51cf51bdad45..c001c375ffb0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Casablanca and b/python/ext-libs/pytz/zoneinfo/Africa/Casablanca differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Ceuta b/python/ext-libs/pytz/zoneinfo/Africa/Ceuta index c9b0c08bc86c..6227e2bb09f7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Ceuta and b/python/ext-libs/pytz/zoneinfo/Africa/Ceuta differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Conakry b/python/ext-libs/pytz/zoneinfo/Africa/Conakry index 75b8523fb299..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Conakry and b/python/ext-libs/pytz/zoneinfo/Africa/Conakry differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Dakar b/python/ext-libs/pytz/zoneinfo/Africa/Dakar index 31104133c293..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Dakar and b/python/ext-libs/pytz/zoneinfo/Africa/Dakar differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Dar_es_Salaam b/python/ext-libs/pytz/zoneinfo/Africa/Dar_es_Salaam index 720d76c8300f..2ddddc5f35f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Dar_es_Salaam and b/python/ext-libs/pytz/zoneinfo/Africa/Dar_es_Salaam differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Djibouti b/python/ext-libs/pytz/zoneinfo/Africa/Djibouti index 297d93a3e464..559aabc163c2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Djibouti and b/python/ext-libs/pytz/zoneinfo/Africa/Djibouti differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Douala b/python/ext-libs/pytz/zoneinfo/Africa/Douala index 8627f2e05e95..b1c97cc5a77e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Douala and b/python/ext-libs/pytz/zoneinfo/Africa/Douala differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/El_Aaiun b/python/ext-libs/pytz/zoneinfo/Africa/El_Aaiun index 08ad52d25a10..805d39e415ab 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/El_Aaiun and b/python/ext-libs/pytz/zoneinfo/Africa/El_Aaiun differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Freetown b/python/ext-libs/pytz/zoneinfo/Africa/Freetown index 720b8e3c905e..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Freetown and b/python/ext-libs/pytz/zoneinfo/Africa/Freetown differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Gaborone b/python/ext-libs/pytz/zoneinfo/Africa/Gaborone index e2abcb664372..424534c49804 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Gaborone and b/python/ext-libs/pytz/zoneinfo/Africa/Gaborone differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Harare b/python/ext-libs/pytz/zoneinfo/Africa/Harare index 258b39363729..0e53de0a33f1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Harare and b/python/ext-libs/pytz/zoneinfo/Africa/Harare differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Johannesburg b/python/ext-libs/pytz/zoneinfo/Africa/Johannesburg index d1bec7381574..ddf3652e159e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Johannesburg and b/python/ext-libs/pytz/zoneinfo/Africa/Johannesburg differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Juba b/python/ext-libs/pytz/zoneinfo/Africa/Juba index 6f62fd764cef..3629188215dd 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Juba and b/python/ext-libs/pytz/zoneinfo/Africa/Juba differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Kampala b/python/ext-libs/pytz/zoneinfo/Africa/Kampala index b018ba26f2f3..c6b5720e06ed 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Kampala and b/python/ext-libs/pytz/zoneinfo/Africa/Kampala differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Khartoum b/python/ext-libs/pytz/zoneinfo/Africa/Khartoum index 6f62fd764cef..3629188215dd 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Khartoum and b/python/ext-libs/pytz/zoneinfo/Africa/Khartoum differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Kigali b/python/ext-libs/pytz/zoneinfo/Africa/Kigali index c9623c56e853..b99c20940b2d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Kigali and b/python/ext-libs/pytz/zoneinfo/Africa/Kigali differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Kinshasa b/python/ext-libs/pytz/zoneinfo/Africa/Kinshasa index e8481f3476aa..b1c97cc5a77e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Kinshasa and b/python/ext-libs/pytz/zoneinfo/Africa/Kinshasa differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Lagos b/python/ext-libs/pytz/zoneinfo/Africa/Lagos index cbdc0450fc3b..b1c97cc5a77e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Lagos and b/python/ext-libs/pytz/zoneinfo/Africa/Lagos differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Libreville b/python/ext-libs/pytz/zoneinfo/Africa/Libreville index d7691ae56f56..b1c97cc5a77e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Libreville and b/python/ext-libs/pytz/zoneinfo/Africa/Libreville differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Lome b/python/ext-libs/pytz/zoneinfo/Africa/Lome index 297ec5dae378..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Lome and b/python/ext-libs/pytz/zoneinfo/Africa/Lome differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Luanda b/python/ext-libs/pytz/zoneinfo/Africa/Luanda index 576b2043cfb3..b1c97cc5a77e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Luanda and b/python/ext-libs/pytz/zoneinfo/Africa/Luanda differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Lubumbashi b/python/ext-libs/pytz/zoneinfo/Africa/Lubumbashi index d3fab52a6ce7..05aad3c8a580 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Lubumbashi and b/python/ext-libs/pytz/zoneinfo/Africa/Lubumbashi differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Lusaka b/python/ext-libs/pytz/zoneinfo/Africa/Lusaka index 87d7a95fc7f1..612a8a07a0b5 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Lusaka and b/python/ext-libs/pytz/zoneinfo/Africa/Lusaka differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Malabo b/python/ext-libs/pytz/zoneinfo/Africa/Malabo index c70de1f99d9f..b1c97cc5a77e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Malabo and b/python/ext-libs/pytz/zoneinfo/Africa/Malabo differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Maputo b/python/ext-libs/pytz/zoneinfo/Africa/Maputo index 31cfad771a5c..5b871dbaa7c2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Maputo and b/python/ext-libs/pytz/zoneinfo/Africa/Maputo differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Maseru b/python/ext-libs/pytz/zoneinfo/Africa/Maseru index 117006eead2a..7fb3b0a7286c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Maseru and b/python/ext-libs/pytz/zoneinfo/Africa/Maseru differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Mbabane b/python/ext-libs/pytz/zoneinfo/Africa/Mbabane index be6ed60baaf8..8f0d40f2607c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Mbabane and b/python/ext-libs/pytz/zoneinfo/Africa/Mbabane differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Mogadishu b/python/ext-libs/pytz/zoneinfo/Africa/Mogadishu index bd08463429de..3c278ab236a3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Mogadishu and b/python/ext-libs/pytz/zoneinfo/Africa/Mogadishu differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Monrovia b/python/ext-libs/pytz/zoneinfo/Africa/Monrovia index bd2fa4e6318a..0f2294ea4655 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Monrovia and b/python/ext-libs/pytz/zoneinfo/Africa/Monrovia differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Nairobi b/python/ext-libs/pytz/zoneinfo/Africa/Nairobi index 72676bb987d4..750d3dc14cab 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Nairobi and b/python/ext-libs/pytz/zoneinfo/Africa/Nairobi differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Ndjamena b/python/ext-libs/pytz/zoneinfo/Africa/Ndjamena index 8779590e04a6..bbfe19d60a5f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Ndjamena and b/python/ext-libs/pytz/zoneinfo/Africa/Ndjamena differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Niamey b/python/ext-libs/pytz/zoneinfo/Africa/Niamey index 799381c310ca..b1c97cc5a77e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Niamey and b/python/ext-libs/pytz/zoneinfo/Africa/Niamey differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Nouakchott b/python/ext-libs/pytz/zoneinfo/Africa/Nouakchott index ead817afcdd3..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Nouakchott and b/python/ext-libs/pytz/zoneinfo/Africa/Nouakchott differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Ouagadougou b/python/ext-libs/pytz/zoneinfo/Africa/Ouagadougou index df782a489c29..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Ouagadougou and b/python/ext-libs/pytz/zoneinfo/Africa/Ouagadougou differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Porto-Novo b/python/ext-libs/pytz/zoneinfo/Africa/Porto-Novo index 600a30d82ac6..b1c97cc5a77e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Porto-Novo and b/python/ext-libs/pytz/zoneinfo/Africa/Porto-Novo differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Sao_Tome b/python/ext-libs/pytz/zoneinfo/Africa/Sao_Tome index ddf7fb42e4e9..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Sao_Tome and b/python/ext-libs/pytz/zoneinfo/Africa/Sao_Tome differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Timbuktu b/python/ext-libs/pytz/zoneinfo/Africa/Timbuktu index da18d7137740..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Timbuktu and b/python/ext-libs/pytz/zoneinfo/Africa/Timbuktu differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Tripoli b/python/ext-libs/pytz/zoneinfo/Africa/Tripoli index bd885315f84f..b32e2202f572 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Tripoli and b/python/ext-libs/pytz/zoneinfo/Africa/Tripoli differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Tunis b/python/ext-libs/pytz/zoneinfo/Africa/Tunis index dd559ee76340..4bd3885a96f6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Tunis and b/python/ext-libs/pytz/zoneinfo/Africa/Tunis differ diff --git a/python/ext-libs/pytz/zoneinfo/Africa/Windhoek b/python/ext-libs/pytz/zoneinfo/Africa/Windhoek index 6f22b0a7df8c..33bdfdf21714 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Africa/Windhoek and b/python/ext-libs/pytz/zoneinfo/Africa/Windhoek differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Adak b/python/ext-libs/pytz/zoneinfo/America/Adak index 391ec98ec0f3..b0a5dd60dc21 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Adak and b/python/ext-libs/pytz/zoneinfo/America/Adak differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Anchorage b/python/ext-libs/pytz/zoneinfo/America/Anchorage index d14735026a09..a4627cac0628 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Anchorage and b/python/ext-libs/pytz/zoneinfo/America/Anchorage differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Anguilla b/python/ext-libs/pytz/zoneinfo/America/Anguilla index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Anguilla and b/python/ext-libs/pytz/zoneinfo/America/Anguilla differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Antigua b/python/ext-libs/pytz/zoneinfo/America/Antigua index 608b635977bd..66ab1474dcd3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Antigua and b/python/ext-libs/pytz/zoneinfo/America/Antigua differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Araguaina b/python/ext-libs/pytz/zoneinfo/America/Araguaina index ceb7977cf5f8..507ea469ff4f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Araguaina and b/python/ext-libs/pytz/zoneinfo/America/Araguaina differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/Buenos_Aires b/python/ext-libs/pytz/zoneinfo/America/Argentina/Buenos_Aires index 5a52a51fc85a..a1fae8c8d7a8 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/Buenos_Aires and b/python/ext-libs/pytz/zoneinfo/America/Argentina/Buenos_Aires differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/Catamarca b/python/ext-libs/pytz/zoneinfo/America/Argentina/Catamarca index b9c987bb5689..7cbc9f4bddf7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/Catamarca and b/python/ext-libs/pytz/zoneinfo/America/Argentina/Catamarca differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/ComodRivadavia b/python/ext-libs/pytz/zoneinfo/America/Argentina/ComodRivadavia index b9c987bb5689..7cbc9f4bddf7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/ComodRivadavia and b/python/ext-libs/pytz/zoneinfo/America/Argentina/ComodRivadavia differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/Cordoba b/python/ext-libs/pytz/zoneinfo/America/Argentina/Cordoba index a703e957d5eb..cd97a24bdb7b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/Cordoba and b/python/ext-libs/pytz/zoneinfo/America/Argentina/Cordoba differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/Jujuy b/python/ext-libs/pytz/zoneinfo/America/Argentina/Jujuy index 86800f0344a0..7be3eeb6d042 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/Jujuy and b/python/ext-libs/pytz/zoneinfo/America/Argentina/Jujuy differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/La_Rioja b/python/ext-libs/pytz/zoneinfo/America/Argentina/La_Rioja index 333819a15f79..1296ed44d5f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/La_Rioja and b/python/ext-libs/pytz/zoneinfo/America/Argentina/La_Rioja differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/Mendoza b/python/ext-libs/pytz/zoneinfo/America/Argentina/Mendoza index 76afd5909e0e..f9eb526c7bef 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/Mendoza and b/python/ext-libs/pytz/zoneinfo/America/Argentina/Mendoza differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/Rio_Gallegos b/python/ext-libs/pytz/zoneinfo/America/Argentina/Rio_Gallegos index 65d0230a2d06..8fd203d1d2a1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/Rio_Gallegos and b/python/ext-libs/pytz/zoneinfo/America/Argentina/Rio_Gallegos differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/Salta b/python/ext-libs/pytz/zoneinfo/America/Argentina/Salta index 963917a01a26..5778059f3531 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/Salta and b/python/ext-libs/pytz/zoneinfo/America/Argentina/Salta differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/San_Juan b/python/ext-libs/pytz/zoneinfo/America/Argentina/San_Juan index fe7007b85ca4..8670279e40f6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/San_Juan and b/python/ext-libs/pytz/zoneinfo/America/Argentina/San_Juan differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/San_Luis b/python/ext-libs/pytz/zoneinfo/America/Argentina/San_Luis index e19478819e73..51eb1d84eaa4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/San_Luis and b/python/ext-libs/pytz/zoneinfo/America/Argentina/San_Luis differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/Tucuman b/python/ext-libs/pytz/zoneinfo/America/Argentina/Tucuman index be7bd271639a..694093e7c4e6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/Tucuman and b/python/ext-libs/pytz/zoneinfo/America/Argentina/Tucuman differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Argentina/Ushuaia b/python/ext-libs/pytz/zoneinfo/America/Argentina/Ushuaia index 18590effb093..dc42621da6d1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Argentina/Ushuaia and b/python/ext-libs/pytz/zoneinfo/America/Argentina/Ushuaia differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Aruba b/python/ext-libs/pytz/zoneinfo/America/Aruba index 2d01c1886049..05e77ab4b3c2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Aruba and b/python/ext-libs/pytz/zoneinfo/America/Aruba differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Asuncion b/python/ext-libs/pytz/zoneinfo/America/Asuncion index 59f78918faaa..79541fddcbdf 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Asuncion and b/python/ext-libs/pytz/zoneinfo/America/Asuncion differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Atikokan b/python/ext-libs/pytz/zoneinfo/America/Atikokan index 1b49e37c943b..5708b55ac6bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Atikokan and b/python/ext-libs/pytz/zoneinfo/America/Atikokan differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Atka b/python/ext-libs/pytz/zoneinfo/America/Atka index 391ec98ec0f3..b0a5dd60dc21 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Atka and b/python/ext-libs/pytz/zoneinfo/America/Atka differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Bahia b/python/ext-libs/pytz/zoneinfo/America/Bahia index 403d9d1060ea..3b599585a7ff 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Bahia and b/python/ext-libs/pytz/zoneinfo/America/Bahia differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Bahia_Banderas b/python/ext-libs/pytz/zoneinfo/America/Bahia_Banderas index cd531078d0e8..21e2b719f33d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Bahia_Banderas and b/python/ext-libs/pytz/zoneinfo/America/Bahia_Banderas differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Barbados b/python/ext-libs/pytz/zoneinfo/America/Barbados index 7bb7ac4d6ab6..633993601486 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Barbados and b/python/ext-libs/pytz/zoneinfo/America/Barbados differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Belem b/python/ext-libs/pytz/zoneinfo/America/Belem index 9c37b6a5c493..d85c0f72792e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Belem and b/python/ext-libs/pytz/zoneinfo/America/Belem differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Belize b/python/ext-libs/pytz/zoneinfo/America/Belize index a18cd39058fa..eada52e70c77 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Belize and b/python/ext-libs/pytz/zoneinfo/America/Belize differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Blanc-Sablon b/python/ext-libs/pytz/zoneinfo/America/Blanc-Sablon index 8a33789afcbb..abcde7d98693 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Blanc-Sablon and b/python/ext-libs/pytz/zoneinfo/America/Blanc-Sablon differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Boa_Vista b/python/ext-libs/pytz/zoneinfo/America/Boa_Vista index cb15afbf5c30..2466a25f9fa4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Boa_Vista and b/python/ext-libs/pytz/zoneinfo/America/Boa_Vista differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Bogota b/python/ext-libs/pytz/zoneinfo/America/Bogota index bddda98a2c92..7a5a445ace50 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Bogota and b/python/ext-libs/pytz/zoneinfo/America/Bogota differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Boise b/python/ext-libs/pytz/zoneinfo/America/Boise index 441afe55c413..ada6d64b1afc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Boise and b/python/ext-libs/pytz/zoneinfo/America/Boise differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Buenos_Aires b/python/ext-libs/pytz/zoneinfo/America/Buenos_Aires index 5a52a51fc85a..a1fae8c8d7a8 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Buenos_Aires and b/python/ext-libs/pytz/zoneinfo/America/Buenos_Aires differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Cambridge_Bay b/python/ext-libs/pytz/zoneinfo/America/Cambridge_Bay index 99c77c5b2083..58e21baac34d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Cambridge_Bay and b/python/ext-libs/pytz/zoneinfo/America/Cambridge_Bay differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Campo_Grande b/python/ext-libs/pytz/zoneinfo/America/Campo_Grande index 46840981043e..d810ae568b45 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Campo_Grande and b/python/ext-libs/pytz/zoneinfo/America/Campo_Grande differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Cancun b/python/ext-libs/pytz/zoneinfo/America/Cancun index 90993faa7051..a99eedd75654 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Cancun and b/python/ext-libs/pytz/zoneinfo/America/Cancun differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Caracas b/python/ext-libs/pytz/zoneinfo/America/Caracas index d96a5c00bffe..15b9a52c2c4c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Caracas and b/python/ext-libs/pytz/zoneinfo/America/Caracas differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Catamarca b/python/ext-libs/pytz/zoneinfo/America/Catamarca index b9c987bb5689..7cbc9f4bddf7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Catamarca and b/python/ext-libs/pytz/zoneinfo/America/Catamarca differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Cayenne b/python/ext-libs/pytz/zoneinfo/America/Cayenne index 7109a98ec5ce..bffe9b02ec9e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Cayenne and b/python/ext-libs/pytz/zoneinfo/America/Cayenne differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Cayman b/python/ext-libs/pytz/zoneinfo/America/Cayman index 98d9b98d3b84..0eb14b75c2d6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Cayman and b/python/ext-libs/pytz/zoneinfo/America/Cayman differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Chicago b/python/ext-libs/pytz/zoneinfo/America/Chicago index 71aae7246a30..3dd8f0fa82a6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Chicago and b/python/ext-libs/pytz/zoneinfo/America/Chicago differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Chihuahua b/python/ext-libs/pytz/zoneinfo/America/Chihuahua index b2687241cd05..e3adbdbfb25b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Chihuahua and b/python/ext-libs/pytz/zoneinfo/America/Chihuahua differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Coral_Harbour b/python/ext-libs/pytz/zoneinfo/America/Coral_Harbour index 1b49e37c943b..5708b55ac6bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Coral_Harbour and b/python/ext-libs/pytz/zoneinfo/America/Coral_Harbour differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Cordoba b/python/ext-libs/pytz/zoneinfo/America/Cordoba index a703e957d5eb..cd97a24bdb7b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Cordoba and b/python/ext-libs/pytz/zoneinfo/America/Cordoba differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Costa_Rica b/python/ext-libs/pytz/zoneinfo/America/Costa_Rica index 018d945b11aa..c247133e334b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Costa_Rica and b/python/ext-libs/pytz/zoneinfo/America/Costa_Rica differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Creston b/python/ext-libs/pytz/zoneinfo/America/Creston index 1cf719ae8374..798f627a81e2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Creston and b/python/ext-libs/pytz/zoneinfo/America/Creston differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Cuiaba b/python/ext-libs/pytz/zoneinfo/America/Cuiaba index 232ef670ff53..e3aec8ccdfe7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Cuiaba and b/python/ext-libs/pytz/zoneinfo/America/Cuiaba differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Curacao b/python/ext-libs/pytz/zoneinfo/America/Curacao index 2d01c1886049..05e77ab4b3c2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Curacao and b/python/ext-libs/pytz/zoneinfo/America/Curacao differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Danmarkshavn b/python/ext-libs/pytz/zoneinfo/America/Danmarkshavn index 9feacfb1c9ff..a8b58ada85a8 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Danmarkshavn and b/python/ext-libs/pytz/zoneinfo/America/Danmarkshavn differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Dawson b/python/ext-libs/pytz/zoneinfo/America/Dawson index fab060999850..61c96889b074 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Dawson and b/python/ext-libs/pytz/zoneinfo/America/Dawson differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Dawson_Creek b/python/ext-libs/pytz/zoneinfo/America/Dawson_Creek index c3fb166b0887..78f907630801 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Dawson_Creek and b/python/ext-libs/pytz/zoneinfo/America/Dawson_Creek differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Denver b/python/ext-libs/pytz/zoneinfo/America/Denver index f8908febf220..7fc669171f88 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Denver and b/python/ext-libs/pytz/zoneinfo/America/Denver differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Detroit b/python/ext-libs/pytz/zoneinfo/America/Detroit index da53d46df347..a123b331e72f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Detroit and b/python/ext-libs/pytz/zoneinfo/America/Detroit differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Dominica b/python/ext-libs/pytz/zoneinfo/America/Dominica index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Dominica and b/python/ext-libs/pytz/zoneinfo/America/Dominica differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Edmonton b/python/ext-libs/pytz/zoneinfo/America/Edmonton index 3fa0579891a9..d02fbcd47f84 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Edmonton and b/python/ext-libs/pytz/zoneinfo/America/Edmonton differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Eirunepe b/python/ext-libs/pytz/zoneinfo/America/Eirunepe index c93d917091ef..3359731e2d23 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Eirunepe and b/python/ext-libs/pytz/zoneinfo/America/Eirunepe differ diff --git a/python/ext-libs/pytz/zoneinfo/America/El_Salvador b/python/ext-libs/pytz/zoneinfo/America/El_Salvador index ac774e83f46b..9b8bc7a8778a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/El_Salvador and b/python/ext-libs/pytz/zoneinfo/America/El_Salvador differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Ensenada b/python/ext-libs/pytz/zoneinfo/America/Ensenada index fffdc24bfc4c..1387475394bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Ensenada and b/python/ext-libs/pytz/zoneinfo/America/Ensenada differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Fort_Wayne b/python/ext-libs/pytz/zoneinfo/America/Fort_Wayne index aa3dfc43730e..4a92c06593d3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Fort_Wayne and b/python/ext-libs/pytz/zoneinfo/America/Fort_Wayne differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Fortaleza b/python/ext-libs/pytz/zoneinfo/America/Fortaleza index 2598c53559d3..c0bcf4dca738 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Fortaleza and b/python/ext-libs/pytz/zoneinfo/America/Fortaleza differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Glace_Bay b/python/ext-libs/pytz/zoneinfo/America/Glace_Bay index 48412a4cbf92..f58522b674c2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Glace_Bay and b/python/ext-libs/pytz/zoneinfo/America/Glace_Bay differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Godthab b/python/ext-libs/pytz/zoneinfo/America/Godthab index 5cb97910f8f7..111d9a8178ca 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Godthab and b/python/ext-libs/pytz/zoneinfo/America/Godthab differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Goose_Bay b/python/ext-libs/pytz/zoneinfo/America/Goose_Bay index 83e5a9b398fd..b4b945e8d8d2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Goose_Bay and b/python/ext-libs/pytz/zoneinfo/America/Goose_Bay differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Grand_Turk b/python/ext-libs/pytz/zoneinfo/America/Grand_Turk index 0dfd686fd554..6cadf96910d8 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Grand_Turk and b/python/ext-libs/pytz/zoneinfo/America/Grand_Turk differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Grenada b/python/ext-libs/pytz/zoneinfo/America/Grenada index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Grenada and b/python/ext-libs/pytz/zoneinfo/America/Grenada differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Guadeloupe b/python/ext-libs/pytz/zoneinfo/America/Guadeloupe index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Guadeloupe and b/python/ext-libs/pytz/zoneinfo/America/Guadeloupe differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Guatemala b/python/ext-libs/pytz/zoneinfo/America/Guatemala index 6118b5ce2d95..abf943be0fe2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Guatemala and b/python/ext-libs/pytz/zoneinfo/America/Guatemala differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Guayaquil b/python/ext-libs/pytz/zoneinfo/America/Guayaquil index e6de7f8da297..08289046dd4a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Guayaquil and b/python/ext-libs/pytz/zoneinfo/America/Guayaquil differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Guyana b/python/ext-libs/pytz/zoneinfo/America/Guyana index 5f98c4a0e88b..036dbe06f502 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Guyana and b/python/ext-libs/pytz/zoneinfo/America/Guyana differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Halifax b/python/ext-libs/pytz/zoneinfo/America/Halifax index 756099abe6ce..f86ece4c4032 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Halifax and b/python/ext-libs/pytz/zoneinfo/America/Halifax differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Havana b/python/ext-libs/pytz/zoneinfo/America/Havana index c2623e05f545..1a58fcdc988e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Havana and b/python/ext-libs/pytz/zoneinfo/America/Havana differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Hermosillo b/python/ext-libs/pytz/zoneinfo/America/Hermosillo index 26c269d96748..ec435c23bc47 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Hermosillo and b/python/ext-libs/pytz/zoneinfo/America/Hermosillo differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Indiana/Indianapolis b/python/ext-libs/pytz/zoneinfo/America/Indiana/Indianapolis index aa3dfc43730e..4a92c06593d3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Indiana/Indianapolis and b/python/ext-libs/pytz/zoneinfo/America/Indiana/Indianapolis differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Indiana/Knox b/python/ext-libs/pytz/zoneinfo/America/Indiana/Knox index 33169f459638..cc785da97de0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Indiana/Knox and b/python/ext-libs/pytz/zoneinfo/America/Indiana/Knox differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Indiana/Marengo b/python/ext-libs/pytz/zoneinfo/America/Indiana/Marengo index 255b739718d2..a23d7b7596fc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Indiana/Marengo and b/python/ext-libs/pytz/zoneinfo/America/Indiana/Marengo differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Indiana/Petersburg b/python/ext-libs/pytz/zoneinfo/America/Indiana/Petersburg index c611106d57e4..f16cb30406e3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Indiana/Petersburg and b/python/ext-libs/pytz/zoneinfo/America/Indiana/Petersburg differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Indiana/Tell_City b/python/ext-libs/pytz/zoneinfo/America/Indiana/Tell_City index 97e319e34350..0250bf90f8fc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Indiana/Tell_City and b/python/ext-libs/pytz/zoneinfo/America/Indiana/Tell_City differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Indiana/Vevay b/python/ext-libs/pytz/zoneinfo/America/Indiana/Vevay index de6167c08291..e934de61adb3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Indiana/Vevay and b/python/ext-libs/pytz/zoneinfo/America/Indiana/Vevay differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Indiana/Vincennes b/python/ext-libs/pytz/zoneinfo/America/Indiana/Vincennes index b79f6725b62a..adbdbeee629e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Indiana/Vincennes and b/python/ext-libs/pytz/zoneinfo/America/Indiana/Vincennes differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Indiana/Winamac b/python/ext-libs/pytz/zoneinfo/America/Indiana/Winamac index b2611e75ee8b..b34f7b27eee8 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Indiana/Winamac and b/python/ext-libs/pytz/zoneinfo/America/Indiana/Winamac differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Indianapolis b/python/ext-libs/pytz/zoneinfo/America/Indianapolis index aa3dfc43730e..4a92c06593d3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Indianapolis and b/python/ext-libs/pytz/zoneinfo/America/Indianapolis differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Inuvik b/python/ext-libs/pytz/zoneinfo/America/Inuvik index c17af37f5f60..077fad4fea55 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Inuvik and b/python/ext-libs/pytz/zoneinfo/America/Inuvik differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Iqaluit b/python/ext-libs/pytz/zoneinfo/America/Iqaluit index cea5c2e0f30f..e67b71fe7ef7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Iqaluit and b/python/ext-libs/pytz/zoneinfo/America/Iqaluit differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Jamaica b/python/ext-libs/pytz/zoneinfo/America/Jamaica index b89c18787ece..24ea5dc09ba7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Jamaica and b/python/ext-libs/pytz/zoneinfo/America/Jamaica differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Jujuy b/python/ext-libs/pytz/zoneinfo/America/Jujuy index 86800f0344a0..7be3eeb6d042 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Jujuy and b/python/ext-libs/pytz/zoneinfo/America/Jujuy differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Juneau b/python/ext-libs/pytz/zoneinfo/America/Juneau index 48bd37e88e27..ade50a8eeaa1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Juneau and b/python/ext-libs/pytz/zoneinfo/America/Juneau differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Kentucky/Louisville b/python/ext-libs/pytz/zoneinfo/America/Kentucky/Louisville index 65e7e1904951..fdf2e88b48ce 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Kentucky/Louisville and b/python/ext-libs/pytz/zoneinfo/America/Kentucky/Louisville differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Kentucky/Monticello b/python/ext-libs/pytz/zoneinfo/America/Kentucky/Monticello index fc2f1b0df86e..60991aa38f5c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Kentucky/Monticello and b/python/ext-libs/pytz/zoneinfo/America/Kentucky/Monticello differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Knox_IN b/python/ext-libs/pytz/zoneinfo/America/Knox_IN index 33169f459638..cc785da97de0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Knox_IN and b/python/ext-libs/pytz/zoneinfo/America/Knox_IN differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Kralendijk b/python/ext-libs/pytz/zoneinfo/America/Kralendijk index 2d01c1886049..05e77ab4b3c2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Kralendijk and b/python/ext-libs/pytz/zoneinfo/America/Kralendijk differ diff --git a/python/ext-libs/pytz/zoneinfo/America/La_Paz b/python/ext-libs/pytz/zoneinfo/America/La_Paz index 2a5a15e4c4f0..cedf0b3afaf2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/La_Paz and b/python/ext-libs/pytz/zoneinfo/America/La_Paz differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Lima b/python/ext-libs/pytz/zoneinfo/America/Lima index a37eeff7de59..789fa5c2480f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Lima and b/python/ext-libs/pytz/zoneinfo/America/Lima differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Los_Angeles b/python/ext-libs/pytz/zoneinfo/America/Los_Angeles index 3b7ce1dceebf..1fa9149f9a92 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Los_Angeles and b/python/ext-libs/pytz/zoneinfo/America/Los_Angeles differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Louisville b/python/ext-libs/pytz/zoneinfo/America/Louisville index 65e7e1904951..fdf2e88b48ce 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Louisville and b/python/ext-libs/pytz/zoneinfo/America/Louisville differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Lower_Princes b/python/ext-libs/pytz/zoneinfo/America/Lower_Princes index 2d01c1886049..05e77ab4b3c2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Lower_Princes and b/python/ext-libs/pytz/zoneinfo/America/Lower_Princes differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Maceio b/python/ext-libs/pytz/zoneinfo/America/Maceio index b5201e81d42f..de74990986bd 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Maceio and b/python/ext-libs/pytz/zoneinfo/America/Maceio differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Managua b/python/ext-libs/pytz/zoneinfo/America/Managua index f1c35040ce46..c543ffd475e3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Managua and b/python/ext-libs/pytz/zoneinfo/America/Managua differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Manaus b/python/ext-libs/pytz/zoneinfo/America/Manaus index 112921184139..e0222f18e2a3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Manaus and b/python/ext-libs/pytz/zoneinfo/America/Manaus differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Marigot b/python/ext-libs/pytz/zoneinfo/America/Marigot index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Marigot and b/python/ext-libs/pytz/zoneinfo/America/Marigot differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Martinique b/python/ext-libs/pytz/zoneinfo/America/Martinique index c223ef5c2011..f9e2399c9d22 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Martinique and b/python/ext-libs/pytz/zoneinfo/America/Martinique differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Matamoros b/python/ext-libs/pytz/zoneinfo/America/Matamoros index 5c59984def29..5671d25816de 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Matamoros and b/python/ext-libs/pytz/zoneinfo/America/Matamoros differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Mazatlan b/python/ext-libs/pytz/zoneinfo/America/Mazatlan index 43ee12d84a7c..afa94c2ac5c1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Mazatlan and b/python/ext-libs/pytz/zoneinfo/America/Mazatlan differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Mendoza b/python/ext-libs/pytz/zoneinfo/America/Mendoza index 76afd5909e0e..f9eb526c7bef 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Mendoza and b/python/ext-libs/pytz/zoneinfo/America/Mendoza differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Menominee b/python/ext-libs/pytz/zoneinfo/America/Menominee index 438f5ff0b846..55d6e326692c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Menominee and b/python/ext-libs/pytz/zoneinfo/America/Menominee differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Merida b/python/ext-libs/pytz/zoneinfo/America/Merida index b46298e1f202..ecc1856e1e51 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Merida and b/python/ext-libs/pytz/zoneinfo/America/Merida differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Metlakatla b/python/ext-libs/pytz/zoneinfo/America/Metlakatla index 4145b9a58164..e66cc3417a0d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Metlakatla and b/python/ext-libs/pytz/zoneinfo/America/Metlakatla differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Mexico_City b/python/ext-libs/pytz/zoneinfo/America/Mexico_City index 1434ab08804d..f11e3d2d66a2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Mexico_City and b/python/ext-libs/pytz/zoneinfo/America/Mexico_City differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Miquelon b/python/ext-libs/pytz/zoneinfo/America/Miquelon index 52cd391ebb47..36f669619ad5 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Miquelon and b/python/ext-libs/pytz/zoneinfo/America/Miquelon differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Moncton b/python/ext-libs/pytz/zoneinfo/America/Moncton index b51125ebf112..51cb1ba3d2de 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Moncton and b/python/ext-libs/pytz/zoneinfo/America/Moncton differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Monterrey b/python/ext-libs/pytz/zoneinfo/America/Monterrey index 7dc50577749b..dcac92bad609 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Monterrey and b/python/ext-libs/pytz/zoneinfo/America/Monterrey differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Montevideo b/python/ext-libs/pytz/zoneinfo/America/Montevideo index 4745f0dfb2d9..ab3d68076d1e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Montevideo and b/python/ext-libs/pytz/zoneinfo/America/Montevideo differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Montreal b/python/ext-libs/pytz/zoneinfo/America/Montreal index 47633bd49f89..89b9f4936622 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Montreal and b/python/ext-libs/pytz/zoneinfo/America/Montreal differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Montserrat b/python/ext-libs/pytz/zoneinfo/America/Montserrat index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Montserrat and b/python/ext-libs/pytz/zoneinfo/America/Montserrat differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Nassau b/python/ext-libs/pytz/zoneinfo/America/Nassau index 5091eb5d8d3a..e5d0289b511f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Nassau and b/python/ext-libs/pytz/zoneinfo/America/Nassau differ diff --git a/python/ext-libs/pytz/zoneinfo/America/New_York b/python/ext-libs/pytz/zoneinfo/America/New_York index b2c2377f4e87..7553fee37a5d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/New_York and b/python/ext-libs/pytz/zoneinfo/America/New_York differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Nipigon b/python/ext-libs/pytz/zoneinfo/America/Nipigon index 619f1f75905e..f8a0292b2599 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Nipigon and b/python/ext-libs/pytz/zoneinfo/America/Nipigon differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Nome b/python/ext-libs/pytz/zoneinfo/America/Nome index b682bfd9cd89..d370ab14bc35 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Nome and b/python/ext-libs/pytz/zoneinfo/America/Nome differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Noronha b/python/ext-libs/pytz/zoneinfo/America/Noronha index c60239009e46..774b14e6cb3a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Noronha and b/python/ext-libs/pytz/zoneinfo/America/Noronha differ diff --git a/python/ext-libs/pytz/zoneinfo/America/North_Dakota/Beulah b/python/ext-libs/pytz/zoneinfo/America/North_Dakota/Beulah index c1e3b025b916..8174c8828851 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/North_Dakota/Beulah and b/python/ext-libs/pytz/zoneinfo/America/North_Dakota/Beulah differ diff --git a/python/ext-libs/pytz/zoneinfo/America/North_Dakota/Center b/python/ext-libs/pytz/zoneinfo/America/North_Dakota/Center index 786ba1778acb..8035b24fafef 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/North_Dakota/Center and b/python/ext-libs/pytz/zoneinfo/America/North_Dakota/Center differ diff --git a/python/ext-libs/pytz/zoneinfo/America/North_Dakota/New_Salem b/python/ext-libs/pytz/zoneinfo/America/North_Dakota/New_Salem index 3488e466d522..5b630ee66715 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/North_Dakota/New_Salem and b/python/ext-libs/pytz/zoneinfo/America/North_Dakota/New_Salem differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Ojinaga b/python/ext-libs/pytz/zoneinfo/America/Ojinaga index 37d78301bd10..190c5c86dd8f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Ojinaga and b/python/ext-libs/pytz/zoneinfo/America/Ojinaga differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Panama b/python/ext-libs/pytz/zoneinfo/America/Panama index 3a4ff2aecf89..5c1c06372c6d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Panama and b/python/ext-libs/pytz/zoneinfo/America/Panama differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Pangnirtung b/python/ext-libs/pytz/zoneinfo/America/Pangnirtung index 80a6009381ef..994da430a9db 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Pangnirtung and b/python/ext-libs/pytz/zoneinfo/America/Pangnirtung differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Paramaribo b/python/ext-libs/pytz/zoneinfo/America/Paramaribo index 6f889ccaf1ff..2f05b2364443 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Paramaribo and b/python/ext-libs/pytz/zoneinfo/America/Paramaribo differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Phoenix b/python/ext-libs/pytz/zoneinfo/America/Phoenix index 67589026c21c..adf28236a2fe 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Phoenix and b/python/ext-libs/pytz/zoneinfo/America/Phoenix differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Port-au-Prince b/python/ext-libs/pytz/zoneinfo/America/Port-au-Prince index 3f86e8ab756d..dd8895c03817 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Port-au-Prince and b/python/ext-libs/pytz/zoneinfo/America/Port-au-Prince differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Port_of_Spain b/python/ext-libs/pytz/zoneinfo/America/Port_of_Spain index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Port_of_Spain and b/python/ext-libs/pytz/zoneinfo/America/Port_of_Spain differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Porto_Acre b/python/ext-libs/pytz/zoneinfo/America/Porto_Acre index 21cf598ff1f3..788d0e9ceb07 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Porto_Acre and b/python/ext-libs/pytz/zoneinfo/America/Porto_Acre differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Porto_Velho b/python/ext-libs/pytz/zoneinfo/America/Porto_Velho index 12774792326b..aa8cf31528ca 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Porto_Velho and b/python/ext-libs/pytz/zoneinfo/America/Porto_Velho differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Puerto_Rico b/python/ext-libs/pytz/zoneinfo/America/Puerto_Rico index eada37a111c0..d4525a68a603 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Puerto_Rico and b/python/ext-libs/pytz/zoneinfo/America/Puerto_Rico differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Rainy_River b/python/ext-libs/pytz/zoneinfo/America/Rainy_River index e006a30dbf35..70dcd2d8014a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Rainy_River and b/python/ext-libs/pytz/zoneinfo/America/Rainy_River differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Rankin_Inlet b/python/ext-libs/pytz/zoneinfo/America/Rankin_Inlet index 99195714c4b3..cc15d8310878 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Rankin_Inlet and b/python/ext-libs/pytz/zoneinfo/America/Rankin_Inlet differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Recife b/python/ext-libs/pytz/zoneinfo/America/Recife index 0903a7719535..f0ad7b9897b4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Recife and b/python/ext-libs/pytz/zoneinfo/America/Recife differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Regina b/python/ext-libs/pytz/zoneinfo/America/Regina index 20c9c84df491..5fe8d6b618e3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Regina and b/python/ext-libs/pytz/zoneinfo/America/Regina differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Resolute b/python/ext-libs/pytz/zoneinfo/America/Resolute index 7713f5bead43..5307941313d0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Resolute and b/python/ext-libs/pytz/zoneinfo/America/Resolute differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Rio_Branco b/python/ext-libs/pytz/zoneinfo/America/Rio_Branco index 21cf598ff1f3..788d0e9ceb07 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Rio_Branco and b/python/ext-libs/pytz/zoneinfo/America/Rio_Branco differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Rosario b/python/ext-libs/pytz/zoneinfo/America/Rosario index a703e957d5eb..cd97a24bdb7b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Rosario and b/python/ext-libs/pytz/zoneinfo/America/Rosario differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Santa_Isabel b/python/ext-libs/pytz/zoneinfo/America/Santa_Isabel index 80a2f2d5b1df..e1c4d161cf4b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Santa_Isabel and b/python/ext-libs/pytz/zoneinfo/America/Santa_Isabel differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Santarem b/python/ext-libs/pytz/zoneinfo/America/Santarem index 45419528f9df..bb469d398cec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Santarem and b/python/ext-libs/pytz/zoneinfo/America/Santarem differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Santiago b/python/ext-libs/pytz/zoneinfo/America/Santiago index 7cf0a1e1877b..92cf5597689b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Santiago and b/python/ext-libs/pytz/zoneinfo/America/Santiago differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Santo_Domingo b/python/ext-libs/pytz/zoneinfo/America/Santo_Domingo index 23ace9adc3e2..77eab315b001 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Santo_Domingo and b/python/ext-libs/pytz/zoneinfo/America/Santo_Domingo differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Sao_Paulo b/python/ext-libs/pytz/zoneinfo/America/Sao_Paulo index 8df63a17bd46..552ce7c29228 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Sao_Paulo and b/python/ext-libs/pytz/zoneinfo/America/Sao_Paulo differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Scoresbysund b/python/ext-libs/pytz/zoneinfo/America/Scoresbysund index fae3757ce9da..85676ca37633 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Scoresbysund and b/python/ext-libs/pytz/zoneinfo/America/Scoresbysund differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Shiprock b/python/ext-libs/pytz/zoneinfo/America/Shiprock index f8908febf220..7fc669171f88 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Shiprock and b/python/ext-libs/pytz/zoneinfo/America/Shiprock differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Sitka b/python/ext-libs/pytz/zoneinfo/America/Sitka index f2ae47a323e7..48fc6affdfaf 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Sitka and b/python/ext-libs/pytz/zoneinfo/America/Sitka differ diff --git a/python/ext-libs/pytz/zoneinfo/America/St_Barthelemy b/python/ext-libs/pytz/zoneinfo/America/St_Barthelemy index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/St_Barthelemy and b/python/ext-libs/pytz/zoneinfo/America/St_Barthelemy differ diff --git a/python/ext-libs/pytz/zoneinfo/America/St_Johns b/python/ext-libs/pytz/zoneinfo/America/St_Johns index e7a18d601d02..a1d14854af6b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/St_Johns and b/python/ext-libs/pytz/zoneinfo/America/St_Johns differ diff --git a/python/ext-libs/pytz/zoneinfo/America/St_Kitts b/python/ext-libs/pytz/zoneinfo/America/St_Kitts index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/St_Kitts and b/python/ext-libs/pytz/zoneinfo/America/St_Kitts differ diff --git a/python/ext-libs/pytz/zoneinfo/America/St_Lucia b/python/ext-libs/pytz/zoneinfo/America/St_Lucia index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/St_Lucia and b/python/ext-libs/pytz/zoneinfo/America/St_Lucia differ diff --git a/python/ext-libs/pytz/zoneinfo/America/St_Thomas b/python/ext-libs/pytz/zoneinfo/America/St_Thomas index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/St_Thomas and b/python/ext-libs/pytz/zoneinfo/America/St_Thomas differ diff --git a/python/ext-libs/pytz/zoneinfo/America/St_Vincent b/python/ext-libs/pytz/zoneinfo/America/St_Vincent index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/St_Vincent and b/python/ext-libs/pytz/zoneinfo/America/St_Vincent differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Swift_Current b/python/ext-libs/pytz/zoneinfo/America/Swift_Current index 8e9ef255eeb1..4db1300a26ed 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Swift_Current and b/python/ext-libs/pytz/zoneinfo/America/Swift_Current differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Tegucigalpa b/python/ext-libs/pytz/zoneinfo/America/Tegucigalpa index 477e93950c2f..7aea8f9989fb 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Tegucigalpa and b/python/ext-libs/pytz/zoneinfo/America/Tegucigalpa differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Thule b/python/ext-libs/pytz/zoneinfo/America/Thule index 2969ebe59bd2..deefcc8df5a1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Thule and b/python/ext-libs/pytz/zoneinfo/America/Thule differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Thunder_Bay b/python/ext-libs/pytz/zoneinfo/America/Thunder_Bay index 34f750b4df72..aa1d48609768 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Thunder_Bay and b/python/ext-libs/pytz/zoneinfo/America/Thunder_Bay differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Tijuana b/python/ext-libs/pytz/zoneinfo/America/Tijuana index fffdc24bfc4c..1387475394bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Tijuana and b/python/ext-libs/pytz/zoneinfo/America/Tijuana differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Toronto b/python/ext-libs/pytz/zoneinfo/America/Toronto index 1698477a4877..7b4682a39e2f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Toronto and b/python/ext-libs/pytz/zoneinfo/America/Toronto differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Tortola b/python/ext-libs/pytz/zoneinfo/America/Tortola index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Tortola and b/python/ext-libs/pytz/zoneinfo/America/Tortola differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Vancouver b/python/ext-libs/pytz/zoneinfo/America/Vancouver index 0c1fa5269049..9b5d924173e6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Vancouver and b/python/ext-libs/pytz/zoneinfo/America/Vancouver differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Virgin b/python/ext-libs/pytz/zoneinfo/America/Virgin index bdedd1bd9bc8..447efbe2c967 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Virgin and b/python/ext-libs/pytz/zoneinfo/America/Virgin differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Whitehorse b/python/ext-libs/pytz/zoneinfo/America/Whitehorse index 15216d55ff54..8604c5c535ed 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Whitehorse and b/python/ext-libs/pytz/zoneinfo/America/Whitehorse differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Winnipeg b/python/ext-libs/pytz/zoneinfo/America/Winnipeg index 2d22791686e8..2ffe3d8d8e01 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Winnipeg and b/python/ext-libs/pytz/zoneinfo/America/Winnipeg differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Yakutat b/python/ext-libs/pytz/zoneinfo/America/Yakutat index 80716027731e..f3d739901c67 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Yakutat and b/python/ext-libs/pytz/zoneinfo/America/Yakutat differ diff --git a/python/ext-libs/pytz/zoneinfo/America/Yellowknife b/python/ext-libs/pytz/zoneinfo/America/Yellowknife index 947bec914be3..21cba6e4ece9 100644 Binary files a/python/ext-libs/pytz/zoneinfo/America/Yellowknife and b/python/ext-libs/pytz/zoneinfo/America/Yellowknife differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/Casey b/python/ext-libs/pytz/zoneinfo/Antarctica/Casey index 8ebf0598ff90..c2a990564dc9 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/Casey and b/python/ext-libs/pytz/zoneinfo/Antarctica/Casey differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/Davis b/python/ext-libs/pytz/zoneinfo/Antarctica/Davis index cd7acad690b6..7321c67fc997 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/Davis and b/python/ext-libs/pytz/zoneinfo/Antarctica/Davis differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/DumontDUrville b/python/ext-libs/pytz/zoneinfo/Antarctica/DumontDUrville index 5ea18e6e776a..c406b8d516f9 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/DumontDUrville and b/python/ext-libs/pytz/zoneinfo/Antarctica/DumontDUrville differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/Macquarie b/python/ext-libs/pytz/zoneinfo/Antarctica/Macquarie index cbad31bb948a..fc7b96fe873a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/Macquarie and b/python/ext-libs/pytz/zoneinfo/Antarctica/Macquarie differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/Mawson b/python/ext-libs/pytz/zoneinfo/Antarctica/Mawson index 48e24e1e5ef8..6c5b0fa1309c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/Mawson and b/python/ext-libs/pytz/zoneinfo/Antarctica/Mawson differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/McMurdo b/python/ext-libs/pytz/zoneinfo/Antarctica/McMurdo index a40767df93d3..a5f5b6d5e60f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/McMurdo and b/python/ext-libs/pytz/zoneinfo/Antarctica/McMurdo differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/Palmer b/python/ext-libs/pytz/zoneinfo/Antarctica/Palmer index a1bcf2784b2e..9e9cdd0bbffe 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/Palmer and b/python/ext-libs/pytz/zoneinfo/Antarctica/Palmer differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/Rothera b/python/ext-libs/pytz/zoneinfo/Antarctica/Rothera index b5dc735639df..28f82baab994 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/Rothera and b/python/ext-libs/pytz/zoneinfo/Antarctica/Rothera differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/South_Pole b/python/ext-libs/pytz/zoneinfo/Antarctica/South_Pole index a40767df93d3..a5f5b6d5e60f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/South_Pole and b/python/ext-libs/pytz/zoneinfo/Antarctica/South_Pole differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/Syowa b/python/ext-libs/pytz/zoneinfo/Antarctica/Syowa index ba6e5f388779..b837b071f8a0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/Syowa and b/python/ext-libs/pytz/zoneinfo/Antarctica/Syowa differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/Troll b/python/ext-libs/pytz/zoneinfo/Antarctica/Troll new file mode 100644 index 000000000000..d973a1226401 Binary files /dev/null and b/python/ext-libs/pytz/zoneinfo/Antarctica/Troll differ diff --git a/python/ext-libs/pytz/zoneinfo/Antarctica/Vostok b/python/ext-libs/pytz/zoneinfo/Antarctica/Vostok index e19e2b7cdb55..cbec909eefdc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Antarctica/Vostok and b/python/ext-libs/pytz/zoneinfo/Antarctica/Vostok differ diff --git a/python/ext-libs/pytz/zoneinfo/Arctic/Longyearbyen b/python/ext-libs/pytz/zoneinfo/Arctic/Longyearbyen index 6326961453f4..239c0174d361 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Arctic/Longyearbyen and b/python/ext-libs/pytz/zoneinfo/Arctic/Longyearbyen differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Aden b/python/ext-libs/pytz/zoneinfo/Asia/Aden index 5948b310b94c..505e1d2225d6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Aden and b/python/ext-libs/pytz/zoneinfo/Asia/Aden differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Almaty b/python/ext-libs/pytz/zoneinfo/Asia/Almaty index 52f941e266a9..75a007deeb1c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Almaty and b/python/ext-libs/pytz/zoneinfo/Asia/Almaty differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Amman b/python/ext-libs/pytz/zoneinfo/Asia/Amman index 281b304e2f8b..c3f0994a7530 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Amman and b/python/ext-libs/pytz/zoneinfo/Asia/Amman differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Anadyr b/python/ext-libs/pytz/zoneinfo/Asia/Anadyr index 2841a6376d9f..766594bc9797 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Anadyr and b/python/ext-libs/pytz/zoneinfo/Asia/Anadyr differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Aqtau b/python/ext-libs/pytz/zoneinfo/Asia/Aqtau index 27a3d50d3739..811ed2f9161c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Aqtau and b/python/ext-libs/pytz/zoneinfo/Asia/Aqtau differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Aqtobe b/python/ext-libs/pytz/zoneinfo/Asia/Aqtobe index 3683be2db87b..ff3b96b3e9d4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Aqtobe and b/python/ext-libs/pytz/zoneinfo/Asia/Aqtobe differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Ashgabat b/python/ext-libs/pytz/zoneinfo/Asia/Ashgabat index 589dbc18ea2d..f79fe0460d1d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Ashgabat and b/python/ext-libs/pytz/zoneinfo/Asia/Ashgabat differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Ashkhabad b/python/ext-libs/pytz/zoneinfo/Asia/Ashkhabad index 589dbc18ea2d..f79fe0460d1d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Ashkhabad and b/python/ext-libs/pytz/zoneinfo/Asia/Ashkhabad differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Baghdad b/python/ext-libs/pytz/zoneinfo/Asia/Baghdad index 3ad361495ce5..f0a96ec3f1a0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Baghdad and b/python/ext-libs/pytz/zoneinfo/Asia/Baghdad differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Bahrain b/python/ext-libs/pytz/zoneinfo/Asia/Bahrain index d87b7ce73915..cda04a151090 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Bahrain and b/python/ext-libs/pytz/zoneinfo/Asia/Bahrain differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Baku b/python/ext-libs/pytz/zoneinfo/Asia/Baku index 72ae96e9cc95..f78e76457497 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Baku and b/python/ext-libs/pytz/zoneinfo/Asia/Baku differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Bangkok b/python/ext-libs/pytz/zoneinfo/Asia/Bangkok index 44a1018ef638..e8e76276a657 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Bangkok and b/python/ext-libs/pytz/zoneinfo/Asia/Bangkok differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Beirut b/python/ext-libs/pytz/zoneinfo/Asia/Beirut index c1270bc1adce..72f0896341a7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Beirut and b/python/ext-libs/pytz/zoneinfo/Asia/Beirut differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Bishkek b/python/ext-libs/pytz/zoneinfo/Asia/Bishkek index fc827d887134..eee8278ab81f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Bishkek and b/python/ext-libs/pytz/zoneinfo/Asia/Bishkek differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Brunei b/python/ext-libs/pytz/zoneinfo/Asia/Brunei index d6e713d436fb..1ac3115acd19 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Brunei and b/python/ext-libs/pytz/zoneinfo/Asia/Brunei differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Calcutta b/python/ext-libs/pytz/zoneinfo/Asia/Calcutta index bc909c92c14d..3c0d5abcb545 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Calcutta and b/python/ext-libs/pytz/zoneinfo/Asia/Calcutta differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Chita b/python/ext-libs/pytz/zoneinfo/Asia/Chita new file mode 100644 index 000000000000..c09065470ef9 Binary files /dev/null and b/python/ext-libs/pytz/zoneinfo/Asia/Chita differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Choibalsan b/python/ext-libs/pytz/zoneinfo/Asia/Choibalsan index 043b7ed5c2d7..f099092610d1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Choibalsan and b/python/ext-libs/pytz/zoneinfo/Asia/Choibalsan differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Chongqing b/python/ext-libs/pytz/zoneinfo/Asia/Chongqing index 8a7a28a480a4..dbd132f2b0bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Chongqing and b/python/ext-libs/pytz/zoneinfo/Asia/Chongqing differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Chungking b/python/ext-libs/pytz/zoneinfo/Asia/Chungking index 8a7a28a480a4..dbd132f2b0bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Chungking and b/python/ext-libs/pytz/zoneinfo/Asia/Chungking differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Colombo b/python/ext-libs/pytz/zoneinfo/Asia/Colombo index c71c0503d999..d10439af138a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Colombo and b/python/ext-libs/pytz/zoneinfo/Asia/Colombo differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Dacca b/python/ext-libs/pytz/zoneinfo/Asia/Dacca index 52e98ffc2c14..b6b326b20eb4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Dacca and b/python/ext-libs/pytz/zoneinfo/Asia/Dacca differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Damascus b/python/ext-libs/pytz/zoneinfo/Asia/Damascus index 4b610b5a0836..ac457646bb02 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Damascus and b/python/ext-libs/pytz/zoneinfo/Asia/Damascus differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Dhaka b/python/ext-libs/pytz/zoneinfo/Asia/Dhaka index 52e98ffc2c14..b6b326b20eb4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Dhaka and b/python/ext-libs/pytz/zoneinfo/Asia/Dhaka differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Dili b/python/ext-libs/pytz/zoneinfo/Asia/Dili index e5b743a6fc12..8124fb70b2d7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Dili and b/python/ext-libs/pytz/zoneinfo/Asia/Dili differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Dubai b/python/ext-libs/pytz/zoneinfo/Asia/Dubai index 53f70d57a15a..415e443ca90d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Dubai and b/python/ext-libs/pytz/zoneinfo/Asia/Dubai differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Dushanbe b/python/ext-libs/pytz/zoneinfo/Asia/Dushanbe index c65ff2a7b3e5..3b1e978b399e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Dushanbe and b/python/ext-libs/pytz/zoneinfo/Asia/Dushanbe differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Gaza b/python/ext-libs/pytz/zoneinfo/Asia/Gaza index a6fb7b3b810e..bd683e831b68 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Gaza and b/python/ext-libs/pytz/zoneinfo/Asia/Gaza differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Harbin b/python/ext-libs/pytz/zoneinfo/Asia/Harbin index 11e352a51106..dbd132f2b0bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Harbin and b/python/ext-libs/pytz/zoneinfo/Asia/Harbin differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Hebron b/python/ext-libs/pytz/zoneinfo/Asia/Hebron index e5e5173da421..0bc7674bc2bb 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Hebron and b/python/ext-libs/pytz/zoneinfo/Asia/Hebron differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Ho_Chi_Minh b/python/ext-libs/pytz/zoneinfo/Asia/Ho_Chi_Minh index 6401a10256bb..86fff6b954fc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Ho_Chi_Minh and b/python/ext-libs/pytz/zoneinfo/Asia/Ho_Chi_Minh differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Hong_Kong b/python/ext-libs/pytz/zoneinfo/Asia/Hong_Kong index 8e5c5813666a..dc9058e4b578 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Hong_Kong and b/python/ext-libs/pytz/zoneinfo/Asia/Hong_Kong differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Hovd b/python/ext-libs/pytz/zoneinfo/Asia/Hovd index 27fab05c1912..71c3cad48c11 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Hovd and b/python/ext-libs/pytz/zoneinfo/Asia/Hovd differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Irkutsk b/python/ext-libs/pytz/zoneinfo/Asia/Irkutsk index 7c38e7fd6b28..1e94a47987ac 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Irkutsk and b/python/ext-libs/pytz/zoneinfo/Asia/Irkutsk differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Istanbul b/python/ext-libs/pytz/zoneinfo/Asia/Istanbul index 864099556bc9..d89aa3a82674 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Istanbul and b/python/ext-libs/pytz/zoneinfo/Asia/Istanbul differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Jakarta b/python/ext-libs/pytz/zoneinfo/Asia/Jakarta index 66450d637022..3130bff56a04 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Jakarta and b/python/ext-libs/pytz/zoneinfo/Asia/Jakarta differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Jayapura b/python/ext-libs/pytz/zoneinfo/Asia/Jayapura index e28f9def305a..a9d12177d57c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Jayapura and b/python/ext-libs/pytz/zoneinfo/Asia/Jayapura differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Jerusalem b/python/ext-libs/pytz/zoneinfo/Asia/Jerusalem index affa0e4eaf7b..df5119935c5b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Jerusalem and b/python/ext-libs/pytz/zoneinfo/Asia/Jerusalem differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Kabul b/python/ext-libs/pytz/zoneinfo/Asia/Kabul index 7392c0497a75..266cc7e9bf2a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Kabul and b/python/ext-libs/pytz/zoneinfo/Asia/Kabul differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Kamchatka b/python/ext-libs/pytz/zoneinfo/Asia/Kamchatka index 090bf488957b..a0541cfa8725 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Kamchatka and b/python/ext-libs/pytz/zoneinfo/Asia/Kamchatka differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Karachi b/python/ext-libs/pytz/zoneinfo/Asia/Karachi index a8ff8cb769d1..6a6de1b24907 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Karachi and b/python/ext-libs/pytz/zoneinfo/Asia/Karachi differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Kashgar b/python/ext-libs/pytz/zoneinfo/Asia/Kashgar index 25e64945cffa..964a5c24b7b8 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Kashgar and b/python/ext-libs/pytz/zoneinfo/Asia/Kashgar differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Kathmandu b/python/ext-libs/pytz/zoneinfo/Asia/Kathmandu index 65c7b6325833..2824709845a0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Kathmandu and b/python/ext-libs/pytz/zoneinfo/Asia/Kathmandu differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Katmandu b/python/ext-libs/pytz/zoneinfo/Asia/Katmandu index 65c7b6325833..2824709845a0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Katmandu and b/python/ext-libs/pytz/zoneinfo/Asia/Katmandu differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Khandyga b/python/ext-libs/pytz/zoneinfo/Asia/Khandyga index 39d2c2df80d3..26becb3291ed 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Khandyga and b/python/ext-libs/pytz/zoneinfo/Asia/Khandyga differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Kolkata b/python/ext-libs/pytz/zoneinfo/Asia/Kolkata index bc909c92c14d..3c0d5abcb545 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Kolkata and b/python/ext-libs/pytz/zoneinfo/Asia/Kolkata differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Krasnoyarsk b/python/ext-libs/pytz/zoneinfo/Asia/Krasnoyarsk index 580e8dd2f43e..3107809022e4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Krasnoyarsk and b/python/ext-libs/pytz/zoneinfo/Asia/Krasnoyarsk differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Kuala_Lumpur b/python/ext-libs/pytz/zoneinfo/Asia/Kuala_Lumpur index 41bba37b0c5f..35b987d2fd11 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Kuala_Lumpur and b/python/ext-libs/pytz/zoneinfo/Asia/Kuala_Lumpur differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Kuching b/python/ext-libs/pytz/zoneinfo/Asia/Kuching index 272f46546e9d..4f891db77dbb 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Kuching and b/python/ext-libs/pytz/zoneinfo/Asia/Kuching differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Kuwait b/python/ext-libs/pytz/zoneinfo/Asia/Kuwait index 1dab31cba01d..5623811db35a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Kuwait and b/python/ext-libs/pytz/zoneinfo/Asia/Kuwait differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Macao b/python/ext-libs/pytz/zoneinfo/Asia/Macao index 7c9377957872..b8f9c3696ac7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Macao and b/python/ext-libs/pytz/zoneinfo/Asia/Macao differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Macau b/python/ext-libs/pytz/zoneinfo/Asia/Macau index 7c9377957872..b8f9c3696ac7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Macau and b/python/ext-libs/pytz/zoneinfo/Asia/Macau differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Magadan b/python/ext-libs/pytz/zoneinfo/Asia/Magadan index e3c76b57f59f..e09c4dc2e2fb 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Magadan and b/python/ext-libs/pytz/zoneinfo/Asia/Magadan differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Makassar b/python/ext-libs/pytz/zoneinfo/Asia/Makassar index eb7d42ef4d83..0d689236dbd5 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Makassar and b/python/ext-libs/pytz/zoneinfo/Asia/Makassar differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Manila b/python/ext-libs/pytz/zoneinfo/Asia/Manila index 0e90ba6326a2..ac0f3a63d739 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Manila and b/python/ext-libs/pytz/zoneinfo/Asia/Manila differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Muscat b/python/ext-libs/pytz/zoneinfo/Asia/Muscat index daee4cc82a0e..53a22190c4bd 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Muscat and b/python/ext-libs/pytz/zoneinfo/Asia/Muscat differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Nicosia b/python/ext-libs/pytz/zoneinfo/Asia/Nicosia index f7f10ab7665e..3e663b215327 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Nicosia and b/python/ext-libs/pytz/zoneinfo/Asia/Nicosia differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Novokuznetsk b/python/ext-libs/pytz/zoneinfo/Asia/Novokuznetsk index f78c1f88bf65..c5cadc0ed663 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Novokuznetsk and b/python/ext-libs/pytz/zoneinfo/Asia/Novokuznetsk differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Novosibirsk b/python/ext-libs/pytz/zoneinfo/Asia/Novosibirsk index c401a9817dab..ed6d7dc5416f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Novosibirsk and b/python/ext-libs/pytz/zoneinfo/Asia/Novosibirsk differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Omsk b/python/ext-libs/pytz/zoneinfo/Asia/Omsk index a3dbb4bb1c5a..760c39106177 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Omsk and b/python/ext-libs/pytz/zoneinfo/Asia/Omsk differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Oral b/python/ext-libs/pytz/zoneinfo/Asia/Oral index 8da2a1dee74d..1467cafcc983 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Oral and b/python/ext-libs/pytz/zoneinfo/Asia/Oral differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Phnom_Penh b/python/ext-libs/pytz/zoneinfo/Asia/Phnom_Penh index 5a52722a1612..37c9e15fb9bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Phnom_Penh and b/python/ext-libs/pytz/zoneinfo/Asia/Phnom_Penh differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Pontianak b/python/ext-libs/pytz/zoneinfo/Asia/Pontianak index 54b3d5081d0b..dcd701406cb5 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Pontianak and b/python/ext-libs/pytz/zoneinfo/Asia/Pontianak differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Pyongyang b/python/ext-libs/pytz/zoneinfo/Asia/Pyongyang index 9dbd3c1ae006..a743fbbac584 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Pyongyang and b/python/ext-libs/pytz/zoneinfo/Asia/Pyongyang differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Qatar b/python/ext-libs/pytz/zoneinfo/Asia/Qatar index 49668c2583c8..3e20373990e3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Qatar and b/python/ext-libs/pytz/zoneinfo/Asia/Qatar differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Qyzylorda b/python/ext-libs/pytz/zoneinfo/Asia/Qyzylorda index fc3bf46bccc5..ce53516181ef 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Qyzylorda and b/python/ext-libs/pytz/zoneinfo/Asia/Qyzylorda differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Rangoon b/python/ext-libs/pytz/zoneinfo/Asia/Rangoon index 68591c56e707..934ca7ef09a6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Rangoon and b/python/ext-libs/pytz/zoneinfo/Asia/Rangoon differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Riyadh b/python/ext-libs/pytz/zoneinfo/Asia/Riyadh index 6ebe393d0b86..c35e42a12163 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Riyadh and b/python/ext-libs/pytz/zoneinfo/Asia/Riyadh differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Saigon b/python/ext-libs/pytz/zoneinfo/Asia/Saigon index 6401a10256bb..86fff6b954fc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Saigon and b/python/ext-libs/pytz/zoneinfo/Asia/Saigon differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Sakhalin b/python/ext-libs/pytz/zoneinfo/Asia/Sakhalin index f5105a363cfd..ec62afc5995a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Sakhalin and b/python/ext-libs/pytz/zoneinfo/Asia/Sakhalin differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Samarkand b/python/ext-libs/pytz/zoneinfo/Asia/Samarkand index 191c07c12755..65fb5b03de72 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Samarkand and b/python/ext-libs/pytz/zoneinfo/Asia/Samarkand differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Seoul b/python/ext-libs/pytz/zoneinfo/Asia/Seoul index 96bb0c36d7e3..6931d782bba5 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Seoul and b/python/ext-libs/pytz/zoneinfo/Asia/Seoul differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Shanghai b/python/ext-libs/pytz/zoneinfo/Asia/Shanghai index af6d6fbbd298..dbd132f2b0bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Shanghai and b/python/ext-libs/pytz/zoneinfo/Asia/Shanghai differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Singapore b/python/ext-libs/pytz/zoneinfo/Asia/Singapore index a6f2db8f3a88..9dd49cb7a72f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Singapore and b/python/ext-libs/pytz/zoneinfo/Asia/Singapore differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Srednekolymsk b/python/ext-libs/pytz/zoneinfo/Asia/Srednekolymsk new file mode 100644 index 000000000000..0929f66debc0 Binary files /dev/null and b/python/ext-libs/pytz/zoneinfo/Asia/Srednekolymsk differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Taipei b/python/ext-libs/pytz/zoneinfo/Asia/Taipei index 70cfb27ca91f..4810a0b61420 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Taipei and b/python/ext-libs/pytz/zoneinfo/Asia/Taipei differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Tashkent b/python/ext-libs/pytz/zoneinfo/Asia/Tashkent index 5bc806238a9e..1f59faa5344c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Tashkent and b/python/ext-libs/pytz/zoneinfo/Asia/Tashkent differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Tbilisi b/python/ext-libs/pytz/zoneinfo/Asia/Tbilisi index d7e40548acec..0d7081e97598 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Tbilisi and b/python/ext-libs/pytz/zoneinfo/Asia/Tbilisi differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Tehran b/python/ext-libs/pytz/zoneinfo/Asia/Tehran index 62d316190d42..871078114d04 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Tehran and b/python/ext-libs/pytz/zoneinfo/Asia/Tehran differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Tel_Aviv b/python/ext-libs/pytz/zoneinfo/Asia/Tel_Aviv index affa0e4eaf7b..df5119935c5b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Tel_Aviv and b/python/ext-libs/pytz/zoneinfo/Asia/Tel_Aviv differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Thimbu b/python/ext-libs/pytz/zoneinfo/Asia/Thimbu index 90294aea2026..0bd94cb446b4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Thimbu and b/python/ext-libs/pytz/zoneinfo/Asia/Thimbu differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Thimphu b/python/ext-libs/pytz/zoneinfo/Asia/Thimphu index 90294aea2026..0bd94cb446b4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Thimphu and b/python/ext-libs/pytz/zoneinfo/Asia/Thimphu differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Tokyo b/python/ext-libs/pytz/zoneinfo/Asia/Tokyo index 058c1e99ba26..024414031e18 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Tokyo and b/python/ext-libs/pytz/zoneinfo/Asia/Tokyo differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Ujung_Pandang b/python/ext-libs/pytz/zoneinfo/Asia/Ujung_Pandang index eb7d42ef4d83..0d689236dbd5 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Ujung_Pandang and b/python/ext-libs/pytz/zoneinfo/Asia/Ujung_Pandang differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Ulaanbaatar b/python/ext-libs/pytz/zoneinfo/Asia/Ulaanbaatar index 39bdd89416a5..61505e95dc53 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Ulaanbaatar and b/python/ext-libs/pytz/zoneinfo/Asia/Ulaanbaatar differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Ulan_Bator b/python/ext-libs/pytz/zoneinfo/Asia/Ulan_Bator index 39bdd89416a5..61505e95dc53 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Ulan_Bator and b/python/ext-libs/pytz/zoneinfo/Asia/Ulan_Bator differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Urumqi b/python/ext-libs/pytz/zoneinfo/Asia/Urumqi index f46ff380a055..964a5c24b7b8 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Urumqi and b/python/ext-libs/pytz/zoneinfo/Asia/Urumqi differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Ust-Nera b/python/ext-libs/pytz/zoneinfo/Asia/Ust-Nera index ae89650f10aa..0efacd6beae6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Ust-Nera and b/python/ext-libs/pytz/zoneinfo/Asia/Ust-Nera differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Vientiane b/python/ext-libs/pytz/zoneinfo/Asia/Vientiane index 7d39589f19e8..67e90e0cf8c4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Vientiane and b/python/ext-libs/pytz/zoneinfo/Asia/Vientiane differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Vladivostok b/python/ext-libs/pytz/zoneinfo/Asia/Vladivostok index 1cae6d0fd988..156c8e6f5283 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Vladivostok and b/python/ext-libs/pytz/zoneinfo/Asia/Vladivostok differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Yakutsk b/python/ext-libs/pytz/zoneinfo/Asia/Yakutsk index 461901f6f83b..58ff25ea1f2f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Yakutsk and b/python/ext-libs/pytz/zoneinfo/Asia/Yakutsk differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Yekaterinburg b/python/ext-libs/pytz/zoneinfo/Asia/Yekaterinburg index aca50c6e1d8b..a1baafaec926 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Yekaterinburg and b/python/ext-libs/pytz/zoneinfo/Asia/Yekaterinburg differ diff --git a/python/ext-libs/pytz/zoneinfo/Asia/Yerevan b/python/ext-libs/pytz/zoneinfo/Asia/Yerevan index c4ab2197f803..fa62c249d07f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Asia/Yerevan and b/python/ext-libs/pytz/zoneinfo/Asia/Yerevan differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/Azores b/python/ext-libs/pytz/zoneinfo/Atlantic/Azores index 19e40040672a..1f5325324590 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/Azores and b/python/ext-libs/pytz/zoneinfo/Atlantic/Azores differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/Bermuda b/python/ext-libs/pytz/zoneinfo/Atlantic/Bermuda index 3a5c6dbf7a9a..548d979bd1ec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/Bermuda and b/python/ext-libs/pytz/zoneinfo/Atlantic/Bermuda differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/Canary b/python/ext-libs/pytz/zoneinfo/Atlantic/Canary index 972388be7176..007dcf494240 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/Canary and b/python/ext-libs/pytz/zoneinfo/Atlantic/Canary differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/Cape_Verde b/python/ext-libs/pytz/zoneinfo/Atlantic/Cape_Verde index 5238ac8a6704..18b676ce5af2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/Cape_Verde and b/python/ext-libs/pytz/zoneinfo/Atlantic/Cape_Verde differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/Faeroe b/python/ext-libs/pytz/zoneinfo/Atlantic/Faeroe index 4dab7ef0859c..c4865186b035 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/Faeroe and b/python/ext-libs/pytz/zoneinfo/Atlantic/Faeroe differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/Faroe b/python/ext-libs/pytz/zoneinfo/Atlantic/Faroe index 4dab7ef0859c..c4865186b035 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/Faroe and b/python/ext-libs/pytz/zoneinfo/Atlantic/Faroe differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/Jan_Mayen b/python/ext-libs/pytz/zoneinfo/Atlantic/Jan_Mayen index 6326961453f4..239c0174d361 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/Jan_Mayen and b/python/ext-libs/pytz/zoneinfo/Atlantic/Jan_Mayen differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/Madeira b/python/ext-libs/pytz/zoneinfo/Atlantic/Madeira index 2175096cf122..3687fd66e3aa 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/Madeira and b/python/ext-libs/pytz/zoneinfo/Atlantic/Madeira differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/Reykjavik b/python/ext-libs/pytz/zoneinfo/Atlantic/Reykjavik index e97f13a65201..35ba7a15f4b6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/Reykjavik and b/python/ext-libs/pytz/zoneinfo/Atlantic/Reykjavik differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/South_Georgia b/python/ext-libs/pytz/zoneinfo/Atlantic/South_Georgia index ab2c8236b00b..b1191c9fb693 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/South_Georgia and b/python/ext-libs/pytz/zoneinfo/Atlantic/South_Georgia differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/St_Helena b/python/ext-libs/pytz/zoneinfo/Atlantic/St_Helena index d365e3ddf349..6fd1af32daec 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/St_Helena and b/python/ext-libs/pytz/zoneinfo/Atlantic/St_Helena differ diff --git a/python/ext-libs/pytz/zoneinfo/Atlantic/Stanley b/python/ext-libs/pytz/zoneinfo/Atlantic/Stanley index 34f9d022cd5a..aec7a5d3665a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Atlantic/Stanley and b/python/ext-libs/pytz/zoneinfo/Atlantic/Stanley differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/ACT b/python/ext-libs/pytz/zoneinfo/Australia/ACT index d95c245e5ee1..aaed12ca284d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/ACT and b/python/ext-libs/pytz/zoneinfo/Australia/ACT differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Adelaide b/python/ext-libs/pytz/zoneinfo/Australia/Adelaide index b350cb6660a6..4f331a87df4e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Adelaide and b/python/ext-libs/pytz/zoneinfo/Australia/Adelaide differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Brisbane b/python/ext-libs/pytz/zoneinfo/Australia/Brisbane index 3e899a163f51..a327d83b7696 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Brisbane and b/python/ext-libs/pytz/zoneinfo/Australia/Brisbane differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Broken_Hill b/python/ext-libs/pytz/zoneinfo/Australia/Broken_Hill index d8f3155c84df..768b167857dd 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Broken_Hill and b/python/ext-libs/pytz/zoneinfo/Australia/Broken_Hill differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Canberra b/python/ext-libs/pytz/zoneinfo/Australia/Canberra index d95c245e5ee1..aaed12ca284d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Canberra and b/python/ext-libs/pytz/zoneinfo/Australia/Canberra differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Currie b/python/ext-libs/pytz/zoneinfo/Australia/Currie index 43ca1e455803..a3f6f29a4961 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Currie and b/python/ext-libs/pytz/zoneinfo/Australia/Currie differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Darwin b/python/ext-libs/pytz/zoneinfo/Australia/Darwin index c44512fbb73b..c6ae9a7ba253 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Darwin and b/python/ext-libs/pytz/zoneinfo/Australia/Darwin differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Eucla b/python/ext-libs/pytz/zoneinfo/Australia/Eucla index e78c2d42514e..baba07a310ad 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Eucla and b/python/ext-libs/pytz/zoneinfo/Australia/Eucla differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Hobart b/python/ext-libs/pytz/zoneinfo/Australia/Hobart index c4604e5386ef..07784ce5d751 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Hobart and b/python/ext-libs/pytz/zoneinfo/Australia/Hobart differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/LHI b/python/ext-libs/pytz/zoneinfo/Australia/LHI index 1f542d3700d5..a653e5166d29 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/LHI and b/python/ext-libs/pytz/zoneinfo/Australia/LHI differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Lindeman b/python/ext-libs/pytz/zoneinfo/Australia/Lindeman index 05c3c1c324cc..71ca143f29f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Lindeman and b/python/ext-libs/pytz/zoneinfo/Australia/Lindeman differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Lord_Howe b/python/ext-libs/pytz/zoneinfo/Australia/Lord_Howe index 1f542d3700d5..a653e5166d29 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Lord_Howe and b/python/ext-libs/pytz/zoneinfo/Australia/Lord_Howe differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Melbourne b/python/ext-libs/pytz/zoneinfo/Australia/Melbourne index af3152f6c4cb..ec8dfe038c2d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Melbourne and b/python/ext-libs/pytz/zoneinfo/Australia/Melbourne differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/NSW b/python/ext-libs/pytz/zoneinfo/Australia/NSW index d95c245e5ee1..aaed12ca284d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/NSW and b/python/ext-libs/pytz/zoneinfo/Australia/NSW differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/North b/python/ext-libs/pytz/zoneinfo/Australia/North index c44512fbb73b..c6ae9a7ba253 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/North and b/python/ext-libs/pytz/zoneinfo/Australia/North differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Perth b/python/ext-libs/pytz/zoneinfo/Australia/Perth index 1c7ebb795cb7..85c26d509a81 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Perth and b/python/ext-libs/pytz/zoneinfo/Australia/Perth differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Queensland b/python/ext-libs/pytz/zoneinfo/Australia/Queensland index 3e899a163f51..a327d83b7696 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Queensland and b/python/ext-libs/pytz/zoneinfo/Australia/Queensland differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/South b/python/ext-libs/pytz/zoneinfo/Australia/South index b350cb6660a6..4f331a87df4e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/South and b/python/ext-libs/pytz/zoneinfo/Australia/South differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Sydney b/python/ext-libs/pytz/zoneinfo/Australia/Sydney index d95c245e5ee1..aaed12ca284d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Sydney and b/python/ext-libs/pytz/zoneinfo/Australia/Sydney differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Tasmania b/python/ext-libs/pytz/zoneinfo/Australia/Tasmania index c4604e5386ef..07784ce5d751 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Tasmania and b/python/ext-libs/pytz/zoneinfo/Australia/Tasmania differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Victoria b/python/ext-libs/pytz/zoneinfo/Australia/Victoria index af3152f6c4cb..ec8dfe038c2d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Victoria and b/python/ext-libs/pytz/zoneinfo/Australia/Victoria differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/West b/python/ext-libs/pytz/zoneinfo/Australia/West index 1c7ebb795cb7..85c26d509a81 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/West and b/python/ext-libs/pytz/zoneinfo/Australia/West differ diff --git a/python/ext-libs/pytz/zoneinfo/Australia/Yancowinna b/python/ext-libs/pytz/zoneinfo/Australia/Yancowinna index d8f3155c84df..768b167857dd 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Australia/Yancowinna and b/python/ext-libs/pytz/zoneinfo/Australia/Yancowinna differ diff --git a/python/ext-libs/pytz/zoneinfo/Brazil/Acre b/python/ext-libs/pytz/zoneinfo/Brazil/Acre index 21cf598ff1f3..788d0e9ceb07 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Brazil/Acre and b/python/ext-libs/pytz/zoneinfo/Brazil/Acre differ diff --git a/python/ext-libs/pytz/zoneinfo/Brazil/DeNoronha b/python/ext-libs/pytz/zoneinfo/Brazil/DeNoronha index c60239009e46..774b14e6cb3a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Brazil/DeNoronha and b/python/ext-libs/pytz/zoneinfo/Brazil/DeNoronha differ diff --git a/python/ext-libs/pytz/zoneinfo/Brazil/East b/python/ext-libs/pytz/zoneinfo/Brazil/East index 8df63a17bd46..552ce7c29228 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Brazil/East and b/python/ext-libs/pytz/zoneinfo/Brazil/East differ diff --git a/python/ext-libs/pytz/zoneinfo/Brazil/West b/python/ext-libs/pytz/zoneinfo/Brazil/West index 112921184139..e0222f18e2a3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Brazil/West and b/python/ext-libs/pytz/zoneinfo/Brazil/West differ diff --git a/python/ext-libs/pytz/zoneinfo/Canada/Atlantic b/python/ext-libs/pytz/zoneinfo/Canada/Atlantic index 756099abe6ce..f86ece4c4032 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Canada/Atlantic and b/python/ext-libs/pytz/zoneinfo/Canada/Atlantic differ diff --git a/python/ext-libs/pytz/zoneinfo/Canada/Central b/python/ext-libs/pytz/zoneinfo/Canada/Central index 2d22791686e8..2ffe3d8d8e01 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Canada/Central and b/python/ext-libs/pytz/zoneinfo/Canada/Central differ diff --git a/python/ext-libs/pytz/zoneinfo/Canada/East-Saskatchewan b/python/ext-libs/pytz/zoneinfo/Canada/East-Saskatchewan index 20c9c84df491..5fe8d6b618e3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Canada/East-Saskatchewan and b/python/ext-libs/pytz/zoneinfo/Canada/East-Saskatchewan differ diff --git a/python/ext-libs/pytz/zoneinfo/Canada/Eastern b/python/ext-libs/pytz/zoneinfo/Canada/Eastern index 1698477a4877..7b4682a39e2f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Canada/Eastern and b/python/ext-libs/pytz/zoneinfo/Canada/Eastern differ diff --git a/python/ext-libs/pytz/zoneinfo/Canada/Mountain b/python/ext-libs/pytz/zoneinfo/Canada/Mountain index 3fa0579891a9..d02fbcd47f84 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Canada/Mountain and b/python/ext-libs/pytz/zoneinfo/Canada/Mountain differ diff --git a/python/ext-libs/pytz/zoneinfo/Canada/Newfoundland b/python/ext-libs/pytz/zoneinfo/Canada/Newfoundland index e7a18d601d02..a1d14854af6b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Canada/Newfoundland and b/python/ext-libs/pytz/zoneinfo/Canada/Newfoundland differ diff --git a/python/ext-libs/pytz/zoneinfo/Canada/Pacific b/python/ext-libs/pytz/zoneinfo/Canada/Pacific index 0c1fa5269049..9b5d924173e6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Canada/Pacific and b/python/ext-libs/pytz/zoneinfo/Canada/Pacific differ diff --git a/python/ext-libs/pytz/zoneinfo/Canada/Saskatchewan b/python/ext-libs/pytz/zoneinfo/Canada/Saskatchewan index 20c9c84df491..5fe8d6b618e3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Canada/Saskatchewan and b/python/ext-libs/pytz/zoneinfo/Canada/Saskatchewan differ diff --git a/python/ext-libs/pytz/zoneinfo/Canada/Yukon b/python/ext-libs/pytz/zoneinfo/Canada/Yukon index 15216d55ff54..8604c5c535ed 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Canada/Yukon and b/python/ext-libs/pytz/zoneinfo/Canada/Yukon differ diff --git a/python/ext-libs/pytz/zoneinfo/Chile/Continental b/python/ext-libs/pytz/zoneinfo/Chile/Continental index 7cf0a1e1877b..92cf5597689b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Chile/Continental and b/python/ext-libs/pytz/zoneinfo/Chile/Continental differ diff --git a/python/ext-libs/pytz/zoneinfo/Chile/EasterIsland b/python/ext-libs/pytz/zoneinfo/Chile/EasterIsland index 1e2f484b79ee..8c8a6c7d9145 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Chile/EasterIsland and b/python/ext-libs/pytz/zoneinfo/Chile/EasterIsland differ diff --git a/python/ext-libs/pytz/zoneinfo/Cuba b/python/ext-libs/pytz/zoneinfo/Cuba index c2623e05f545..1a58fcdc988e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Cuba and b/python/ext-libs/pytz/zoneinfo/Cuba differ diff --git a/python/ext-libs/pytz/zoneinfo/EST b/python/ext-libs/pytz/zoneinfo/EST index 074a4fc76ad8..ae346633c169 100644 Binary files a/python/ext-libs/pytz/zoneinfo/EST and b/python/ext-libs/pytz/zoneinfo/EST differ diff --git a/python/ext-libs/pytz/zoneinfo/Egypt b/python/ext-libs/pytz/zoneinfo/Egypt index 1c6a2fc8fa68..0eeed1138f28 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Egypt and b/python/ext-libs/pytz/zoneinfo/Egypt differ diff --git a/python/ext-libs/pytz/zoneinfo/Eire b/python/ext-libs/pytz/zoneinfo/Eire index 3dec02693d78..a7cffbbb9561 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Eire and b/python/ext-libs/pytz/zoneinfo/Eire differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT b/python/ext-libs/pytz/zoneinfo/Etc/GMT index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT and b/python/ext-libs/pytz/zoneinfo/Etc/GMT differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+0 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+0 index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+0 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+0 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+1 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+1 index 67b88c96237f..2f40cc768a61 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+1 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+1 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+10 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+10 index d564b28a6f8c..2087965ed9e2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+10 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+10 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+11 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+11 index 52eb573057b7..af4a6b3409c2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+11 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+11 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+12 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+12 index c54cead625d2..f0955345ef00 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+12 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+12 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+2 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+2 index e43b63f66b6c..85a1fc1d2240 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+2 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+2 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+3 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+3 index f029bac683c7..a24f58702c97 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+3 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+3 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+4 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+4 index 0ad0ee3229bd..ab7451745717 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+4 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+4 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+5 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+5 index e53f3febecf6..01f1d77597fc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+5 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+5 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+6 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+6 index b41149616a31..3ced48bbe523 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+6 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+6 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+7 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+7 index 32fa6dcb42cc..5f58127edbbe 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+7 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+7 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+8 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+8 index 512578ca6d7c..be23d9660e98 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+8 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+8 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT+9 b/python/ext-libs/pytz/zoneinfo/Etc/GMT+9 index d3e47e7b24e5..d00c50c5aca1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT+9 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT+9 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-0 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-0 index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-0 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-0 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-1 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-1 index 9a6adebc882e..088a76ed53b2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-1 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-1 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-10 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-10 index 37b93fb9d15d..a4da44f5edb5 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-10 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-10 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-11 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-11 index f1af0e290c98..e0112a9ce2d3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-11 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-11 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-12 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-12 index 0fa4a8dc03dd..c1e08b772143 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-12 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-12 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-13 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-13 index 0a5dbe16cde2..1ab051994f36 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-13 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-13 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-14 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-14 index 41c6a1d1ca0a..afaf3fa93145 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-14 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-14 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-2 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-2 index 9f63268d09e0..6289cad88f9b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-2 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-2 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-3 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-3 index 38ccd8a6108b..27434cdb7e5c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-3 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-3 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-4 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-4 index 43badfb220c4..2fc696638f18 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-4 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-4 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-5 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-5 index c88cf210c3ba..8508e72381f7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-5 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-5 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-6 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-6 index c1a0634cf5ca..5b9678ea2809 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-6 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-6 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-7 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-7 index bc152efdaf3c..ccf4c3948048 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-7 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-7 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-8 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-8 index 2c0de20faa3e..db4cfa6af7de 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-8 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-8 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT-9 b/python/ext-libs/pytz/zoneinfo/Etc/GMT-9 index 8a3bd45af31a..56ea117410b5 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT-9 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT-9 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/GMT0 b/python/ext-libs/pytz/zoneinfo/Etc/GMT0 index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/GMT0 and b/python/ext-libs/pytz/zoneinfo/Etc/GMT0 differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/Greenwich b/python/ext-libs/pytz/zoneinfo/Etc/Greenwich index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/Greenwich and b/python/ext-libs/pytz/zoneinfo/Etc/Greenwich differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/UCT b/python/ext-libs/pytz/zoneinfo/Etc/UCT index a88c4b665b3e..40147b9e8349 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/UCT and b/python/ext-libs/pytz/zoneinfo/Etc/UCT differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/UTC b/python/ext-libs/pytz/zoneinfo/Etc/UTC index 5583f5b0c6e6..c3b97f1a1994 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/UTC and b/python/ext-libs/pytz/zoneinfo/Etc/UTC differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/Universal b/python/ext-libs/pytz/zoneinfo/Etc/Universal index 5583f5b0c6e6..c3b97f1a1994 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/Universal and b/python/ext-libs/pytz/zoneinfo/Etc/Universal differ diff --git a/python/ext-libs/pytz/zoneinfo/Etc/Zulu b/python/ext-libs/pytz/zoneinfo/Etc/Zulu index 5583f5b0c6e6..c3b97f1a1994 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Etc/Zulu and b/python/ext-libs/pytz/zoneinfo/Etc/Zulu differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Amsterdam b/python/ext-libs/pytz/zoneinfo/Europe/Amsterdam index 30ca3243a5ab..f74769d4cf1c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Amsterdam and b/python/ext-libs/pytz/zoneinfo/Europe/Amsterdam differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Andorra b/python/ext-libs/pytz/zoneinfo/Europe/Andorra index cf9533a3e4d5..b06de7a5904d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Andorra and b/python/ext-libs/pytz/zoneinfo/Europe/Andorra differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Athens b/python/ext-libs/pytz/zoneinfo/Europe/Athens index 726e56c3fe18..0001602fdccd 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Athens and b/python/ext-libs/pytz/zoneinfo/Europe/Athens differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Belfast b/python/ext-libs/pytz/zoneinfo/Europe/Belfast index fe63ff7e7f1e..4527515ca3f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Belfast and b/python/ext-libs/pytz/zoneinfo/Europe/Belfast differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Belgrade b/python/ext-libs/pytz/zoneinfo/Europe/Belgrade index 5f0389f03919..79c25d70ef09 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Belgrade and b/python/ext-libs/pytz/zoneinfo/Europe/Belgrade differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Berlin b/python/ext-libs/pytz/zoneinfo/Europe/Berlin index 96059c7854e1..b4f2a2af6de4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Berlin and b/python/ext-libs/pytz/zoneinfo/Europe/Berlin differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Bratislava b/python/ext-libs/pytz/zoneinfo/Europe/Bratislava index 9ab78e9156f2..4eabe5c81bd1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Bratislava and b/python/ext-libs/pytz/zoneinfo/Europe/Bratislava differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Brussels b/python/ext-libs/pytz/zoneinfo/Europe/Brussels index 2791edeba35c..d8f19a6312a2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Brussels and b/python/ext-libs/pytz/zoneinfo/Europe/Brussels differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Bucharest b/python/ext-libs/pytz/zoneinfo/Europe/Bucharest index de2a5f0af1a4..e0eac4ce3315 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Bucharest and b/python/ext-libs/pytz/zoneinfo/Europe/Bucharest differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Budapest b/python/ext-libs/pytz/zoneinfo/Europe/Budapest index 1b787b16cea3..3ddf6a528983 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Budapest and b/python/ext-libs/pytz/zoneinfo/Europe/Budapest differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Busingen b/python/ext-libs/pytz/zoneinfo/Europe/Busingen index 440f158c1413..9c2b600b103d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Busingen and b/python/ext-libs/pytz/zoneinfo/Europe/Busingen differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Chisinau b/python/ext-libs/pytz/zoneinfo/Europe/Chisinau index 983cc7071676..7998b2d84e3b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Chisinau and b/python/ext-libs/pytz/zoneinfo/Europe/Chisinau differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Copenhagen b/python/ext-libs/pytz/zoneinfo/Europe/Copenhagen index af7e9269e5e4..be87cf162e1a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Copenhagen and b/python/ext-libs/pytz/zoneinfo/Europe/Copenhagen differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Dublin b/python/ext-libs/pytz/zoneinfo/Europe/Dublin index 3dec02693d78..a7cffbbb9561 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Dublin and b/python/ext-libs/pytz/zoneinfo/Europe/Dublin differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Gibraltar b/python/ext-libs/pytz/zoneinfo/Europe/Gibraltar index f3dbeb65ecce..a7105faaeb14 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Gibraltar and b/python/ext-libs/pytz/zoneinfo/Europe/Gibraltar differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Guernsey b/python/ext-libs/pytz/zoneinfo/Europe/Guernsey index fe63ff7e7f1e..4527515ca3f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Guernsey and b/python/ext-libs/pytz/zoneinfo/Europe/Guernsey differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Helsinki b/python/ext-libs/pytz/zoneinfo/Europe/Helsinki index 19d7babd531f..29b3c817f463 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Helsinki and b/python/ext-libs/pytz/zoneinfo/Europe/Helsinki differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Isle_of_Man b/python/ext-libs/pytz/zoneinfo/Europe/Isle_of_Man index fe63ff7e7f1e..4527515ca3f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Isle_of_Man and b/python/ext-libs/pytz/zoneinfo/Europe/Isle_of_Man differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Istanbul b/python/ext-libs/pytz/zoneinfo/Europe/Istanbul index 864099556bc9..d89aa3a82674 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Istanbul and b/python/ext-libs/pytz/zoneinfo/Europe/Istanbul differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Jersey b/python/ext-libs/pytz/zoneinfo/Europe/Jersey index fe63ff7e7f1e..4527515ca3f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Jersey and b/python/ext-libs/pytz/zoneinfo/Europe/Jersey differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Kaliningrad b/python/ext-libs/pytz/zoneinfo/Europe/Kaliningrad index fa6bab862037..4805fe4251e0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Kaliningrad and b/python/ext-libs/pytz/zoneinfo/Europe/Kaliningrad differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Kiev b/python/ext-libs/pytz/zoneinfo/Europe/Kiev index 075cc02fd893..b3e20a7e3946 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Kiev and b/python/ext-libs/pytz/zoneinfo/Europe/Kiev differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Lisbon b/python/ext-libs/pytz/zoneinfo/Europe/Lisbon index 168accf060c3..b9aff3a51cae 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Lisbon and b/python/ext-libs/pytz/zoneinfo/Europe/Lisbon differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Ljubljana b/python/ext-libs/pytz/zoneinfo/Europe/Ljubljana index 5f0389f03919..79c25d70ef09 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Ljubljana and b/python/ext-libs/pytz/zoneinfo/Europe/Ljubljana differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/London b/python/ext-libs/pytz/zoneinfo/Europe/London index fe63ff7e7f1e..4527515ca3f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/London and b/python/ext-libs/pytz/zoneinfo/Europe/London differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Luxembourg b/python/ext-libs/pytz/zoneinfo/Europe/Luxembourg index 6c194a5cdcb2..6fae86c53176 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Luxembourg and b/python/ext-libs/pytz/zoneinfo/Europe/Luxembourg differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Madrid b/python/ext-libs/pytz/zoneinfo/Europe/Madrid index 931195955a1b..af474328e580 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Madrid and b/python/ext-libs/pytz/zoneinfo/Europe/Madrid differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Malta b/python/ext-libs/pytz/zoneinfo/Europe/Malta index 5f518a1f1773..d2519389e5e1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Malta and b/python/ext-libs/pytz/zoneinfo/Europe/Malta differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Mariehamn b/python/ext-libs/pytz/zoneinfo/Europe/Mariehamn index 19d7babd531f..29b3c817f463 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Mariehamn and b/python/ext-libs/pytz/zoneinfo/Europe/Mariehamn differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Minsk b/python/ext-libs/pytz/zoneinfo/Europe/Minsk index ba9971c63138..fa1e2e4ef8e0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Minsk and b/python/ext-libs/pytz/zoneinfo/Europe/Minsk differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Monaco b/python/ext-libs/pytz/zoneinfo/Europe/Monaco index 664f6161ab6c..0b40f1ec9321 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Monaco and b/python/ext-libs/pytz/zoneinfo/Europe/Monaco differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Moscow b/python/ext-libs/pytz/zoneinfo/Europe/Moscow index 6068f8b9e584..bdbbaebe05e0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Moscow and b/python/ext-libs/pytz/zoneinfo/Europe/Moscow differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Nicosia b/python/ext-libs/pytz/zoneinfo/Europe/Nicosia index f7f10ab7665e..3e663b215327 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Nicosia and b/python/ext-libs/pytz/zoneinfo/Europe/Nicosia differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Oslo b/python/ext-libs/pytz/zoneinfo/Europe/Oslo index 6326961453f4..239c0174d361 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Oslo and b/python/ext-libs/pytz/zoneinfo/Europe/Oslo differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Paris b/python/ext-libs/pytz/zoneinfo/Europe/Paris index fd8ea7dbae9e..cf6e2e2ee953 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Paris and b/python/ext-libs/pytz/zoneinfo/Europe/Paris differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Podgorica b/python/ext-libs/pytz/zoneinfo/Europe/Podgorica index 5f0389f03919..79c25d70ef09 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Podgorica and b/python/ext-libs/pytz/zoneinfo/Europe/Podgorica differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Prague b/python/ext-libs/pytz/zoneinfo/Europe/Prague index 9ab78e9156f2..4eabe5c81bd1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Prague and b/python/ext-libs/pytz/zoneinfo/Europe/Prague differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Riga b/python/ext-libs/pytz/zoneinfo/Europe/Riga index abea45d309b7..b729ee8c2ee2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Riga and b/python/ext-libs/pytz/zoneinfo/Europe/Riga differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Rome b/python/ext-libs/pytz/zoneinfo/Europe/Rome index 28ddffe0d93e..5cc30403c37c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Rome and b/python/ext-libs/pytz/zoneinfo/Europe/Rome differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Samara b/python/ext-libs/pytz/zoneinfo/Europe/Samara index fe5060094b50..79759f537744 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Samara and b/python/ext-libs/pytz/zoneinfo/Europe/Samara differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/San_Marino b/python/ext-libs/pytz/zoneinfo/Europe/San_Marino index 28ddffe0d93e..5cc30403c37c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/San_Marino and b/python/ext-libs/pytz/zoneinfo/Europe/San_Marino differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Sarajevo b/python/ext-libs/pytz/zoneinfo/Europe/Sarajevo index 5f0389f03919..79c25d70ef09 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Sarajevo and b/python/ext-libs/pytz/zoneinfo/Europe/Sarajevo differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Simferopol b/python/ext-libs/pytz/zoneinfo/Europe/Simferopol index ebb63b4450b0..ebe9017d40ae 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Simferopol and b/python/ext-libs/pytz/zoneinfo/Europe/Simferopol differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Skopje b/python/ext-libs/pytz/zoneinfo/Europe/Skopje index 5f0389f03919..79c25d70ef09 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Skopje and b/python/ext-libs/pytz/zoneinfo/Europe/Skopje differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Sofia b/python/ext-libs/pytz/zoneinfo/Europe/Sofia index d8032335b20a..763e074795b3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Sofia and b/python/ext-libs/pytz/zoneinfo/Europe/Sofia differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Stockholm b/python/ext-libs/pytz/zoneinfo/Europe/Stockholm index 3bc6dbd9d12b..43c7f2e23f3c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Stockholm and b/python/ext-libs/pytz/zoneinfo/Europe/Stockholm differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Tallinn b/python/ext-libs/pytz/zoneinfo/Europe/Tallinn index 4ba4424121ae..8a4f12402f0e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Tallinn and b/python/ext-libs/pytz/zoneinfo/Europe/Tallinn differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Tirane b/python/ext-libs/pytz/zoneinfo/Europe/Tirane index 0b86017d243f..52c16a42bf1a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Tirane and b/python/ext-libs/pytz/zoneinfo/Europe/Tirane differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Tiraspol b/python/ext-libs/pytz/zoneinfo/Europe/Tiraspol index 983cc7071676..7998b2d84e3b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Tiraspol and b/python/ext-libs/pytz/zoneinfo/Europe/Tiraspol differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Uzhgorod b/python/ext-libs/pytz/zoneinfo/Europe/Uzhgorod index 7032ab9b34f9..8ddba9097f80 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Uzhgorod and b/python/ext-libs/pytz/zoneinfo/Europe/Uzhgorod differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Vaduz b/python/ext-libs/pytz/zoneinfo/Europe/Vaduz index 440f158c1413..9c2b600b103d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Vaduz and b/python/ext-libs/pytz/zoneinfo/Europe/Vaduz differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Vatican b/python/ext-libs/pytz/zoneinfo/Europe/Vatican index 28ddffe0d93e..5cc30403c37c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Vatican and b/python/ext-libs/pytz/zoneinfo/Europe/Vatican differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Vienna b/python/ext-libs/pytz/zoneinfo/Europe/Vienna index 8e4c9a9b5f09..9c0fac5369e4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Vienna and b/python/ext-libs/pytz/zoneinfo/Europe/Vienna differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Vilnius b/python/ext-libs/pytz/zoneinfo/Europe/Vilnius index b6545b24949c..3b11880de100 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Vilnius and b/python/ext-libs/pytz/zoneinfo/Europe/Vilnius differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Volgograd b/python/ext-libs/pytz/zoneinfo/Europe/Volgograd index b91e4fbff6b4..c62c32a653f1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Volgograd and b/python/ext-libs/pytz/zoneinfo/Europe/Volgograd differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Warsaw b/python/ext-libs/pytz/zoneinfo/Europe/Warsaw index 3797b1cb6532..5cbba412eef4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Warsaw and b/python/ext-libs/pytz/zoneinfo/Europe/Warsaw differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Zagreb b/python/ext-libs/pytz/zoneinfo/Europe/Zagreb index 5f0389f03919..79c25d70ef09 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Zagreb and b/python/ext-libs/pytz/zoneinfo/Europe/Zagreb differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Zaporozhye b/python/ext-libs/pytz/zoneinfo/Europe/Zaporozhye index 2ccf8998b24f..49b568e773a7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Zaporozhye and b/python/ext-libs/pytz/zoneinfo/Europe/Zaporozhye differ diff --git a/python/ext-libs/pytz/zoneinfo/Europe/Zurich b/python/ext-libs/pytz/zoneinfo/Europe/Zurich index 440f158c1413..9c2b600b103d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Europe/Zurich and b/python/ext-libs/pytz/zoneinfo/Europe/Zurich differ diff --git a/python/ext-libs/pytz/zoneinfo/Factory b/python/ext-libs/pytz/zoneinfo/Factory index a65f97edd26d..6e6c452ee1f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Factory and b/python/ext-libs/pytz/zoneinfo/Factory differ diff --git a/python/ext-libs/pytz/zoneinfo/GB b/python/ext-libs/pytz/zoneinfo/GB index fe63ff7e7f1e..4527515ca3f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/GB and b/python/ext-libs/pytz/zoneinfo/GB differ diff --git a/python/ext-libs/pytz/zoneinfo/GB-Eire b/python/ext-libs/pytz/zoneinfo/GB-Eire index fe63ff7e7f1e..4527515ca3f2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/GB-Eire and b/python/ext-libs/pytz/zoneinfo/GB-Eire differ diff --git a/python/ext-libs/pytz/zoneinfo/GMT b/python/ext-libs/pytz/zoneinfo/GMT index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/GMT and b/python/ext-libs/pytz/zoneinfo/GMT differ diff --git a/python/ext-libs/pytz/zoneinfo/GMT+0 b/python/ext-libs/pytz/zoneinfo/GMT+0 index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/GMT+0 and b/python/ext-libs/pytz/zoneinfo/GMT+0 differ diff --git a/python/ext-libs/pytz/zoneinfo/GMT-0 b/python/ext-libs/pytz/zoneinfo/GMT-0 index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/GMT-0 and b/python/ext-libs/pytz/zoneinfo/GMT-0 differ diff --git a/python/ext-libs/pytz/zoneinfo/GMT0 b/python/ext-libs/pytz/zoneinfo/GMT0 index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/GMT0 and b/python/ext-libs/pytz/zoneinfo/GMT0 differ diff --git a/python/ext-libs/pytz/zoneinfo/Greenwich b/python/ext-libs/pytz/zoneinfo/Greenwich index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Greenwich and b/python/ext-libs/pytz/zoneinfo/Greenwich differ diff --git a/python/ext-libs/pytz/zoneinfo/HST b/python/ext-libs/pytz/zoneinfo/HST index 616c31bc5ea6..03e4db076900 100644 Binary files a/python/ext-libs/pytz/zoneinfo/HST and b/python/ext-libs/pytz/zoneinfo/HST differ diff --git a/python/ext-libs/pytz/zoneinfo/Hongkong b/python/ext-libs/pytz/zoneinfo/Hongkong index 8e5c5813666a..dc9058e4b578 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Hongkong and b/python/ext-libs/pytz/zoneinfo/Hongkong differ diff --git a/python/ext-libs/pytz/zoneinfo/Iceland b/python/ext-libs/pytz/zoneinfo/Iceland index e97f13a65201..35ba7a15f4b6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Iceland and b/python/ext-libs/pytz/zoneinfo/Iceland differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Antananarivo b/python/ext-libs/pytz/zoneinfo/Indian/Antananarivo index ef6e745c4517..33d59cc974ae 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Antananarivo and b/python/ext-libs/pytz/zoneinfo/Indian/Antananarivo differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Chagos b/python/ext-libs/pytz/zoneinfo/Indian/Chagos index 864d3e29a2b0..a616bdfbbe15 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Chagos and b/python/ext-libs/pytz/zoneinfo/Indian/Chagos differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Christmas b/python/ext-libs/pytz/zoneinfo/Indian/Christmas index 686d5b3c6542..ebcd2624864e 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Christmas and b/python/ext-libs/pytz/zoneinfo/Indian/Christmas differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Cocos b/python/ext-libs/pytz/zoneinfo/Indian/Cocos index 6f7d869f0fb3..cd603f24790c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Cocos and b/python/ext-libs/pytz/zoneinfo/Indian/Cocos differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Comoro b/python/ext-libs/pytz/zoneinfo/Indian/Comoro index 297c6db63c06..298db9b7dba0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Comoro and b/python/ext-libs/pytz/zoneinfo/Indian/Comoro differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Kerguelen b/python/ext-libs/pytz/zoneinfo/Indian/Kerguelen index 1f42bbc1ffcb..462851ebbe65 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Kerguelen and b/python/ext-libs/pytz/zoneinfo/Indian/Kerguelen differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Mahe b/python/ext-libs/pytz/zoneinfo/Indian/Mahe index d048242cac78..5f42819b66e4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Mahe and b/python/ext-libs/pytz/zoneinfo/Indian/Mahe differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Maldives b/python/ext-libs/pytz/zoneinfo/Indian/Maldives index 65e7eeee8db7..cec224ff348c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Maldives and b/python/ext-libs/pytz/zoneinfo/Indian/Maldives differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Mauritius b/python/ext-libs/pytz/zoneinfo/Indian/Mauritius index 54f222010893..66ecc8f51a7d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Mauritius and b/python/ext-libs/pytz/zoneinfo/Indian/Mauritius differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Mayotte b/python/ext-libs/pytz/zoneinfo/Indian/Mayotte index 8401a37aa0ba..c915d90973bf 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Mayotte and b/python/ext-libs/pytz/zoneinfo/Indian/Mayotte differ diff --git a/python/ext-libs/pytz/zoneinfo/Indian/Reunion b/python/ext-libs/pytz/zoneinfo/Indian/Reunion index 9b3830ec31a1..c4d0da90d373 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Indian/Reunion and b/python/ext-libs/pytz/zoneinfo/Indian/Reunion differ diff --git a/python/ext-libs/pytz/zoneinfo/Iran b/python/ext-libs/pytz/zoneinfo/Iran index 62d316190d42..871078114d04 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Iran and b/python/ext-libs/pytz/zoneinfo/Iran differ diff --git a/python/ext-libs/pytz/zoneinfo/Israel b/python/ext-libs/pytz/zoneinfo/Israel index affa0e4eaf7b..df5119935c5b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Israel and b/python/ext-libs/pytz/zoneinfo/Israel differ diff --git a/python/ext-libs/pytz/zoneinfo/Jamaica b/python/ext-libs/pytz/zoneinfo/Jamaica index b89c18787ece..24ea5dc09ba7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Jamaica and b/python/ext-libs/pytz/zoneinfo/Jamaica differ diff --git a/python/ext-libs/pytz/zoneinfo/Japan b/python/ext-libs/pytz/zoneinfo/Japan index 058c1e99ba26..024414031e18 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Japan and b/python/ext-libs/pytz/zoneinfo/Japan differ diff --git a/python/ext-libs/pytz/zoneinfo/Kwajalein b/python/ext-libs/pytz/zoneinfo/Kwajalein index b57237272d54..094c3cfd75c3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Kwajalein and b/python/ext-libs/pytz/zoneinfo/Kwajalein differ diff --git a/python/ext-libs/pytz/zoneinfo/Libya b/python/ext-libs/pytz/zoneinfo/Libya index bd885315f84f..b32e2202f572 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Libya and b/python/ext-libs/pytz/zoneinfo/Libya differ diff --git a/python/ext-libs/pytz/zoneinfo/MST b/python/ext-libs/pytz/zoneinfo/MST index da3e926d23e7..a1bee7c6f0b7 100644 Binary files a/python/ext-libs/pytz/zoneinfo/MST and b/python/ext-libs/pytz/zoneinfo/MST differ diff --git a/python/ext-libs/pytz/zoneinfo/Mexico/BajaNorte b/python/ext-libs/pytz/zoneinfo/Mexico/BajaNorte index fffdc24bfc4c..1387475394bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Mexico/BajaNorte and b/python/ext-libs/pytz/zoneinfo/Mexico/BajaNorte differ diff --git a/python/ext-libs/pytz/zoneinfo/Mexico/BajaSur b/python/ext-libs/pytz/zoneinfo/Mexico/BajaSur index 43ee12d84a7c..afa94c2ac5c1 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Mexico/BajaSur and b/python/ext-libs/pytz/zoneinfo/Mexico/BajaSur differ diff --git a/python/ext-libs/pytz/zoneinfo/Mexico/General b/python/ext-libs/pytz/zoneinfo/Mexico/General index 1434ab08804d..f11e3d2d66a2 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Mexico/General and b/python/ext-libs/pytz/zoneinfo/Mexico/General differ diff --git a/python/ext-libs/pytz/zoneinfo/NZ b/python/ext-libs/pytz/zoneinfo/NZ index a40767df93d3..a5f5b6d5e60f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/NZ and b/python/ext-libs/pytz/zoneinfo/NZ differ diff --git a/python/ext-libs/pytz/zoneinfo/NZ-CHAT b/python/ext-libs/pytz/zoneinfo/NZ-CHAT index 6329e4fce0e5..59bc4ede9874 100644 Binary files a/python/ext-libs/pytz/zoneinfo/NZ-CHAT and b/python/ext-libs/pytz/zoneinfo/NZ-CHAT differ diff --git a/python/ext-libs/pytz/zoneinfo/Navajo b/python/ext-libs/pytz/zoneinfo/Navajo index f8908febf220..7fc669171f88 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Navajo and b/python/ext-libs/pytz/zoneinfo/Navajo differ diff --git a/python/ext-libs/pytz/zoneinfo/PRC b/python/ext-libs/pytz/zoneinfo/PRC index af6d6fbbd298..dbd132f2b0bc 100644 Binary files a/python/ext-libs/pytz/zoneinfo/PRC and b/python/ext-libs/pytz/zoneinfo/PRC differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Apia b/python/ext-libs/pytz/zoneinfo/Pacific/Apia index efe6d5a1de7f..cc5d2cd2d443 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Apia and b/python/ext-libs/pytz/zoneinfo/Pacific/Apia differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Auckland b/python/ext-libs/pytz/zoneinfo/Pacific/Auckland index a40767df93d3..a5f5b6d5e60f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Auckland and b/python/ext-libs/pytz/zoneinfo/Pacific/Auckland differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Chatham b/python/ext-libs/pytz/zoneinfo/Pacific/Chatham index 6329e4fce0e5..59bc4ede9874 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Chatham and b/python/ext-libs/pytz/zoneinfo/Pacific/Chatham differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Chuuk b/python/ext-libs/pytz/zoneinfo/Pacific/Chuuk index 0ef473871d55..28356bbf1b23 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Chuuk and b/python/ext-libs/pytz/zoneinfo/Pacific/Chuuk differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Easter b/python/ext-libs/pytz/zoneinfo/Pacific/Easter index 1e2f484b79ee..8c8a6c7d9145 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Easter and b/python/ext-libs/pytz/zoneinfo/Pacific/Easter differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Efate b/python/ext-libs/pytz/zoneinfo/Pacific/Efate index c46154a8056c..1d99519b3782 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Efate and b/python/ext-libs/pytz/zoneinfo/Pacific/Efate differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Enderbury b/python/ext-libs/pytz/zoneinfo/Pacific/Enderbury index 69e75d754e2c..48610523b747 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Enderbury and b/python/ext-libs/pytz/zoneinfo/Pacific/Enderbury differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Fakaofo b/python/ext-libs/pytz/zoneinfo/Pacific/Fakaofo index 22902f98fee2..e02e18e26800 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Fakaofo and b/python/ext-libs/pytz/zoneinfo/Pacific/Fakaofo differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Fiji b/python/ext-libs/pytz/zoneinfo/Pacific/Fiji index 747ee3ef2b74..d91c7e5da89d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Fiji and b/python/ext-libs/pytz/zoneinfo/Pacific/Fiji differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Funafuti b/python/ext-libs/pytz/zoneinfo/Pacific/Funafuti index 66cf5e1df3fc..576dea30104c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Funafuti and b/python/ext-libs/pytz/zoneinfo/Pacific/Funafuti differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Galapagos b/python/ext-libs/pytz/zoneinfo/Pacific/Galapagos index 7504cc66f500..c9a7371d6b82 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Galapagos and b/python/ext-libs/pytz/zoneinfo/Pacific/Galapagos differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Gambier b/python/ext-libs/pytz/zoneinfo/Pacific/Gambier index fc49c03f6e04..4ab6c206075c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Gambier and b/python/ext-libs/pytz/zoneinfo/Pacific/Gambier differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Guadalcanal b/python/ext-libs/pytz/zoneinfo/Pacific/Guadalcanal index 3a4ec12e56d7..b183d1ea6b63 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Guadalcanal and b/python/ext-libs/pytz/zoneinfo/Pacific/Guadalcanal differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Guam b/python/ext-libs/pytz/zoneinfo/Pacific/Guam index a05292f4bacf..4286e6bac870 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Guam and b/python/ext-libs/pytz/zoneinfo/Pacific/Guam differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Honolulu b/python/ext-libs/pytz/zoneinfo/Pacific/Honolulu index 1b4684b9b47f..bd855772054f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Honolulu and b/python/ext-libs/pytz/zoneinfo/Pacific/Honolulu differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Johnston b/python/ext-libs/pytz/zoneinfo/Pacific/Johnston index 1b4684b9b47f..bd855772054f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Johnston and b/python/ext-libs/pytz/zoneinfo/Pacific/Johnston differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Kiritimati b/python/ext-libs/pytz/zoneinfo/Pacific/Kiritimati index 7131453c5540..c2eafbc71e9f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Kiritimati and b/python/ext-libs/pytz/zoneinfo/Pacific/Kiritimati differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Kosrae b/python/ext-libs/pytz/zoneinfo/Pacific/Kosrae index 61b7561589cb..66c4d658103c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Kosrae and b/python/ext-libs/pytz/zoneinfo/Pacific/Kosrae differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Kwajalein b/python/ext-libs/pytz/zoneinfo/Pacific/Kwajalein index b57237272d54..094c3cfd75c3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Kwajalein and b/python/ext-libs/pytz/zoneinfo/Pacific/Kwajalein differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Majuro b/python/ext-libs/pytz/zoneinfo/Pacific/Majuro index eab93a2af990..d53b7c2d8321 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Majuro and b/python/ext-libs/pytz/zoneinfo/Pacific/Majuro differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Marquesas b/python/ext-libs/pytz/zoneinfo/Pacific/Marquesas index cd2d5b073aff..c717c12251b4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Marquesas and b/python/ext-libs/pytz/zoneinfo/Pacific/Marquesas differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Midway b/python/ext-libs/pytz/zoneinfo/Pacific/Midway index 8889a26fa7c8..f2a2f63ccc20 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Midway and b/python/ext-libs/pytz/zoneinfo/Pacific/Midway differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Nauru b/python/ext-libs/pytz/zoneinfo/Pacific/Nauru index 1d8179bcb50d..896ffeee297c 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Nauru and b/python/ext-libs/pytz/zoneinfo/Pacific/Nauru differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Niue b/python/ext-libs/pytz/zoneinfo/Pacific/Niue index b9f18a544ab4..d772edf5b48a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Niue and b/python/ext-libs/pytz/zoneinfo/Pacific/Niue differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Norfolk b/python/ext-libs/pytz/zoneinfo/Pacific/Norfolk index 2e989c255617..3a286be3d203 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Norfolk and b/python/ext-libs/pytz/zoneinfo/Pacific/Norfolk differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Noumea b/python/ext-libs/pytz/zoneinfo/Pacific/Noumea index ae9e138fa566..fcc44e6030d3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Noumea and b/python/ext-libs/pytz/zoneinfo/Pacific/Noumea differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Pago_Pago b/python/ext-libs/pytz/zoneinfo/Pacific/Pago_Pago index fa084ba584c6..1d7649ff71d0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Pago_Pago and b/python/ext-libs/pytz/zoneinfo/Pacific/Pago_Pago differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Palau b/python/ext-libs/pytz/zoneinfo/Pacific/Palau index efc556b14024..28992d2d938a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Palau and b/python/ext-libs/pytz/zoneinfo/Pacific/Palau differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Pitcairn b/python/ext-libs/pytz/zoneinfo/Pacific/Pitcairn index 51f01c6410da..d62c648b8e00 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Pitcairn and b/python/ext-libs/pytz/zoneinfo/Pacific/Pitcairn differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Pohnpei b/python/ext-libs/pytz/zoneinfo/Pacific/Pohnpei index f175ea587502..59bd764622fe 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Pohnpei and b/python/ext-libs/pytz/zoneinfo/Pacific/Pohnpei differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Ponape b/python/ext-libs/pytz/zoneinfo/Pacific/Ponape index f175ea587502..59bd764622fe 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Ponape and b/python/ext-libs/pytz/zoneinfo/Pacific/Ponape differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Port_Moresby b/python/ext-libs/pytz/zoneinfo/Pacific/Port_Moresby index 8d4d12ccb094..dffa4573a457 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Port_Moresby and b/python/ext-libs/pytz/zoneinfo/Pacific/Port_Moresby differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Rarotonga b/python/ext-libs/pytz/zoneinfo/Pacific/Rarotonga index 581299788a61..2a2549024e40 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Rarotonga and b/python/ext-libs/pytz/zoneinfo/Pacific/Rarotonga differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Saipan b/python/ext-libs/pytz/zoneinfo/Pacific/Saipan index 519c86e96683..c54473cd630a 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Saipan and b/python/ext-libs/pytz/zoneinfo/Pacific/Saipan differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Samoa b/python/ext-libs/pytz/zoneinfo/Pacific/Samoa index fa084ba584c6..1d7649ff71d0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Samoa and b/python/ext-libs/pytz/zoneinfo/Pacific/Samoa differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Tahiti b/python/ext-libs/pytz/zoneinfo/Pacific/Tahiti index 22f86974672e..bfc9a7c925f6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Tahiti and b/python/ext-libs/pytz/zoneinfo/Pacific/Tahiti differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Tarawa b/python/ext-libs/pytz/zoneinfo/Pacific/Tarawa index 065dcd819473..1e8189ce66b4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Tarawa and b/python/ext-libs/pytz/zoneinfo/Pacific/Tarawa differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Tongatapu b/python/ext-libs/pytz/zoneinfo/Pacific/Tongatapu index 01ab6b87ef92..71d899bb9637 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Tongatapu and b/python/ext-libs/pytz/zoneinfo/Pacific/Tongatapu differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Truk b/python/ext-libs/pytz/zoneinfo/Pacific/Truk index 0ef473871d55..28356bbf1b23 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Truk and b/python/ext-libs/pytz/zoneinfo/Pacific/Truk differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Wake b/python/ext-libs/pytz/zoneinfo/Pacific/Wake index f89c52829a00..9e2a37cc4243 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Wake and b/python/ext-libs/pytz/zoneinfo/Pacific/Wake differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Wallis b/python/ext-libs/pytz/zoneinfo/Pacific/Wallis index 9aaf558f1da2..b8944715544b 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Wallis and b/python/ext-libs/pytz/zoneinfo/Pacific/Wallis differ diff --git a/python/ext-libs/pytz/zoneinfo/Pacific/Yap b/python/ext-libs/pytz/zoneinfo/Pacific/Yap index 0ef473871d55..28356bbf1b23 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Pacific/Yap and b/python/ext-libs/pytz/zoneinfo/Pacific/Yap differ diff --git a/python/ext-libs/pytz/zoneinfo/Poland b/python/ext-libs/pytz/zoneinfo/Poland index 3797b1cb6532..5cbba412eef4 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Poland and b/python/ext-libs/pytz/zoneinfo/Poland differ diff --git a/python/ext-libs/pytz/zoneinfo/Portugal b/python/ext-libs/pytz/zoneinfo/Portugal index 168accf060c3..b9aff3a51cae 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Portugal and b/python/ext-libs/pytz/zoneinfo/Portugal differ diff --git a/python/ext-libs/pytz/zoneinfo/ROC b/python/ext-libs/pytz/zoneinfo/ROC index 70cfb27ca91f..4810a0b61420 100644 Binary files a/python/ext-libs/pytz/zoneinfo/ROC and b/python/ext-libs/pytz/zoneinfo/ROC differ diff --git a/python/ext-libs/pytz/zoneinfo/ROK b/python/ext-libs/pytz/zoneinfo/ROK index 96bb0c36d7e3..6931d782bba5 100644 Binary files a/python/ext-libs/pytz/zoneinfo/ROK and b/python/ext-libs/pytz/zoneinfo/ROK differ diff --git a/python/ext-libs/pytz/zoneinfo/Singapore b/python/ext-libs/pytz/zoneinfo/Singapore index a6f2db8f3a88..9dd49cb7a72f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Singapore and b/python/ext-libs/pytz/zoneinfo/Singapore differ diff --git a/python/ext-libs/pytz/zoneinfo/Turkey b/python/ext-libs/pytz/zoneinfo/Turkey index 864099556bc9..d89aa3a82674 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Turkey and b/python/ext-libs/pytz/zoneinfo/Turkey differ diff --git a/python/ext-libs/pytz/zoneinfo/UCT b/python/ext-libs/pytz/zoneinfo/UCT index a88c4b665b3e..40147b9e8349 100644 Binary files a/python/ext-libs/pytz/zoneinfo/UCT and b/python/ext-libs/pytz/zoneinfo/UCT differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Alaska b/python/ext-libs/pytz/zoneinfo/US/Alaska index d14735026a09..a4627cac0628 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Alaska and b/python/ext-libs/pytz/zoneinfo/US/Alaska differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Aleutian b/python/ext-libs/pytz/zoneinfo/US/Aleutian index 391ec98ec0f3..b0a5dd60dc21 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Aleutian and b/python/ext-libs/pytz/zoneinfo/US/Aleutian differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Arizona b/python/ext-libs/pytz/zoneinfo/US/Arizona index 67589026c21c..adf28236a2fe 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Arizona and b/python/ext-libs/pytz/zoneinfo/US/Arizona differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Central b/python/ext-libs/pytz/zoneinfo/US/Central index 71aae7246a30..3dd8f0fa82a6 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Central and b/python/ext-libs/pytz/zoneinfo/US/Central differ diff --git a/python/ext-libs/pytz/zoneinfo/US/East-Indiana b/python/ext-libs/pytz/zoneinfo/US/East-Indiana index aa3dfc43730e..4a92c06593d3 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/East-Indiana and b/python/ext-libs/pytz/zoneinfo/US/East-Indiana differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Eastern b/python/ext-libs/pytz/zoneinfo/US/Eastern index b2c2377f4e87..7553fee37a5d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Eastern and b/python/ext-libs/pytz/zoneinfo/US/Eastern differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Hawaii b/python/ext-libs/pytz/zoneinfo/US/Hawaii index 1b4684b9b47f..bd855772054f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Hawaii and b/python/ext-libs/pytz/zoneinfo/US/Hawaii differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Indiana-Starke b/python/ext-libs/pytz/zoneinfo/US/Indiana-Starke index 33169f459638..cc785da97de0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Indiana-Starke and b/python/ext-libs/pytz/zoneinfo/US/Indiana-Starke differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Michigan b/python/ext-libs/pytz/zoneinfo/US/Michigan index da53d46df347..a123b331e72f 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Michigan and b/python/ext-libs/pytz/zoneinfo/US/Michigan differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Mountain b/python/ext-libs/pytz/zoneinfo/US/Mountain index f8908febf220..7fc669171f88 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Mountain and b/python/ext-libs/pytz/zoneinfo/US/Mountain differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Pacific b/python/ext-libs/pytz/zoneinfo/US/Pacific index 3b7ce1dceebf..1fa9149f9a92 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Pacific and b/python/ext-libs/pytz/zoneinfo/US/Pacific differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Pacific-New b/python/ext-libs/pytz/zoneinfo/US/Pacific-New index 3b7ce1dceebf..1fa9149f9a92 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Pacific-New and b/python/ext-libs/pytz/zoneinfo/US/Pacific-New differ diff --git a/python/ext-libs/pytz/zoneinfo/US/Samoa b/python/ext-libs/pytz/zoneinfo/US/Samoa index fa084ba584c6..1d7649ff71d0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/US/Samoa and b/python/ext-libs/pytz/zoneinfo/US/Samoa differ diff --git a/python/ext-libs/pytz/zoneinfo/UTC b/python/ext-libs/pytz/zoneinfo/UTC index 5583f5b0c6e6..c3b97f1a1994 100644 Binary files a/python/ext-libs/pytz/zoneinfo/UTC and b/python/ext-libs/pytz/zoneinfo/UTC differ diff --git a/python/ext-libs/pytz/zoneinfo/Universal b/python/ext-libs/pytz/zoneinfo/Universal index 5583f5b0c6e6..c3b97f1a1994 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Universal and b/python/ext-libs/pytz/zoneinfo/Universal differ diff --git a/python/ext-libs/pytz/zoneinfo/W-SU b/python/ext-libs/pytz/zoneinfo/W-SU index 6068f8b9e584..bdbbaebe05e0 100644 Binary files a/python/ext-libs/pytz/zoneinfo/W-SU and b/python/ext-libs/pytz/zoneinfo/W-SU differ diff --git a/python/ext-libs/pytz/zoneinfo/Zulu b/python/ext-libs/pytz/zoneinfo/Zulu index 5583f5b0c6e6..c3b97f1a1994 100644 Binary files a/python/ext-libs/pytz/zoneinfo/Zulu and b/python/ext-libs/pytz/zoneinfo/Zulu differ diff --git a/python/ext-libs/pytz/zoneinfo/iso3166.tab b/python/ext-libs/pytz/zoneinfo/iso3166.tab index a1e4b42e4443..0b0b8426d474 100644 --- a/python/ext-libs/pytz/zoneinfo/iso3166.tab +++ b/python/ext-libs/pytz/zoneinfo/iso3166.tab @@ -3,21 +3,21 @@ # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. # -# From Paul Eggert (2013-05-27): +# From Paul Eggert (2014-07-18): +# This file contains a table of two-letter country codes. Columns are +# separated by a single tab. Lines beginning with '#' are comments. +# Although all text currently uses ASCII encoding, this is planned to +# change to UTF-8 soon. The columns of the table are as follows: # -# This file contains a table with the following columns: # 1. ISO 3166-1 alpha-2 country code, current as of -# ISO 3166-1 Newsletter VI-15 (2013-05-10). See: Updates on ISO 3166 +# ISO 3166-1 Newsletter VI-16 (2013-07-11). See: Updates on ISO 3166 # http://www.iso.org/iso/home/standards/country_codes/updates_on_iso_3166.htm # 2. The usual English name for the coded region, # chosen so that alphabetic sorting of subsets produces helpful lists. # This is not the same as the English name in the ISO 3166 tables. # -# Columns are separated by a single tab. # The table is sorted by country code. # -# Lines beginning with `#' are comments. -# # This table is intended as an aid for users, to help them select time # zone data appropriate for their practical needs. It is not intended # to take or endorse any position on legal or territorial claims. diff --git a/python/ext-libs/pytz/zoneinfo/localtime b/python/ext-libs/pytz/zoneinfo/localtime index 2ee14295f108..c05e45fddbba 100644 Binary files a/python/ext-libs/pytz/zoneinfo/localtime and b/python/ext-libs/pytz/zoneinfo/localtime differ diff --git a/python/ext-libs/pytz/zoneinfo/posixrules b/python/ext-libs/pytz/zoneinfo/posixrules index b2c2377f4e87..7553fee37a5d 100644 Binary files a/python/ext-libs/pytz/zoneinfo/posixrules and b/python/ext-libs/pytz/zoneinfo/posixrules differ diff --git a/python/ext-libs/pytz/zoneinfo/zone.tab b/python/ext-libs/pytz/zoneinfo/zone.tab index fa4df5f6887a..084bb2fb7f5d 100644 --- a/python/ext-libs/pytz/zoneinfo/zone.tab +++ b/python/ext-libs/pytz/zoneinfo/zone.tab @@ -1,36 +1,24 @@ -# TZ zone descriptions +# tz zone descriptions (deprecated version) # # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. # -# From Paul Eggert (2013-08-14): +# From Paul Eggert (2014-07-31): +# This file is intended as a backward-compatibility aid for older programs. +# New programs should use zone1970.tab. This file is like zone1970.tab (see +# zone1970.tab's comments), but with the following additional restrictions: # -# This file contains a table where each row stands for an area that is -# the intersection of a region identified by a country code and of a -# zone where civil clocks have agreed since 1970. The columns of the -# table are as follows: +# 1. This file contains only ASCII characters. +# 2. The first data column contains exactly one country code. # -# 1. ISO 3166 2-character country code. See the file 'iso3166.tab'. -# 2. Latitude and longitude of the area's principal location -# in ISO 6709 sign-degrees-minutes-seconds format, -# either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS, -# first latitude (+ is north), then longitude (+ is east). -# 3. Zone name used in value of TZ environment variable. -# Please see the 'Theory' file for how zone names are chosen. -# If multiple zones overlap a country, each has a row in the -# table, with column 1 being duplicated. -# 4. Comments; present if and only if the country has multiple rows. -# -# Columns are separated by a single tab. -# The table is sorted first by country, then an order within the country that -# (1) makes some geographical sense, and -# (2) puts the most populous areas first, where that does not contradict (1). -# -# Lines beginning with '#' are comments. +# Because of (2), each row stands for an area that is the intersection +# of a region identified by a country code and of a zone where civil +# clocks have agreed since 1970; this is a narrower definition than +# that of zone1970.tab. # # This table is intended as an aid for users, to help them select time -# zone data appropriate for their practical needs. It is not intended -# to take or endorse any position on legal or territorial claims. +# zone data entries appropriate for their practical needs. It is not +# intended to take or endorse any position on legal or territorial claims. # #country- #code coordinates TZ comments @@ -49,8 +37,9 @@ AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula AQ -7824+10654 Antarctica/Vostok Vostok Station, Lake Vostok -AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie +AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Adelie Land AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I +AQ -720041+0023206 Antarctica/Troll Troll Station, Queen Maud Land AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF) AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, MN, SE, SF) AR -2447-06525 America/Argentina/Salta (SA, LP, NQ, RN) @@ -127,7 +116,7 @@ CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario CA +6344-06828 America/Iqaluit Eastern Time - east Nunavut - most locations CA +6608-06544 America/Pangnirtung Eastern Time - Pangnirtung, Nunavut -CA +744144-0944945 America/Resolute Central Standard Time - Resolute, Nunavut +CA +744144-0944945 America/Resolute Central Time - Resolute, Nunavut CA +484531-0913718 America/Atikokan Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut CA +624900-0920459 America/Rankin_Inlet Central Time - central Nunavut CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario @@ -152,13 +141,10 @@ CH +4723+00832 Europe/Zurich CI +0519-00402 Africa/Abidjan CK -2114-15946 Pacific/Rarotonga CL -3327-07040 America/Santiago most locations -CL -2709-10926 Pacific/Easter Easter Island & Sala y Gomez +CL -2709-10926 Pacific/Easter Easter Island CM +0403+00942 Africa/Douala -CN +3114+12128 Asia/Shanghai east China - Beijing, Guangdong, Shanghai, etc. -CN +4545+12641 Asia/Harbin Heilongjiang (except Mohe), Jilin -CN +2934+10635 Asia/Chongqing central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc. -CN +4348+08735 Asia/Urumqi most of Tibet & Xinjiang -CN +3929+07559 Asia/Kashgar west Tibet & Xinjiang +CN +3114+12128 Asia/Shanghai Beijing Time +CN +4348+08735 Asia/Urumqi Xinjiang Time CO +0436-07405 America/Bogota CR +0956-08405 America/Costa_Rica CU +2308-08222 America/Havana @@ -340,23 +326,26 @@ RE -2052+05528 Indian/Reunion RO +4426+02606 Europe/Bucharest RS +4450+02030 Europe/Belgrade RU +5443+02030 Europe/Kaliningrad Moscow-01 - Kaliningrad -RU +5545+03735 Europe/Moscow Moscow+00 - west Russia +RU +554521+0373704 Europe/Moscow Moscow+00 - west Russia +RU +4457+03406 Europe/Simferopol Moscow+00 - Crimea RU +4844+04425 Europe/Volgograd Moscow+00 - Caspian Sea -RU +5312+05009 Europe/Samara Moscow+00 - Samara, Udmurtia +RU +5312+05009 Europe/Samara Moscow+00 (Moscow+01 after 2014-10-26) - Samara, Udmurtia RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk -RU +5345+08707 Asia/Novokuznetsk Moscow+03 - Novokuznetsk +RU +5345+08707 Asia/Novokuznetsk Moscow+03 (Moscow+04 after 2014-10-26) - Kemerovo RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal +RU +5203+11328 Asia/Chita Moscow+06 (Moscow+05 after 2014-10-26) - Zabaykalsky RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River RU +623923+1353314 Asia/Khandyga Moscow+06 - Tomponsky, Ust-Maysky RU +4310+13156 Asia/Vladivostok Moscow+07 - Amur River RU +4658+14242 Asia/Sakhalin Moscow+07 - Sakhalin Island RU +643337+1431336 Asia/Ust-Nera Moscow+07 - Oymyakonsky -RU +5934+15048 Asia/Magadan Moscow+08 - Magadan -RU +5301+15839 Asia/Kamchatka Moscow+08 - Kamchatka -RU +6445+17729 Asia/Anadyr Moscow+08 - Bering Sea +RU +5934+15048 Asia/Magadan Moscow+08 (Moscow+07 after 2014-10-26) - Magadan +RU +6728+15343 Asia/Srednekolymsk Moscow+08 - E Sakha, N Kuril Is +RU +5301+15839 Asia/Kamchatka Moscow+08 (Moscow+09 after 2014-10-26) - Kamchatka +RU +6445+17729 Asia/Anadyr Moscow+08 (Moscow+09 after 2014-10-26) - Bering Sea RW -0157+03004 Africa/Kigali SA +2438+04643 Asia/Riyadh SB -0932+16012 Pacific/Guadalcanal @@ -398,7 +387,6 @@ TZ -0648+03917 Africa/Dar_es_Salaam UA +5026+03031 Europe/Kiev most locations UA +4837+02218 Europe/Uzhgorod Ruthenia UA +4750+03510 Europe/Zaporozhye Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk -UA +4457+03406 Europe/Simferopol central Crimea UG +0019+03225 Africa/Kampala UM +1645-16931 Pacific/Johnston Johnston Atoll UM +2813-17722 Pacific/Midway Midway Islands @@ -424,13 +412,13 @@ US +394421-1045903 America/Denver Mountain Time US +433649-1161209 America/Boise Mountain Time - south Idaho & east Oregon US +332654-1120424 America/Phoenix Mountain Standard Time - Arizona (except Navajo) US +340308-1181434 America/Los_Angeles Pacific Time +US +550737-1313435 America/Metlakatla Pacific Standard Time - Annette Island, Alaska US +611305-1495401 America/Anchorage Alaska Time US +581807-1342511 America/Juneau Alaska Time - Alaska panhandle US +571035-1351807 America/Sitka Alaska Time - southeast Alaska panhandle US +593249-1394338 America/Yakutat Alaska Time - Alaska panhandle neck US +643004-1652423 America/Nome Alaska Time - west Alaska US +515248-1763929 America/Adak Aleutian Islands -US +550737-1313435 America/Metlakatla Metlakatla Time - Annette Island US +211825-1575130 Pacific/Honolulu Hawaii UY -3453-05611 America/Montevideo UZ +3940+06648 Asia/Samarkand west Uzbekistan diff --git a/python/ext-libs/pytz/zoneinfo/zone1970.tab b/python/ext-libs/pytz/zoneinfo/zone1970.tab new file mode 100644 index 000000000000..03c50d89a630 --- /dev/null +++ b/python/ext-libs/pytz/zoneinfo/zone1970.tab @@ -0,0 +1,369 @@ +# tz zone descriptions +# +# This file is in the public domain. +# +# From Paul Eggert (2014-07-31): +# This file contains a table where each row stands for a zone where +# civil time stamps have agreed since 1970. Columns are separated by +# a single tab. Lines beginning with '#' are comments. All text uses +# UTF-8 encoding. The columns of the table are as follows: +# +# 1. The countries that overlap the zone, as a comma-separated list +# of ISO 3166 2-character country codes. See the file 'iso3166.tab'. +# 2. Latitude and longitude of the zone's principal location +# in ISO 6709 sign-degrees-minutes-seconds format, +# either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS, +# first latitude (+ is north), then longitude (+ is east). +# 3. Zone name used in value of TZ environment variable. +# Please see the 'Theory' file for how zone names are chosen. +# If multiple zones overlap a country, each has a row in the +# table, with each column 1 containing the country code. +# 4. Comments; present if and only if a country has multiple zones. +# +# If a zone covers multiple countries, the most-populous city is used, +# and that country is listed first in column 1; any other countries +# are listed alphabetically by country code. The table is sorted +# first by country code, then (if possible) by an order within the +# country that (1) makes some geographical sense, and (2) puts the +# most populous zones first, where that does not contradict (1). +# +# This table is intended as an aid for users, to help them select time +# zone data entries appropriate for their practical needs. It is not +# intended to take or endorse any position on legal or territorial claims. +# +#country- +#codes coordinates TZ comments +AD +4230+00131 Europe/Andorra +AE,OM +2518+05518 Asia/Dubai +AF +3431+06912 Asia/Kabul +AL +4120+01950 Europe/Tirane +AM +4011+04430 Asia/Yerevan +AQ -6734-06808 Antarctica/Rothera Rothera Station, Adelaide Island +AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island +AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay +AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills +AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula +AQ -7824+10654 Antarctica/Vostok Vostok Station, Lake Vostok +AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Adélie Land +AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I +AQ -720041+0023206 Antarctica/Troll Troll Station, Queen Maud Land +AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF) +AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, MN, SE, SF) +AR -2447-06525 America/Argentina/Salta (SA, LP, NQ, RN) +AR -2411-06518 America/Argentina/Jujuy Jujuy (JY) +AR -2649-06513 America/Argentina/Tucuman Tucumán (TM) +AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH) +AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR) +AR -3132-06831 America/Argentina/San_Juan San Juan (SJ) +AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ) +AR -3319-06621 America/Argentina/San_Luis San Luis (SL) +AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC) +AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF) +AS,UM -1416-17042 Pacific/Pago_Pago Samoa, Midway +AT +4813+01620 Europe/Vienna +AU -3133+15905 Australia/Lord_Howe Lord Howe Island +AU -5430+15857 Antarctica/Macquarie Macquarie Island +AU -4253+14719 Australia/Hobart Tasmania - most locations +AU -3956+14352 Australia/Currie Tasmania - King Island +AU -3749+14458 Australia/Melbourne Victoria +AU -3352+15113 Australia/Sydney New South Wales - most locations +AU -3157+14127 Australia/Broken_Hill New South Wales - Yancowinna +AU -2728+15302 Australia/Brisbane Queensland - most locations +AU -2016+14900 Australia/Lindeman Queensland - Holiday Islands +AU -3455+13835 Australia/Adelaide South Australia +AU -1228+13050 Australia/Darwin Northern Territory +AU -3157+11551 Australia/Perth Western Australia - most locations +AU -3143+12852 Australia/Eucla Western Australia - Eucla area +AZ +4023+04951 Asia/Baku +BB +1306-05937 America/Barbados +BD +2343+09025 Asia/Dhaka +BE +5050+00420 Europe/Brussels +BG +4241+02319 Europe/Sofia +BM +3217-06446 Atlantic/Bermuda +BN +0456+11455 Asia/Brunei +BO -1630-06809 America/La_Paz +BR -0351-03225 America/Noronha Atlantic islands +BR -0127-04829 America/Belem Amapá, E Pará +BR -0343-03830 America/Fortaleza NE Brazil (MA, PI, CE, RN, PB) +BR -0803-03454 America/Recife Pernambuco +BR -0712-04812 America/Araguaina Tocantins +BR -0940-03543 America/Maceio Alagoas, Sergipe +BR -1259-03831 America/Bahia Bahia +BR -2332-04637 America/Sao_Paulo S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS) +BR -2027-05437 America/Campo_Grande Mato Grosso do Sul +BR -1535-05605 America/Cuiaba Mato Grosso +BR -0226-05452 America/Santarem W Pará +BR -0846-06354 America/Porto_Velho Rondônia +BR +0249-06040 America/Boa_Vista Roraima +BR -0308-06001 America/Manaus E Amazonas +BR -0640-06952 America/Eirunepe W Amazonas +BR -0958-06748 America/Rio_Branco Acre +BS +2505-07721 America/Nassau +BT +2728+08939 Asia/Thimphu +BY +5354+02734 Europe/Minsk +BZ +1730-08812 America/Belize +CA +4734-05243 America/St_Johns Newfoundland Time, including SE Labrador +CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), PEI +CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971 +CA +4606-06447 America/Moncton Atlantic Time - New Brunswick +CA +5320-06025 America/Goose_Bay Atlantic Time - Labrador - most locations +CA +5125-05707 America/Blanc-Sablon Atlantic Standard Time - Quebec - Lower North Shore +CA +4339-07923 America/Toronto Eastern Time - Ontario & Quebec - most locations +CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973 +CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario +CA +6344-06828 America/Iqaluit Eastern Time - east Nunavut - most locations +CA +6608-06544 America/Pangnirtung Eastern Time - Pangnirtung, Nunavut +CA +744144-0944945 America/Resolute Central Time - Resolute, Nunavut +CA +484531-0913718 America/Atikokan Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut +CA +624900-0920459 America/Rankin_Inlet Central Time - central Nunavut +CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario +CA +4843-09434 America/Rainy_River Central Time - Rainy River & Fort Frances, Ontario +CA +5024-10439 America/Regina Central Standard Time - Saskatchewan - most locations +CA +5017-10750 America/Swift_Current Central Standard Time - Saskatchewan - midwest +CA +5333-11328 America/Edmonton Mountain Time - Alberta, east British Columbia & west Saskatchewan +CA +690650-1050310 America/Cambridge_Bay Mountain Time - west Nunavut +CA +6227-11421 America/Yellowknife Mountain Time - central Northwest Territories +CA +682059-1334300 America/Inuvik Mountain Time - west Northwest Territories +CA +4906-11631 America/Creston Mountain Standard Time - Creston, British Columbia +CA +5946-12014 America/Dawson_Creek Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia +CA +4916-12307 America/Vancouver Pacific Time - west British Columbia +CA +6043-13503 America/Whitehorse Pacific Time - south Yukon +CA +6404-13925 America/Dawson Pacific Time - north Yukon +CC -1210+09655 Indian/Cocos +CH,DE,LI +4723+00832 Europe/Zurich Swiss time +CI,BF,GM,GN,ML,MR,SH,SL,SN,ST,TG +0519-00402 Africa/Abidjan +CK -2114-15946 Pacific/Rarotonga +CL -3327-07040 America/Santiago most locations +CL -2709-10926 Pacific/Easter Easter Island +CN +3114+12128 Asia/Shanghai Beijing Time +CN +4348+08735 Asia/Urumqi Xinjiang Time +CO +0436-07405 America/Bogota +CR +0956-08405 America/Costa_Rica +CU +2308-08222 America/Havana +CV +1455-02331 Atlantic/Cape_Verde +CW,AW,BQ,SX +1211-06900 America/Curacao +CX -1025+10543 Indian/Christmas +CY +3510+03322 Asia/Nicosia +CZ,SK +5005+01426 Europe/Prague +DE +5230+01322 Europe/Berlin Berlin time +DK +5540+01235 Europe/Copenhagen +DO +1828-06954 America/Santo_Domingo +DZ +3647+00303 Africa/Algiers +EC -0210-07950 America/Guayaquil mainland +EC -0054-08936 Pacific/Galapagos Galápagos Islands +EE +5925+02445 Europe/Tallinn +EG +3003+03115 Africa/Cairo +EH +2709-01312 Africa/El_Aaiun +ES +4024-00341 Europe/Madrid mainland +ES +3553-00519 Africa/Ceuta Ceuta & Melilla +ES +2806-01524 Atlantic/Canary Canary Islands +FI,AX +6010+02458 Europe/Helsinki +FJ -1808+17825 Pacific/Fiji +FK -5142-05751 Atlantic/Stanley +FM +0725+15147 Pacific/Chuuk Chuuk (Truk) and Yap +FM +0658+15813 Pacific/Pohnpei Pohnpei (Ponape) +FM +0519+16259 Pacific/Kosrae Kosrae +FO +6201-00646 Atlantic/Faroe +FR +4852+00220 Europe/Paris +GB,GG,IM,JE +513030-0000731 Europe/London +GE +4143+04449 Asia/Tbilisi +GF +0456-05220 America/Cayenne +GH +0533-00013 Africa/Accra +GI +3608-00521 Europe/Gibraltar +GL +6411-05144 America/Godthab most locations +GL +7646-01840 America/Danmarkshavn east coast, north of Scoresbysund +GL +7029-02158 America/Scoresbysund Scoresbysund / Ittoqqortoormiit +GL +7634-06847 America/Thule Thule / Pituffik +GR +3758+02343 Europe/Athens +GS -5416-03632 Atlantic/South_Georgia +GT +1438-09031 America/Guatemala +GU,MP +1328+14445 Pacific/Guam +GW +1151-01535 Africa/Bissau +GY +0648-05810 America/Guyana +HK +2217+11409 Asia/Hong_Kong +HN +1406-08713 America/Tegucigalpa +HT +1832-07220 America/Port-au-Prince +HU +4730+01905 Europe/Budapest +ID -0610+10648 Asia/Jakarta Java & Sumatra +ID -0002+10920 Asia/Pontianak west & central Borneo +ID -0507+11924 Asia/Makassar east & south Borneo, Sulawesi (Celebes), Bali, Nusa Tengarra, west Timor +ID -0232+14042 Asia/Jayapura west New Guinea (Irian Jaya) & Malukus (Moluccas) +IE +5320-00615 Europe/Dublin +IL +314650+0351326 Asia/Jerusalem +IN +2232+08822 Asia/Kolkata +IO -0720+07225 Indian/Chagos +IQ +3321+04425 Asia/Baghdad +IR +3540+05126 Asia/Tehran +IS +6409-02151 Atlantic/Reykjavik +IT,SM,VA +4154+01229 Europe/Rome +JM +175805-0764736 America/Jamaica +JO +3157+03556 Asia/Amman +JP +353916+1394441 Asia/Tokyo +KE,DJ,ER,ET,KM,MG,SO,TZ,UG,YT -0117+03649 Africa/Nairobi +KG +4254+07436 Asia/Bishkek +KI +0125+17300 Pacific/Tarawa Gilbert Islands +KI -0308-17105 Pacific/Enderbury Phoenix Islands +KI +0152-15720 Pacific/Kiritimati Line Islands +KP +3901+12545 Asia/Pyongyang +KR +3733+12658 Asia/Seoul +KZ +4315+07657 Asia/Almaty most locations +KZ +4448+06528 Asia/Qyzylorda Qyzylorda (Kyzylorda, Kzyl-Orda) +KZ +5017+05710 Asia/Aqtobe Aqtobe (Aktobe) +KZ +4431+05016 Asia/Aqtau Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau) +KZ +5113+05121 Asia/Oral West Kazakhstan +LB +3353+03530 Asia/Beirut +LK +0656+07951 Asia/Colombo +LR +0618-01047 Africa/Monrovia +LT +5441+02519 Europe/Vilnius +LU +4936+00609 Europe/Luxembourg +LV +5657+02406 Europe/Riga +LY +3254+01311 Africa/Tripoli +MA +3339-00735 Africa/Casablanca +MC +4342+00723 Europe/Monaco +MD +4700+02850 Europe/Chisinau +MH +0709+17112 Pacific/Majuro most locations +MH +0905+16720 Pacific/Kwajalein Kwajalein +MM +1647+09610 Asia/Rangoon +MN +4755+10653 Asia/Ulaanbaatar most locations +MN +4801+09139 Asia/Hovd Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan +MN +4804+11430 Asia/Choibalsan Dornod, Sükhbaatar +MO +2214+11335 Asia/Macau +MQ +1436-06105 America/Martinique +MT +3554+01431 Europe/Malta +MU -2010+05730 Indian/Mauritius +MV +0410+07330 Indian/Maldives +MX +1924-09909 America/Mexico_City Central Time - most locations +MX +2105-08646 America/Cancun Central Time - Quintana Roo +MX +2058-08937 America/Merida Central Time - Campeche, Yucatán +MX +2540-10019 America/Monterrey Mexican Central Time - Coahuila, Durango, Nuevo León, Tamaulipas away from US border +MX +2550-09730 America/Matamoros US Central Time - Coahuila, Durango, Nuevo León, Tamaulipas near US border +MX +2313-10625 America/Mazatlan Mountain Time - S Baja, Nayarit, Sinaloa +MX +2838-10605 America/Chihuahua Mexican Mountain Time - Chihuahua away from US border +MX +2934-10425 America/Ojinaga US Mountain Time - Chihuahua near US border +MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora +MX +3232-11701 America/Tijuana US Pacific Time - Baja California near US border +MX +3018-11452 America/Santa_Isabel Mexican Pacific Time - Baja California away from US border +MX +2048-10515 America/Bahia_Banderas Mexican Central Time - Bahía de Banderas +MY +0310+10142 Asia/Kuala_Lumpur peninsular Malaysia +MY +0133+11020 Asia/Kuching Sabah & Sarawak +MZ,BI,BW,CD,MW,RW,ZM,ZW -2558+03235 Africa/Maputo Central Africa Time (UTC+2) +NA -2234+01706 Africa/Windhoek +NC -2216+16627 Pacific/Noumea +NF -2903+16758 Pacific/Norfolk +NG,AO,BJ,CD,CF,CG,CM,GA,GQ,NE +0627+00324 Africa/Lagos West Africa Time (UTC+1) +NI +1209-08617 America/Managua +NL +5222+00454 Europe/Amsterdam +NO,SJ +5955+01045 Europe/Oslo +NP +2743+08519 Asia/Kathmandu +NR -0031+16655 Pacific/Nauru +NU -1901-16955 Pacific/Niue +NZ,AQ -3652+17446 Pacific/Auckland New Zealand time +NZ -4357-17633 Pacific/Chatham Chatham Islands +PA,KY +0858-07932 America/Panama +PE -1203-07703 America/Lima +PF -1732-14934 Pacific/Tahiti Society Islands +PF -0900-13930 Pacific/Marquesas Marquesas Islands +PF -2308-13457 Pacific/Gambier Gambier Islands +PG -0930+14710 Pacific/Port_Moresby +PH +1435+12100 Asia/Manila +PK +2452+06703 Asia/Karachi +PL +5215+02100 Europe/Warsaw +PM +4703-05620 America/Miquelon +PN -2504-13005 Pacific/Pitcairn +PR +182806-0660622 America/Puerto_Rico +PS +3130+03428 Asia/Gaza Gaza Strip +PS +313200+0350542 Asia/Hebron West Bank +PT +3843-00908 Europe/Lisbon mainland +PT +3238-01654 Atlantic/Madeira Madeira Islands +PT +3744-02540 Atlantic/Azores Azores +PW +0720+13429 Pacific/Palau +PY -2516-05740 America/Asuncion +QA,BH +2517+05132 Asia/Qatar +RE,TF -2052+05528 Indian/Reunion Réunion, Crozet Is, Scattered Is +RO +4426+02606 Europe/Bucharest +RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade +RU +5443+02030 Europe/Kaliningrad Moscow-01 - Kaliningrad +RU +554521+0373704 Europe/Moscow Moscow+00 - west Russia +RU +4457+03406 Europe/Simferopol Moscow+00 - Crimea +RU +4844+04425 Europe/Volgograd Moscow+00 - Caspian Sea +RU +5312+05009 Europe/Samara Moscow+00 (Moscow+01 after 2014-10-26) - Samara, Udmurtia +RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals +RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia +RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk +RU +5345+08707 Asia/Novokuznetsk Moscow+03 (Moscow+04 after 2014-10-26) - Kemerovo +RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River +RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal +RU +5203+11328 Asia/Chita Moscow+06 (Moscow+05 after 2014-10-26) - Zabaykalsky +RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River +RU +623923+1353314 Asia/Khandyga Moscow+06 - Tomponsky, Ust-Maysky +RU +4310+13156 Asia/Vladivostok Moscow+07 - Amur River +RU +4658+14242 Asia/Sakhalin Moscow+07 - Sakhalin Island +RU +643337+1431336 Asia/Ust-Nera Moscow+07 - Oymyakonsky +RU +5934+15048 Asia/Magadan Moscow+08 (Moscow+07 after 2014-10-26) - Magadan +RU +6728+15343 Asia/Srednekolymsk Moscow+08 - E Sakha, N Kuril Is +RU +5301+15839 Asia/Kamchatka Moscow+08 (Moscow+09 after 2014-10-26) - Kamchatka +RU +6445+17729 Asia/Anadyr Moscow+08 (Moscow+09 after 2014-10-26) - Bering Sea +SA,KW,YE +2438+04643 Asia/Riyadh +SB -0932+16012 Pacific/Guadalcanal +SC -0440+05528 Indian/Mahe +SD,SS +1536+03232 Africa/Khartoum +SE +5920+01803 Europe/Stockholm +SG +0117+10351 Asia/Singapore +SR +0550-05510 America/Paramaribo +SV +1342-08912 America/El_Salvador +SY +3330+03618 Asia/Damascus +TC +2128-07108 America/Grand_Turk +TD +1207+01503 Africa/Ndjamena +TF -492110+0701303 Indian/Kerguelen Kerguelen, St Paul I, Amsterdam I +TH,KH,LA,VN +1345+10031 Asia/Bangkok +TJ +3835+06848 Asia/Dushanbe +TK -0922-17114 Pacific/Fakaofo +TL -0833+12535 Asia/Dili +TM +3757+05823 Asia/Ashgabat +TN +3648+01011 Africa/Tunis +TO -2110-17510 Pacific/Tongatapu +TR +4101+02858 Europe/Istanbul +TT,AG,AI,BL,DM,GD,GP,MF,LC,KN,MS,VC,VG,VI +1039-06131 America/Port_of_Spain +TV -0831+17913 Pacific/Funafuti +TW +2503+12130 Asia/Taipei +UA +5026+03031 Europe/Kiev most locations +UA +4837+02218 Europe/Uzhgorod Ruthenia +UA +4750+03510 Europe/Zaporozhye Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk +UM +1917+16637 Pacific/Wake Wake Island +US +404251-0740023 America/New_York Eastern Time +US +421953-0830245 America/Detroit Eastern Time - Michigan - most locations +US +381515-0854534 America/Kentucky/Louisville Eastern Time - Kentucky - Louisville area +US +364947-0845057 America/Kentucky/Monticello Eastern Time - Kentucky - Wayne County +US +394606-0860929 America/Indiana/Indianapolis Eastern Time - Indiana - most locations +US +384038-0873143 America/Indiana/Vincennes Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties +US +410305-0863611 America/Indiana/Winamac Eastern Time - Indiana - Pulaski County +US +382232-0862041 America/Indiana/Marengo Eastern Time - Indiana - Crawford County +US +382931-0871643 America/Indiana/Petersburg Eastern Time - Indiana - Pike County +US +384452-0850402 America/Indiana/Vevay Eastern Time - Indiana - Switzerland County +US +415100-0873900 America/Chicago Central Time +US +375711-0864541 America/Indiana/Tell_City Central Time - Indiana - Perry County +US +411745-0863730 America/Indiana/Knox Central Time - Indiana - Starke County +US +450628-0873651 America/Menominee Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties +US +470659-1011757 America/North_Dakota/Center Central Time - North Dakota - Oliver County +US +465042-1012439 America/North_Dakota/New_Salem Central Time - North Dakota - Morton County (except Mandan area) +US +471551-1014640 America/North_Dakota/Beulah Central Time - North Dakota - Mercer County +US +394421-1045903 America/Denver Mountain Time +US +433649-1161209 America/Boise Mountain Time - south Idaho & east Oregon +US +332654-1120424 America/Phoenix Mountain Standard Time - Arizona (except Navajo) +US +340308-1181434 America/Los_Angeles Pacific Time +US +550737-1313435 America/Metlakatla Pacific Standard Time - Annette Island, Alaska +US +611305-1495401 America/Anchorage Alaska Time +US +581807-1342511 America/Juneau Alaska Time - Alaska panhandle +US +571035-1351807 America/Sitka Alaska Time - southeast Alaska panhandle +US +593249-1394338 America/Yakutat Alaska Time - Alaska panhandle neck +US +643004-1652423 America/Nome Alaska Time - west Alaska +US +515248-1763929 America/Adak Aleutian Islands +US,UM +211825-1575130 Pacific/Honolulu Hawaii time +UY -3453-05611 America/Montevideo +UZ +3940+06648 Asia/Samarkand west Uzbekistan +UZ +4120+06918 Asia/Tashkent east Uzbekistan +VE +1030-06656 America/Caracas +VU -1740+16825 Pacific/Efate +WF -1318-17610 Pacific/Wallis +WS -1350-17144 Pacific/Apia +ZA,LS,SZ -2615+02800 Africa/Johannesburg diff --git a/python/ext-libs/six-1.5.2-py2.7.egg-info/PKG-INFO b/python/ext-libs/six-1.7.3-py2.7.egg-info/PKG-INFO similarity index 98% rename from python/ext-libs/six-1.5.2-py2.7.egg-info/PKG-INFO rename to python/ext-libs/six-1.7.3-py2.7.egg-info/PKG-INFO index fc313354aba4..265b68cb15d8 100644 --- a/python/ext-libs/six-1.5.2-py2.7.egg-info/PKG-INFO +++ b/python/ext-libs/six-1.7.3-py2.7.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: six -Version: 1.5.2 +Version: 1.7.3 Summary: Python 2 and 3 compatibility utilities Home-page: http://pypi.python.org/pypi/six/ Author: Benjamin Peterson diff --git a/python/ext-libs/six-1.5.2-py2.7.egg-info/SOURCES.txt b/python/ext-libs/six-1.7.3-py2.7.egg-info/SOURCES.txt similarity index 100% rename from python/ext-libs/six-1.5.2-py2.7.egg-info/SOURCES.txt rename to python/ext-libs/six-1.7.3-py2.7.egg-info/SOURCES.txt diff --git a/python/ext-libs/six-1.5.2-py2.7.egg-info/dependency_links.txt b/python/ext-libs/six-1.7.3-py2.7.egg-info/dependency_links.txt similarity index 100% rename from python/ext-libs/six-1.5.2-py2.7.egg-info/dependency_links.txt rename to python/ext-libs/six-1.7.3-py2.7.egg-info/dependency_links.txt diff --git a/python/ext-libs/six-1.5.2-py2.7.egg-info/installed-files.txt b/python/ext-libs/six-1.7.3-py2.7.egg-info/installed-files.txt similarity index 100% rename from python/ext-libs/six-1.5.2-py2.7.egg-info/installed-files.txt rename to python/ext-libs/six-1.7.3-py2.7.egg-info/installed-files.txt diff --git a/python/ext-libs/six-1.5.2-py2.7.egg-info/top_level.txt b/python/ext-libs/six-1.7.3-py2.7.egg-info/top_level.txt similarity index 100% rename from python/ext-libs/six-1.5.2-py2.7.egg-info/top_level.txt rename to python/ext-libs/six-1.7.3-py2.7.egg-info/top_level.txt diff --git a/python/ext-libs/six.py b/python/ext-libs/six.py index 7ec7f1bec102..f8f7d402ff0b 100644 --- a/python/ext-libs/six.py +++ b/python/ext-libs/six.py @@ -20,12 +20,13 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +import functools import operator import sys import types __author__ = "Benjamin Peterson " -__version__ = "1.5.2" +__version__ = "1.7.3" # Useful for very coarse version differentiation. @@ -105,14 +106,6 @@ def _resolve(self): return _import_module(self.mod) def __getattr__(self, attr): - # Hack around the Django autoreloader. The reloader tries to get - # __file__ or __name__ of every module in sys.modules. This doesn't work - # well if this MovedModule is for an module that is unavailable on this - # machine (like winreg on Unix systems). Thus, we pretend __file__ and - # __name__ don't exist if the module hasn't been loaded yet. See issues - # #51 and #53. - if attr in ("__file__", "__name__") and self.mod not in sys.modules: - raise AttributeError _module = self._resolve() value = getattr(_module, attr) setattr(self, attr, value) @@ -159,9 +152,72 @@ def _resolve(self): return getattr(module, self.attr) +class _SixMetaPathImporter(object): + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + class _MovedItems(_LazyModule): """Lazy loading of moved objects""" + __path__ = [] # mark as package _moved_attributes = [ @@ -174,6 +230,8 @@ class _MovedItems(_LazyModule): MovedAttribute("reload_module", "__builtin__", "imp", "reload"), MovedAttribute("reduce", "__builtin__", "functools"), MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), MovedAttribute("UserString", "UserString", "collections"), MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), @@ -183,6 +241,7 @@ class _MovedItems(_LazyModule): MovedModule("configparser", "ConfigParser"), MovedModule("copyreg", "copy_reg"), MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), MovedModule("http_cookies", "Cookie", "http.cookies"), MovedModule("html_entities", "htmlentitydefs", "html.entities"), @@ -222,17 +281,19 @@ class _MovedItems(_LazyModule): MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), MovedModule("winreg", "_winreg"), ] for attr in _moved_attributes: setattr(_MovedItems, attr.name, attr) if isinstance(attr, MovedModule): - sys.modules[__name__ + ".moves." + attr.name] = attr + _importer._add_module(attr, "moves." + attr.name) del attr _MovedItems._moved_attributes = _moved_attributes -moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves") +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") class Module_six_moves_urllib_parse(_LazyModule): @@ -241,6 +302,7 @@ class Module_six_moves_urllib_parse(_LazyModule): _urllib_parse_moved_attributes = [ MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), MovedAttribute("parse_qs", "urlparse", "urllib.parse"), MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), MovedAttribute("urldefrag", "urlparse", "urllib.parse"), @@ -254,6 +316,7 @@ class Module_six_moves_urllib_parse(_LazyModule): MovedAttribute("unquote", "urllib", "urllib.parse"), MovedAttribute("unquote_plus", "urllib", "urllib.parse"), MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), ] for attr in _urllib_parse_moved_attributes: setattr(Module_six_moves_urllib_parse, attr.name, attr) @@ -261,7 +324,8 @@ class Module_six_moves_urllib_parse(_LazyModule): Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes -sys.modules[__name__ + ".moves.urllib_parse"] = sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse") +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") class Module_six_moves_urllib_error(_LazyModule): @@ -279,7 +343,8 @@ class Module_six_moves_urllib_error(_LazyModule): Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes -sys.modules[__name__ + ".moves.urllib_error"] = sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error") +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") class Module_six_moves_urllib_request(_LazyModule): @@ -327,7 +392,8 @@ class Module_six_moves_urllib_request(_LazyModule): Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes -sys.modules[__name__ + ".moves.urllib_request"] = sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request") +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") class Module_six_moves_urllib_response(_LazyModule): @@ -346,7 +412,8 @@ class Module_six_moves_urllib_response(_LazyModule): Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes -sys.modules[__name__ + ".moves.urllib_response"] = sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response") +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") class Module_six_moves_urllib_robotparser(_LazyModule): @@ -362,22 +429,24 @@ class Module_six_moves_urllib_robotparser(_LazyModule): Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes -sys.modules[__name__ + ".moves.urllib_robotparser"] = sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser") +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") class Module_six_moves_urllib(types.ModuleType): """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" - parse = sys.modules[__name__ + ".moves.urllib_parse"] - error = sys.modules[__name__ + ".moves.urllib_error"] - request = sys.modules[__name__ + ".moves.urllib_request"] - response = sys.modules[__name__ + ".moves.urllib_response"] - robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"] + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") def __dir__(self): return ['parse', 'error', 'request', 'response', 'robotparser'] - -sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib") +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") def add_move(move): @@ -404,11 +473,6 @@ def remove_move(name): _func_code = "__code__" _func_defaults = "__defaults__" _func_globals = "__globals__" - - _iterkeys = "keys" - _itervalues = "values" - _iteritems = "items" - _iterlists = "lists" else: _meth_func = "im_func" _meth_self = "im_self" @@ -418,11 +482,6 @@ def remove_move(name): _func_defaults = "func_defaults" _func_globals = "func_globals" - _iterkeys = "iterkeys" - _itervalues = "itervalues" - _iteritems = "iteritems" - _iterlists = "iterlists" - try: advance_iterator = next @@ -471,21 +530,37 @@ def next(self): get_function_globals = operator.attrgetter(_func_globals) -def iterkeys(d, **kw): - """Return an iterator over the keys of a dictionary.""" - return iter(getattr(d, _iterkeys)(**kw)) +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) +else: + def iterkeys(d, **kw): + return iter(d.iterkeys(**kw)) + + def itervalues(d, **kw): + return iter(d.itervalues(**kw)) -def itervalues(d, **kw): - """Return an iterator over the values of a dictionary.""" - return iter(getattr(d, _itervalues)(**kw)) + def iteritems(d, **kw): + return iter(d.iteritems(**kw)) -def iteritems(d, **kw): - """Return an iterator over the (key, value) pairs of a dictionary.""" - return iter(getattr(d, _iteritems)(**kw)) + def iterlists(d, **kw): + return iter(d.iterlists(**kw)) -def iterlists(d, **kw): - """Return an iterator over the (key, [values]) pairs of a dictionary.""" - return iter(getattr(d, _iterlists)(**kw)) +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") if PY3: @@ -611,10 +686,26 @@ def write(data): _add_doc(reraise, """Reraise an exception.""") +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped): + def wrapper(f): + f = functools.wraps(wrapped)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" - return meta("NewBase", bases, {}) + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + def add_metaclass(metaclass): """Class decorator for creating a class with a metaclass.""" @@ -630,3 +721,27 @@ def wrapper(cls): orig_vars.pop(slots_var) return metaclass(cls.__name__, cls.__bases__, orig_vars) return wrapper + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/python/plugins/MetaSearch/__init__.py b/python/plugins/MetaSearch/__init__.py index 73215234427e..c7b2df719af7 100644 --- a/python/plugins/MetaSearch/__init__.py +++ b/python/plugins/MetaSearch/__init__.py @@ -14,7 +14,7 @@ # # This code is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along @@ -26,6 +26,9 @@ import os import site +site.addsitedir(os.path.abspath('%s/ext-libs' % os.path.dirname(__file__))) + + def classFactory(iface): """invoke plugin""" from MetaSearch.plugin import MetaSearchPlugin diff --git a/python/plugins/MetaSearch/dialogs/maindialog.py b/python/plugins/MetaSearch/dialogs/maindialog.py index ecdb89ac05c7..7e9b2dc47ea8 100644 --- a/python/plugins/MetaSearch/dialogs/maindialog.py +++ b/python/plugins/MetaSearch/dialogs/maindialog.py @@ -49,16 +49,19 @@ from owslib.wms import WebMapService from owslib.wmts import WebMapTileService +from MetaSearch import link_types from MetaSearch.dialogs.manageconnectionsdialog import ManageConnectionsDialog from MetaSearch.dialogs.newconnectiondialog import NewConnectionDialog from MetaSearch.dialogs.recorddialog import RecordDialog from MetaSearch.dialogs.xmldialog import XMLDialog -from MetaSearch.util import (get_connections_from_file, highlight_xml, - open_url, render_template, StaticContext) -from MetaSearch.ui.maindialog import Ui_MetaSearchDialog +from MetaSearch.util import (get_connections_from_file, get_ui_class, + highlight_xml, normalize_text, open_url, + render_template, StaticContext) +BASE_CLASS = get_ui_class('maindialog.ui') -class MetaSearchDialog(QDialog, Ui_MetaSearchDialog): + +class MetaSearchDialog(QDialog, BASE_CLASS): """main dialogue""" def __init__(self, iface): """init window""" @@ -106,6 +109,7 @@ def __init__(self, iface): self.buttonBox.button(QDialogButtonBox.Close).setAutoDefault(False) # launch help from button self.buttonBox.helpRequested.connect(self.help) + self.btnCanvasBbox.setAutoDefault(False) self.btnCanvasBbox.clicked.connect(self.set_bbox_from_map) self.btnGlobalBbox.clicked.connect(self.set_bbox_global) @@ -120,11 +124,6 @@ def __init__(self, iface): self.btnAddToWcs.clicked.connect(self.add_to_ows) self.btnShowXml.clicked.connect(self.show_xml) - # settings stuff - self.radioTitleAsk.clicked.connect(self.set_ows_save_title_ask) - self.radioTitleNoAsk.clicked.connect(self.set_ows_save_title_no_ask) - self.radioTempName.clicked.connect(self.set_ows_save_temp_name) - self.manageGui() def manageGui(self): @@ -143,16 +142,6 @@ def manageGui(self): self.reset_buttons() - # get preferred connection save strategy from settings and set it - save_strat = self.settings.value( - '/MetaSearch/ows_save_strategy', 'title_ask') - if save_strat == 'temp_name': - self.radioTempName.setChecked(True) - elif save_strat == 'title_no_ask': - self.radioTitleNoAsk.setChecked(True) - else: - self.radioTitleAsk.setChecked(True) - # install proxy handler if specified in QGIS settings self.install_proxy() @@ -300,7 +289,7 @@ def delete_connection(self): key = '/MetaSearch/%s' % current_text - msg = self.tr('Remove service %s?') % current_text + msg = self.tr('Remove service %s?' % current_text) result = QMessageBox.information(self, self.tr('Confirm delete'), msg, QMessageBox.Ok | QMessageBox.Cancel) @@ -334,7 +323,7 @@ def add_default_connections(self): name = server.attrib.get('name') # check for duplicates if name in keys: - msg = self.tr('%s exists. Overwrite?') % name + msg = self.tr('%s exists. Overwrite?' % name) res = QMessageBox.warning(self, self.tr('Loading connections'), msg, QMessageBox.Yes | QMessageBox.No) @@ -411,7 +400,6 @@ def search(self): # clear all fields and disable buttons self.lblResults.clear() self.treeRecords.clear() - self.textAbstract.clear() self.reset_buttons() @@ -462,12 +450,12 @@ def search(self): except ExceptionReport, err: QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('Search error'), - self.tr('Search error: %s') % err) + self.tr('Search error: %s' % err)) return except Exception, err: QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('Connection error'), - self.tr('Connection error: %s') % err) + self.tr('Connection error: %s' % err)) return if self.catalog.results['matches'] == 0: @@ -485,21 +473,22 @@ def display_results(self): position = self.catalog.results['returned'] + self.startfrom - msg = self.tr('Showing %d - %d of %d result%s') % ( - self.startfrom + 1, position, - self.catalog.results['matches'], - 's'[self.catalog.results['matches'] == 1:]) + msg = self.tr('Showing %d - %d of %d result%s' % + (self.startfrom + 1, position, + self.catalog.results['matches'], + 's'[self.catalog.results['matches'] == 1:])) self.lblResults.setText(msg) for rec in self.catalog.records: item = QTreeWidgetItem(self.treeRecords) if self.catalog.records[rec].type: - item.setText(0, self.catalog.records[rec].type) + item.setText(0, normalize_text(self.catalog.records[rec].type)) else: item.setText(0, 'unknown') if self.catalog.records[rec].title: - item.setText(1, self.catalog.records[rec].title) + item.setText(1, + normalize_text(self.catalog.records[rec].title)) if self.catalog.records[rec].identifier: set_item_data(item, 'identifier', self.catalog.records[rec].identifier) @@ -532,21 +521,23 @@ def record_clicked(self): identifier = get_item_data(item, 'identifier') record = self.catalog.records[identifier] - if record.abstract: - self.textAbstract.setText(record.abstract.strip()) - else: - self.textAbstract.setText(self.tr('No abstract')) - # if the record has a bbox, show a footprint on the map if record.bbox is not None: points = bbox_to_polygon(record.bbox) - - src = QgsCoordinateReferenceSystem(4326) - dst = self.map.mapRenderer().destinationCrs() - ctr = QgsCoordinateTransform(src, dst) - geom = QgsGeometry.fromPolygon(points) - geom.transform(ctr) - self.rubber_band.setToGeometry(geom, None) + if points is not None: + src = QgsCoordinateReferenceSystem(4326) + dst = self.map.mapRenderer().destinationCrs() + geom = QgsGeometry.fromPolygon(points) + if src.postgisSrid() != dst.postgisSrid(): + ctr = QgsCoordinateTransform(src, dst) + try: + geom.transform(ctr) + except Exception, err: + QMessageBox.warning( + self, + self.tr('Coordinate Transformation Error'), + str(err)) + self.rubber_band.setToGeometry(geom, None) # figure out if the data is interactive and can be operated on self.find_services(record, item) @@ -569,33 +560,22 @@ def find_services(self, record, item): if link_type is not None: link_type = link_type.upper() + wmswmst_link_types = map(str.upper, link_types.WMSWMST_LINK_TYPES) + wfs_link_types = map(str.upper, link_types.WFS_LINK_TYPES) + wcs_link_types = map(str.upper, link_types.WCS_LINK_TYPES) + # if the link type exists, and it is one of the acceptable # interactive link types, then set if all([link_type is not None, - link_type in ['OGC:WMS', 'OGC:WMTS', - 'OGC:WMS-1.1.1-HTTP-GET-MAP', - 'OGC:WMS-1.1.1-HTTP-GET-CAPABILITIES', - 'OGC:WMS-1.3.0-HTTP-GET-MAP', - 'OGC:WMS-1.3.0-HTTP-GET-CAPABILITIES', - 'OGC:WFS', - 'OGC:WFS-1.0.0-HTTP-GET-CAPABILITIES', - 'OGC:WFS-1.1.0-HTTP-GET-CAPABILITIES', - 'OGC:WCS', - 'OGC:WCS-1.1.0-HTTP-GET-CAPABILITIES']]): - if link_type in ['OGC:WMS', 'OGC:WMTS', - 'OGC:WMS-1.1.1-HTTP-GET-MAP', - 'OGC:WMS-1.1.1-HTTP-GET-CAPABILITIES', - 'OGC:WMS-1.3.0-HTTP-GET-MAP', - 'OGC:WMS-1.3.0-HTTP-GET-CAPABILITIES']: + link_type in wmswmst_link_types + wfs_link_types + + wcs_link_types]): + if link_type in wmswmst_link_types: services['wms'] = link['url'] self.btnAddToWms.setEnabled(True) - if link_type in ['OGC:WFS', - 'OGC:WFS-1.0.0-HTTP-GET-CAPABILITIES', - 'OGC:WFS-1.1.0-HTTP-GET-CAPABILITIES']: + if link_type in wfs_link_types: services['wfs'] = link['url'] self.btnAddToWfs.setEnabled(True) - if link_type in ['OGC:WCS', - 'OGC:WCS-1.1.0-HTTP-GET-CAPABILITIES']: + if link_type in wcs_link_types: services['wcs'] = link['url'] self.btnAddToWcs.setEnabled(True) @@ -669,37 +649,9 @@ def add_to_ows(self): stype = ['OGC:WCS', 'wcs', 'wcs'] data_url = item_data['wcs'] - # test if URL is valid WMS server - try: - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - - service_type = stype[0] - if service_type == 'OGC:WMS/OGC:WMTS': - try: - ows = WebMapService(data_url) - except Exception, err: - ows = WebMapTileService(data_url) - elif service_type == 'OGC:WFS': - ows = WebFeatureService(data_url) - elif service_type == 'OGC:WCS': - # TODO: remove version once OWSLib defaults to 1.0.0 - ows = WebCoverageService(data_url, '1.0.0') - except Exception, err: - QApplication.restoreOverrideCursor() - msg = self.tr('Error connecting to %s: %s') % (stype[0], err) - QMessageBox.warning(self, self.tr('Connection error'), msg) - return - QApplication.restoreOverrideCursor() - # ows save connection strategies, one of - # 1) use ows title but always ask before overwriting - # 2) use ows title but always overwrite (never ask) - # 3) use a temp name (which can be changed later) - if ows.identification.title is None or self.radioTempName.isChecked(): - sname = '%s from MetaSearch' % stype[1] - else: - sname = ows.identification.title + sname = '%s from MetaSearch' % stype[1] # store connection # check if there is a connection with same name @@ -708,8 +660,8 @@ def add_to_ows(self): self.settings.endGroup() # check for duplicates - if sname in keys and self.radioTitleAsk.isChecked(): - msg = self.tr('Connection %s exists. Overwrite?') % sname + if sname in keys: + msg = self.tr('Connection %s exists. Overwrite?' % sname) res = QMessageBox.warning(self, self.tr('Saving server'), msg, QMessageBox.Yes | QMessageBox.No) if res != QMessageBox.Yes: @@ -723,6 +675,9 @@ def add_to_ows(self): # open provider window ows_provider = QgsProviderRegistry.instance().selectWidget(stype[2], self) + + service_type = stype[0] + # connect dialog signals to iface slots if service_type == 'OGC:WMS/OGC:WMTS': ows_provider.connect( @@ -778,7 +733,7 @@ def show_metadata(self): except ExceptionReport, err: QApplication.restoreOverrideCursor() QMessageBox.warning(self, self.tr('GetRecords error'), - self.tr('Error getting response: %s') % err) + self.tr('Error getting response: %s' % err)) return QApplication.restoreOverrideCursor() @@ -847,11 +802,11 @@ def _get_csw(self): self.catalog = CatalogueServiceWeb(self.catalog_url) return True except ExceptionReport, err: - msg = self.tr('Error connecting to service: %s') % err + msg = self.tr('Error connecting to service: %s' % err) except ValueError, err: - msg = self.tr('Value Error: %s') % err + msg = self.tr('Value Error: %s' % err) except Exception, err: - msg = self.tr('Unknown Error: %s') % err + msg = self.tr('Unknown Error: %s' % err) QMessageBox.warning(self, self.tr('CSW Connection error'), msg) QApplication.restoreOverrideCursor() @@ -919,14 +874,20 @@ def _get_field_value(field): def bbox_to_polygon(bbox): """converts OWSLib bbox object to list of QgsPoint objects""" - minx = float(bbox.minx) - miny = float(bbox.miny) - maxx = float(bbox.maxx) - maxy = float(bbox.maxy) - - return [[ - QgsPoint(minx, miny), - QgsPoint(minx, maxy), - QgsPoint(maxx, maxy), - QgsPoint(maxx, miny) - ]] + if all([bbox.minx is not None, + bbox.maxx is not None, + bbox.miny is not None, + bbox.maxy is not None]): + minx = float(bbox.minx) + miny = float(bbox.miny) + maxx = float(bbox.maxx) + maxy = float(bbox.maxy) + + return [[ + QgsPoint(minx, miny), + QgsPoint(minx, maxy), + QgsPoint(maxx, maxy), + QgsPoint(maxx, miny) + ]] + else: + return None diff --git a/python/plugins/MetaSearch/dialogs/manageconnectionsdialog.py b/python/plugins/MetaSearch/dialogs/manageconnectionsdialog.py index eb54ab7d26d5..5f6634d41df6 100644 --- a/python/plugins/MetaSearch/dialogs/manageconnectionsdialog.py +++ b/python/plugins/MetaSearch/dialogs/manageconnectionsdialog.py @@ -33,11 +33,13 @@ from PyQt4.QtGui import (QDialog, QDialogButtonBox, QFileDialog, QListWidgetItem, QMessageBox) -from MetaSearch.ui.manageconnectionsdialog import Ui_ManageConnectionsDialog -from MetaSearch.util import get_connections_from_file, prettify_xml +from MetaSearch.util import (get_connections_from_file, get_ui_class, + prettify_xml) +BASE_CLASS = get_ui_class('manageconnectionsdialog.ui') -class ManageConnectionsDialog(QDialog, Ui_ManageConnectionsDialog): + +class ManageConnectionsDialog(QDialog, BASE_CLASS): """manage connections""" def __init__(self, mode): """init dialog""" @@ -131,7 +133,7 @@ def save(self, connections): with open(self.filename, 'w') as fileobj: fileobj.write(prettify_xml(etree.tostring(doc))) QMessageBox.information(self, self.tr('Save Connections'), - self.tr('Saved to %s') % self.filename) + self.tr('Saved to %s' % self.filename)) self.reject() def load(self, items): @@ -152,7 +154,7 @@ def load(self, items): # check for duplicates if conn_name in keys: - label = self.tr('File %s exists. Overwrite?') % conn_name + label = self.tr('File %s exists. Overwrite?' % conn_name) res = QMessageBox.warning(self, self.tr('Loading Connections'), label, QMessageBox.Yes | QMessageBox.No) diff --git a/python/plugins/MetaSearch/dialogs/newconnectiondialog.py b/python/plugins/MetaSearch/dialogs/newconnectiondialog.py index 0f2de0fa4c99..288e5d68ead6 100644 --- a/python/plugins/MetaSearch/dialogs/newconnectiondialog.py +++ b/python/plugins/MetaSearch/dialogs/newconnectiondialog.py @@ -30,10 +30,12 @@ from PyQt4.QtCore import QSettings from PyQt4.QtGui import QDialog, QMessageBox -from MetaSearch.ui.newconnectiondialog import Ui_NewConnectionDialog +from MetaSearch.util import get_ui_class +BASE_CLASS = get_ui_class('newconnectiondialog.ui') -class NewConnectionDialog(QDialog, Ui_NewConnectionDialog): + +class NewConnectionDialog(QDialog, BASE_CLASS): """Dialogue to add a new CSW entry""" def __init__(self, conn_name=None): """init""" @@ -64,7 +66,7 @@ def accept(self): if all([self.conn_name_orig != conn_name, self.settings.contains(keyurl)]): res = QMessageBox.warning(self, self.tr('Save connection'), - self.tr('Overwrite %s?') % conn_name, + self.tr('Overwrite %s?' % conn_name), QMessageBox.Ok | QMessageBox.Cancel) if res == QMessageBox.Cancel: return diff --git a/python/plugins/MetaSearch/dialogs/recorddialog.py b/python/plugins/MetaSearch/dialogs/recorddialog.py index 4ff01d766205..6b5e476fe74f 100644 --- a/python/plugins/MetaSearch/dialogs/recorddialog.py +++ b/python/plugins/MetaSearch/dialogs/recorddialog.py @@ -29,10 +29,12 @@ from PyQt4.QtGui import QDialog -from MetaSearch.ui.recorddialog import Ui_RecordDialog +from MetaSearch.util import get_ui_class +BASE_CLASS = get_ui_class('recorddialog.ui') -class RecordDialog(QDialog, Ui_RecordDialog): + +class RecordDialog(QDialog, BASE_CLASS): """Record Metadata Dialogue""" def __init__(self): """init""" diff --git a/python/plugins/MetaSearch/dialogs/xmldialog.py b/python/plugins/MetaSearch/dialogs/xmldialog.py index c2a2cfd69f66..d9aeda4a497b 100644 --- a/python/plugins/MetaSearch/dialogs/xmldialog.py +++ b/python/plugins/MetaSearch/dialogs/xmldialog.py @@ -25,10 +25,12 @@ from PyQt4.QtGui import QDialog -from MetaSearch.ui.xmldialog import Ui_XMLDialog +from MetaSearch.util import get_ui_class +BASE_CLASS = get_ui_class('xmldialog.ui') -class XMLDialog(QDialog, Ui_XMLDialog): + +class XMLDialog(QDialog, BASE_CLASS): """Raw XML Dialogue""" def __init__(self): """init""" diff --git a/python/plugins/MetaSearch/ui/__init__.py b/python/plugins/MetaSearch/link_types.py similarity index 51% rename from python/plugins/MetaSearch/ui/__init__.py rename to python/plugins/MetaSearch/link_types.py index 1feea0bcfc58..aa3fc86e4806 100644 --- a/python/plugins/MetaSearch/ui/__init__.py +++ b/python/plugins/MetaSearch/link_types.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- ############################################################################### # +# MetaSearch Catalogue Client +# # Copyright (C) 2014 Tom Kralidis (tomkralidis@gmail.com) # # This source is free software; you can redistribute it and/or modify it under @@ -10,7 +12,7 @@ # # This code is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along @@ -18,3 +20,29 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # ############################################################################### + +WMSWMST_LINK_TYPES = [ + 'OGC:WMS', + 'OGC:WMTS', + 'OGC:WMS-1.1.1-http-get-map', + 'OGC:WMS-1.1.1-http-get-capabilities', + 'OGC:WMS-1.3.0-http-get-map', + 'OGC:WMS-1.3.0-http-get-capabilities', + 'urn:x-esri:specification:ServiceType:wms:url', + 'urn:x-esri:specification:ServiceType:Gmd:URL.wms' +] + +WFS_LINK_TYPES = [ + 'OGC:WFS', + 'OGC:WFS-1.0.0-http-get-capabilities', + 'OGC:WFS-1.1.0-http-get-capabilities', + 'urn:x-esri:specification:ServiceType:wfs:url', + 'urn:x-esri:specification:ServiceType:Gmd:URL.wfs' +] + +WCS_LINK_TYPES = [ + 'OGC:WCS', + 'OGC:WCS-1.1.0-http-get-capabilities', + 'urn:x-esri:specification:ServiceType:wcs:url', + 'urn:x-esri:specification:ServiceType:Gmd:URL.wcs' +] diff --git a/python/plugins/MetaSearch/locale/cs/LC_MESSAGES/ui.qm b/python/plugins/MetaSearch/locale/cs/LC_MESSAGES/ui.qm index acaeb80ddeff..ae75403e966e 100644 Binary files a/python/plugins/MetaSearch/locale/cs/LC_MESSAGES/ui.qm and b/python/plugins/MetaSearch/locale/cs/LC_MESSAGES/ui.qm differ diff --git a/python/plugins/MetaSearch/locale/cs/LC_MESSAGES/ui.ts b/python/plugins/MetaSearch/locale/cs/LC_MESSAGES/ui.ts index 0f54ad055e45..e6ac7a3e6755 100644 --- a/python/plugins/MetaSearch/locale/cs/LC_MESSAGES/ui.ts +++ b/python/plugins/MetaSearch/locale/cs/LC_MESSAGES/ui.ts @@ -8,7 +8,7 @@ Spravovat připojení - + Save to file Uložit do souboru @@ -18,52 +18,52 @@ Prohlížet - + Load from file Načíst ze souboru - + Load Načíst - + Save Uložit - + eXtensible Markup Language (*.xml *.XML) rozšiřitelný značkovací jazyk (*.xml *.XML) - + Save connections Uložit připojení - + Load connections Načíst připojení - + Save Connections Uložit připojení - + Saved to %s Uloženo do %s - + File %s exists. Overwrite? Soubor %s existuje. Přepsat? - + Loading Connections Načítám připojení @@ -71,22 +71,22 @@ MetaSearch - + MetaSearch plugin Zásuvný modul MetaSearch - + Search Metadata Catalogues Prohledávat Metadatové katalogy - + MetaSearch plugin help Nápověda k zásuvnému modulu MetaSearch - + Get Help on MetaSearch Získat nápovědu k MetaSearch @@ -99,330 +99,325 @@ MetaSearch - + Search Vyhledávání - + Find Najít - + Set global Nastavit globálně - + Map extent Rozsah mapy - + -180 -180 - + 90 90 - - Records - Záznamy - - - + -90 -90 - + 180 180 - + From Od - + Keywords Klíčová slova - + Results Výsledky - + > > - + << << - + Add WCS Přidat WCS - + Add WMS/WMTS Přidat WMS/WMTS - + < < - + Add WFS Přidat WFS - - Abstract - Abstract - - - + Double click to see full record information Dvojklik pro zobrazení celého záznamu - + Type Typ - + Title Nadpis - + View search results as XML Zobrazit výsledky vyhledávání jako XML - + >> >> - + Services Služby - + Service info Informace o službě - + GetCapabilities response Odpověď GetCapabilities - + New Nový - + Edit Editovat - + Delete Smazat - + Save Uložit - + Add default services Přidat výchozí služby - + Load Načíst - + Settings Nastavení - - Connection naming - Jméno připojení - - - - When saving the connection of an OWS service - Při uložení připojení služby OWS - - - - Use the OWS Service Title and ask before overwriting - Použít nadpis služby OWS a zeptat se před přepsáním - - - - Use the OWS Service Title and always overwrite if already available - Použít nadpis služby OWS a vždy přepsat pokud již byl zadán - - - - Use a temporary name, which you can change later - Použít dočasné jméno, které může být později změněno - - - + No services/connections defined. To get started with MetaSearch, create a new connection by clicking 'New' or click 'Add default services'. Nebyly zadány žádné služby/připojení. Musíte vytvořit nové připojení kliknutím na 'Nový' nebo klinutím na 'Přidat výchozí služby', abyste mohli začít pracovat s MetaSearch. - + New Catalogue service Nová katalogová služba - + Edit Catalogue service Editovat katalogovou službu - + Remove service %s? Odstranit službu %s? - + Confirm delete Potvrdit smazání - + %s exists. Overwrite? %s již existuje. Přepsat? - + Loading connections Načítám připojení - + Search error Chyba vyhledávání - + Search error: %s Chyba vyhledávání: %s - + Connection error Chyba připojení - + Connection error: %s Chyba připojení: %s - + 0 results 0 záznamů - + Showing %d - %d of %d result%s Zobrazuji %d - %d z %d výsledků - - No abstract - Žádný abstrakt - - - + End of results. Go to start? Konec výsledků. Jít na začátek? - + Navigation Navigace - + Start of results. Go to end? Začátek výsledků. Jít na konec? - - Error connecting to %s: %s - Chyba při připojování k %s: %s - - - + Connection %s exists. Overwrite? Připojení %s existuje. Přepsat? - + Saving server Ukládám server - + GetRecords error Chyba GetRecords - + Error getting response: %s Chyba při získávání odpovědi: %s - + Error connecting to service: %s Chyba při připojování ke službě: %s - + Value Error: %s Chyba hodnoty: %s - + Unknown Error: %s Neznámá chyba: %s - + CSW Connection error Chyba připojení CS-W + + + Xmax + + + + + Ymax + + + + + Xmin + + + + + Ymin + + + + + Results paging + + + + + Show + + + + + results at a time + + + + + Coordinate Transformation Error + + NewConnectionDialog @@ -442,17 +437,17 @@ URL - + Save connection Uložit připojení - + Both Name and URL must be provided Položky Název a URL musí být zadány - + Overwrite %s? Přepsat %s? diff --git a/python/plugins/MetaSearch/locale/de/LC_MESSAGES/templates.mo b/python/plugins/MetaSearch/locale/de/LC_MESSAGES/templates.mo index 70cd3917226b..c19217ee4fd1 100644 Binary files a/python/plugins/MetaSearch/locale/de/LC_MESSAGES/templates.mo and b/python/plugins/MetaSearch/locale/de/LC_MESSAGES/templates.mo differ diff --git a/python/plugins/MetaSearch/locale/de/LC_MESSAGES/templates.po b/python/plugins/MetaSearch/locale/de/LC_MESSAGES/templates.po index 7db1daaf2afa..e94b2464cae5 100644 --- a/python/plugins/MetaSearch/locale/de/LC_MESSAGES/templates.po +++ b/python/plugins/MetaSearch/locale/de/LC_MESSAGES/templates.po @@ -1,13 +1,13 @@ # # Translators: -# macho , 2014 +# Werner Macho , 2014 msgid "" msgstr "" "Project-Id-Version: MetaSearch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2014-02-25 12:58-0500\n" "PO-Revision-Date: 2014-03-08 12:25+0000\n" -"Last-Translator: macho \n" +"Last-Translator: Werner Macho \n" "Language-Team: German (http://www.transifex.com/projects/p/MetaSearch/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" diff --git a/python/plugins/MetaSearch/locale/de/LC_MESSAGES/ui.qm b/python/plugins/MetaSearch/locale/de/LC_MESSAGES/ui.qm index 9dad8dffceb9..e898519b721e 100644 Binary files a/python/plugins/MetaSearch/locale/de/LC_MESSAGES/ui.qm and b/python/plugins/MetaSearch/locale/de/LC_MESSAGES/ui.qm differ diff --git a/python/plugins/MetaSearch/locale/de/LC_MESSAGES/ui.ts b/python/plugins/MetaSearch/locale/de/LC_MESSAGES/ui.ts index 7d91ca0d62ff..c029f17c72c6 100644 --- a/python/plugins/MetaSearch/locale/de/LC_MESSAGES/ui.ts +++ b/python/plugins/MetaSearch/locale/de/LC_MESSAGES/ui.ts @@ -5,12 +5,12 @@ Manage connections - + Verbindungsverwaltung - + Save to file - + Speichern in Datei @@ -18,52 +18,52 @@ - + Load from file - + Aus Datei laden - + Load - + Laden - + Save - + Speichern - + eXtensible Markup Language (*.xml *.XML) - + Save connections - + Load connections - + Save Connections - + Saved to %s - + File %s exists. Overwrite? - + Loading Connections @@ -71,22 +71,22 @@ MetaSearch - + MetaSearch plugin - + Search Metadata Catalogues - + MetaSearch plugin help - + Get Help on MetaSearch @@ -99,330 +99,325 @@ - + Search - + Find - + Set global - + Map extent - + -180 - + 90 - - Records - - - - + -90 - + 180 - + From - + Keywords - + Results - + > - + << - + Add WCS - + Add WMS/WMTS - + < - + Add WFS - - Abstract - - - - + Double click to see full record information - + Type - + Title - + View search results as XML - + >> - + Services - + Service info - + GetCapabilities response - + New - + Edit - + Delete - + Save - + Speichern - + Add default services - + Load - + Laden - + Settings - - Connection naming - - - - - When saving the connection of an OWS service - - - - - Use the OWS Service Title and ask before overwriting - - - - - Use the OWS Service Title and always overwrite if already available - - - - - Use a temporary name, which you can change later - - - - + No services/connections defined. To get started with MetaSearch, create a new connection by clicking 'New' or click 'Add default services'. - + New Catalogue service - + Edit Catalogue service - + Remove service %s? - + Confirm delete - + %s exists. Overwrite? - + Loading connections - + Search error - + Search error: %s - + Connection error - + Connection error: %s - + 0 results - + Showing %d - %d of %d result%s - - No abstract - - - - + End of results. Go to start? - + Navigation - + Start of results. Go to end? - - Error connecting to %s: %s - - - - + Connection %s exists. Overwrite? - + Saving server - + GetRecords error - + Error getting response: %s - + Error connecting to service: %s - + Value Error: %s - + Unknown Error: %s - + CSW Connection error + + + Xmax + + + + + Ymax + + + + + Xmin + + + + + Ymin + + + + + Results paging + + + + + Show + + + + + results at a time + + + + + Coordinate Transformation Error + + NewConnectionDialog @@ -442,17 +437,17 @@ - + Save connection - + Both Name and URL must be provided - + Overwrite %s? diff --git a/python/plugins/MetaSearch/locale/en/LC_MESSAGES/ui.ts b/python/plugins/MetaSearch/locale/en/LC_MESSAGES/ui.ts index a7b657f3f27b..281569fca19b 100644 --- a/python/plugins/MetaSearch/locale/en/LC_MESSAGES/ui.ts +++ b/python/plugins/MetaSearch/locale/en/LC_MESSAGES/ui.ts @@ -8,7 +8,7 @@ - + Save to file @@ -18,52 +18,52 @@ - + Load from file - + Load - + Save - + eXtensible Markup Language (*.xml *.XML) - + Save connections - + Load connections - + Save Connections - + Saved to %s - + File %s exists. Overwrite? - + Loading Connections @@ -71,22 +71,22 @@ MetaSearch - + MetaSearch plugin - + Search Metadata Catalogues - + MetaSearch plugin help - + Get Help on MetaSearch @@ -99,327 +99,322 @@ - + Search - + Find - - Set global + + Keywords - + Map extent - - -180 + + Set global - - 90 + + Xmax - - Records + + 180 - - -90 + + Ymax - - 180 + + 90 - - From + + Xmin - - Keywords + + -180 - - Results + + Ymin - - > + + -90 - - << + + From - - Add WCS + + Results - - Add WMS/WMTS + + Double click to see full record information - - < + + Type - - Add WFS + + Title - - Abstract + + < - - Double click to see full record information + + View search results as XML - - Type + + << - - Title + + Add WMS/WMTS - - View search results as XML + + Add WFS - + >> - + + Add WCS + + + + + > + + + + Services - + Service info - + GetCapabilities response - + New - + Edit - + Delete - + Save - + Add default services - + Load - + Settings - - Connection naming - - - - - When saving the connection of an OWS service + + Results paging - - Use the OWS Service Title and ask before overwriting + + Show - - Use the OWS Service Title and always overwrite if already available + + results at a time - - Use a temporary name, which you can change later - - - - + No services/connections defined. To get started with MetaSearch, create a new connection by clicking 'New' or click 'Add default services'. - + New Catalogue service - + Edit Catalogue service - + Remove service %s? - + Confirm delete - + %s exists. Overwrite? - + Loading connections - + Search error - + Search error: %s - + Connection error - + Connection error: %s - + 0 results - + Showing %d - %d of %d result%s - - No abstract + + Coordinate Transformation Error - + End of results. Go to start? - + Navigation - + Start of results. Go to end? - - Error connecting to %s: %s - - - - + Connection %s exists. Overwrite? - + Saving server - + GetRecords error - + Error getting response: %s - + Error connecting to service: %s - + Value Error: %s - + Unknown Error: %s - + CSW Connection error @@ -442,17 +437,17 @@ - + Save connection - + Both Name and URL must be provided - + Overwrite %s? diff --git a/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/templates.po b/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/templates.po index 56e4b3a1347c..ae8781b77c9f 100644 --- a/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/templates.po +++ b/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/templates.po @@ -106,7 +106,7 @@ msgid "Modified" msgstr "Modifié" msgid "Language" -msgstr "Langue" +msgstr "Langage" msgid "Format" msgstr "Format" diff --git a/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/ui.qm b/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/ui.qm index dc6efc7a108c..2ae5deb4d762 100644 Binary files a/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/ui.qm and b/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/ui.qm differ diff --git a/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/ui.ts b/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/ui.ts index 7aa058ac41af..5fb5c521fadd 100644 --- a/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/ui.ts +++ b/python/plugins/MetaSearch/locale/fr/LC_MESSAGES/ui.ts @@ -8,7 +8,7 @@ Gérer les connexions - + Save to file Sauvegarder sous @@ -18,52 +18,52 @@ Parcourir - + Load from file Charger depuis un fichier - + Load Charger - + Save Sauvegarder - + eXtensible Markup Language (*.xml *.XML) eXtensible Markup Language (*.xml *.XML) - + Save connections Sauvegarder les connexions - + Load connections Charger les connexions - + Save Connections Sauvegarder les connexions - + Saved to %s Sauvegardé sous %s - + File %s exists. Overwrite? Le fichier %s existe déjà. Voulez-vous l'écraser ? - + Loading Connections Chargement des connexions @@ -71,22 +71,22 @@ MetaSearch - + MetaSearch plugin Extension MetaSearch - + Search Metadata Catalogues Rechercher des catalogues de métadonnées - + MetaSearch plugin help Documentation de l'extension MetaSearch - + Get Help on MetaSearch Obtenir de l'aide pour MetaSearch @@ -99,330 +99,325 @@ MetaSearch - + Search Rechercher - + Find Trouver - + Set global Etendue globale - + Map extent Etendue de la carte - + -180 -180 - + 90 90 - - Records - Enregistrements - - - + -90 -90 - + 180 180 - + From Depuis - + Keywords Mots-clés - + Results Résultats - + > > - + << << - + Add WCS Ajouter une couche WCS - + Add WMS/WMTS Ajouter une couche WMS/WMST - + < < - + Add WFS Ajouter une couche WFS - - Abstract - Résumé - - - + Double click to see full record information Double-cliquer pour accéder à l'ensemble de la métadonnée - + Type Type - + Title Titre - + View search results as XML Voir les résultats de la recherche en XML - + >> >> - + Services Services - + Service info Information sur le service - + GetCapabilities response Réponse GetCapabilities - + New Nouveau - + Edit Modifier - + Delete Supprimer - + Save Sauvegarder - + Add default services Ajouter des services par défaut - + Load Charger - + Settings Paramètres - - Connection naming - Nommage de la connexion - - - - When saving the connection of an OWS service - Lors de la sauvegarde d'une connexion à un service web OGC - - - - Use the OWS Service Title and ask before overwriting - Utiliser le Titre du service web OGC et demander confirmation avant d'écraser - - - - Use the OWS Service Title and always overwrite if already available - Utiliser le Titre du service web OGC et toujours écraser si existe déjà - - - - Use a temporary name, which you can change later - Utiliser un nom temporaire, que vous pourrez modifier ultérieurement - - - + No services/connections defined. To get started with MetaSearch, create a new connection by clicking 'New' or click 'Add default services'. Aucun service/connexion n'est spécifié. Pour démarrer avec MetaSearch créer une nouvelle connexion en cliquant sur 'Nouveau' ou sur 'Ajouter des services par défaut'. - + New Catalogue service Nouveau Service de Catalogage - + Edit Catalogue service Modifier le service de Catalogage - + Remove service %s? Supprimer le service %s ? - + Confirm delete Confirmer la suppression ? - + %s exists. Overwrite? %s existe déjà. L'écraser ? - + Loading connections Chargement des connexions - + Search error Erreur dans la recherche - + Search error: %s Erreur dans la recherche : %s - + Connection error Erreur de connexion - + Connection error: %s Erreur de connexion : %s - + 0 results 0 résultat - + Showing %d - %d of %d result%s Affichage de %d - %d de %d résultats%s - - No abstract - Pas de résumé - - - + End of results. Go to start? Fin des résultats. Revenir au début ? - + Navigation Navigation - + Start of results. Go to end? Début des résultats. Aller à la fin ? - - Error connecting to %s: %s - Erreur de connexion à %s : %s - - - + Connection %s exists. Overwrite? La connexion %s existe déjà. L'écraser ? - + Saving server Sauvegarde du serveur - + GetRecords error Erreur GetRecords - + Error getting response: %s Erreur de récupération de la réponse : %s - + Error connecting to service: %s Erreur de connexion au service : %s - + Value Error: %s Erreur dans la valeur : %s - + Unknown Error: %s Erreur inconnue : &s - + CSW Connection error Erreur de connexion CSW + + + Xmax + + + + + Ymax + + + + + Xmin + + + + + Ymin + + + + + Results paging + + + + + Show + + + + + results at a time + + + + + Coordinate Transformation Error + + NewConnectionDialog @@ -442,17 +437,17 @@ URL - + Save connection Sauvegarder la connexion - + Both Name and URL must be provided Le Nom et l'URL doivent être spécifiés - + Overwrite %s? Ecraser %s ? diff --git a/python/plugins/MetaSearch/locale/it/LC_MESSAGES/ui.qm b/python/plugins/MetaSearch/locale/it/LC_MESSAGES/ui.qm index 0d61ca557b3c..2d8cbefcdbe3 100644 Binary files a/python/plugins/MetaSearch/locale/it/LC_MESSAGES/ui.qm and b/python/plugins/MetaSearch/locale/it/LC_MESSAGES/ui.qm differ diff --git a/python/plugins/MetaSearch/locale/it/LC_MESSAGES/ui.ts b/python/plugins/MetaSearch/locale/it/LC_MESSAGES/ui.ts index 806d02434502..0d47d121bf0c 100644 --- a/python/plugins/MetaSearch/locale/it/LC_MESSAGES/ui.ts +++ b/python/plugins/MetaSearch/locale/it/LC_MESSAGES/ui.ts @@ -8,7 +8,7 @@ Gestione connessioni - + Save to file Salva su file @@ -18,52 +18,52 @@ Eslpora - + Load from file Carica da file - + Load Carica - + Save Salva - + eXtensible Markup Language (*.xml *.XML) eXtensible Markup Language (*.xml *.XML) - + Save connections Salva connessioni - + Load connections Carica connessioni - + Save Connections Salva Connessioni - + Saved to %s Salvato su %s - + File %s exists. Overwrite? Il file %s esiste. Sovrascriverlo? - + Loading Connections Caricamento connessioni @@ -71,22 +71,22 @@ MetaSearch - + MetaSearch plugin Plugin MetaSearch - + Search Metadata Catalogues Ricerca cataloghi di metadati - + MetaSearch plugin help Aiuto plugin MetaSearch - + Get Help on MetaSearch Ottieni aiuto su MetaSearch @@ -99,330 +99,325 @@ MetaSearch - + Search Ricerca - + Find Trova - + Set global Imposta globale - + Map extent Estensione mappa - + -180 -180 - + 90 90 - - Records - Record - - - + -90 -90 - + 180 180 - + From Da - + Keywords Parole chiave - + Results Risultati - + > > - + << << - + Add WCS Aggiungi WCS - + Add WMS/WMTS Aggiungi WMS/WMTS - + < < - + Add WFS Aggiungi WFS - - Abstract - Riassunto - - - + Double click to see full record information Doppio click per visualizzare le informazioni complete del record - + Type Tipo - + Title Titolo - + View search results as XML Visualizza i risultati come XML - + >> >> - + Services Servizi - + Service info Informazioni sul servizio - + GetCapabilities response Risposta GetCapabilities - + New Nuovo - + Edit Modifica - + Delete Cancella - + Save Salva - + Add default services Aggiungi servizi predefiniti - + Load Carica - + Settings Impostazioni - - Connection naming - Assegnare nome a connessione - - - - When saving the connection of an OWS service - Quando si salva la connessione ad un servizio OWS - - - - Use the OWS Service Title and ask before overwriting - Usa il titolo del servizio OWS e chiedi prima di sovrascrivere - - - - Use the OWS Service Title and always overwrite if already available - Usa il titolo del servizio OWS e sovrascrivi sempre se già presente - - - - Use a temporary name, which you can change later - Usa un nome temporaneo, che puoi cambiare più tardi - - - + No services/connections defined. To get started with MetaSearch, create a new connection by clicking 'New' or click 'Add default services'. Nessun servizio o connessione definita. Per iniziare a lavorare con MetaSearch, crea una nuova connessione cliccando su 'New' o su 'Aggiungi servizi predefiniti' - + New Catalogue service Nuovo Catalogo - + Edit Catalogue service Edita Catalogo - + Remove service %s? Rimuovo il servizio %s? - + Confirm delete Conferma la cancellazione - + %s exists. Overwrite? %s esiste. Sovrascrivi? - + Loading connections Caricamento connessioni - + Search error Ricerca errore - + Search error: %s Ricerca errore: %s - + Connection error Errore di connessione - + Connection error: %s Errore di connessione: %s - + 0 results 0 risultati - + Showing %d - %d of %d result%s Mostrando %d - %d di %d risultato/i - - No abstract - Nessun riassunto - - - + End of results. Go to start? Fine dei risultati. Tornare all'inizio? - + Navigation Naviga - + Start of results. Go to end? Inizio dei risultati. Andare alla fine? - - Error connecting to %s: %s - Errore di connessione a %s: %s - - - + Connection %s exists. Overwrite? Connessione %s esiste. Sovrascrivere? - + Saving server Salvataggio server - + GetRecords error errore GetRecords - + Error getting response: %s Errore di risposta: %s - + Error connecting to service: %s Errore di connessione al servizio: %s - + Value Error: %s Errore di valore: %s - + Unknown Error: %s Errore sconosciuto: %s - + CSW Connection error Errore di connessione a CSW + + + Xmax + + + + + Ymax + + + + + Xmin + + + + + Ymin + + + + + Results paging + + + + + Show + + + + + results at a time + + + + + Coordinate Transformation Error + + NewConnectionDialog @@ -442,17 +437,17 @@ Indirizzo - + Save connection Salva connessione - + Both Name and URL must be provided Sia il nome che l'indirizzo devono essere inseriti - + Overwrite %s? Sovrascrivere %s? diff --git a/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/templates.mo b/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/templates.mo index faee7e9ca9f4..144198f4f0b8 100644 Binary files a/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/templates.mo and b/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/templates.mo differ diff --git a/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/templates.po b/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/templates.po index 91a2f17ac8e3..767dd7a40324 100644 --- a/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/templates.po +++ b/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/templates.po @@ -6,7 +6,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2014-02-25 12:58-0500\n" "PO-Revision-Date: 2014-02-28 19:41+0000\n" -"Last-Translator: rduivenvoorde \n" +"Last-Translator: Richard Duivenvoorde \n" "Language-Team: Dutch (http://www.transifex.com/projects/p/MetaSearch/language/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" diff --git a/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/ui.qm b/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/ui.qm index 1938da7a6a1b..033d18078dd5 100644 Binary files a/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/ui.qm and b/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/ui.qm differ diff --git a/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/ui.ts b/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/ui.ts index 5d725a8d62aa..e59d3153be93 100644 --- a/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/ui.ts +++ b/python/plugins/MetaSearch/locale/nl/LC_MESSAGES/ui.ts @@ -8,7 +8,7 @@ Beheer verbindingen - + Save to file Opslaan naar bestand @@ -18,52 +18,52 @@ Openen - + Load from file Bestand laden - + Load Laden - + Save Opslaan - + eXtensible Markup Language (*.xml *.XML) eXtensible Markup Language (*.xml *.XML) - + Save connections Verbindingen opslaan - + Load connections Verbindingen laden - + Save Connections Verbindingen opslaan - + Saved to %s Opgeslagen als %s - + File %s exists. Overwrite? Bestand %s bestaat al. Overschijven? - + Loading Connections Verbindingen worden geladen @@ -71,22 +71,22 @@ MetaSearch - + MetaSearch plugin MetaSearch plugin - + Search Metadata Catalogues Zoek Metadata Catalogi - + MetaSearch plugin help MetaSearch plugin help - + Get Help on MetaSearch Hulp zoeken voor MetaSearch @@ -99,330 +99,325 @@ MetaSearch - + Search Zoeken - + Find Vind - + Set global Wereldbox - + Map extent Kaart extent - + -180 -180 - + 90 90 - - Records - Resultaten - - - + -90 -90 - + 180 180 - + From Van - + Keywords Zoekwoorden - + Results Resultaten - + > > - + << << - + Add WCS WCS Toevoegen - + Add WMS/WMTS WMS/WMTS Toevoegen - + < < - + Add WFS WFS Toevoegen - - Abstract - Samenvatting - - - + Double click to see full record information Dubbelklikken om de volledige record info te zien - + Type Type - + Title Titel - + View search results as XML Resultaten tonen als XML - + >> >> - + Services Services - + Service info Service info - + GetCapabilities response GetCapabilities antwoord - + New Nieuw - + Edit Aanpassen - + Delete Verwijderen - + Save Opslaan - + Add default services Standaard services toevoegen - + Load Laden - + Settings Instellingen - - Connection naming - Namen voor verbindingen - - - - When saving the connection of an OWS service - Bij het opslaan van een OWS service - - - - Use the OWS Service Title and ask before overwriting - De OWS Service Title gebruiken en vragen om te overschrijven - - - - Use the OWS Service Title and always overwrite if already available - De OWS Service Title gebruiken en altijd overschrijven - - - - Use a temporary name, which you can change later - Een tijdelijke naam gebruiken welke u later kunt aanpassen - - - + No services/connections defined. To get started with MetaSearch, create a new connection by clicking 'New' or click 'Add default services'. Er zijn geen service/CSW verbindinen beschikbaar. Om te beginnen met MetaSearch, maak een nieuwe verbinding aan, of klik op 'Standaard services toevoegen'. - + New Catalogue service Nieuwe Catalogus service - + Edit Catalogue service Catalogus service aanpassen - + Remove service %s? Service %s verwijderen? - + Confirm delete Verwijdering bevestigen - + %s exists. Overwrite? %s bestaat al. Overschrijven? - + Loading connections Verbindingen laden - + Search error Fout opgetreden tijdens zoekactie - + Search error: %s Foutmeldinge: %s - + Connection error Verbindingsfout - + Connection error: %s Verbindingsfout: %s - + 0 results 0 resultaten - + Showing %d - %d of %d result%s %d - %d van de %d resultaten tonen - - No abstract - Geen samenvatting - - - + End of results. Go to start? Einde van resulaten. Terug naar start? - + Navigation Navigeren - + Start of results. Go to end? Start van de resultaten. Naar laatste? - - Error connecting to %s: %s - Fout bij verbinden met %s: %s - - - + Connection %s exists. Overwrite? Verbinding %s bestaat al. Overschrijven? - + Saving server Server opslaan - + GetRecords error GetRecords fout - + Error getting response: %s Fout in de response: %s - + Error connecting to service: %s Verbindingsfout bij service: %s - + Value Error: %s Datawaarde Fout: %s - + Unknown Error: %s Onbekende fout: %s - + CSW Connection error CSW Verbindings fout + + + Xmax + + + + + Ymax + + + + + Xmin + + + + + Ymin + + + + + Results paging + + + + + Show + + + + + results at a time + + + + + Coordinate Transformation Error + + NewConnectionDialog @@ -442,17 +437,17 @@ URL - + Save connection Verbinding opslaan - + Both Name and URL must be provided Zowel Naam als URL zijn verplichte velden - + Overwrite %s? %s overschrijven? diff --git a/python/plugins/MetaSearch/metadata.txt b/python/plugins/MetaSearch/metadata.txt index 9faa482f7dcc..2710a2e52b20 100644 --- a/python/plugins/MetaSearch/metadata.txt +++ b/python/plugins/MetaSearch/metadata.txt @@ -2,7 +2,7 @@ name=MetaSearch Catalogue Client description=MetaSearch is a QGIS plugin to interact with metadata catalogue services (CSW). category=Web -version=0.2.0 +version=0.3.1 qgisMinimumVersion=2.0 icon=images/MetaSearch.png author=Tom Kralidis @@ -13,13 +13,5 @@ tracker=https://github.com/geopython/MetaSearch/issues repository=https://github.com/geopython/MetaSearch.git experimental=False deprecated=False -changelog=Version 0.2.0 (2014-03-21) - - add different ows save strategies - - add HTTP proxy support - - synchronize connection dropdrop lists between tabs - - setup localization in Transifex for ui, docs - - add settings tab - - use 'MetaSearch' as settings namespace - - reproject bbox on canvas if required - - fix cursor overrides on exceptions - - numerous template display updates +changelog=Version 0.3.1 (2014-09-03) + - fix packaging and translation diff --git a/python/plugins/MetaSearch/plugin.py b/python/plugins/MetaSearch/plugin.py index 7d7e87029d52..6260fa8beb1b 100644 --- a/python/plugins/MetaSearch/plugin.py +++ b/python/plugins/MetaSearch/plugin.py @@ -87,7 +87,7 @@ def initGui(self): self.action_run.triggered.connect(self.run) - self.iface.addToolBarIcon(self.action_run) + self.iface.addWebToolBarIcon(self.action_run) self.iface.addPluginToWebMenu(self.web_menu, self.action_run) # help @@ -110,8 +110,7 @@ def unload(self): # remove the plugin menu item and icon self.iface.removePluginWebMenu(self.web_menu, self.action_run) self.iface.removePluginWebMenu(self.web_menu, self.action_help) - self.iface.removeToolBarIcon(self.action_run) - self.iface.removeToolBarIcon(self.action_help) + self.iface.removeWebToolBarIcon(self.action_run) def run(self): """open MetaSearch""" diff --git a/python/plugins/MetaSearch/ui/maindialog.py b/python/plugins/MetaSearch/ui/maindialog.py deleted file mode 100644 index 2df78b97acfb..000000000000 --- a/python/plugins/MetaSearch/ui/maindialog.py +++ /dev/null @@ -1,238 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/tkralidi/work/foss4g/MetaSearch/MetaSearch/plugin/MetaSearch/ui/maindialog.ui' -# -# Created: Thu Mar 20 21:56:34 2014 -# by: PyQt4 UI code generator 4.9.3 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -try: - _fromUtf8 = QtCore.QString.fromUtf8 -except AttributeError: - _fromUtf8 = lambda s: s - -class Ui_MetaSearchDialog(object): - def setupUi(self, MetaSearchDialog): - MetaSearchDialog.setObjectName(_fromUtf8("MetaSearchDialog")) - MetaSearchDialog.resize(598, 650) - self.verticalLayout = QtGui.QVBoxLayout(MetaSearchDialog) - self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) - self.tabWidget = QtGui.QTabWidget(MetaSearchDialog) - self.tabWidget.setObjectName(_fromUtf8("tabWidget")) - self.tabSearch = QtGui.QWidget() - self.tabSearch.setObjectName(_fromUtf8("tabSearch")) - self.verticalLayout_2 = QtGui.QVBoxLayout(self.tabSearch) - self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2")) - self.groupBox = QtGui.QGroupBox(self.tabSearch) - self.groupBox.setObjectName(_fromUtf8("groupBox")) - self.gridLayout_4 = QtGui.QGridLayout(self.groupBox) - self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4")) - self.btnGlobalBbox = QtGui.QPushButton(self.groupBox) - self.btnGlobalBbox.setObjectName(_fromUtf8("btnGlobalBbox")) - self.gridLayout_4.addWidget(self.btnGlobalBbox, 2, 6, 1, 1) - self.cmbConnectionsSearch = QtGui.QComboBox(self.groupBox) - self.cmbConnectionsSearch.setObjectName(_fromUtf8("cmbConnectionsSearch")) - self.gridLayout_4.addWidget(self.cmbConnectionsSearch, 0, 5, 1, 2) - self.btnCanvasBbox = QtGui.QPushButton(self.groupBox) - self.btnCanvasBbox.setObjectName(_fromUtf8("btnCanvasBbox")) - self.gridLayout_4.addWidget(self.btnCanvasBbox, 2, 5, 1, 1) - self.leWest = QtGui.QLineEdit(self.groupBox) - self.leWest.setObjectName(_fromUtf8("leWest")) - self.gridLayout_4.addWidget(self.leWest, 2, 0, 1, 2) - self.leNorth = QtGui.QLineEdit(self.groupBox) - self.leNorth.setObjectName(_fromUtf8("leNorth")) - self.gridLayout_4.addWidget(self.leNorth, 2, 4, 1, 1) - self.spnRecords = QtGui.QSpinBox(self.groupBox) - self.spnRecords.setObjectName(_fromUtf8("spnRecords")) - self.gridLayout_4.addWidget(self.spnRecords, 3, 5, 1, 1) - self.label_2 = QtGui.QLabel(self.groupBox) - self.label_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.label_2.setObjectName(_fromUtf8("label_2")) - self.gridLayout_4.addWidget(self.label_2, 3, 6, 1, 1) - self.btnSearch = QtGui.QPushButton(self.groupBox) - self.btnSearch.setObjectName(_fromUtf8("btnSearch")) - self.gridLayout_4.addWidget(self.btnSearch, 3, 0, 1, 5) - self.leSouth = QtGui.QLineEdit(self.groupBox) - self.leSouth.setObjectName(_fromUtf8("leSouth")) - self.gridLayout_4.addWidget(self.leSouth, 2, 2, 1, 1) - self.leEast = QtGui.QLineEdit(self.groupBox) - self.leEast.setObjectName(_fromUtf8("leEast")) - self.gridLayout_4.addWidget(self.leEast, 2, 3, 1, 1) - self.leKeywords = QtGui.QLineEdit(self.groupBox) - self.leKeywords.setObjectName(_fromUtf8("leKeywords")) - self.gridLayout_4.addWidget(self.leKeywords, 0, 2, 1, 2) - self.label = QtGui.QLabel(self.groupBox) - self.label.setObjectName(_fromUtf8("label")) - self.gridLayout_4.addWidget(self.label, 0, 4, 1, 1) - self.label_3 = QtGui.QLabel(self.groupBox) - self.label_3.setObjectName(_fromUtf8("label_3")) - self.gridLayout_4.addWidget(self.label_3, 0, 0, 1, 1) - self.verticalLayout_2.addWidget(self.groupBox) - self.groupBox_2 = QtGui.QGroupBox(self.tabSearch) - self.groupBox_2.setObjectName(_fromUtf8("groupBox_2")) - self.gridLayout_5 = QtGui.QGridLayout(self.groupBox_2) - self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5")) - self.btnNext = QtGui.QPushButton(self.groupBox_2) - self.btnNext.setObjectName(_fromUtf8("btnNext")) - self.gridLayout_5.addWidget(self.btnNext, 2, 2, 1, 1) - self.btnFirst = QtGui.QPushButton(self.groupBox_2) - self.btnFirst.setObjectName(_fromUtf8("btnFirst")) - self.gridLayout_5.addWidget(self.btnFirst, 2, 0, 1, 1) - self.btnAddToWcs = QtGui.QPushButton(self.groupBox_2) - self.btnAddToWcs.setObjectName(_fromUtf8("btnAddToWcs")) - self.gridLayout_5.addWidget(self.btnAddToWcs, 6, 2, 1, 1) - self.btnAddToWms = QtGui.QPushButton(self.groupBox_2) - self.btnAddToWms.setObjectName(_fromUtf8("btnAddToWms")) - self.gridLayout_5.addWidget(self.btnAddToWms, 6, 0, 1, 1) - self.textAbstract = QtGui.QTextEdit(self.groupBox_2) - self.textAbstract.setObjectName(_fromUtf8("textAbstract")) - self.gridLayout_5.addWidget(self.textAbstract, 4, 0, 1, 5) - self.btnPrev = QtGui.QPushButton(self.groupBox_2) - self.btnPrev.setObjectName(_fromUtf8("btnPrev")) - self.gridLayout_5.addWidget(self.btnPrev, 2, 1, 1, 1) - self.btnAddToWfs = QtGui.QPushButton(self.groupBox_2) - self.btnAddToWfs.setObjectName(_fromUtf8("btnAddToWfs")) - self.gridLayout_5.addWidget(self.btnAddToWfs, 6, 1, 1, 1) - self.label_4 = QtGui.QLabel(self.groupBox_2) - self.label_4.setObjectName(_fromUtf8("label_4")) - self.gridLayout_5.addWidget(self.label_4, 3, 0, 1, 2) - self.lblResults = QtGui.QLabel(self.groupBox_2) - self.lblResults.setText(_fromUtf8("")) - self.lblResults.setObjectName(_fromUtf8("lblResults")) - self.gridLayout_5.addWidget(self.lblResults, 0, 0, 1, 3) - self.treeRecords = QtGui.QTreeWidget(self.groupBox_2) - self.treeRecords.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) - self.treeRecords.setAlternatingRowColors(True) - self.treeRecords.setRootIsDecorated(False) - self.treeRecords.setItemsExpandable(False) - self.treeRecords.setAllColumnsShowFocus(True) - self.treeRecords.setObjectName(_fromUtf8("treeRecords")) - self.treeRecords.header().setStretchLastSection(True) - self.gridLayout_5.addWidget(self.treeRecords, 1, 0, 1, 5) - self.btnShowXml = QtGui.QPushButton(self.groupBox_2) - self.btnShowXml.setObjectName(_fromUtf8("btnShowXml")) - self.gridLayout_5.addWidget(self.btnShowXml, 0, 3, 1, 2) - self.btnLast = QtGui.QPushButton(self.groupBox_2) - self.btnLast.setObjectName(_fromUtf8("btnLast")) - self.gridLayout_5.addWidget(self.btnLast, 2, 3, 1, 1) - self.verticalLayout_2.addWidget(self.groupBox_2) - self.tabWidget.addTab(self.tabSearch, _fromUtf8("")) - self.tabServers = QtGui.QWidget() - self.tabServers.setObjectName(_fromUtf8("tabServers")) - self.gridLayout = QtGui.QGridLayout(self.tabServers) - self.gridLayout.setObjectName(_fromUtf8("gridLayout")) - self.cmbConnectionsServices = QtGui.QComboBox(self.tabServers) - self.cmbConnectionsServices.setObjectName(_fromUtf8("cmbConnectionsServices")) - self.gridLayout.addWidget(self.cmbConnectionsServices, 0, 0, 1, 5) - self.btnServerInfo = QtGui.QPushButton(self.tabServers) - self.btnServerInfo.setObjectName(_fromUtf8("btnServerInfo")) - self.gridLayout.addWidget(self.btnServerInfo, 1, 0, 1, 1) - self.btnCapabilities = QtGui.QPushButton(self.tabServers) - self.btnCapabilities.setObjectName(_fromUtf8("btnCapabilities")) - self.gridLayout.addWidget(self.btnCapabilities, 1, 1, 1, 2) - self.btnNew = QtGui.QPushButton(self.tabServers) - self.btnNew.setObjectName(_fromUtf8("btnNew")) - self.gridLayout.addWidget(self.btnNew, 2, 0, 1, 1) - self.btnEdit = QtGui.QPushButton(self.tabServers) - self.btnEdit.setObjectName(_fromUtf8("btnEdit")) - self.gridLayout.addWidget(self.btnEdit, 2, 1, 1, 1) - self.btnDelete = QtGui.QPushButton(self.tabServers) - self.btnDelete.setObjectName(_fromUtf8("btnDelete")) - self.gridLayout.addWidget(self.btnDelete, 2, 2, 1, 1) - self.btnSave = QtGui.QPushButton(self.tabServers) - self.btnSave.setObjectName(_fromUtf8("btnSave")) - self.gridLayout.addWidget(self.btnSave, 2, 4, 1, 1) - self.textMetadata = QtGui.QTextBrowser(self.tabServers) - self.textMetadata.setOpenExternalLinks(True) - self.textMetadata.setObjectName(_fromUtf8("textMetadata")) - self.gridLayout.addWidget(self.textMetadata, 3, 0, 1, 5) - self.btnAddDefault = QtGui.QPushButton(self.tabServers) - self.btnAddDefault.setObjectName(_fromUtf8("btnAddDefault")) - self.gridLayout.addWidget(self.btnAddDefault, 1, 3, 1, 2) - self.btnLoad = QtGui.QPushButton(self.tabServers) - self.btnLoad.setObjectName(_fromUtf8("btnLoad")) - self.gridLayout.addWidget(self.btnLoad, 2, 3, 1, 1) - self.tabWidget.addTab(self.tabServers, _fromUtf8("")) - self.tabSettings = QtGui.QWidget() - self.tabSettings.setObjectName(_fromUtf8("tabSettings")) - self.saveStrategyGroup = QtGui.QGroupBox(self.tabSettings) - self.saveStrategyGroup.setGeometry(QtCore.QRect(10, 10, 558, 548)) - self.saveStrategyGroup.setObjectName(_fromUtf8("saveStrategyGroup")) - self.verticalLayout_3 = QtGui.QVBoxLayout(self.saveStrategyGroup) - self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3")) - self.lblSaveStrategy = QtGui.QLabel(self.saveStrategyGroup) - self.lblSaveStrategy.setObjectName(_fromUtf8("lblSaveStrategy")) - self.verticalLayout_3.addWidget(self.lblSaveStrategy) - self.radioTitleAsk = QtGui.QRadioButton(self.saveStrategyGroup) - self.radioTitleAsk.setChecked(True) - self.radioTitleAsk.setObjectName(_fromUtf8("radioTitleAsk")) - self.verticalLayout_3.addWidget(self.radioTitleAsk) - self.radioTitleNoAsk = QtGui.QRadioButton(self.saveStrategyGroup) - self.radioTitleNoAsk.setObjectName(_fromUtf8("radioTitleNoAsk")) - self.verticalLayout_3.addWidget(self.radioTitleNoAsk) - self.radioTempName = QtGui.QRadioButton(self.saveStrategyGroup) - self.radioTempName.setObjectName(_fromUtf8("radioTempName")) - self.verticalLayout_3.addWidget(self.radioTempName) - spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_3.addItem(spacerItem) - self.tabWidget.addTab(self.tabSettings, _fromUtf8("")) - self.verticalLayout.addWidget(self.tabWidget) - self.buttonBox = QtGui.QDialogButtonBox(MetaSearchDialog) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close|QtGui.QDialogButtonBox.Help) - self.buttonBox.setObjectName(_fromUtf8("buttonBox")) - self.verticalLayout.addWidget(self.buttonBox) - - self.retranslateUi(MetaSearchDialog) - self.tabWidget.setCurrentIndex(0) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), MetaSearchDialog.accept) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), MetaSearchDialog.reject) - QtCore.QMetaObject.connectSlotsByName(MetaSearchDialog) - - def retranslateUi(self, MetaSearchDialog): - MetaSearchDialog.setWindowTitle(QtGui.QApplication.translate("MetaSearchDialog", "MetaSearch", None, QtGui.QApplication.UnicodeUTF8)) - self.groupBox.setTitle(QtGui.QApplication.translate("MetaSearchDialog", "Find", None, QtGui.QApplication.UnicodeUTF8)) - self.btnGlobalBbox.setText(QtGui.QApplication.translate("MetaSearchDialog", "Set global", None, QtGui.QApplication.UnicodeUTF8)) - self.btnCanvasBbox.setText(QtGui.QApplication.translate("MetaSearchDialog", "Map extent", None, QtGui.QApplication.UnicodeUTF8)) - self.leWest.setText(QtGui.QApplication.translate("MetaSearchDialog", "-180", None, QtGui.QApplication.UnicodeUTF8)) - self.leNorth.setText(QtGui.QApplication.translate("MetaSearchDialog", "90", None, QtGui.QApplication.UnicodeUTF8)) - self.label_2.setText(QtGui.QApplication.translate("MetaSearchDialog", "Records", None, QtGui.QApplication.UnicodeUTF8)) - self.btnSearch.setText(QtGui.QApplication.translate("MetaSearchDialog", "Search", None, QtGui.QApplication.UnicodeUTF8)) - self.leSouth.setText(QtGui.QApplication.translate("MetaSearchDialog", "-90", None, QtGui.QApplication.UnicodeUTF8)) - self.leEast.setText(QtGui.QApplication.translate("MetaSearchDialog", "180", None, QtGui.QApplication.UnicodeUTF8)) - self.label.setText(QtGui.QApplication.translate("MetaSearchDialog", " From", None, QtGui.QApplication.UnicodeUTF8)) - self.label_3.setText(QtGui.QApplication.translate("MetaSearchDialog", "Keywords", None, QtGui.QApplication.UnicodeUTF8)) - self.groupBox_2.setTitle(QtGui.QApplication.translate("MetaSearchDialog", "Results", None, QtGui.QApplication.UnicodeUTF8)) - self.btnNext.setText(QtGui.QApplication.translate("MetaSearchDialog", ">", None, QtGui.QApplication.UnicodeUTF8)) - self.btnFirst.setText(QtGui.QApplication.translate("MetaSearchDialog", "<<", None, QtGui.QApplication.UnicodeUTF8)) - self.btnAddToWcs.setText(QtGui.QApplication.translate("MetaSearchDialog", "Add WCS", None, QtGui.QApplication.UnicodeUTF8)) - self.btnAddToWms.setText(QtGui.QApplication.translate("MetaSearchDialog", "Add WMS/WMTS", None, QtGui.QApplication.UnicodeUTF8)) - self.btnPrev.setText(QtGui.QApplication.translate("MetaSearchDialog", "<", None, QtGui.QApplication.UnicodeUTF8)) - self.btnAddToWfs.setText(QtGui.QApplication.translate("MetaSearchDialog", "Add WFS", None, QtGui.QApplication.UnicodeUTF8)) - self.label_4.setText(QtGui.QApplication.translate("MetaSearchDialog", "Abstract", None, QtGui.QApplication.UnicodeUTF8)) - self.treeRecords.setToolTip(QtGui.QApplication.translate("MetaSearchDialog", "Double click to see full record information", None, QtGui.QApplication.UnicodeUTF8)) - self.treeRecords.setSortingEnabled(True) - self.treeRecords.headerItem().setText(0, QtGui.QApplication.translate("MetaSearchDialog", "Type", None, QtGui.QApplication.UnicodeUTF8)) - self.treeRecords.headerItem().setText(1, QtGui.QApplication.translate("MetaSearchDialog", "Title", None, QtGui.QApplication.UnicodeUTF8)) - self.btnShowXml.setText(QtGui.QApplication.translate("MetaSearchDialog", "View search results as XML", None, QtGui.QApplication.UnicodeUTF8)) - self.btnLast.setText(QtGui.QApplication.translate("MetaSearchDialog", ">>", None, QtGui.QApplication.UnicodeUTF8)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabSearch), QtGui.QApplication.translate("MetaSearchDialog", "Search", None, QtGui.QApplication.UnicodeUTF8)) - self.btnServerInfo.setText(QtGui.QApplication.translate("MetaSearchDialog", "Service info", None, QtGui.QApplication.UnicodeUTF8)) - self.btnCapabilities.setText(QtGui.QApplication.translate("MetaSearchDialog", "GetCapabilities response", None, QtGui.QApplication.UnicodeUTF8)) - self.btnNew.setText(QtGui.QApplication.translate("MetaSearchDialog", "New", None, QtGui.QApplication.UnicodeUTF8)) - self.btnEdit.setText(QtGui.QApplication.translate("MetaSearchDialog", "Edit", None, QtGui.QApplication.UnicodeUTF8)) - self.btnDelete.setText(QtGui.QApplication.translate("MetaSearchDialog", "Delete", None, QtGui.QApplication.UnicodeUTF8)) - self.btnSave.setText(QtGui.QApplication.translate("MetaSearchDialog", "Save", None, QtGui.QApplication.UnicodeUTF8)) - self.btnAddDefault.setText(QtGui.QApplication.translate("MetaSearchDialog", "Add default services", None, QtGui.QApplication.UnicodeUTF8)) - self.btnLoad.setText(QtGui.QApplication.translate("MetaSearchDialog", "Load", None, QtGui.QApplication.UnicodeUTF8)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabServers), QtGui.QApplication.translate("MetaSearchDialog", "Services", None, QtGui.QApplication.UnicodeUTF8)) - self.saveStrategyGroup.setTitle(QtGui.QApplication.translate("MetaSearchDialog", "Connection naming", None, QtGui.QApplication.UnicodeUTF8)) - self.lblSaveStrategy.setText(QtGui.QApplication.translate("MetaSearchDialog", "When saving the connection of an OWS service", None, QtGui.QApplication.UnicodeUTF8)) - self.radioTitleAsk.setText(QtGui.QApplication.translate("MetaSearchDialog", "Use the OWS Service Title and ask before overwriting", None, QtGui.QApplication.UnicodeUTF8)) - self.radioTitleNoAsk.setText(QtGui.QApplication.translate("MetaSearchDialog", "Use the OWS Service Title and always overwrite if already available", None, QtGui.QApplication.UnicodeUTF8)) - self.radioTempName.setText(QtGui.QApplication.translate("MetaSearchDialog", "Use a temporary name, which you can change later", None, QtGui.QApplication.UnicodeUTF8)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabSettings), QtGui.QApplication.translate("MetaSearchDialog", "Settings", None, QtGui.QApplication.UnicodeUTF8)) - diff --git a/python/plugins/MetaSearch/ui/maindialog.ui b/python/plugins/MetaSearch/ui/maindialog.ui index 0fc1bf1278d6..6bd8f32cc172 100644 --- a/python/plugins/MetaSearch/ui/maindialog.ui +++ b/python/plugins/MetaSearch/ui/maindialog.ui @@ -6,8 +6,8 @@ 0 0 - 598 - 650 + 653 + 550 @@ -26,153 +26,173 @@ + + + 0 + 0 + + Find - - - - - Set global + + + + + + 0 + 0 + - - - - - - - Map extent - - - - - - - -180 - - - - - + + - 90 + Keywords - - - - - + + - Records - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Map extent - + Search - - + + - -90 + Set global - - - - 180 + + + + + 0 + 0 + - - + + + + + + Xmax + + + + + + + true + + + + 85 + 0 + + + + 180 + + + + + + + Ymax + + + + + + + + 85 + 0 + + + + 90 + + + + + + + Xmin + + + + + + + + 85 + 0 + + + + -180 + + + + + + + Ymin + + + + + + + + 85 + 0 + + + + -90 + + + + - + From - - - - Keywords - - - + + + 0 + 0 + + Results - - - - > - - - - - - - << - - - - - - - Add WCS - - - - - - - Add WMS/WMTS - - - - - - - - - - < - - - - - - - Add WFS - - - - - - - Abstract - - - @@ -218,6 +238,19 @@ + + + + + 145 + 27 + + + + < + + + @@ -225,26 +258,95 @@ - + + + + << + + + + + + + + 0 + 0 + + + + Add WMS/WMTS + + + + + + + + 0 + 0 + + + + + 145 + 27 + + + + Add WFS + + + + + + + 140 + 0 + + >> + + + + + 0 + 0 + + + + Add WCS + + + + + + + + 140 + 0 + + + + > + + + treeRecords lblResults btnPrev btnFirst - btnNext - label_4 - textAbstract - btnAddToWms btnShowXml - btnLast + btnAddToWms btnAddToWfs + btnLast btnAddToWcs + btnNext @@ -326,64 +428,57 @@ Settings - + 10 10 - 558 - 548 + 571 + 71 - Connection naming + Results paging - - - - - When saving the connection of an OWS service - - - - - - - Use the OWS Service Title and ask before overwriting - - - true - - - - - - - Use the OWS Service Title and always overwrite if already available - - - - - - - Use a temporary name, which you can change later - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + + + + 10 + 30 + 41 + 26 + + + + Show + + + + + + 60 + 30 + 104 + 26 + + + + + + + 170 + 30 + 229 + 26 + + + + results at a time + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + diff --git a/python/plugins/MetaSearch/ui/manageconnectionsdialog.py b/python/plugins/MetaSearch/ui/manageconnectionsdialog.py deleted file mode 100644 index 04cac986cab7..000000000000 --- a/python/plugins/MetaSearch/ui/manageconnectionsdialog.py +++ /dev/null @@ -1,56 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/tkralidi/work/foss4g/MetaSearch/MetaSearch/plugin/MetaSearch/ui/manageconnectionsdialog.ui' -# -# Created: Thu Mar 20 21:56:34 2014 -# by: PyQt4 UI code generator 4.9.3 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -try: - _fromUtf8 = QtCore.QString.fromUtf8 -except AttributeError: - _fromUtf8 = lambda s: s - -class Ui_ManageConnectionsDialog(object): - def setupUi(self, ManageConnectionsDialog): - ManageConnectionsDialog.setObjectName(_fromUtf8("ManageConnectionsDialog")) - ManageConnectionsDialog.resize(400, 300) - self.verticalLayout = QtGui.QVBoxLayout(ManageConnectionsDialog) - self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) - self.horizontalLayout = QtGui.QHBoxLayout() - self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout")) - self.label = QtGui.QLabel(ManageConnectionsDialog) - self.label.setObjectName(_fromUtf8("label")) - self.horizontalLayout.addWidget(self.label) - self.leFileName = QtGui.QLineEdit(ManageConnectionsDialog) - self.leFileName.setObjectName(_fromUtf8("leFileName")) - self.horizontalLayout.addWidget(self.leFileName) - self.btnBrowse = QtGui.QPushButton(ManageConnectionsDialog) - self.btnBrowse.setObjectName(_fromUtf8("btnBrowse")) - self.horizontalLayout.addWidget(self.btnBrowse) - self.verticalLayout.addLayout(self.horizontalLayout) - self.listConnections = QtGui.QListWidget(ManageConnectionsDialog) - self.listConnections.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) - self.listConnections.setAlternatingRowColors(True) - self.listConnections.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) - self.listConnections.setObjectName(_fromUtf8("listConnections")) - self.verticalLayout.addWidget(self.listConnections) - self.buttonBox = QtGui.QDialogButtonBox(ManageConnectionsDialog) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) - self.buttonBox.setObjectName(_fromUtf8("buttonBox")) - self.verticalLayout.addWidget(self.buttonBox) - - self.retranslateUi(ManageConnectionsDialog) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), ManageConnectionsDialog.accept) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), ManageConnectionsDialog.reject) - QtCore.QMetaObject.connectSlotsByName(ManageConnectionsDialog) - - def retranslateUi(self, ManageConnectionsDialog): - ManageConnectionsDialog.setWindowTitle(QtGui.QApplication.translate("ManageConnectionsDialog", "Manage connections", None, QtGui.QApplication.UnicodeUTF8)) - self.label.setText(QtGui.QApplication.translate("ManageConnectionsDialog", "Save to file", None, QtGui.QApplication.UnicodeUTF8)) - self.btnBrowse.setText(QtGui.QApplication.translate("ManageConnectionsDialog", "Browse", None, QtGui.QApplication.UnicodeUTF8)) - diff --git a/python/plugins/MetaSearch/ui/newconnectiondialog.py b/python/plugins/MetaSearch/ui/newconnectiondialog.py deleted file mode 100644 index 260b61a51233..000000000000 --- a/python/plugins/MetaSearch/ui/newconnectiondialog.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/tkralidi/work/foss4g/MetaSearch/MetaSearch/plugin/MetaSearch/ui/newconnectiondialog.ui' -# -# Created: Thu Mar 20 21:56:34 2014 -# by: PyQt4 UI code generator 4.9.3 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -try: - _fromUtf8 = QtCore.QString.fromUtf8 -except AttributeError: - _fromUtf8 = lambda s: s - -class Ui_NewConnectionDialog(object): - def setupUi(self, NewConnectionDialog): - NewConnectionDialog.setObjectName(_fromUtf8("NewConnectionDialog")) - NewConnectionDialog.resize(368, 120) - self.gridLayout = QtGui.QGridLayout(NewConnectionDialog) - self.gridLayout.setObjectName(_fromUtf8("gridLayout")) - self.label = QtGui.QLabel(NewConnectionDialog) - self.label.setObjectName(_fromUtf8("label")) - self.gridLayout.addWidget(self.label, 0, 0, 1, 1) - self.leName = QtGui.QLineEdit(NewConnectionDialog) - self.leName.setObjectName(_fromUtf8("leName")) - self.gridLayout.addWidget(self.leName, 0, 1, 1, 1) - self.label_2 = QtGui.QLabel(NewConnectionDialog) - self.label_2.setObjectName(_fromUtf8("label_2")) - self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) - self.leURL = QtGui.QLineEdit(NewConnectionDialog) - self.leURL.setObjectName(_fromUtf8("leURL")) - self.gridLayout.addWidget(self.leURL, 1, 1, 1, 1) - self.buttonBox = QtGui.QDialogButtonBox(NewConnectionDialog) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) - self.buttonBox.setObjectName(_fromUtf8("buttonBox")) - self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 2) - - self.retranslateUi(NewConnectionDialog) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), NewConnectionDialog.accept) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), NewConnectionDialog.reject) - QtCore.QMetaObject.connectSlotsByName(NewConnectionDialog) - - def retranslateUi(self, NewConnectionDialog): - NewConnectionDialog.setWindowTitle(QtGui.QApplication.translate("NewConnectionDialog", "Create a new Catalogue connection", None, QtGui.QApplication.UnicodeUTF8)) - self.label.setText(QtGui.QApplication.translate("NewConnectionDialog", "Name", None, QtGui.QApplication.UnicodeUTF8)) - self.label_2.setText(QtGui.QApplication.translate("NewConnectionDialog", "URL", None, QtGui.QApplication.UnicodeUTF8)) - diff --git a/python/plugins/MetaSearch/ui/recorddialog.py b/python/plugins/MetaSearch/ui/recorddialog.py deleted file mode 100644 index 9a35ce95a232..000000000000 --- a/python/plugins/MetaSearch/ui/recorddialog.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/tkralidi/work/foss4g/MetaSearch/MetaSearch/plugin/MetaSearch/ui/recorddialog.ui' -# -# Created: Thu Mar 20 21:56:35 2014 -# by: PyQt4 UI code generator 4.9.3 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -try: - _fromUtf8 = QtCore.QString.fromUtf8 -except AttributeError: - _fromUtf8 = lambda s: s - -class Ui_RecordDialog(object): - def setupUi(self, RecordDialog): - RecordDialog.setObjectName(_fromUtf8("RecordDialog")) - RecordDialog.resize(600, 400) - self.verticalLayout = QtGui.QVBoxLayout(RecordDialog) - self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) - self.textMetadata = QtGui.QTextBrowser(RecordDialog) - self.textMetadata.setLineWrapMode(QtGui.QTextEdit.NoWrap) - self.textMetadata.setOpenExternalLinks(True) - self.textMetadata.setObjectName(_fromUtf8("textMetadata")) - self.verticalLayout.addWidget(self.textMetadata) - self.buttonBox = QtGui.QDialogButtonBox(RecordDialog) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close) - self.buttonBox.setObjectName(_fromUtf8("buttonBox")) - self.verticalLayout.addWidget(self.buttonBox) - - self.retranslateUi(RecordDialog) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), RecordDialog.accept) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), RecordDialog.reject) - QtCore.QMetaObject.connectSlotsByName(RecordDialog) - - def retranslateUi(self, RecordDialog): - RecordDialog.setWindowTitle(QtGui.QApplication.translate("RecordDialog", "Record Metadata", None, QtGui.QApplication.UnicodeUTF8)) - diff --git a/python/plugins/MetaSearch/ui/xmldialog.py b/python/plugins/MetaSearch/ui/xmldialog.py deleted file mode 100644 index 79416c34789d..000000000000 --- a/python/plugins/MetaSearch/ui/xmldialog.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/tkralidi/work/foss4g/MetaSearch/MetaSearch/plugin/MetaSearch/ui/xmldialog.ui' -# -# Created: Thu Mar 20 21:56:35 2014 -# by: PyQt4 UI code generator 4.9.3 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -try: - _fromUtf8 = QtCore.QString.fromUtf8 -except AttributeError: - _fromUtf8 = lambda s: s - -class Ui_XMLDialog(object): - def setupUi(self, XMLDialog): - XMLDialog.setObjectName(_fromUtf8("XMLDialog")) - XMLDialog.resize(812, 767) - self.verticalLayout = QtGui.QVBoxLayout(XMLDialog) - self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) - self.lblXMLRequest = QtGui.QLabel(XMLDialog) - self.lblXMLRequest.setObjectName(_fromUtf8("lblXMLRequest")) - self.verticalLayout.addWidget(self.lblXMLRequest) - self.txtbrXMLRequest = QtGui.QTextBrowser(XMLDialog) - self.txtbrXMLRequest.setObjectName(_fromUtf8("txtbrXMLRequest")) - self.verticalLayout.addWidget(self.txtbrXMLRequest) - self.lblXMLResponse = QtGui.QLabel(XMLDialog) - self.lblXMLResponse.setObjectName(_fromUtf8("lblXMLResponse")) - self.verticalLayout.addWidget(self.lblXMLResponse) - self.txtbrXMLResponse = QtGui.QTextBrowser(XMLDialog) - self.txtbrXMLResponse.setLineWrapMode(QtGui.QTextEdit.NoWrap) - self.txtbrXMLResponse.setOpenExternalLinks(True) - self.txtbrXMLResponse.setObjectName(_fromUtf8("txtbrXMLResponse")) - self.verticalLayout.addWidget(self.txtbrXMLResponse) - self.buttonBox = QtGui.QDialogButtonBox(XMLDialog) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close) - self.buttonBox.setObjectName(_fromUtf8("buttonBox")) - self.verticalLayout.addWidget(self.buttonBox) - - self.retranslateUi(XMLDialog) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), XMLDialog.accept) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), XMLDialog.reject) - QtCore.QMetaObject.connectSlotsByName(XMLDialog) - - def retranslateUi(self, XMLDialog): - XMLDialog.setWindowTitle(QtGui.QApplication.translate("XMLDialog", "XML Request / Response", None, QtGui.QApplication.UnicodeUTF8)) - self.lblXMLRequest.setText(QtGui.QApplication.translate("XMLDialog", "Request", None, QtGui.QApplication.UnicodeUTF8)) - self.lblXMLResponse.setText(QtGui.QApplication.translate("XMLDialog", "Response", None, QtGui.QApplication.UnicodeUTF8)) - diff --git a/python/plugins/MetaSearch/util.py b/python/plugins/MetaSearch/util.py index c4096030e655..0ccd63b85775 100644 --- a/python/plugins/MetaSearch/util.py +++ b/python/plugins/MetaSearch/util.py @@ -37,6 +37,7 @@ from pygments.lexers import XmlLexer from pygments.formatters import HtmlFormatter from PyQt4.QtGui import QMessageBox +from PyQt4.uic import loadUiType LOGGER = logging.getLogger('MetaSearch') @@ -51,6 +52,13 @@ def __init__(self): self.metadata.readfp(open(os.path.join(self.ppath, 'metadata.txt'))) +def get_ui_class(ui_file): + """return class object of a uifile""" + ui_file_full = '%s%sui%s%s' % (os.path.dirname(os.path.abspath(__file__)), + os.sep, os.sep, ui_file) + return loadUiType(ui_file_full)[0] + + def render_template(language, context, data, template): """Renders HTML display of metadata XML""" @@ -117,3 +125,9 @@ def open_url(url): """open URL in web browser""" webbrowser.open(url) + + +def normalize_text(text): + """tidy up string""" + + return text.replace('\n', '')