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í
-
+ Uložit do souboru
@@ -18,52 +18,52 @@
Prohlížet
-
+ Načíst ze souboru
-
+ Načíst
-
+ Uložit
-
+ rozšiřitelný značkovací jazyk (*.xml *.XML)
-
+ Uložit připojení
-
+ Načíst připojení
-
+ Uložit připojení
-
+ Uloženo do %s
-
+ Soubor %s existuje. Přepsat?
-
+ Načítám připojení
@@ -71,22 +71,22 @@
MetaSearch
-
+ Zásuvný modul MetaSearch
-
+ Prohledávat Metadatové katalogy
-
+ Nápověda k zásuvnému modulu MetaSearch
-
+ Získat nápovědu k MetaSearch
@@ -99,330 +99,325 @@
MetaSearch
-
+ Vyhledávání
-
+ Najít
-
+ Nastavit globálně
-
+ Rozsah mapy
-
+ -180
-
+ 90
-
-
- Záznamy
-
-
-
+ -90
-
+ 180
-
+ Od
-
+ Klíčová slova
-
+ Výsledky
-
+ >
-
+ <<
-
+ Přidat WCS
-
+ Přidat WMS/WMTS
-
+ <
-
+ Přidat WFS
-
-
- Abstract
-
-
-
+ Dvojklik pro zobrazení celého záznamu
-
+ Typ
-
+ Nadpis
-
+ Zobrazit výsledky vyhledávání jako XML
-
+ >>
-
+ Služby
-
+ Informace o službě
-
+ Odpověď GetCapabilities
-
+ Nový
-
+ Editovat
-
+ Smazat
-
+ Uložit
-
+ Přidat výchozí služby
-
+ Načíst
-
+ Nastavení
-
-
- Jméno připojení
-
-
-
-
- Při uložení připojení služby OWS
-
-
-
-
- Použít nadpis služby OWS a zeptat se před přepsáním
-
-
-
-
- Použít nadpis služby OWS a vždy přepsat pokud již byl zadán
-
-
-
-
- Použít dočasné jméno, které může být později změněno
-
-
-
+ 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.
-
+ Nová katalogová služba
-
+ Editovat katalogovou službu
-
+ Odstranit službu %s?
-
+ Potvrdit smazání
-
+ %s již existuje. Přepsat?
-
+ Načítám připojení
-
+ Chyba vyhledávání
-
+ Chyba vyhledávání: %s
-
+ Chyba připojení
-
+ Chyba připojení: %s
-
+ 0 záznamů
-
+ Zobrazuji %d - %d z %d výsledků
-
-
- Žádný abstrakt
-
-
-
+ Konec výsledků. Jít na začátek?
-
+ Navigace
-
+ Začátek výsledků. Jít na konec?
-
-
- Chyba při připojování k %s: %s
-
-
-
+ Připojení %s existuje. Přepsat?
-
+ Ukládám server
-
+ Chyba GetRecords
-
+ Chyba při získávání odpovědi: %s
-
+ Chyba při připojování ke službě: %s
-
+ Chyba hodnoty: %s
-
+ Neznámá chyba: %s
-
+ Chyba připojení CS-W
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NewConnectionDialog
@@ -442,17 +437,17 @@
URL
-
+ Uložit připojení
-
+ Položky Název a URL musí být zadány
-
+ 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 @@
-
+ Verbindungsverwaltung
-
+
-
+ Speichern in Datei
@@ -18,52 +18,52 @@
-
+
-
+ Aus Datei laden
-
+
-
+ Laden
-
+
-
+ Speichern
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -71,22 +71,22 @@
MetaSearch
-
+
-
+
-
+
-
+
@@ -99,330 +99,325 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+ Speichern
-
+
-
+
-
+ Laden
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
+
-
+
-
+
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NewConnectionDialog
@@ -442,17 +437,17 @@
-
+
-
+
-
+
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 @@
-
+
@@ -18,52 +18,52 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -71,22 +71,22 @@
MetaSearch
-
+
-
+
-
+
-
+
@@ -99,327 +99,322 @@
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -442,17 +437,17 @@
-
+
-
+
-
+
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
-
+ Sauvegarder sous
@@ -18,52 +18,52 @@
Parcourir
-
+ Charger depuis un fichier
-
+ Charger
-
+ Sauvegarder
-
+ eXtensible Markup Language (*.xml *.XML)
-
+ Sauvegarder les connexions
-
+ Charger les connexions
-
+ Sauvegarder les connexions
-
+ Sauvegardé sous %s
-
+ Le fichier %s existe déjà. Voulez-vous l'écraser ?
-
+ Chargement des connexions
@@ -71,22 +71,22 @@
MetaSearch
-
+ Extension MetaSearch
-
+ Rechercher des catalogues de métadonnées
-
+ Documentation de l'extension MetaSearch
-
+ Obtenir de l'aide pour MetaSearch
@@ -99,330 +99,325 @@
MetaSearch
-
+ Rechercher
-
+ Trouver
-
+ Etendue globale
-
+ Etendue de la carte
-
+ -180
-
+ 90
-
-
- Enregistrements
-
-
-
+ -90
-
+ 180
-
+ Depuis
-
+ Mots-clés
-
+ Résultats
-
+ >
-
+ <<
-
+ Ajouter une couche WCS
-
+ Ajouter une couche WMS/WMST
-
+ <
-
+ Ajouter une couche WFS
-
-
- Résumé
-
-
-
+ Double-cliquer pour accéder à l'ensemble de la métadonnée
-
+ Type
-
+ Titre
-
+ Voir les résultats de la recherche en XML
-
+ >>
-
+ Services
-
+ Information sur le service
-
+ Réponse GetCapabilities
-
+ Nouveau
-
+ Modifier
-
+ Supprimer
-
+ Sauvegarder
-
+ Ajouter des services par défaut
-
+ Charger
-
+ Paramètres
-
-
- Nommage de la connexion
-
-
-
-
- Lors de la sauvegarde d'une connexion à un service web OGC
-
-
-
-
- Utiliser le Titre du service web OGC et demander confirmation avant d'écraser
-
-
-
-
- Utiliser le Titre du service web OGC et toujours écraser si existe déjà
-
-
-
-
- Utiliser un nom temporaire, que vous pourrez modifier ultérieurement
-
-
-
+ 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'.
-
+ Nouveau Service de Catalogage
-
+ Modifier le service de Catalogage
-
+ Supprimer le service %s ?
-
+ Confirmer la suppression ?
-
+ %s existe déjà. L'écraser ?
-
+ Chargement des connexions
-
+ Erreur dans la recherche
-
+ Erreur dans la recherche : %s
-
+ Erreur de connexion
-
+ Erreur de connexion : %s
-
+ 0 résultat
-
+ Affichage de %d - %d de %d résultats%s
-
-
- Pas de résumé
-
-
-
+ Fin des résultats. Revenir au début ?
-
+ Navigation
-
+ Début des résultats. Aller à la fin ?
-
-
- Erreur de connexion à %s : %s
-
-
-
+ La connexion %s existe déjà. L'écraser ?
-
+ Sauvegarde du serveur
-
+ Erreur GetRecords
-
+ Erreur de récupération de la réponse : %s
-
+ Erreur de connexion au service : %s
-
+ Erreur dans la valeur : %s
-
+ Erreur inconnue : &s
-
+ Erreur de connexion CSW
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NewConnectionDialog
@@ -442,17 +437,17 @@
URL
-
+ Sauvegarder la connexion
-
+ Le Nom et l'URL doivent être spécifié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
-
+ Salva su file
@@ -18,52 +18,52 @@
Eslpora
-
+ Carica da file
-
+ Carica
-
+ Salva
-
+ eXtensible Markup Language (*.xml *.XML)
-
+ Salva connessioni
-
+ Carica connessioni
-
+ Salva Connessioni
-
+ Salvato su %s
-
+ Il file %s esiste. Sovrascriverlo?
-
+ Caricamento connessioni
@@ -71,22 +71,22 @@
MetaSearch
-
+ Plugin MetaSearch
-
+ Ricerca cataloghi di metadati
-
+ Aiuto plugin MetaSearch
-
+ Ottieni aiuto su MetaSearch
@@ -99,330 +99,325 @@
MetaSearch
-
+ Ricerca
-
+ Trova
-
+ Imposta globale
-
+ Estensione mappa
-
+ -180
-
+ 90
-
-
- Record
-
-
-
+ -90
-
+ 180
-
+ Da
-
+ Parole chiave
-
+ Risultati
-
+ >
-
+ <<
-
+ Aggiungi WCS
-
+ Aggiungi WMS/WMTS
-
+ <
-
+ Aggiungi WFS
-
-
- Riassunto
-
-
-
+ Doppio click per visualizzare le informazioni complete del record
-
+ Tipo
-
+ Titolo
-
+ Visualizza i risultati come XML
-
+ >>
-
+ Servizi
-
+ Informazioni sul servizio
-
+ Risposta GetCapabilities
-
+ Nuovo
-
+ Modifica
-
+ Cancella
-
+ Salva
-
+ Aggiungi servizi predefiniti
-
+ Carica
-
+ Impostazioni
-
-
- Assegnare nome a connessione
-
-
-
-
- Quando si salva la connessione ad un servizio OWS
-
-
-
-
- Usa il titolo del servizio OWS e chiedi prima di sovrascrivere
-
-
-
-
- Usa il titolo del servizio OWS e sovrascrivi sempre se già presente
-
-
-
-
- Usa un nome temporaneo, che puoi cambiare più tardi
-
-
-
+ Nessun servizio o connessione definita. Per iniziare a lavorare con MetaSearch, crea una nuova connessione cliccando su 'New' o su 'Aggiungi servizi predefiniti'
-
+ Nuovo Catalogo
-
+ Edita Catalogo
-
+ Rimuovo il servizio %s?
-
+ Conferma la cancellazione
-
+ %s esiste. Sovrascrivi?
-
+ Caricamento connessioni
-
+ Ricerca errore
-
+ Ricerca errore: %s
-
+ Errore di connessione
-
+ Errore di connessione: %s
-
+ 0 risultati
-
+ Mostrando %d - %d di %d risultato/i
-
-
- Nessun riassunto
-
-
-
+ Fine dei risultati. Tornare all'inizio?
-
+ Naviga
-
+ Inizio dei risultati. Andare alla fine?
-
-
- Errore di connessione a %s: %s
-
-
-
+ Connessione %s esiste. Sovrascrivere?
-
+ Salvataggio server
-
+ errore GetRecords
-
+ Errore di risposta: %s
-
+ Errore di connessione al servizio: %s
-
+ Errore di valore: %s
-
+ Errore sconosciuto: %s
-
+ Errore di connessione a CSW
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NewConnectionDialog
@@ -442,17 +437,17 @@
Indirizzo
-
+ Salva connessione
-
+ Sia il nome che l'indirizzo devono essere inseriti
-
+ 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
-
+ Opslaan naar bestand
@@ -18,52 +18,52 @@
Openen
-
+ Bestand laden
-
+ Laden
-
+ Opslaan
-
+ eXtensible Markup Language (*.xml *.XML)
-
+ Verbindingen opslaan
-
+ Verbindingen laden
-
+ Verbindingen opslaan
-
+ Opgeslagen als %s
-
+ Bestand %s bestaat al. Overschijven?
-
+ Verbindingen worden geladen
@@ -71,22 +71,22 @@
MetaSearch
-
+ MetaSearch plugin
-
+ Zoek Metadata Catalogi
-
+ MetaSearch plugin help
-
+ Hulp zoeken voor MetaSearch
@@ -99,330 +99,325 @@
MetaSearch
-
+ Zoeken
-
+ Vind
-
+ Wereldbox
-
+ Kaart extent
-
+ -180
-
+ 90
-
-
- Resultaten
-
-
-
+ -90
-
+ 180
-
+ Van
-
+ Zoekwoorden
-
+ Resultaten
-
+ >
-
+ <<
-
+ WCS Toevoegen
-
+ WMS/WMTS Toevoegen
-
+ <
-
+ WFS Toevoegen
-
-
- Samenvatting
-
-
-
+ Dubbelklikken om de volledige record info te zien
-
+ Type
-
+ Titel
-
+ Resultaten tonen als XML
-
+ >>
-
+ Services
-
+ Service info
-
+ GetCapabilities antwoord
-
+ Nieuw
-
+ Aanpassen
-
+ Verwijderen
-
+ Opslaan
-
+ Standaard services toevoegen
-
+ Laden
-
+ Instellingen
-
-
- Namen voor verbindingen
-
-
-
-
- Bij het opslaan van een OWS service
-
-
-
-
- De OWS Service Title gebruiken en vragen om te overschrijven
-
-
-
-
- De OWS Service Title gebruiken en altijd overschrijven
-
-
-
-
- Een tijdelijke naam gebruiken welke u later kunt aanpassen
-
-
-
+ Er zijn geen service/CSW verbindinen beschikbaar. Om te beginnen met MetaSearch, maak een nieuwe verbinding aan, of klik op 'Standaard services toevoegen'.
-
+ Nieuwe Catalogus service
-
+ Catalogus service aanpassen
-
+ Service %s verwijderen?
-
+ Verwijdering bevestigen
-
+ %s bestaat al. Overschrijven?
-
+ Verbindingen laden
-
+ Fout opgetreden tijdens zoekactie
-
+ Foutmeldinge: %s
-
+ Verbindingsfout
-
+ Verbindingsfout: %s
-
+ 0 resultaten
-
+ %d - %d van de %d resultaten tonen
-
-
- Geen samenvatting
-
-
-
+ Einde van resulaten. Terug naar start?
-
+ Navigeren
-
+ Start van de resultaten. Naar laatste?
-
-
- Fout bij verbinden met %s: %s
-
-
-
+ Verbinding %s bestaat al. Overschrijven?
-
+ Server opslaan
-
+ GetRecords fout
-
+ Fout in de response: %s
-
+ Verbindingsfout bij service: %s
-
+ Datawaarde Fout: %s
-
+ Onbekende fout: %s
-
+ CSW Verbindings fout
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NewConnectionDialog
@@ -442,17 +437,17 @@
URL
-
+ Verbinding opslaan
-
+ Zowel Naam als URL zijn verplichte velden
-
+ %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 @@
00
- 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
+
+
+
+ >
+
+
+ treeRecordslblResultsbtnPrevbtnFirst
- btnNext
- label_4
- textAbstract
- btnAddToWmsbtnShowXml
- btnLast
+ btnAddToWmsbtnAddToWfs
+ btnLastbtnAddToWcs
+ btnNext
@@ -326,64 +428,57 @@
Settings
-
+ 1010
- 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', '')