diff --git a/lib/README.md b/lib/README.md index 13558c12e2c748bb4fddac8fce943833caace1e9..cf54967cd17098e25c2728a7572ca1ecdfbfe287 100644 --- a/lib/README.md +++ b/lib/README.md @@ -66,5 +66,6 @@ xmltodict==0.11.0 ``` pip install --target=lib -U --global-option="--no-user-cfg" --no-binary :all --no-compile --no-cache-dir babelfish tzlocal Unidecode validators xmltodict tornado==4.5 mako python-twitter python-dateutil PyGithub markdown2 html5lib bencode pysocks requests requests-oauthlib tzlocal - pip install --target=lib -U --global-option="--no-user-cfg" --no-binary :all --no-compile --no-cache-dir git+https://github.com/Diaoul/subliminal.git@4ad5d31a6c52c7fa0061ad0da16254580d31dc2a#egg=subliminal +#pip install --target=lib -U --global-option="--no-user-cfg" --no-binary :all --no-compile --no-cache-dir git+https://github.com/Diaoul/subliminal.git@4ad5d31a6c52c7fa0061ad0da16254580d31dc2a#egg=subliminal +pip install --target=lib -U --global-option="--no-user-cfg" --no-binary :all --no-compile --no-cache-dir git+https://github.com/SickRage/subliminal.git@bc92dbd#egg=subliminal ``` diff --git a/lib/certifi/__init__.py b/lib/certifi/__init__.py index 556193cefbf1f8b9b65cab70f394e28481af1fea..0c4963ef6050d85f50925ff2d0108ca50a1f232d 100644 --- a/lib/certifi/__init__.py +++ b/lib/certifi/__init__.py @@ -1,3 +1,3 @@ from .core import where, old_where -__version__ = "2018.01.18" +__version__ = "2018.04.16" diff --git a/lib/certifi/cacert.pem b/lib/certifi/cacert.pem index 101ac98fa42d9eb4b27836e122cc81d495e33c21..2713f541c44982d22ed24d8d2bf10a0f40f2e0a6 100644 --- a/lib/certifi/cacert.pem +++ b/lib/certifi/cacert.pem @@ -3483,39 +3483,6 @@ AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ 5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- -# Issuer: CN=T\xdcRKTRUST Elektronik Sertifika Hizmet Sa\u011flay\u0131c\u0131s\u0131 H5 O=T\xdcRKTRUST Bilgi \u0130leti\u015fim ve Bili\u015fim G\xfcvenli\u011fi Hizmetleri A.\u015e. -# Subject: CN=T\xdcRKTRUST Elektronik Sertifika Hizmet Sa\u011flay\u0131c\u0131s\u0131 H5 O=T\xdcRKTRUST Bilgi \u0130leti\u015fim ve Bili\u015fim G\xfcvenli\u011fi Hizmetleri A.\u015e. -# Label: "T\xdcRKTRUST Elektronik Sertifika Hizmet Sa\u011flay\u0131c\u0131s\u0131 H5" -# Serial: 156233699172481 -# MD5 Fingerprint: da:70:8e:f0:22:df:93:26:f6:5f:9f:d3:15:06:52:4e -# SHA1 Fingerprint: c4:18:f6:4d:46:d1:df:00:3d:27:30:13:72:43:a9:12:11:c6:75:fb -# SHA256 Fingerprint: 49:35:1b:90:34:44:c1:85:cc:dc:5c:69:3d:24:d8:55:5c:b2:08:d6:a8:14:13:07:69:9f:4a:f0:63:19:9d:78 ------BEGIN CERTIFICATE----- -MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UE -BhMCVFIxDzANBgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxn -aSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkg -QS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1QgRWxla3Ryb25payBTZXJ0aWZpa2Eg -SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAwODA3MDFaFw0yMzA0 -MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYD -VQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 -dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApCUZ4WWe60ghUEoI5RHwWrom -/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537jVJp45wnEFPzpALFp/kR -Gml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1mep5Fimh3 -4khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z -5UNP9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0 -hO8EuPbJbKoCPrZV4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QID -AQABo0IwQDAdBgNVHQ4EFgQUVpkHHtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/ -BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ5FdnsX -SDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPoBP5yCccLqh0l -VX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq -URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nf -peYVhDfwwvJllpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CF -Yv4HAqGEVka+lgqaE9chTLd8B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW -+qtB4Uu2NQvAmxU= ------END CERTIFICATE----- - # Issuer: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903 # Subject: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903 # Label: "Certinomis - Root CA" diff --git a/lib/dateutil/_version.py b/lib/dateutil/_version.py index 3aa93e975693f5071e1da099d432e41deafc6348..de463291c4108ed2c631fe1a1a2eefa330b6cbe7 100644 --- a/lib/dateutil/_version.py +++ b/lib/dateutil/_version.py @@ -1,4 +1,4 @@ # coding: utf-8 # file generated by setuptools_scm # don't change, don't track in version control -version = u'2.7.0' +version = u'2.7.2' diff --git a/lib/dateutil/parser/_parser.py b/lib/dateutil/parser/_parser.py index 1b5aabf1b6cdd297577fe4f7a1950502e6eb6fe5..0eac592f94a473ec3de9c5c44b0d154abb9a624d 100644 --- a/lib/dateutil/parser/_parser.py +++ b/lib/dateutil/parser/_parser.py @@ -836,7 +836,11 @@ class parser(object): def _parse_numeric_token(self, tokens, idx, info, ymd, res, fuzzy): # Token is a number value_repr = tokens[idx] - value = Decimal(value_repr) + try: + value = self._to_decimal(value_repr) + except Exception as e: + six.raise_from(ValueError('Unknown numeric token'), e) + len_li = len(value_repr) len_l = len(tokens) @@ -895,7 +899,7 @@ class parser(object): elif idx + 2 < len_l and tokens[idx + 1] == ':': # HH:MM[:SS[.ss]] res.hour = int(value) - value = Decimal(tokens[idx + 2]) # TODO: try/except for this? + value = self._to_decimal(tokens[idx + 2]) # TODO: try/except for this? (res.minute, res.second) = self._parse_min_sec(value) if idx + 4 < len_l and tokens[idx + 3] == ':': @@ -996,7 +1000,7 @@ class parser(object): def _assign_hms(self, res, value_repr, hms): # See GH issue #427, fixing float rounding - value = Decimal(value_repr) + value = self._to_decimal(value_repr) if hms == 0: # Hour @@ -1196,6 +1200,13 @@ class parser(object): return dt + def _to_decimal(self, val): + try: + return Decimal(val) + except Exception as e: + msg = "Could not convert %s to decimal" % val + six.raise_from(ValueError(msg), e) + DEFAULTPARSER = parser() diff --git a/lib/dateutil/rrule.py b/lib/dateutil/rrule.py index 6d6adb10a60b9dd8328e3f2367b25d7909786812..ef4607a346927868d58a96e8162cd993451679e6 100644 --- a/lib/dateutil/rrule.py +++ b/lib/dateutil/rrule.py @@ -21,6 +21,7 @@ from six.moves import _thread, range import heapq from ._common import weekday as weekdaybase +from .tz import tzutc, tzlocal # For warning about deprecation of until and count from warnings import warn @@ -447,6 +448,20 @@ class rrule(rrulebase): until = datetime.datetime.fromordinal(until.toordinal()) self._until = until + if self._dtstart and self._until: + if (self._dtstart.tzinfo is not None) != (self._until.tzinfo is not None): + # According to RFC5545 Section 3.3.10: + # https://tools.ietf.org/html/rfc5545#section-3.3.10 + # + # > If the "DTSTART" property is specified as a date with UTC + # > time or a date with local time and time zone reference, + # > then the UNTIL rule part MUST be specified as a date with + # > UTC time. + raise ValueError( + 'RRULE UNTIL values must be specified in UTC when DTSTART ' + 'is timezone-aware' + ) + if count is not None and until: warn("Using both 'count' and 'until' is inconsistent with RFC 5545" " and has been deprecated in dateutil. Future versions will " diff --git a/lib/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz b/lib/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz index c1722f643090bf004e5521dee56ad5204079033d..5b76ea17dca6d2b68d0802ee7d395b099fedee97 100644 Binary files a/lib/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz and b/lib/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz differ diff --git a/lib/pbr/builddoc.py b/lib/pbr/builddoc.py index c1a2e6f475304a997a1303bc7a1ad34c080397bb..167d13e04a5be8ef9a66c2abcb4f0fc4189b9352 100644 --- a/lib/pbr/builddoc.py +++ b/lib/pbr/builddoc.py @@ -25,7 +25,19 @@ except ImportError: import io as cStringIO try: - from sphinx import apidoc + import sphinx + # NOTE(dhellmann): Newer versions of Sphinx have moved the apidoc + # module into sphinx.ext and the API is slightly different (the + # function expects sys.argv[1:] instead of sys.argv[:]. So, figure + # out where we can import it from and set a flag so we can invoke + # it properly. See this change in sphinx for details: + # https://github.com/sphinx-doc/sphinx/commit/87630c8ae8bff8c0e23187676e6343d8903003a6 + try: + from sphinx.ext import apidoc + apidoc_use_padding = False + except ImportError: + from sphinx import apidoc + apidoc_use_padding = True from sphinx import application from sphinx import setup_command except Exception as e: @@ -42,6 +54,7 @@ except Exception as e: raise ImportError(str(e)) from pbr import git from pbr import options +from pbr import version _rst_template = """%(heading)s @@ -117,7 +130,9 @@ class LocalBuildDoc(setup_command.BuildDoc): def _sphinx_tree(self): source_dir = self._get_source_dir() - cmd = ['apidoc', '.', '-H', 'Modules', '-o', source_dir] + cmd = ['-H', 'Modules', '-o', source_dir, '.'] + if apidoc_use_padding: + cmd.insert(0, 'apidoc') apidoc.main(cmd + self.autodoc_tree_excludes) def _sphinx_run(self): @@ -186,15 +201,34 @@ class LocalBuildDoc(setup_command.BuildDoc): "autodoc_exclude_modules", [None, ""])[1].split())) - # TODO(stephenfin): Deprecate this functionality once we depend on - # Sphinx 1.6, which includes a similar feature, in g-r - # https://github.com/sphinx-doc/sphinx/pull/3476 self.finalize_options() - if hasattr(self, "builder_target_dirs"): - # Sphinx >= 1.6.1 + + is_multibuilder_sphinx = version.SemanticVersion.from_pip_string( + sphinx.__version__) >= version.SemanticVersion(1, 6) + + # TODO(stephenfin): Remove support for Sphinx < 1.6 in 4.0 + if not is_multibuilder_sphinx: + log.warn('[pbr] Support for Sphinx < 1.6 will be dropped in ' + 'pbr 4.0. Upgrade to Sphinx 1.6+') + + # TODO(stephenfin): Remove this at the next MAJOR version bump + if self.builders != ['html']: + log.warn("[pbr] Sphinx 1.6 added native support for " + "specifying multiple builders in the " + "'[sphinx_build] builder' configuration option, " + "found in 'setup.cfg'. As a result, the " + "'[sphinx_build] builders' option has been " + "deprecated and will be removed in pbr 4.0. Migrate " + "to the 'builder' configuration option.") + if is_multibuilder_sphinx: + self.builder = self.builders + + if is_multibuilder_sphinx: + # Sphinx >= 1.6 return setup_command.BuildDoc.run(self) + # Sphinx < 1.6 - for builder in self.builders: + for builder in self.builder: self.builder = builder self.finalize_options() self._sphinx_run() @@ -208,6 +242,8 @@ class LocalBuildDoc(setup_command.BuildDoc): self.autodoc_tree_excludes = ['setup.py'] def finalize_options(self): + from pbr import util + # Not a new style class, super keyword does not work. setup_command.BuildDoc.finalize_options(self) @@ -228,8 +264,8 @@ class LocalBuildDoc(setup_command.BuildDoc): opt = 'autodoc_tree_excludes' option_dict = self.distribution.get_option_dict('pbr') if opt in option_dict: - self.autodoc_tree_excludes = option_dict[opt][1] - self.ensure_string_list(opt) + self.autodoc_tree_excludes = util.split_multiline( + option_dict[opt][1]) # handle Sphinx < 1.5.0 if not hasattr(self, 'warning_is_error'): diff --git a/lib/pbr/core.py b/lib/pbr/core.py index 71d1e5696009e2de568423e5d92e0cce2b60ad34..a93253baddf4796a1d3be3c80ef0f0979cf95d54 100644 --- a/lib/pbr/core.py +++ b/lib/pbr/core.py @@ -50,22 +50,9 @@ import os import sys import warnings -from setuptools import dist - from pbr import util -_saved_core_distribution = core.Distribution - - -def _monkeypatch_distribution(): - core.Distribution = dist._get_unpatched(core.Distribution) - - -def _restore_distribution_monkeypatch(): - core.Distribution = _saved_core_distribution - - if sys.version_info[0] == 3: string_type = str integer_types = (int,) @@ -94,63 +81,54 @@ def pbr(dist, attr, value): not work well with distributions that do use a `Distribution` subclass. """ + if not value: + return + if isinstance(value, string_type): + path = os.path.abspath(value) + else: + path = os.path.abspath('setup.cfg') + if not os.path.exists(path): + raise errors.DistutilsFileError( + 'The setup.cfg file %s does not exist.' % path) + + # Converts the setup.cfg file to setup() arguments try: - _monkeypatch_distribution() - if not value: - return - if isinstance(value, string_type): - path = os.path.abspath(value) - else: - path = os.path.abspath('setup.cfg') - if not os.path.exists(path): - raise errors.DistutilsFileError( - 'The setup.cfg file %s does not exist.' % path) - - # Converts the setup.cfg file to setup() arguments - try: - attrs = util.cfg_to_args(path, dist.script_args) - except Exception: - e = sys.exc_info()[1] - # NB: This will output to the console if no explicit logging has - # been setup - but thats fine, this is a fatal distutils error, so - # being pretty isn't the #1 goal.. being diagnosable is. - logging.exception('Error parsing') - raise errors.DistutilsSetupError( - 'Error parsing %s: %s: %s' % (path, e.__class__.__name__, e)) - - # Repeat some of the Distribution initialization code with the newly - # provided attrs - if attrs: - # Skips 'options' and 'licence' support which are rarely used; may - # add back in later if demanded - for key, val in attrs.items(): - if hasattr(dist.metadata, 'set_' + key): - getattr(dist.metadata, 'set_' + key)(val) - elif hasattr(dist.metadata, key): - setattr(dist.metadata, key, val) - elif hasattr(dist, key): - setattr(dist, key, val) - else: - msg = 'Unknown distribution option: %s' % repr(key) - warnings.warn(msg) - - # Re-finalize the underlying Distribution - core.Distribution.finalize_options(dist) - - # This bit comes out of distribute/setuptools - if isinstance(dist.metadata.version, integer_types + (float,)): - # Some people apparently take "version number" too literally :) - dist.metadata.version = str(dist.metadata.version) - - # This bit of hackery is necessary so that the Distribution will ignore - # normally unsupport command options (namely pre-hooks and post-hooks). - # dist.command_options is normally a dict mapping command names to - # dicts of their options. Now it will be a defaultdict that returns - # IgnoreDicts for the each command's options so we can pass through the - # unsupported options - ignore = ['pre_hook.*', 'post_hook.*'] - dist.command_options = util.DefaultGetDict( - lambda: util.IgnoreDict(ignore) - ) - finally: - _restore_distribution_monkeypatch() + attrs = util.cfg_to_args(path, dist.script_args) + except Exception: + e = sys.exc_info()[1] + # NB: This will output to the console if no explicit logging has + # been setup - but thats fine, this is a fatal distutils error, so + # being pretty isn't the #1 goal.. being diagnosable is. + logging.exception('Error parsing') + raise errors.DistutilsSetupError( + 'Error parsing %s: %s: %s' % (path, e.__class__.__name__, e)) + + # Repeat some of the Distribution initialization code with the newly + # provided attrs + if attrs: + # Skips 'options' and 'licence' support which are rarely used; may + # add back in later if demanded + for key, val in attrs.items(): + if hasattr(dist.metadata, 'set_' + key): + getattr(dist.metadata, 'set_' + key)(val) + elif hasattr(dist.metadata, key): + setattr(dist.metadata, key, val) + elif hasattr(dist, key): + setattr(dist, key, val) + else: + msg = 'Unknown distribution option: %s' % repr(key) + warnings.warn(msg) + + # Re-finalize the underlying Distribution + try: + super(dist.__class__, dist).finalize_options() + except TypeError: + # If dist is not declared as a new-style class (with object as + # a subclass) then super() will not work on it. This is the case + # for Python 2. In that case, fall back to doing this the ugly way + dist.__class__.__bases__[-1].finalize_options(dist) + + # This bit comes out of distribute/setuptools + if isinstance(dist.metadata.version, integer_types + (float,)): + # Some people apparently take "version number" too literally :) + dist.metadata.version = str(dist.metadata.version) diff --git a/lib/pbr/packaging.py b/lib/pbr/packaging.py index c8eedbdb16df54916f9e871cbb89e5d55ad0fe69..1ff28da9b15cf2dc0c3191d9baef5f61c12d3e60 100644 --- a/lib/pbr/packaging.py +++ b/lib/pbr/packaging.py @@ -27,6 +27,7 @@ import email.errors import os import re import sys +import warnings import pkg_resources import setuptools @@ -45,6 +46,8 @@ from pbr import testr_command from pbr import version REQUIREMENTS_FILES = ('requirements.txt', 'tools/pip-requires') +PY_REQUIREMENTS_FILES = [x % sys.version_info[0] for x in ( + 'requirements-py%d.txt', 'tools/pip-requires-py%d')] TEST_REQUIREMENTS_FILES = ('test-requirements.txt', 'tools/test-requires') @@ -56,9 +59,8 @@ def get_requirements_files(): # - REQUIREMENTS_FILES with -py2 or -py3 in the name # (e.g. requirements-py3.txt) # - REQUIREMENTS_FILES - return (list(map(('-py' + str(sys.version_info[0])).join, - map(os.path.splitext, REQUIREMENTS_FILES))) - + list(REQUIREMENTS_FILES)) + + return PY_REQUIREMENTS_FILES + list(REQUIREMENTS_FILES) def append_text_list(config, key, text_list): @@ -77,9 +79,20 @@ def _any_existing(file_list): # Get requirements from the first file that exists def get_reqs_from_files(requirements_files): - for requirements_file in _any_existing(requirements_files): + existing = _any_existing(requirements_files) + + deprecated = [f for f in existing if f in PY_REQUIREMENTS_FILES] + if deprecated: + warnings.warn('Support for \'-pyN\'-suffixed requirements files is ' + 'deprecated in pbr 4.0 and will be removed in 5.0. ' + 'Use environment markers instead. Conflicting files: ' + '%r' % deprecated, + DeprecationWarning) + + for requirements_file in existing: with open(requirements_file, 'r') as fil: return fil.read().split('\n') + return [] @@ -259,8 +272,14 @@ try: """Fallback test runner if testr is a no-go.""" command_name = 'test' + description = 'DEPRECATED: Run unit tests using nose' def run(self): + warnings.warn('nose integration in pbr is deprecated. Please use ' + 'the native nose setuptools configuration or call ' + 'nose directly', + DeprecationWarning) + # Can't use super - base class old-style class commands.nosetests.run(self) @@ -390,8 +409,6 @@ class LocalDevelop(develop.develop): command_name = 'develop' def install_wrapper_scripts(self, dist): - if sys.platform == 'win32': - return develop.develop.install_wrapper_scripts(self, dist) if not self.exclude_scripts: for args in override_get_script_args(dist): self.write_script(*args) @@ -445,13 +462,7 @@ class LocalInstallScripts(install_scripts.install_scripts): # entry-points listed for this package. return - if os.name != 'nt': - get_script_args = override_get_script_args - else: - get_script_args = easy_install.get_script_args - executable = '"%s"' % executable - - for args in get_script_args(dist, executable, is_wininst): + for args in override_get_script_args(dist, executable, is_wininst): self.write_script(*args) @@ -532,11 +543,57 @@ class LocalSDist(sdist.sdist): command_name = 'sdist' + def checking_reno(self): + """Ensure reno is installed and configured. + + We can't run reno-based commands if reno isn't installed/available, and + don't want to if the user isn't using it. + """ + if hasattr(self, '_has_reno'): + return self._has_reno + + try: + # versions of reno witout this module will not have the required + # feature, hence the import + from reno import setup_command # noqa + except ImportError: + log.info('[pbr] reno was not found or is too old. Skipping ' + 'release notes') + self._has_reno = False + return False + + conf, output_file, cache_file = setup_command.load_config( + self.distribution) + + if not os.path.exists(os.path.join(conf.reporoot, conf.notespath)): + log.info('[pbr] reno does not appear to be configured. Skipping ' + 'release notes') + self._has_reno = False + return False + + self._files = [output_file, cache_file] + + log.info('[pbr] Generating release notes') + self._has_reno = True + + return True + + sub_commands = [('build_reno', checking_reno)] + sdist.sdist.sub_commands + def run(self): _from_git(self.distribution) # sdist.sdist is an old style class, can't use super() sdist.sdist.run(self) + def make_distribution(self): + # This is included in make_distribution because setuptools doesn't use + # 'get_file_list'. As such, this is the only hook point that runs after + # the commands in 'sub_commands' + if self.checking_reno(): + self.filelist.extend(self._files) + self.filelist.sort() + sdist.sdist.make_distribution(self) + try: from pbr import builddoc _have_sphinx = True @@ -565,10 +622,14 @@ def _get_increment_kwargs(git_dir, tag): version_spec = tag + "..HEAD" else: version_spec = "HEAD" - changelog = git._run_git_command(['log', version_spec], git_dir) - header_len = len(' sem-ver:') + # Get the raw body of the commit messages so that we don't have to + # parse out any formatting whitespace and to avoid user settings on + # git log output affecting out ability to have working sem ver headers. + changelog = git._run_git_command(['log', '--pretty=%B', version_spec], + git_dir) + header_len = len('sem-ver:') commands = [line[header_len:].strip() for line in changelog.split('\n') - if line.lower().startswith(' sem-ver:')] + if line.lower().startswith('sem-ver:')] symbols = set() for command in commands: symbols.update([symbol.strip() for symbol in command.split(',')]) diff --git a/lib/pbr/testr_command.py b/lib/pbr/testr_command.py index cd179a27a65bd691bf763ffa536ed4244cd095b9..d143565fb66f664fafdebba377599fedd4884355 100644 --- a/lib/pbr/testr_command.py +++ b/lib/pbr/testr_command.py @@ -45,13 +45,14 @@ import distutils.errors import logging import os import sys +import warnings logger = logging.getLogger(__name__) class TestrReal(cmd.Command): - description = "Run unit tests using testr" + description = "DEPRECATED: Run unit tests using testr" user_options = [ ('coverage', None, "Replace PYTHON with coverage and merge coverage " @@ -100,6 +101,11 @@ class TestrReal(cmd.Command): def run(self): """Set up testr repo, then run testr.""" logger.debug("run called") + + warnings.warn('testr integration in pbr is deprecated. Please use ' + 'the \'testr\' setup command or call testr directly', + DeprecationWarning) + if not os.path.isdir(".testrepository"): self._run_testr("init") diff --git a/lib/pbr/tests/test_hooks.py b/lib/pbr/tests/test_hooks.py index 07597060ad3f9c482334e8f0f947bf3f23c9fd55..0fcf96cac2cad32cbbde1e21451e6c8fbfefebd4 100644 --- a/lib/pbr/tests/test_hooks.py +++ b/lib/pbr/tests/test_hooks.py @@ -39,9 +39,7 @@ # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS import os -import textwrap -from testtools import content from testtools import matchers from pbr.tests import base @@ -56,10 +54,6 @@ class TestHooks(base.BaseTestCase): cfg.set('global', 'setup-hooks', 'pbr_testpackage._setup_hooks.test_hook_1\n' 'pbr_testpackage._setup_hooks.test_hook_2') - cfg.set('build_ext', 'pre-hook.test_pre_hook', - 'pbr_testpackage._setup_hooks.test_pre_hook') - cfg.set('build_ext', 'post-hook.test_post_hook', - 'pbr_testpackage._setup_hooks.test_post_hook') def test_global_setup_hooks(self): """Test setup_hooks. @@ -72,28 +66,6 @@ class TestHooks(base.BaseTestCase): assert 'test_hook_1\ntest_hook_2' in stdout assert return_code == 0 - def test_command_hooks(self): - """Test command hooks. - - Simple test that the appropriate command hooks run at the - beginning/end of the appropriate command. - """ - - stdout, _, return_code = self.run_setup('egg_info') - assert 'build_ext pre-hook' not in stdout - assert 'build_ext post-hook' not in stdout - assert return_code == 0 - - stdout, stderr, return_code = self.run_setup('build_ext') - self.addDetailUniqueName('stderr', content.text_content(stderr)) - assert textwrap.dedent(""" - running build_ext - running pre_hook pbr_testpackage._setup_hooks.test_pre_hook for command build_ext - build_ext pre-hook - """) in stdout # flake8: noqa - self.expectThat(stdout, matchers.EndsWith('build_ext post-hook')) - assert return_code == 0 - def test_custom_commands_known(self): stdout, _, return_code = self.run_setup('--help-commands') self.assertFalse(return_code) diff --git a/lib/pbr/tests/test_packaging.py b/lib/pbr/tests/test_packaging.py index 9efcbd7892e1284e675d676edb856e336b2ac324..5512d5d62aa995aec42f51fd340a21a0aa8ae0c2 100644 --- a/lib/pbr/tests/test_packaging.py +++ b/lib/pbr/tests/test_packaging.py @@ -43,6 +43,7 @@ import email.errors import imp import os import re +import sys import sysconfig import tempfile import textwrap @@ -51,6 +52,7 @@ import fixtures import mock import pkg_resources import six +import testscenarios import testtools from testtools import matchers import virtualenv @@ -486,9 +488,47 @@ class TestPresenceOfGit(base.BaseTestCase): self.assertEqual(False, git._git_is_installed()) -class TestIndexInRequirements(base.BaseTestCase): +class ParseRequirementsTest(base.BaseTestCase): - def test_index_in_requirement(self): + def test_empty_requirements(self): + actual = packaging.parse_requirements([]) + self.assertEqual([], actual) + + def test_default_requirements(self): + """Ensure default files used if no files provided.""" + tempdir = tempfile.mkdtemp() + requirements = os.path.join(tempdir, 'requirements.txt') + with open(requirements, 'w') as f: + f.write('pbr') + # the defaults are relative to where pbr is called from so we need to + # override them. This is OK, however, as we want to validate that + # defaults are used - not what those defaults are + with mock.patch.object(packaging, 'REQUIREMENTS_FILES', ( + requirements,)): + result = packaging.parse_requirements() + self.assertEqual(['pbr'], result) + + def test_override_with_env(self): + """Ensure environment variable used if no files provided.""" + _, tmp_file = tempfile.mkstemp(prefix='openstack', suffix='.setup') + with open(tmp_file, 'w') as fh: + fh.write("foo\nbar") + self.useFixture( + fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES', tmp_file)) + self.assertEqual(['foo', 'bar'], + packaging.parse_requirements()) + + def test_override_with_env_multiple_files(self): + _, tmp_file = tempfile.mkstemp(prefix='openstack', suffix='.setup') + with open(tmp_file, 'w') as fh: + fh.write("foo\nbar") + self.useFixture( + fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES', + "no-such-file," + tmp_file)) + self.assertEqual(['foo', 'bar'], + packaging.parse_requirements()) + + def test_index_present(self): tempdir = tempfile.mkdtemp() requirements = os.path.join(tempdir, 'requirements.txt') with open(requirements, 'w') as f: @@ -498,10 +538,7 @@ class TestIndexInRequirements(base.BaseTestCase): result = packaging.parse_requirements([requirements]) self.assertEqual([], result) - -class TestNestedRequirements(base.BaseTestCase): - - def test_nested_requirement(self): + def test_nested_requirements(self): tempdir = tempfile.mkdtemp() requirements = os.path.join(tempdir, 'requirements.txt') nested = os.path.join(tempdir, 'nested.txt') @@ -512,6 +549,94 @@ class TestNestedRequirements(base.BaseTestCase): result = packaging.parse_requirements([requirements]) self.assertEqual(['pbr'], result) + @mock.patch('warnings.warn') + def test_python_version(self, mock_warn): + with open("requirements-py%d.txt" % sys.version_info[0], + "w") as fh: + fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz") + self.assertEqual(['foobar', 'foobaz'], + packaging.parse_requirements()) + mock_warn.assert_called_once_with(mock.ANY, DeprecationWarning) + + @mock.patch('warnings.warn') + def test_python_version_multiple_options(self, mock_warn): + with open("requirements-py1.txt", "w") as fh: + fh.write("thisisatrap") + with open("requirements-py%d.txt" % sys.version_info[0], + "w") as fh: + fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz") + self.assertEqual(['foobar', 'foobaz'], + packaging.parse_requirements()) + # even though we have multiple offending files, this should only be + # called once + mock_warn.assert_called_once_with(mock.ANY, DeprecationWarning) + + +class ParseRequirementsTestScenarios(base.BaseTestCase): + + versioned_scenarios = [ + ('non-versioned', {'versioned': False, 'expected': ['bar']}), + ('versioned', {'versioned': True, 'expected': ['bar>=1.2.3']}) + ] + + scenarios = [ + ('normal', {'url': "foo\nbar", 'expected': ['foo', 'bar']}), + ('normal_with_comments', { + 'url': "# this is a comment\nfoo\n# and another one\nbar", + 'expected': ['foo', 'bar']}), + ('removes_index_lines', {'url': '-f foobar', 'expected': []}), + ] + + scenarios = scenarios + testscenarios.multiply_scenarios([ + ('ssh_egg_url', {'url': 'git+ssh://foo.com/zipball#egg=bar'}), + ('git_https_egg_url', {'url': 'git+https://foo.com/zipball#egg=bar'}), + ('http_egg_url', {'url': 'https://foo.com/zipball#egg=bar'}), + ], versioned_scenarios) + + scenarios = scenarios + testscenarios.multiply_scenarios( + [ + ('git_egg_url', + {'url': 'git://foo.com/zipball#egg=bar', 'name': 'bar'}) + ], [ + ('non-editable', {'editable': False}), + ('editable', {'editable': True}), + ], + versioned_scenarios) + + def test_parse_requirements(self): + tmp_file = tempfile.NamedTemporaryFile() + req_string = self.url + if hasattr(self, 'editable') and self.editable: + req_string = ("-e %s" % req_string) + if hasattr(self, 'versioned') and self.versioned: + req_string = ("%s-1.2.3" % req_string) + with open(tmp_file.name, 'w') as fh: + fh.write(req_string) + self.assertEqual(self.expected, + packaging.parse_requirements([tmp_file.name])) + + +class ParseDependencyLinksTest(base.BaseTestCase): + + def setUp(self): + super(ParseDependencyLinksTest, self).setUp() + _, self.tmp_file = tempfile.mkstemp(prefix="openstack", + suffix=".setup") + + def test_parse_dependency_normal(self): + with open(self.tmp_file, "w") as fh: + fh.write("http://test.com\n") + self.assertEqual( + ["http://test.com"], + packaging.parse_dependency_links([self.tmp_file])) + + def test_parse_dependency_with_git_egg_url(self): + with open(self.tmp_file, "w") as fh: + fh.write("-e git://foo.com/zipball#egg=bar") + self.assertEqual( + ["git://foo.com/zipball#egg=bar"], + packaging.parse_dependency_links([self.tmp_file])) + class TestVersions(base.BaseTestCase): @@ -759,7 +884,7 @@ class TestRequirementParsing(base.BaseTestCase): expected_requirements = { None: ['bar', 'requests-aws>=0.1.4'], ":(python_version=='2.6')": ['quux<1.0'], - ":(python_version=='2.7')": ['Routes>=1.12.3,!=2.0,!=2.1', + ":(python_version=='2.7')": ['Routes!=2.0,!=2.1,>=1.12.3', 'requests-kerberos>=0.6'], 'test': ['foo'], "test:(python_version=='2.7')": ['baz>3.2', 'bar>3.3'] @@ -778,7 +903,20 @@ class TestRequirementParsing(base.BaseTestCase): generated_requirements = dict( pkg_resources.split_sections(requires)) - self.assertEqual(expected_requirements, generated_requirements) + # NOTE(dhellmann): We have to spell out the comparison because + # the rendering for version specifiers in a range is not + # consistent across versions of setuptools. + + for section, expected in expected_requirements.items(): + exp_parsed = [ + pkg_resources.Requirement.parse(s) + for s in expected + ] + gen_parsed = [ + pkg_resources.Requirement.parse(s) + for s in generated_requirements[section] + ] + self.assertEqual(exp_parsed, gen_parsed) def get_soabi(): diff --git a/lib/pbr/tests/test_setup.py b/lib/pbr/tests/test_setup.py index 0b9c81be9c26d4ef0c1fe47339c4b8ad43772f98..85d40ebf30dccf60d9b27ea4f8a6f7f480bcd178 100644 --- a/lib/pbr/tests/test_setup.py +++ b/lib/pbr/tests/test_setup.py @@ -17,9 +17,6 @@ from __future__ import print_function import os -import sys -import tempfile -import testscenarios try: import cStringIO as io @@ -446,115 +443,3 @@ class APIAutoDocTest(base.BaseTestCase): self.assertTrue( os.path.exists( "contributor/api/fake_package.fake_private_module.rst")) - - -class ParseRequirementsTestScenarios(base.BaseTestCase): - - versioned_scenarios = [ - ('non-versioned', {'versioned': False, 'expected': ['bar']}), - ('versioned', {'versioned': True, 'expected': ['bar>=1.2.3']}) - ] - - scenarios = [ - ('normal', {'url': "foo\nbar", 'expected': ['foo', 'bar']}), - ('normal_with_comments', { - 'url': "# this is a comment\nfoo\n# and another one\nbar", - 'expected': ['foo', 'bar']}), - ('removes_index_lines', {'url': '-f foobar', 'expected': []}), - ] - - scenarios = scenarios + testscenarios.multiply_scenarios([ - ('ssh_egg_url', {'url': 'git+ssh://foo.com/zipball#egg=bar'}), - ('git_https_egg_url', {'url': 'git+https://foo.com/zipball#egg=bar'}), - ('http_egg_url', {'url': 'https://foo.com/zipball#egg=bar'}), - ], versioned_scenarios) - - scenarios = scenarios + testscenarios.multiply_scenarios( - [ - ('git_egg_url', - {'url': 'git://foo.com/zipball#egg=bar', 'name': 'bar'}) - ], [ - ('non-editable', {'editable': False}), - ('editable', {'editable': True}), - ], - versioned_scenarios) - - def test_parse_requirements(self): - tmp_file = tempfile.NamedTemporaryFile() - req_string = self.url - if hasattr(self, 'editable') and self.editable: - req_string = ("-e %s" % req_string) - if hasattr(self, 'versioned') and self.versioned: - req_string = ("%s-1.2.3" % req_string) - with open(tmp_file.name, 'w') as fh: - fh.write(req_string) - self.assertEqual(self.expected, - packaging.parse_requirements([tmp_file.name])) - - -class ParseRequirementsTest(base.BaseTestCase): - - def setUp(self): - super(ParseRequirementsTest, self).setUp() - (fd, self.tmp_file) = tempfile.mkstemp(prefix='openstack', - suffix='.setup') - - def test_parse_requirements_override_with_env(self): - with open(self.tmp_file, 'w') as fh: - fh.write("foo\nbar") - self.useFixture( - fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES', - self.tmp_file)) - self.assertEqual(['foo', 'bar'], - packaging.parse_requirements()) - - def test_parse_requirements_override_with_env_multiple_files(self): - with open(self.tmp_file, 'w') as fh: - fh.write("foo\nbar") - self.useFixture( - fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES', - "no-such-file," + self.tmp_file)) - self.assertEqual(['foo', 'bar'], - packaging.parse_requirements()) - - def test_get_requirement_from_file_empty(self): - actual = packaging.get_reqs_from_files([]) - self.assertEqual([], actual) - - def test_parse_requirements_python_version(self): - with open("requirements-py%d.txt" % sys.version_info[0], - "w") as fh: - fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz") - self.assertEqual(['foobar', 'foobaz'], - packaging.parse_requirements()) - - def test_parse_requirements_right_python_version(self): - with open("requirements-py1.txt", "w") as fh: - fh.write("thisisatrap") - with open("requirements-py%d.txt" % sys.version_info[0], - "w") as fh: - fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz") - self.assertEqual(['foobar', 'foobaz'], - packaging.parse_requirements()) - - -class ParseDependencyLinksTest(base.BaseTestCase): - - def setUp(self): - super(ParseDependencyLinksTest, self).setUp() - (fd, self.tmp_file) = tempfile.mkstemp(prefix="openstack", - suffix=".setup") - - def test_parse_dependency_normal(self): - with open(self.tmp_file, "w") as fh: - fh.write("http://test.com\n") - self.assertEqual( - ["http://test.com"], - packaging.parse_dependency_links([self.tmp_file])) - - def test_parse_dependency_with_git_egg_url(self): - with open(self.tmp_file, "w") as fh: - fh.write("-e git://foo.com/zipball#egg=bar") - self.assertEqual( - ["git://foo.com/zipball#egg=bar"], - packaging.parse_dependency_links([self.tmp_file])) diff --git a/lib/pbr/tests/test_util.py b/lib/pbr/tests/test_util.py index 048b2b96815a1ab010e3c1d48c7c00e088e54d9e..370a7deee25e1adce773e99c55f167e9767f2d3f 100644 --- a/lib/pbr/tests/test_util.py +++ b/lib/pbr/tests/test_util.py @@ -36,8 +36,12 @@ class TestExtrasRequireParsingScenarios(base.BaseTestCase): baz>=3.2 foo """, - 'expected_extra_requires': {'first': ['foo', 'bar==1.0'], - 'second': ['baz>=3.2', 'foo']} + 'expected_extra_requires': { + 'first': ['foo', 'bar==1.0'], + 'second': ['baz>=3.2', 'foo'], + 'test': ['requests-mock'], + "test:(python_version=='2.6')": ['ordereddict'], + } }), ('with_markers', { 'config_text': """ diff --git a/lib/pbr/tests/test_version.py b/lib/pbr/tests/test_version.py index 14c8d173674447fc4e7b872f4f4a1b46cebbdef7..d861d572031141fd92aaf8844503d9b89ae84905 100644 --- a/lib/pbr/tests/test_version.py +++ b/lib/pbr/tests/test_version.py @@ -84,6 +84,19 @@ class TestSemanticVersion(base.BaseTestCase): lambda: from_pip_string('1.2.3.post5.dev6'), matchers.raises(ValueError)) + def test_from_pip_string_v_version(self): + parsed = from_pip_string('v1.2.3') + expected = version.SemanticVersion(1, 2, 3) + self.expectThat(expected, matchers.Equals(parsed)) + + expected = version.SemanticVersion(1, 2, 3, 'a', 5, dev_count=6) + parsed = from_pip_string('V1.2.3.0a4.post6') + self.expectThat(expected, matchers.Equals(parsed)) + + self.expectThat( + lambda: from_pip_string('x1.2.3'), + matchers.raises(ValueError)) + def test_from_pip_string_legacy_nonzero_lead_in(self): # reported in bug 1361251 expected = version.SemanticVersion( diff --git a/lib/pbr/tests/testpackage/setup.cfg b/lib/pbr/tests/testpackage/setup.cfg index 242c9c613bfb0c5686c216d6cad6dfc55243c10b..bf4c26a2758ac178ed115f9bec0e731c14d80acf 100644 --- a/lib/pbr/tests/testpackage/setup.cfg +++ b/lib/pbr/tests/testpackage/setup.cfg @@ -6,10 +6,15 @@ version = 0.1.dev author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = http://pypi.python.org/pypi/pbr +project_urls = + Bug Tracker = https://bugs.launchpad.net/pbr/ + Documentation = https://docs.openstack.org/pbr/ + Source Code = https://git.openstack.org/cgit/openstack-dev/pbr/ summary = Test package for testing pbr description-file = README.txt CHANGES.txt +description-content-type = text/plain; charset=UTF-8 requires-python = >=2.5 requires-dist = @@ -51,7 +56,3 @@ optional = True # pbr_testpackage._setup_hooks.test_hook_1 # pbr_testpackage._setup_hooks.test_hook_2 commands = pbr_testpackage._setup_hooks.test_command - -[build_ext] -#pre-hook.test_pre_hook = pbr_testpackage._setup_hooks.test_pre_hook -#post-hook.test_post_hook = pbr_testpackage._setup_hooks.test_post_hook diff --git a/lib/pbr/tests/testpackage/test-requirements.txt b/lib/pbr/tests/testpackage/test-requirements.txt index f283aff52509d7ddc1dcfcc30b83db86d52e1883..8755eb4caea86fcdec52e163036caf9d8fac1616 100644 --- a/lib/pbr/tests/testpackage/test-requirements.txt +++ b/lib/pbr/tests/testpackage/test-requirements.txt @@ -1 +1,2 @@ ordereddict;python_version=='2.6' +requests-mock diff --git a/lib/pbr/util.py b/lib/pbr/util.py index a117785517b23ba1f4880780c12dc6628c41dbed..31a2a2622989937513e87b0ac997cb661fb6775c 100644 --- a/lib/pbr/util.py +++ b/lib/pbr/util.py @@ -101,9 +101,11 @@ D1_D2_SETUP_ARGS = { "maintainer": ("metadata",), "maintainer_email": ("metadata",), "url": ("metadata", "home_page"), + "project_urls": ("metadata",), "description": ("metadata", "summary"), "keywords": ("metadata",), "long_description": ("metadata", "description"), + "long_description_content_type": ("metadata", "description_content_type"), "download_url": ("metadata",), "classifiers": ("metadata", "classifier"), "platforms": ("metadata", "platform"), # ** @@ -148,6 +150,9 @@ MULTI_FIELDS = ("classifiers", "tests_require", "cmdclass") +# setup() arguments that can have mapping values in setup.cfg +MAP_FIELDS = ("project_urls",) + # setup() arguments that contain boolean values BOOL_FIELDS = ("use_2to3", "zip_safe", "include_package_data") @@ -193,9 +198,9 @@ def cfg_to_args(path='setup.cfg', script_args=()): This method uses an existing setup.cfg to generate a dictionary of keywords that can be used by distutils.core.setup(kwargs**). - :param file: + :param path: The setup.cfg path. - :parm script_args: + :param script_args: List of commands setup.py was called with. :raises DistutilsFileError: When the setup.cfg file is not found. @@ -209,7 +214,11 @@ def cfg_to_args(path='setup.cfg', script_args=()): if not os.path.exists(path): raise errors.DistutilsFileError("file '%s' does not exist" % os.path.abspath(path)) - parser.read(path) + try: + parser.read(path, encoding='utf-8') + except TypeError: + # Python 2 doesn't accept the encoding kwarg + parser.read(path) config = {} for section in parser.sections(): config[section] = dict() @@ -264,8 +273,6 @@ def cfg_to_args(path='setup.cfg', script_args=()): if entry_points: kwargs['entry_points'] = entry_points - wrap_commands(kwargs) - # Handle the [files]/extra_files option files_extra_files = has_get_option(config, 'files', 'extra_files') if files_extra_files: @@ -323,6 +330,12 @@ def setup_cfg_to_setup_kwargs(config, script_args=()): in_cfg_value = split_csv(in_cfg_value) if arg in MULTI_FIELDS: in_cfg_value = split_multiline(in_cfg_value) + elif arg in MAP_FIELDS: + in_cfg_map = {} + for i in split_multiline(in_cfg_value): + k, v = i.split('=') + in_cfg_map[k.strip()] = v.strip() + in_cfg_value = in_cfg_map elif arg in BOOL_FIELDS: # Provide some flexibility here... if in_cfg_value.lower() in ('true', 't', '1', 'yes', 'y'): @@ -402,6 +415,13 @@ def setup_cfg_to_setup_kwargs(config, script_args=()): if 'extras' in config: requirement_pattern = '(?P<package>[^:]*):?(?P<env_marker>[^#]*?)(?:\s*#.*)?$' extras = config['extras'] + # Add contents of test-requirements, if any, into an extra named + # 'test' if one does not already exist. + if 'test' not in extras: + from pbr import packaging + extras['test'] = "\n".join(packaging.parse_requirements( + packaging.TEST_REQUIREMENTS_FILES)).replace(';', ':') + for extra in extras: extra_requirements = [] requirements = split_multiline(extras[extra]) @@ -552,103 +572,6 @@ def get_entry_points(config): for option, value in config['entry_points'].items()) -def wrap_commands(kwargs): - dist = st_dist.Distribution() - - # This should suffice to get the same config values and command classes - # that the actual Distribution will see (not counting cmdclass, which is - # handled below) - dist.parse_config_files() - - # Setuptools doesn't patch get_command_list, and as such we do not get - # extra commands from entry_points. As we need to be compatable we deal - # with this here. - for ep in pkg_resources.iter_entry_points('distutils.commands'): - if ep.name not in dist.cmdclass: - if hasattr(ep, 'resolve'): - cmdclass = ep.resolve() - else: - # Old setuptools does not have ep.resolve, and load with - # arguments is depricated in 11+. Use resolve, 12+, if we - # can, otherwise fall back to load. - # Setuptools 11 will throw a deprication warning, as it - # uses _load instead of resolve. - cmdclass = ep.load(False) - dist.cmdclass[ep.name] = cmdclass - - for cmd, _ in dist.get_command_list(): - hooks = {} - for opt, val in dist.get_option_dict(cmd).items(): - val = val[1] - if opt.startswith('pre_hook.') or opt.startswith('post_hook.'): - hook_type, alias = opt.split('.', 1) - hook_dict = hooks.setdefault(hook_type, {}) - hook_dict[alias] = val - if not hooks: - continue - - if 'cmdclass' in kwargs and cmd in kwargs['cmdclass']: - cmdclass = kwargs['cmdclass'][cmd] - else: - cmdclass = dist.get_command_class(cmd) - - new_cmdclass = wrap_command(cmd, cmdclass, hooks) - kwargs.setdefault('cmdclass', {})[cmd] = new_cmdclass - - -def wrap_command(cmd, cmdclass, hooks): - def run(self, cmdclass=cmdclass): - self.run_command_hooks('pre_hook') - cmdclass.run(self) - self.run_command_hooks('post_hook') - - return type(cmd, (cmdclass, object), - {'run': run, 'run_command_hooks': run_command_hooks, - 'pre_hook': hooks.get('pre_hook'), - 'post_hook': hooks.get('post_hook')}) - - -def run_command_hooks(cmd_obj, hook_kind): - """Run hooks registered for that command and phase. - - *cmd_obj* is a finalized command object; *hook_kind* is either - 'pre_hook' or 'post_hook'. - """ - - if hook_kind not in ('pre_hook', 'post_hook'): - raise ValueError('invalid hook kind: %r' % hook_kind) - - hooks = getattr(cmd_obj, hook_kind, None) - - if hooks is None: - return - - for hook in hooks.values(): - if isinstance(hook, str): - try: - hook_obj = resolve_name(hook) - except ImportError: - err = sys.exc_info()[1] # For py3k - raise errors.DistutilsModuleError('cannot find hook %s: %s' % - (hook,err)) - else: - hook_obj = hook - - if not hasattr(hook_obj, '__call__'): - raise errors.DistutilsOptionError('hook %r is not callable' % hook) - - log.info('running %s %s for command %s', - hook_kind, hook, cmd_obj.get_command_name()) - - try : - hook_obj(cmd_obj) - except: - e = sys.exc_info()[1] - log.error('hook %s raised exception: %s\n' % (hook, e)) - log.error(traceback.format_exc()) - sys.exit(1) - - def has_get_option(config, section, option): if section in config and option in config[section]: return config[section][option] @@ -661,7 +584,7 @@ def split_multiline(value): value = [element for element in (line.strip() for line in value.split('\n')) - if element] + if element and not element.startswith('#')] return value @@ -674,21 +597,6 @@ def split_csv(value): return value -def monkeypatch_method(cls): - """A function decorator to monkey-patch a method of the same name on the - given class. - """ - - def wrapper(func): - orig = getattr(cls, func.__name__, None) - if orig and not hasattr(orig, '_orig'): # Already patched - setattr(func, '_orig', orig) - setattr(cls, func.__name__, func) - return func - - return wrapper - - # The following classes are used to hack Distribution.command_options a bit class DefaultGetDict(defaultdict): """Like defaultdict, but the get() method also sets and returns the default @@ -699,20 +607,3 @@ class DefaultGetDict(defaultdict): if default is None: default = self.default_factory() return super(DefaultGetDict, self).setdefault(key, default) - - -class IgnoreDict(dict): - """A dictionary that ignores any insertions in which the key is a string - matching any string in `ignore`. The ignore list can also contain wildcard - patterns using '*'. - """ - - def __init__(self, ignore): - self.__ignore = re.compile(r'(%s)' % ('|'.join( - [pat.replace('*', '.*') - for pat in ignore]))) - - def __setitem__(self, key, val): - if self.__ignore.match(key): - return - super(IgnoreDict, self).__setitem__(key, val) diff --git a/lib/pbr/version.py b/lib/pbr/version.py index 474faf16a0db64d7fa3e8885d627956f62592506..5eb217afe89900fe32fcd48c78460e3962a05912 100644 --- a/lib/pbr/version.py +++ b/lib/pbr/version.py @@ -149,6 +149,7 @@ class SemanticVersion(object): @classmethod def _from_pip_string_unsafe(klass, version_string): # Versions need to start numerically, ignore if not + version_string = version_string.lstrip('vV') if not version_string[:1].isdigit(): raise ValueError("Invalid version %r" % version_string) input_components = version_string.split('.') diff --git a/lib/pytz/__init__.py b/lib/pytz/__init__.py index 5f753b6648084db92e08872295a442a3030b0e64..178d3c46fc4a881804f49a8270d9e86475da0ce4 100644 --- a/lib/pytz/__init__.py +++ b/lib/pytz/__init__.py @@ -17,13 +17,13 @@ from pytz.exceptions import InvalidTimeError from pytz.exceptions import NonExistentTimeError from pytz.exceptions import UnknownTimeZoneError from pytz.lazy import LazyDict, LazyList, LazySet -from pytz.tzinfo import unpickler +from pytz.tzinfo import unpickler, BaseTzInfo from pytz.tzfile import build_tzinfo # The IANA (nee Olson) database is updated several times a year. -OLSON_VERSION = '2018c' -VERSION = '2018.3' # Switching to pip compatible version numbering. +OLSON_VERSION = '2018d' +VERSION = '2018.4' # pip compatible version number. __version__ = VERSION OLSEN_VERSION = OLSON_VERSION # Old releases had this misspelling @@ -37,10 +37,7 @@ __all__ = [ ] -try: - unicode - -except NameError: # Python 3.x +if sys.version_info[0] > 2: # Python 3.x # Python 3.x doesn't have unicode(), making writing code # for Python 2.3 and Python 3.x a pain. @@ -191,7 +188,7 @@ ZERO = datetime.timedelta(0) HOUR = datetime.timedelta(hours=1) -class UTC(datetime.tzinfo): +class UTC(BaseTzInfo): """UTC Optimized UTC implementation. It unpickles using the single module global @@ -416,18 +413,18 @@ def FixedOffset(offset, _tzinfos={}): >>> one = FixedOffset(-330) >>> one pytz.FixedOffset(-330) - >>> one.utcoffset(datetime.datetime.now()) - datetime.timedelta(-1, 66600) - >>> one.dst(datetime.datetime.now()) - datetime.timedelta(0) + >>> str(one.utcoffset(datetime.datetime.now())) + '-1 day, 18:30:00' + >>> str(one.dst(datetime.datetime.now())) + '0:00:00' >>> two = FixedOffset(1380) >>> two pytz.FixedOffset(1380) - >>> two.utcoffset(datetime.datetime.now()) - datetime.timedelta(0, 82800) - >>> two.dst(datetime.datetime.now()) - datetime.timedelta(0) + >>> str(two.utcoffset(datetime.datetime.now())) + '23:00:00' + >>> str(two.dst(datetime.datetime.now())) + '0:00:00' The datetime.timedelta must be between the range of -1 and 1 day, non-inclusive. diff --git a/lib/pytz/lazy.py b/lib/pytz/lazy.py index fe91ff8dfd9b2167842494bc8496f224f9cb768a..39344fc1f8c77d5ec43539d0c8e655f4b5d7d6f6 100644 --- a/lib/pytz/lazy.py +++ b/lib/pytz/lazy.py @@ -1,8 +1,11 @@ from threading import RLock try: - from UserDict import DictMixin -except ImportError: - from collections import Mapping as DictMixin + from collections.abc import Mapping as DictMixin +except ImportError: # Python < 3.3 + try: + from UserDict import DictMixin # Python 2 + except ImportError: # Python 3.0-3.3 + from collections import Mapping as DictMixin # With lazy loading, we might end up with multiple threads triggering diff --git a/lib/pytz/tzinfo.py b/lib/pytz/tzinfo.py index d78c2edc1d252dc506c914044afa51d9612e7e85..725978d53720202bf7b1a64f356f47c49d42fd92 100644 --- a/lib/pytz/tzinfo.py +++ b/lib/pytz/tzinfo.py @@ -403,11 +403,11 @@ class DstTzInfo(BaseTzInfo): >>> tz = timezone('America/St_Johns') >>> ambiguous = datetime(2009, 10, 31, 23, 30) - >>> tz.utcoffset(ambiguous, is_dst=False) - datetime.timedelta(-1, 73800) + >>> str(tz.utcoffset(ambiguous, is_dst=False)) + '-1 day, 20:30:00' - >>> tz.utcoffset(ambiguous, is_dst=True) - datetime.timedelta(-1, 77400) + >>> str(tz.utcoffset(ambiguous, is_dst=True)) + '-1 day, 21:30:00' >>> try: ... tz.utcoffset(ambiguous) @@ -435,19 +435,19 @@ class DstTzInfo(BaseTzInfo): >>> normal = datetime(2009, 9, 1) - >>> tz.dst(normal) - datetime.timedelta(0, 3600) - >>> tz.dst(normal, is_dst=False) - datetime.timedelta(0, 3600) - >>> tz.dst(normal, is_dst=True) - datetime.timedelta(0, 3600) + >>> str(tz.dst(normal)) + '1:00:00' + >>> str(tz.dst(normal, is_dst=False)) + '1:00:00' + >>> str(tz.dst(normal, is_dst=True)) + '1:00:00' >>> ambiguous = datetime(2009, 10, 31, 23, 30) - >>> tz.dst(ambiguous, is_dst=False) - datetime.timedelta(0) - >>> tz.dst(ambiguous, is_dst=True) - datetime.timedelta(0, 3600) + >>> str(tz.dst(ambiguous, is_dst=False)) + '0:00:00' + >>> str(tz.dst(ambiguous, is_dst=True)) + '1:00:00' >>> try: ... tz.dst(ambiguous) ... except AmbiguousTimeError: diff --git a/lib/pytz/zoneinfo/Africa/Bissau b/lib/pytz/zoneinfo/Africa/Bissau index 4e6fbe10367ca149b5e532e7c63489ae26bfd6cf..8e32be3e6e843379e69000273552ab8588c5ca34 100644 Binary files a/lib/pytz/zoneinfo/Africa/Bissau and b/lib/pytz/zoneinfo/Africa/Bissau differ diff --git a/lib/pytz/zoneinfo/Africa/Sao_Tome b/lib/pytz/zoneinfo/Africa/Sao_Tome index 3c0d33b0cbbc84b25dc00df433264a940fb01235..a4ece7ff2b7aba7f8e99fb8ee4ddbe1d439056cf 100644 Binary files a/lib/pytz/zoneinfo/Africa/Sao_Tome and b/lib/pytz/zoneinfo/Africa/Sao_Tome differ diff --git a/lib/pytz/zoneinfo/America/Grand_Turk b/lib/pytz/zoneinfo/America/Grand_Turk index a9740dae6876987c641a1f061b048288f7a577b0..4c8ca6f7fe8e432b6d0a2f511d7993546f3a5c68 100644 Binary files a/lib/pytz/zoneinfo/America/Grand_Turk and b/lib/pytz/zoneinfo/America/Grand_Turk differ diff --git a/lib/pytz/zoneinfo/America/Jamaica b/lib/pytz/zoneinfo/America/Jamaica index 006689bc895854db5deb33a29ff5d99c6c205fc6..7aedd262a57f096cda47a8542b3b66633561641d 100644 Binary files a/lib/pytz/zoneinfo/America/Jamaica and b/lib/pytz/zoneinfo/America/Jamaica differ diff --git a/lib/pytz/zoneinfo/America/Montevideo b/lib/pytz/zoneinfo/America/Montevideo index 9c6abeb93c2c25ade68add3f9626506739908ada..f524fd219e753111d18e26ea890a8ea16b5e0566 100644 Binary files a/lib/pytz/zoneinfo/America/Montevideo and b/lib/pytz/zoneinfo/America/Montevideo differ diff --git a/lib/pytz/zoneinfo/Antarctica/Casey b/lib/pytz/zoneinfo/Antarctica/Casey index 676f06da4a89848a21cfc9dbfd4ea7a40cc4c22a..d0bbacc8a9647d6d31b36a561c6b5922c71d505c 100644 Binary files a/lib/pytz/zoneinfo/Antarctica/Casey and b/lib/pytz/zoneinfo/Antarctica/Casey differ diff --git a/lib/pytz/zoneinfo/Asia/Gaza b/lib/pytz/zoneinfo/Asia/Gaza index 1818affb54a514d740b3636bd96f9f9dc9f25df0..60d0de00ad21c8a7260046dc49fdfa9e040838f1 100644 Binary files a/lib/pytz/zoneinfo/Asia/Gaza and b/lib/pytz/zoneinfo/Asia/Gaza differ diff --git a/lib/pytz/zoneinfo/Asia/Hebron b/lib/pytz/zoneinfo/Asia/Hebron index 286a9351372a529574f14f1299f9672123fa74b2..a2e1b364f9b50814468b5bf76290bfeec2bac37c 100644 Binary files a/lib/pytz/zoneinfo/Asia/Hebron and b/lib/pytz/zoneinfo/Asia/Hebron differ diff --git a/lib/pytz/zoneinfo/Asia/Macao b/lib/pytz/zoneinfo/Asia/Macao index 46c1bad540095a7bbcfb42ee62324242a8128162..2c20a32651d9da10d1d6f63495c3cf1fd55c7f16 100644 Binary files a/lib/pytz/zoneinfo/Asia/Macao and b/lib/pytz/zoneinfo/Asia/Macao differ diff --git a/lib/pytz/zoneinfo/Asia/Macau b/lib/pytz/zoneinfo/Asia/Macau index 46c1bad540095a7bbcfb42ee62324242a8128162..2c20a32651d9da10d1d6f63495c3cf1fd55c7f16 100644 Binary files a/lib/pytz/zoneinfo/Asia/Macau and b/lib/pytz/zoneinfo/Asia/Macau differ diff --git a/lib/pytz/zoneinfo/Atlantic/Azores b/lib/pytz/zoneinfo/Atlantic/Azores index 37218e127e4bc6dc6993c525023ae8b5c4d25105..1895e1b1e19120123e67367e55de3f2a5dac99cb 100644 Binary files a/lib/pytz/zoneinfo/Atlantic/Azores and b/lib/pytz/zoneinfo/Atlantic/Azores differ diff --git a/lib/pytz/zoneinfo/Atlantic/Cape_Verde b/lib/pytz/zoneinfo/Atlantic/Cape_Verde index 1c012da59793fc7ab7cddd643d6010d473c62cbb..6bda6db7604c316edf78226eed2f785ee5f8aecd 100644 Binary files a/lib/pytz/zoneinfo/Atlantic/Cape_Verde and b/lib/pytz/zoneinfo/Atlantic/Cape_Verde differ diff --git a/lib/pytz/zoneinfo/Atlantic/Madeira b/lib/pytz/zoneinfo/Atlantic/Madeira index 9c60071e4964de7b32d7d095b075d253e1fe5c3f..e25f8a599622cb45cd2afd7bf739e4d1ed5ed589 100644 Binary files a/lib/pytz/zoneinfo/Atlantic/Madeira and b/lib/pytz/zoneinfo/Atlantic/Madeira differ diff --git a/lib/pytz/zoneinfo/Europe/Lisbon b/lib/pytz/zoneinfo/Europe/Lisbon index b9aff3a51cae6888cbd0dce88d4f2d1ace1e88ae..a85653044e0094363ea0f30d017a20ccdce2227d 100644 Binary files a/lib/pytz/zoneinfo/Europe/Lisbon and b/lib/pytz/zoneinfo/Europe/Lisbon differ diff --git a/lib/pytz/zoneinfo/Jamaica b/lib/pytz/zoneinfo/Jamaica index 006689bc895854db5deb33a29ff5d99c6c205fc6..7aedd262a57f096cda47a8542b3b66633561641d 100644 Binary files a/lib/pytz/zoneinfo/Jamaica and b/lib/pytz/zoneinfo/Jamaica differ diff --git a/lib/pytz/zoneinfo/Pacific/Enderbury b/lib/pytz/zoneinfo/Pacific/Enderbury index b729b256a18079893515880d52c4f06e0acc175f..a3f30e5c7b9166d408a0851bfac437293c72b0cf 100644 Binary files a/lib/pytz/zoneinfo/Pacific/Enderbury and b/lib/pytz/zoneinfo/Pacific/Enderbury differ diff --git a/lib/pytz/zoneinfo/Pacific/Kiritimati b/lib/pytz/zoneinfo/Pacific/Kiritimati index 94384558c70125ad7d1ed0c47e5fef6d86cfa832..762275d3c1d28a472dda088be5b602336e38e84d 100644 Binary files a/lib/pytz/zoneinfo/Pacific/Kiritimati and b/lib/pytz/zoneinfo/Pacific/Kiritimati differ diff --git a/lib/pytz/zoneinfo/Portugal b/lib/pytz/zoneinfo/Portugal index b9aff3a51cae6888cbd0dce88d4f2d1ace1e88ae..a85653044e0094363ea0f30d017a20ccdce2227d 100644 Binary files a/lib/pytz/zoneinfo/Portugal and b/lib/pytz/zoneinfo/Portugal differ diff --git a/lib/pytz/zoneinfo/tzdata.zi b/lib/pytz/zoneinfo/tzdata.zi index 0b938fce9f0050e5d7ab7f816bb9507cd022813a..0841ab7e53d892ce2b5c2bfd81f31a4293958e1f 100644 --- a/lib/pytz/zoneinfo/tzdata.zi +++ b/lib/pytz/zoneinfo/tzdata.zi @@ -32,7 +32,7 @@ Z Africa/Algiers 0:12:12 - LMT 1891 Mar 15 0:1 1 A CE%sT 1979 O 26 0 A WE%sT 1981 May 1 - CET -Z Atlantic/Cape_Verde -1:34:4 - LMT 1907 +Z Atlantic/Cape_Verde -1:34:4 - LMT 1912 Ja 1 2u -2 - -02 1942 S -2 1 -01 1945 O 15 -2 - -02 1975 N 25 2 @@ -86,11 +86,11 @@ R B 2014 o - Jul 31 24 1 S R B 2014 o - S lastTh 24 0 - Z Africa/Cairo 2:5:9 - LMT 1900 O 2 B EE%sT -R C 1920 1942 - S 1 0 0:20 GHST -R C 1920 1942 - D 31 0 0 GMT +R C 1920 1942 - S 1 0 0:20 - +R C 1920 1942 - D 31 0 0 - Z Africa/Accra -0:0:52 - LMT 1918 0 C GMT/+0020 -Z Africa/Bissau -1:2:20 - LMT 1912 +Z Africa/Bissau -1:2:20 - LMT 1912 Ja 1 1u -1 - -01 1975 0 - GMT Z Africa/Nairobi 2:27:16 - LMT 1928 Jul @@ -137,9 +137,9 @@ Z Africa/Tripoli 0:52:44 - LMT 1920 2 - EET 2012 N 10 2 1 D CE%sT 2013 O 25 2 2 - EET -R E 1982 o - O 10 0 1 S +R E 1982 o - O 10 0 1 - R E 1983 o - Mar 21 0 0 - -R E 2008 o - O lastSun 2 1 S +R E 2008 o - O lastSun 2 1 - R E 2009 o - Mar lastSun 2 0 - Z Indian/Mauritius 3:50 - LMT 1907 4 E +04/+05 @@ -238,7 +238,7 @@ Li Africa/Lagos Africa/Porto-Novo Z Indian/Reunion 3:41:52 - LMT 1911 Jun 4 - +04 Z Africa/Sao_Tome 0:26:56 - LMT 1884 --0:36:45 - LMT 1912 +-0:36:45 - LMT 1912 Ja 1 0u 0 - GMT 2018 Ja 1 1 1 - WAT Z Indian/Mahe 3:41:48 - LMT 1906 Jun @@ -295,7 +295,8 @@ Z Antarctica/Casey 0 - -00 1969 8 - +08 2011 O 28 2 11 - +11 2012 F 21 17u 8 - +08 2016 O 22 -11 - +11 +11 - +11 2018 Mar 11 4 +8 - +08 Z Antarctica/Davis 0 - -00 1957 Ja 13 7 - +07 1964 N 0 - -00 1969 F @@ -326,7 +327,7 @@ Z Antarctica/Rothera 0 - -00 1976 D Z Asia/Kabul 4:36:48 - LMT 1890 4 - +04 1945 4:30 - +0430 -R L 2011 o - Mar lastSun 2s 1 S +R L 2011 o - Mar lastSun 2s 1 - R L 2011 o - O lastSun 2s 0 - Z Asia/Yerevan 2:58 - LMT 1924 May 2 3 - +03 1957 Mar @@ -335,7 +336,7 @@ Z Asia/Yerevan 2:58 - LMT 1924 May 2 4 - +04 1997 4 M +04/+05 2011 4 L +04/+05 -R N 1997 2015 - Mar lastSun 4 1 S +R N 1997 2015 - Mar lastSun 4 1 - R N 1997 2015 - O lastSun 5 0 - Z Asia/Baku 3:19:24 - LMT 1924 May 2 3 - +03 1957 Mar @@ -344,7 +345,7 @@ Z Asia/Baku 3:19:24 - LMT 1924 May 2 4 - +04 1996 4 O +04/+05 1997 4 N +04/+05 -R P 2009 o - Jun 19 23 1 S +R P 2009 o - Jun 19 23 1 - R P 2009 o - D 31 24 0 - Z Asia/Dhaka 6:1:40 - LMT 1890 5:53:20 - HMT 1941 O @@ -434,7 +435,7 @@ R U 1974 1977 - O Sun>=15 3:30 0 S R U 1975 1977 - Ap Sun>=15 3:30 1 D R U 1978 1980 - Ap Sun>=15 0 1 D R U 1978 1980 - O Sun>=15 0 0 S -Z Asia/Macau 7:34:20 - LMT 1912 +Z Asia/Macau 7:34:20 - LMT 1911 D 31 16u 8 U C%sT R V 1975 o - Ap 13 0 1 S R V 1975 o - O 12 0 0 - @@ -505,68 +506,68 @@ Z Asia/Jayapura 9:22:48 - LMT 1932 N 9 - +09 1944 S 9:30 - +0930 1964 9 - WIT -R X 1978 1980 - Mar 21 0 1 D -R X 1978 o - O 21 0 0 S -R X 1979 o - S 19 0 0 S -R X 1980 o - S 23 0 0 S -R X 1991 o - May 3 0 1 D -R X 1992 1995 - Mar 22 0 1 D -R X 1991 1995 - S 22 0 0 S -R X 1996 o - Mar 21 0 1 D -R X 1996 o - S 21 0 0 S -R X 1997 1999 - Mar 22 0 1 D -R X 1997 1999 - S 22 0 0 S -R X 2000 o - Mar 21 0 1 D -R X 2000 o - S 21 0 0 S -R X 2001 2003 - Mar 22 0 1 D -R X 2001 2003 - S 22 0 0 S -R X 2004 o - Mar 21 0 1 D -R X 2004 o - S 21 0 0 S -R X 2005 o - Mar 22 0 1 D -R X 2005 o - S 22 0 0 S -R X 2008 o - Mar 21 0 1 D -R X 2008 o - S 21 0 0 S -R X 2009 2011 - Mar 22 0 1 D -R X 2009 2011 - S 22 0 0 S -R X 2012 o - Mar 21 0 1 D -R X 2012 o - S 21 0 0 S -R X 2013 2015 - Mar 22 0 1 D -R X 2013 2015 - S 22 0 0 S -R X 2016 o - Mar 21 0 1 D -R X 2016 o - S 21 0 0 S -R X 2017 2019 - Mar 22 0 1 D -R X 2017 2019 - S 22 0 0 S -R X 2020 o - Mar 21 0 1 D -R X 2020 o - S 21 0 0 S -R X 2021 2023 - Mar 22 0 1 D -R X 2021 2023 - S 22 0 0 S -R X 2024 o - Mar 21 0 1 D -R X 2024 o - S 21 0 0 S -R X 2025 2027 - Mar 22 0 1 D -R X 2025 2027 - S 22 0 0 S -R X 2028 2029 - Mar 21 0 1 D -R X 2028 2029 - S 21 0 0 S -R X 2030 2031 - Mar 22 0 1 D -R X 2030 2031 - S 22 0 0 S -R X 2032 2033 - Mar 21 0 1 D -R X 2032 2033 - S 21 0 0 S -R X 2034 2035 - Mar 22 0 1 D -R X 2034 2035 - S 22 0 0 S -R X 2036 ma - Mar 21 0 1 D -R X 2036 ma - S 21 0 0 S +R X 1978 1980 - Mar 21 0 1 - +R X 1978 o - O 21 0 0 - +R X 1979 o - S 19 0 0 - +R X 1980 o - S 23 0 0 - +R X 1991 o - May 3 0 1 - +R X 1992 1995 - Mar 22 0 1 - +R X 1991 1995 - S 22 0 0 - +R X 1996 o - Mar 21 0 1 - +R X 1996 o - S 21 0 0 - +R X 1997 1999 - Mar 22 0 1 - +R X 1997 1999 - S 22 0 0 - +R X 2000 o - Mar 21 0 1 - +R X 2000 o - S 21 0 0 - +R X 2001 2003 - Mar 22 0 1 - +R X 2001 2003 - S 22 0 0 - +R X 2004 o - Mar 21 0 1 - +R X 2004 o - S 21 0 0 - +R X 2005 o - Mar 22 0 1 - +R X 2005 o - S 22 0 0 - +R X 2008 o - Mar 21 0 1 - +R X 2008 o - S 21 0 0 - +R X 2009 2011 - Mar 22 0 1 - +R X 2009 2011 - S 22 0 0 - +R X 2012 o - Mar 21 0 1 - +R X 2012 o - S 21 0 0 - +R X 2013 2015 - Mar 22 0 1 - +R X 2013 2015 - S 22 0 0 - +R X 2016 o - Mar 21 0 1 - +R X 2016 o - S 21 0 0 - +R X 2017 2019 - Mar 22 0 1 - +R X 2017 2019 - S 22 0 0 - +R X 2020 o - Mar 21 0 1 - +R X 2020 o - S 21 0 0 - +R X 2021 2023 - Mar 22 0 1 - +R X 2021 2023 - S 22 0 0 - +R X 2024 o - Mar 21 0 1 - +R X 2024 o - S 21 0 0 - +R X 2025 2027 - Mar 22 0 1 - +R X 2025 2027 - S 22 0 0 - +R X 2028 2029 - Mar 21 0 1 - +R X 2028 2029 - S 21 0 0 - +R X 2030 2031 - Mar 22 0 1 - +R X 2030 2031 - S 22 0 0 - +R X 2032 2033 - Mar 21 0 1 - +R X 2032 2033 - S 21 0 0 - +R X 2034 2035 - Mar 22 0 1 - +R X 2034 2035 - S 22 0 0 - +R X 2036 ma - Mar 21 0 1 - +R X 2036 ma - S 21 0 0 - Z Asia/Tehran 3:25:44 - LMT 1916 3:25:44 - TMT 1946 3:30 - +0330 1977 N 4 X +04/+05 1979 3:30 X +0330/+0430 -R Y 1982 o - May 1 0 1 D -R Y 1982 1984 - O 1 0 0 S -R Y 1983 o - Mar 31 0 1 D -R Y 1984 1985 - Ap 1 0 1 D -R Y 1985 1990 - S lastSun 1s 0 S -R Y 1986 1990 - Mar lastSun 1s 1 D -R Y 1991 2007 - Ap 1 3s 1 D -R Y 1991 2007 - O 1 3s 0 S +R Y 1982 o - May 1 0 1 - +R Y 1982 1984 - O 1 0 0 - +R Y 1983 o - Mar 31 0 1 - +R Y 1984 1985 - Ap 1 0 1 - +R Y 1985 1990 - S lastSun 1s 0 - +R Y 1986 1990 - Mar lastSun 1s 1 - +R Y 1991 2007 - Ap 1 3s 1 - +R Y 1991 2007 - O 1 3s 0 - Z Asia/Baghdad 2:57:40 - LMT 1890 2:57:36 - BMT 1918 3 - +03 1982 May @@ -753,9 +754,9 @@ Z Asia/Oral 3:25:24 - LMT 1924 May 2 5 M +05/+06 1992 Mar 29 2s 4 M +04/+05 2004 O 31 2s 5 - +05 -R c 1992 1996 - Ap Sun>=7 0s 1 S +R c 1992 1996 - Ap Sun>=7 0s 1 - R c 1992 1996 - S lastSun 0 0 - -R c 1997 2005 - Mar lastSun 2:30 1 S +R c 1997 2005 - Mar lastSun 2:30 1 - R c 1997 2004 - O lastSun 2:30 0 - Z Asia/Bishkek 4:58:24 - LMT 1924 May 2 5 - +05 1930 Jun 21 @@ -814,7 +815,7 @@ R e 1993 1998 - S lastSun 0 0 - R e 1999 ma - O lastSun 0 0 - Z Asia/Beirut 2:22 - LMT 1880 2 e EE%sT -R f 1935 1941 - S 14 0 0:20 TS +R f 1935 1941 - S 14 0 0:20 - R f 1935 1941 - D 14 0 0 - Z Asia/Kuala_Lumpur 6:46:46 - LMT 1901 6:55:25 - SMT 1905 Jun @@ -833,14 +834,14 @@ Z Asia/Kuching 7:21:20 - LMT 1926 Mar Z Indian/Maldives 4:54 - LMT 1880 4:54 - MMT 1960 5 - +05 -R g 1983 1984 - Ap 1 0 1 S +R g 1983 1984 - Ap 1 0 1 - R g 1983 o - O 1 0 0 - -R g 1985 1998 - Mar lastSun 0 1 S +R g 1985 1998 - Mar lastSun 0 1 - R g 1984 1998 - S lastSun 0 0 - -R g 2001 o - Ap lastSat 2 1 S +R g 2001 o - Ap lastSat 2 1 - R g 2001 2006 - S lastSat 2 0 - -R g 2002 2006 - Mar lastSat 2 1 S -R g 2015 2016 - Mar lastSat 2 1 S +R g 2002 2006 - Mar lastSat 2 1 - +R g 2015 2016 - Mar lastSat 2 1 - R g 2015 2016 - S lastSat 0 0 - Z Asia/Hovd 6:6:36 - LMT 1905 Au 6 - +06 1978 @@ -888,7 +889,7 @@ R i 2012 o - S 21 1 0 - R i 2013 o - S F>=21 0 0 - R i 2014 2015 - O F>=21 0 0 - R i 2015 o - Mar lastF 24 1 S -R i 2016 ma - Mar lastSat 1 1 S +R i 2016 ma - Mar Sat>=22 1 1 S R i 2016 ma - O lastSat 1 0 - Z Asia/Gaza 2:17:52 - LMT 1900 O 2 Z EET/EEST 1948 May 15 @@ -908,11 +909,11 @@ Z Asia/Hebron 2:20:23 - LMT 1900 O 2 Z I%sT 1996 2 b EE%sT 1999 2 i EE%sT -R j 1936 o - N 1 0 1 S +R j 1936 o - N 1 0 1 - R j 1937 o - F 1 0 0 - -R j 1954 o - Ap 12 0 1 S +R j 1954 o - Ap 12 0 1 - R j 1954 o - Jul 1 0 0 - -R j 1978 o - Mar 22 0 1 S +R j 1978 o - Mar 22 0 1 - R j 1978 o - S 21 0 0 - Z Asia/Manila -15:56 - LMT 1844 D 31 8:4 - LMT 1899 May 11 @@ -1156,20 +1157,20 @@ Z Australia/Broken_Hill 9:25:48 - LMT 1895 F 9:30 l AC%sT 1971 9:30 s AC%sT 2000 9:30 p AC%sT -R t 1981 1984 - O lastSun 2 1 D -R t 1982 1985 - Mar Sun>=1 2 0 S -R t 1985 o - O lastSun 2 0:30 D -R t 1986 1989 - Mar Sun>=15 2 0 S -R t 1986 o - O 19 2 0:30 D -R t 1987 1999 - O lastSun 2 0:30 D -R t 1990 1995 - Mar Sun>=1 2 0 S -R t 1996 2005 - Mar lastSun 2 0 S -R t 2000 o - Au lastSun 2 0:30 D -R t 2001 2007 - O lastSun 2 0:30 D -R t 2006 o - Ap Sun>=1 2 0 S -R t 2007 o - Mar lastSun 2 0 S -R t 2008 ma - Ap Sun>=1 2 0 S -R t 2008 ma - O Sun>=1 2 0:30 D +R t 1981 1984 - O lastSun 2 1 - +R t 1982 1985 - Mar Sun>=1 2 0 - +R t 1985 o - O lastSun 2 0:30 - +R t 1986 1989 - Mar Sun>=15 2 0 - +R t 1986 o - O 19 2 0:30 - +R t 1987 1999 - O lastSun 2 0:30 - +R t 1990 1995 - Mar Sun>=1 2 0 - +R t 1996 2005 - Mar lastSun 2 0 - +R t 2000 o - Au lastSun 2 0:30 - +R t 2001 2007 - O lastSun 2 0:30 - +R t 2006 o - Ap Sun>=1 2 0 - +R t 2007 o - Mar lastSun 2 0 - +R t 2008 ma - Ap Sun>=1 2 0 - +R t 2008 ma - O Sun>=1 2 0:30 - Z Australia/Lord_Howe 10:36:20 - LMT 1895 F 10 - AEST 1981 Mar 10:30 t +1030/+1130 1985 Jul @@ -1186,15 +1187,15 @@ Z Indian/Christmas 7:2:52 - LMT 1895 F 7 - +07 Z Indian/Cocos 6:27:40 - LMT 1900 6:30 - +0630 -R u 1998 1999 - N Sun>=1 2 1 S +R u 1998 1999 - N Sun>=1 2 1 - R u 1999 2000 - F lastSun 3 0 - -R u 2009 o - N 29 2 1 S +R u 2009 o - N 29 2 1 - R u 2010 o - Mar lastSun 3 0 - -R u 2010 2013 - O Sun>=21 2 1 S +R u 2010 2013 - O Sun>=21 2 1 - R u 2011 o - Mar Sun>=1 3 0 - R u 2012 2013 - Ja Sun>=18 3 0 - R u 2014 o - Ja Sun>=18 2 0 - -R u 2014 ma - N Sun>=1 2 1 S +R u 2014 ma - N Sun>=1 2 1 - R u 2015 ma - Ja Sun>=14 3 0 - Z Pacific/Fiji 11:55:44 - LMT 1915 O 26 12 u +12/+13 @@ -1213,11 +1214,11 @@ Z Pacific/Tarawa 11:32:4 - LMT 1901 12 - +12 Z Pacific/Enderbury -11:24:20 - LMT 1901 -12 - -12 1979 O --11 - -11 1995 +-11 - -11 1994 D 31 13 - +13 Z Pacific/Kiritimati -10:29:20 - LMT 1901 -10:40 - -1040 1979 O --10 - -10 1995 +-10 - -10 1994 D 31 14 - +14 Z Pacific/Majuro 11:24:48 - LMT 1901 11 - +11 1969 O @@ -1239,9 +1240,9 @@ Z Pacific/Nauru 11:7:40 - LMT 1921 Ja 15 9 - +09 1944 Au 15 11:30 - +1130 1979 May 12 - +12 -R v 1977 1978 - D Sun>=1 0 1 S +R v 1977 1978 - D Sun>=1 0 1 - R v 1978 1979 - F 27 0 0 - -R v 1996 o - D 1 2s 1 S +R v 1996 o - D 1 2s 1 - R v 1997 o - Mar 2 2s 0 - Z Pacific/Noumea 11:5:48 - LMT 1912 Ja 13 11 v +11/+12 @@ -1253,23 +1254,23 @@ R w 1934 1940 - Ap lastSun 2 0 M R w 1934 1940 - S lastSun 2 0:30 S R w 1946 o - Ja 1 0 0 S R w 1974 o - N Sun>=1 2s 1 D -R x 1974 o - N Sun>=1 2:45s 1 D +R x 1974 o - N Sun>=1 2:45s 1 - R w 1975 o - F lastSun 2s 0 S -R x 1975 o - F lastSun 2:45s 0 S +R x 1975 o - F lastSun 2:45s 0 - R w 1975 1988 - O lastSun 2s 1 D -R x 1975 1988 - O lastSun 2:45s 1 D +R x 1975 1988 - O lastSun 2:45s 1 - R w 1976 1989 - Mar Sun>=1 2s 0 S -R x 1976 1989 - Mar Sun>=1 2:45s 0 S +R x 1976 1989 - Mar Sun>=1 2:45s 0 - R w 1989 o - O Sun>=8 2s 1 D -R x 1989 o - O Sun>=8 2:45s 1 D +R x 1989 o - O Sun>=8 2:45s 1 - R w 1990 2006 - O Sun>=1 2s 1 D -R x 1990 2006 - O Sun>=1 2:45s 1 D +R x 1990 2006 - O Sun>=1 2:45s 1 - R w 1990 2007 - Mar Sun>=15 2s 0 S -R x 1990 2007 - Mar Sun>=15 2:45s 0 S +R x 1990 2007 - Mar Sun>=15 2:45s 0 - R w 2007 ma - S lastSun 2s 1 D -R x 2007 ma - S lastSun 2:45s 1 D +R x 2007 ma - S lastSun 2:45s 1 - R w 2008 ma - Ap Sun>=1 2s 0 S -R x 2008 ma - Ap Sun>=1 2:45s 0 S +R x 2008 ma - Ap Sun>=1 2:45s 0 - Z Pacific/Auckland 11:39:4 - LMT 1868 N 2 11:30 w NZ%sT 1946 12 w NZ%sT @@ -1277,9 +1278,9 @@ Z Pacific/Chatham 12:13:48 - LMT 1868 N 2 12:15 - +1215 1946 12:45 x +1245/+1345 Li Pacific/Auckland Antarctica/McMurdo -R y 1978 o - N 12 0 0:30 HS +R y 1978 o - N 12 0 0:30 - R y 1979 1991 - Mar Sun>=1 0 0 - -R y 1979 1990 - O lastSun 0 0:30 HS +R y 1979 1990 - O lastSun 0 0:30 - Z Pacific/Rarotonga -10:39:4 - LMT 1901 -10:30 - -1030 1978 N 12 -10 y -10/-0930 @@ -1311,11 +1312,11 @@ Z Pacific/Pago_Pago 12:37:12 - LMT 1892 Jul 5 -11:22:48 - LMT 1911 -11 - SST Li Pacific/Pago_Pago Pacific/Midway -R z 2010 o - S lastSun 0 1 D -R z 2011 o - Ap Sat>=1 4 0 S -R z 2011 o - S lastSat 3 1 D -R z 2012 ma - Ap Sun>=1 4 0 S -R z 2012 ma - S lastSun 3 1 D +R z 2010 o - S lastSun 0 1 - +R z 2011 o - Ap Sat>=1 4 0 - +R z 2011 o - S lastSat 3 1 - +R z 2012 ma - Ap Sun>=1 4 0 - +R z 2012 ma - S lastSun 3 1 - Z Pacific/Apia 12:33:4 - LMT 1892 Jul 5 -11:26:56 - LMT 1911 -11:30 - -1130 1950 @@ -1326,11 +1327,11 @@ Z Pacific/Guadalcanal 10:39:48 - LMT 1912 O Z Pacific/Fakaofo -11:24:56 - LMT 1901 -11 - -11 2011 D 30 13 - +13 -R ! 1999 o - O 7 2s 1 S +R ! 1999 o - O 7 2s 1 - R ! 2000 o - Mar 19 2s 0 - -R ! 2000 2001 - N Sun>=1 2 1 S +R ! 2000 2001 - N Sun>=1 2 1 - R ! 2001 2002 - Ja lastSun 2 0 - -R ! 2016 o - N Sun>=1 2 1 S +R ! 2016 o - N Sun>=1 2 1 - R ! 2017 o - Ja Sun>=15 3 0 - Z Pacific/Tongatapu 12:19:20 - LMT 1901 12:20 - +1220 1941 @@ -1340,12 +1341,12 @@ Z Pacific/Funafuti 11:56:52 - LMT 1901 12 - +12 Z Pacific/Wake 11:6:28 - LMT 1901 12 - +12 -R $ 1983 o - S 25 0 1 S +R $ 1983 o - S 25 0 1 - R $ 1984 1991 - Mar Sun>=23 0 0 - -R $ 1984 o - O 23 0 1 S -R $ 1985 1991 - S Sun>=23 0 1 S +R $ 1984 o - O 23 0 1 - +R $ 1985 1991 - S Sun>=23 0 1 - R $ 1992 1993 - Ja Sun>=23 0 0 - -R $ 1992 o - O Sun>=23 0 1 S +R $ 1992 o - O Sun>=23 0 1 - Z Pacific/Efate 11:13:16 - LMT 1912 Ja 13 11 $ +11/+12 Z Pacific/Wallis 12:15:20 - LMT 1901 @@ -1799,19 +1800,19 @@ Z Europe/Budapest 1:16:20 - LMT 1890 O 1 ' CE%sT 1945 1 ? CE%sT 1980 S 28 2s 1 O CE%sT -R @ 1917 1919 - F 19 23 1 S +R @ 1917 1919 - F 19 23 1 - R @ 1917 o - O 21 1 0 - R @ 1918 1919 - N 16 1 0 - -R @ 1921 o - Mar 19 23 1 S +R @ 1921 o - Mar 19 23 1 - R @ 1921 o - Jun 23 1 0 - -R @ 1939 o - Ap 29 23 1 S +R @ 1939 o - Ap 29 23 1 - R @ 1939 o - O 29 2 0 - -R @ 1940 o - F 25 2 1 S +R @ 1940 o - F 25 2 1 - R @ 1940 1941 - N Sun>=2 1s 0 - -R @ 1941 1942 - Mar Sun>=2 1s 1 S -R @ 1943 1946 - Mar Sun>=1 1s 1 S +R @ 1941 1942 - Mar Sun>=2 1s 1 - +R @ 1943 1946 - Mar Sun>=1 1s 1 - R @ 1942 1948 - O Sun>=22 1s 0 - -R @ 1947 1967 - Ap Sun>=1 1s 1 S +R @ 1947 1967 - Ap Sun>=1 1s 1 - R @ 1949 o - O 30 1s 0 - R @ 1950 1966 - O Sun>=22 1s 0 - R @ 1967 o - O 29 1s 0 - @@ -2077,7 +2078,7 @@ R ~ 1980 o - Mar lastSun 0s 1 S R ~ 1981 1982 - Mar lastSun 1s 1 S R ~ 1983 o - Mar lastSun 2s 1 S Z Europe/Lisbon -0:36:45 - LMT 1884 --0:36:45 - LMT 1912 +-0:36:45 - LMT 1912 Ja 1 0u 0 ~ WE%sT 1966 Ap 3 2 1 - CET 1976 S 26 1 0 ~ WE%sT 1983 S 25 1s @@ -2085,7 +2086,7 @@ Z Europe/Lisbon -0:36:45 - LMT 1884 1 O CE%sT 1996 Mar 31 1u 0 O WE%sT Z Atlantic/Azores -1:42:40 - LMT 1884 --1:54:32 - HMT 1912 +-1:54:32 - HMT 1912 Ja 1 2u -2 ~ -02/-01 1942 Ap 25 22s -2 ~ +00 1942 Au 15 22s -2 ~ -02/-01 1943 Ap 17 22s @@ -2100,7 +2101,7 @@ Z Atlantic/Azores -1:42:40 - LMT 1884 0 O WE%sT 1993 Mar 28 1u -1 O -01/+00 Z Atlantic/Madeira -1:7:36 - LMT 1884 --1:7:36 - FMT 1912 +-1:7:36 - FMT 1912 Ja 1 1u -1 ~ -01/+00 1942 Ap 25 22s -1 ~ +01 1942 Au 15 22s -1 ~ -01/+00 1943 Ap 17 22s @@ -3395,8 +3396,8 @@ R Ao 2006 o - May Sun>=1 0 1 D R Ao 2006 o - Au M>=1 0 0 S Z America/Tegucigalpa -5:48:52 - LMT 1921 Ap -6 Ao C%sT -Z America/Jamaica -5:7:11 - LMT 1890 --5:7:11 - KMT 1912 F +Z America/Jamaica -5:7:10 - LMT 1890 +-5:7:10 - KMT 1912 F -5 - EST 1974 -5 AE E%sT 1984 -5 - EST @@ -3433,40 +3434,40 @@ Z America/Miquelon -3:44:40 - LMT 1911 May 15 -3 - -03 1987 -3 AT -03/-02 Z America/Grand_Turk -4:44:32 - LMT 1890 --5:7:11 - KMT 1912 F +-5:7:10 - KMT 1912 F -5 - EST 1979 -5 AE E%sT 2015 N Sun>=1 2 -4 - AST 2018 Mar 11 3 -5 AE E%sT -R Aq 1930 o - D 1 0 1 S +R Aq 1930 o - D 1 0 1 - R Aq 1931 o - Ap 1 0 0 - -R Aq 1931 o - O 15 0 1 S +R Aq 1931 o - O 15 0 1 - R Aq 1932 1940 - Mar 1 0 0 - -R Aq 1932 1939 - N 1 0 1 S -R Aq 1940 o - Jul 1 0 1 S +R Aq 1932 1939 - N 1 0 1 - +R Aq 1940 o - Jul 1 0 1 - R Aq 1941 o - Jun 15 0 0 - -R Aq 1941 o - O 15 0 1 S +R Aq 1941 o - O 15 0 1 - R Aq 1943 o - Au 1 0 0 - -R Aq 1943 o - O 15 0 1 S +R Aq 1943 o - O 15 0 1 - R Aq 1946 o - Mar 1 0 0 - -R Aq 1946 o - O 1 0 1 S +R Aq 1946 o - O 1 0 1 - R Aq 1963 o - O 1 0 0 - -R Aq 1963 o - D 15 0 1 S +R Aq 1963 o - D 15 0 1 - R Aq 1964 1966 - Mar 1 0 0 - -R Aq 1964 1966 - O 15 0 1 S +R Aq 1964 1966 - O 15 0 1 - R Aq 1967 o - Ap 2 0 0 - -R Aq 1967 1968 - O Sun>=1 0 1 S +R Aq 1967 1968 - O Sun>=1 0 1 - R Aq 1968 1969 - Ap Sun>=1 0 0 - -R Aq 1974 o - Ja 23 0 1 S +R Aq 1974 o - Ja 23 0 1 - R Aq 1974 o - May 1 0 0 - -R Aq 1988 o - D 1 0 1 S +R Aq 1988 o - D 1 0 1 - R Aq 1989 1993 - Mar Sun>=1 0 0 - -R Aq 1989 1992 - O Sun>=15 0 1 S -R Aq 1999 o - O Sun>=1 0 1 S +R Aq 1989 1992 - O Sun>=15 0 1 - +R Aq 1999 o - O Sun>=1 0 1 - R Aq 2000 o - Mar 3 0 0 - -R Aq 2007 o - D 30 0 1 S +R Aq 2007 o - D 30 0 1 - R Aq 2008 2009 - Mar Sun>=15 0 0 - -R Aq 2008 o - O Sun>=15 0 1 S +R Aq 2008 o - O Sun>=15 0 1 - Z America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 O 31 -4:16:48 - CMT 1920 May -4 - -04 1930 D @@ -3570,7 +3571,7 @@ Z America/Argentina/Mendoza -4:35:16 - LMT 1894 O 31 -3 Aq -03/-02 2008 O 18 -3 - -03 R Ar 2008 2009 - Mar Sun>=8 0 0 - -R Ar 2007 2008 - O Sun>=8 0 1 S +R Ar 2007 2008 - O Sun>=8 0 1 - Z America/Argentina/San_Luis -4:25:24 - LMT 1894 O 31 -4:16:48 - CMT 1920 May -4 - -04 1930 D @@ -3612,63 +3613,63 @@ Z America/La_Paz -4:32:36 - LMT 1890 -4:32:36 - CMT 1931 O 15 -4:32:36 1 BST 1932 Mar 21 -4 - -04 -R As 1931 o - O 3 11 1 S +R As 1931 o - O 3 11 1 - R As 1932 1933 - Ap 1 0 0 - -R As 1932 o - O 3 0 1 S -R As 1949 1952 - D 1 0 1 S +R As 1932 o - O 3 0 1 - +R As 1949 1952 - D 1 0 1 - R As 1950 o - Ap 16 1 0 - R As 1951 1952 - Ap 1 0 0 - R As 1953 o - Mar 1 0 0 - -R As 1963 o - D 9 0 1 S +R As 1963 o - D 9 0 1 - R As 1964 o - Mar 1 0 0 - -R As 1965 o - Ja 31 0 1 S +R As 1965 o - Ja 31 0 1 - R As 1965 o - Mar 31 0 0 - -R As 1965 o - D 1 0 1 S +R As 1965 o - D 1 0 1 - R As 1966 1968 - Mar 1 0 0 - -R As 1966 1967 - N 1 0 1 S -R As 1985 o - N 2 0 1 S +R As 1966 1967 - N 1 0 1 - +R As 1985 o - N 2 0 1 - R As 1986 o - Mar 15 0 0 - -R As 1986 o - O 25 0 1 S +R As 1986 o - O 25 0 1 - R As 1987 o - F 14 0 0 - -R As 1987 o - O 25 0 1 S +R As 1987 o - O 25 0 1 - R As 1988 o - F 7 0 0 - -R As 1988 o - O 16 0 1 S +R As 1988 o - O 16 0 1 - R As 1989 o - Ja 29 0 0 - -R As 1989 o - O 15 0 1 S +R As 1989 o - O 15 0 1 - R As 1990 o - F 11 0 0 - -R As 1990 o - O 21 0 1 S +R As 1990 o - O 21 0 1 - R As 1991 o - F 17 0 0 - -R As 1991 o - O 20 0 1 S +R As 1991 o - O 20 0 1 - R As 1992 o - F 9 0 0 - -R As 1992 o - O 25 0 1 S +R As 1992 o - O 25 0 1 - R As 1993 o - Ja 31 0 0 - -R As 1993 1995 - O Sun>=11 0 1 S +R As 1993 1995 - O Sun>=11 0 1 - R As 1994 1995 - F Sun>=15 0 0 - R As 1996 o - F 11 0 0 - -R As 1996 o - O 6 0 1 S +R As 1996 o - O 6 0 1 - R As 1997 o - F 16 0 0 - -R As 1997 o - O 6 0 1 S +R As 1997 o - O 6 0 1 - R As 1998 o - Mar 1 0 0 - -R As 1998 o - O 11 0 1 S +R As 1998 o - O 11 0 1 - R As 1999 o - F 21 0 0 - -R As 1999 o - O 3 0 1 S +R As 1999 o - O 3 0 1 - R As 2000 o - F 27 0 0 - -R As 2000 2001 - O Sun>=8 0 1 S +R As 2000 2001 - O Sun>=8 0 1 - R As 2001 2006 - F Sun>=15 0 0 - -R As 2002 o - N 3 0 1 S -R As 2003 o - O 19 0 1 S -R As 2004 o - N 2 0 1 S -R As 2005 o - O 16 0 1 S -R As 2006 o - N 5 0 1 S +R As 2002 o - N 3 0 1 - +R As 2003 o - O 19 0 1 - +R As 2004 o - N 2 0 1 - +R As 2005 o - O 16 0 1 - +R As 2006 o - N 5 0 1 - R As 2007 o - F 25 0 0 - -R As 2007 o - O Sun>=8 0 1 S -R As 2008 2017 - O Sun>=15 0 1 S +R As 2007 o - O Sun>=8 0 1 - +R As 2008 2017 - O Sun>=15 0 1 - R As 2008 2011 - F Sun>=15 0 0 - R As 2012 o - F Sun>=22 0 0 - R As 2013 2014 - F Sun>=15 0 0 - R As 2015 o - F Sun>=22 0 0 - R As 2016 2022 - F Sun>=15 0 0 - -R As 2018 ma - N Sun>=1 0 1 S +R As 2018 ma - N Sun>=1 0 1 - R As 2023 o - F Sun>=22 0 0 - R As 2024 2025 - F Sun>=15 0 0 - R As 2026 o - F Sun>=22 0 0 - @@ -3761,38 +3762,38 @@ Z America/Rio_Branco -4:31:12 - LMT 1914 -5 - -05 2008 Jun 24 -4 - -04 2013 N 10 -5 - -05 -R At 1927 1931 - S 1 0 1 S +R At 1927 1931 - S 1 0 1 - R At 1928 1932 - Ap 1 0 0 - -R At 1968 o - N 3 4u 1 S +R At 1968 o - N 3 4u 1 - R At 1969 o - Mar 30 3u 0 - -R At 1969 o - N 23 4u 1 S +R At 1969 o - N 23 4u 1 - R At 1970 o - Mar 29 3u 0 - R At 1971 o - Mar 14 3u 0 - -R At 1970 1972 - O Sun>=9 4u 1 S +R At 1970 1972 - O Sun>=9 4u 1 - R At 1972 1986 - Mar Sun>=9 3u 0 - -R At 1973 o - S 30 4u 1 S -R At 1974 1987 - O Sun>=9 4u 1 S +R At 1973 o - S 30 4u 1 - +R At 1974 1987 - O Sun>=9 4u 1 - R At 1987 o - Ap 12 3u 0 - R At 1988 1990 - Mar Sun>=9 3u 0 - -R At 1988 1989 - O Sun>=9 4u 1 S -R At 1990 o - S 16 4u 1 S +R At 1988 1989 - O Sun>=9 4u 1 - +R At 1990 o - S 16 4u 1 - R At 1991 1996 - Mar Sun>=9 3u 0 - -R At 1991 1997 - O Sun>=9 4u 1 S +R At 1991 1997 - O Sun>=9 4u 1 - R At 1997 o - Mar 30 3u 0 - R At 1998 o - Mar Sun>=9 3u 0 - -R At 1998 o - S 27 4u 1 S +R At 1998 o - S 27 4u 1 - R At 1999 o - Ap 4 3u 0 - -R At 1999 2010 - O Sun>=9 4u 1 S +R At 1999 2010 - O Sun>=9 4u 1 - R At 2000 2007 - Mar Sun>=9 3u 0 - R At 2008 o - Mar 30 3u 0 - R At 2009 o - Mar Sun>=9 3u 0 - R At 2010 o - Ap Sun>=1 3u 0 - R At 2011 o - May Sun>=2 3u 0 - -R At 2011 o - Au Sun>=16 4u 1 S +R At 2011 o - Au Sun>=16 4u 1 - R At 2012 2014 - Ap Sun>=23 3u 0 - -R At 2012 2014 - S Sun>=2 4u 1 S +R At 2012 2014 - S Sun>=2 4u 1 - R At 2016 ma - May Sun>=9 3u 0 - -R At 2016 ma - Au Sun>=9 4u 1 S +R At 2016 ma - Au Sun>=9 4u 1 - Z America/Santiago -4:42:46 - LMT 1890 -4:42:46 - SMT 1910 Ja 10 -5 - -05 1916 Jul @@ -3829,7 +3830,7 @@ Z Antarctica/Palmer 0 - -00 1965 -3 Aq -03/-02 1982 May -4 At -04/-03 2016 D 4 -3 - -03 -R Au 1992 o - May 3 0 1 S +R Au 1992 o - May 3 0 1 - R Au 1993 o - Ap 4 0 0 - Z America/Bogota -4:56:16 - LMT 1884 Mar 13 -4:56:16 - BMT 1914 N 23 @@ -3839,7 +3840,7 @@ Z America/Curacao -4:35:47 - LMT 1912 F 12 -4 - AST Li America/Curacao America/Lower_Princes Li America/Curacao America/Kralendijk -R Av 1992 o - N 28 0 1 S +R Av 1992 o - N 28 0 1 - R Av 1993 o - F 5 0 0 - Z America/Guayaquil -5:19:20 - LMT 1890 -5:14 - QMT 1931 @@ -3847,18 +3848,18 @@ Z America/Guayaquil -5:19:20 - LMT 1890 Z Pacific/Galapagos -5:58:24 - LMT 1931 -5 - -05 1986 -6 Av -06/-05 -R Aw 1937 1938 - S lastSun 0 1 S +R Aw 1937 1938 - S lastSun 0 1 - R Aw 1938 1942 - Mar Sun>=19 0 0 - -R Aw 1939 o - O 1 0 1 S -R Aw 1940 1942 - S lastSun 0 1 S +R Aw 1939 o - O 1 0 1 - +R Aw 1940 1942 - S lastSun 0 1 - R Aw 1943 o - Ja 1 0 0 - -R Aw 1983 o - S lastSun 0 1 S +R Aw 1983 o - S lastSun 0 1 - R Aw 1984 1985 - Ap lastSun 0 0 - -R Aw 1984 o - S 16 0 1 S -R Aw 1985 2000 - S Sun>=9 0 1 S +R Aw 1984 o - S 16 0 1 - +R Aw 1985 2000 - S Sun>=9 0 1 - R Aw 1986 2000 - Ap Sun>=16 0 0 - R Aw 2001 2010 - Ap Sun>=15 2 0 - -R Aw 2001 2010 - S Sun>=1 2 1 S +R Aw 2001 2010 - S Sun>=1 2 1 - Z Atlantic/Stanley -3:51:24 - LMT 1890 -3:51:24 - SMT 1912 Mar 12 -4 Aw -04/-03 1983 May @@ -3872,26 +3873,26 @@ Z America/Guyana -3:52:40 - LMT 1915 Mar -3:45 - -0345 1975 Jul 31 -3 - -03 1991 -4 - -04 -R Ax 1975 1988 - O 1 0 1 S +R Ax 1975 1988 - O 1 0 1 - R Ax 1975 1978 - Mar 1 0 0 - R Ax 1979 1991 - Ap 1 0 0 - -R Ax 1989 o - O 22 0 1 S -R Ax 1990 o - O 1 0 1 S -R Ax 1991 o - O 6 0 1 S +R Ax 1989 o - O 22 0 1 - +R Ax 1990 o - O 1 0 1 - +R Ax 1991 o - O 6 0 1 - R Ax 1992 o - Mar 1 0 0 - -R Ax 1992 o - O 5 0 1 S +R Ax 1992 o - O 5 0 1 - R Ax 1993 o - Mar 31 0 0 - -R Ax 1993 1995 - O 1 0 1 S +R Ax 1993 1995 - O 1 0 1 - R Ax 1994 1995 - F lastSun 0 0 - R Ax 1996 o - Mar 1 0 0 - -R Ax 1996 2001 - O Sun>=1 0 1 S +R Ax 1996 2001 - O Sun>=1 0 1 - R Ax 1997 o - F lastSun 0 0 - R Ax 1998 2001 - Mar Sun>=1 0 0 - R Ax 2002 2004 - Ap Sun>=1 0 0 - -R Ax 2002 2003 - S Sun>=1 0 1 S -R Ax 2004 2009 - O Sun>=15 0 1 S +R Ax 2002 2003 - S Sun>=1 0 1 - +R Ax 2004 2009 - O Sun>=15 0 1 - R Ax 2005 2009 - Mar Sun>=8 0 0 - -R Ax 2010 ma - O Sun>=1 0 1 S +R Ax 2010 ma - O Sun>=1 0 1 - R Ax 2010 2012 - Ap Sun>=8 0 0 - R Ax 2013 ma - Mar Sun>=22 0 0 - Z America/Asuncion -3:50:40 - LMT 1890 @@ -3899,15 +3900,15 @@ Z America/Asuncion -3:50:40 - LMT 1890 -4 - -04 1972 O -3 - -03 1974 Ap -4 Ax -04/-03 -R Ay 1938 o - Ja 1 0 1 S +R Ay 1938 o - Ja 1 0 1 - R Ay 1938 o - Ap 1 0 0 - -R Ay 1938 1939 - S lastSun 0 1 S +R Ay 1938 1939 - S lastSun 0 1 - R Ay 1939 1940 - Mar Sun>=24 0 0 - -R Ay 1986 1987 - Ja 1 0 1 S +R Ay 1986 1987 - Ja 1 0 1 - R Ay 1986 1987 - Ap 1 0 0 - -R Ay 1990 o - Ja 1 0 1 S +R Ay 1990 o - Ja 1 0 1 - R Ay 1990 o - Ap 1 0 0 - -R Ay 1994 o - Ja 1 0 1 S +R Ay 1994 o - Ja 1 0 1 - R Ay 1994 o - Ap 1 0 0 - Z America/Lima -5:8:12 - LMT 1890 -5:8:36 - LMT 1908 Jul 28 @@ -3934,57 +3935,63 @@ Li America/Port_of_Spain America/St_Lucia Li America/Port_of_Spain America/St_Thomas Li America/Port_of_Spain America/St_Vincent Li America/Port_of_Spain America/Tortola -R Az 1923 o - O 2 0 0:30 HS +R Az 1923 1925 - O 1 0 0:30 - R Az 1924 1926 - Ap 1 0 0 - -R Az 1924 1925 - O 1 0 0:30 HS -R Az 1933 1935 - O lastSun 0 0:30 HS -R Az 1934 1936 - Mar Sat>=25 23:30s 0 - -R Az 1936 o - N 1 0 0:30 HS -R Az 1937 1941 - Mar lastSun 0 0 - -R Az 1937 1940 - O lastSun 0 0:30 HS -R Az 1941 o - Au 1 0 0:30 HS -R Az 1942 o - Ja 1 0 0 - -R Az 1942 o - D 14 0 1 S +R Az 1933 1938 - O lastSun 0 0:30 - +R Az 1934 1941 - Mar lastSat 24 0 - +R Az 1939 o - O 1 0 0:30 - +R Az 1940 o - O 27 0 0:30 - +R Az 1941 o - Au 1 0 0:30 - +R Az 1942 o - D 14 0 0:30 - R Az 1943 o - Mar 14 0 0 - -R Az 1959 o - May 24 0 1 S +R Az 1959 o - May 24 0 0:30 - R Az 1959 o - N 15 0 0 - -R Az 1960 o - Ja 17 0 1 S +R Az 1960 o - Ja 17 0 1 - R Az 1960 o - Mar 6 0 0 - -R Az 1965 1967 - Ap Sun>=1 0 1 S +R Az 1965 o - Ap 4 0 1 - R Az 1965 o - S 26 0 0 - -R Az 1966 1967 - O 31 0 0 - -R Az 1968 1970 - May 27 0 0:30 HS -R Az 1968 1970 - D 2 0 0 - -R Az 1972 o - Ap 24 0 1 S -R Az 1972 o - Au 15 0 0 - -R Az 1974 o - Mar 10 0 0:30 HS -R Az 1974 o - D 22 0 1 S -R Az 1976 o - O 1 0 0 - -R Az 1977 o - D 4 0 1 S -R Az 1978 o - Ap 1 0 0 - -R Az 1979 o - O 1 0 1 S -R Az 1980 o - May 1 0 0 - -R Az 1987 o - D 14 0 1 S -R Az 1988 o - Mar 14 0 0 - -R Az 1988 o - D 11 0 1 S -R Az 1989 o - Mar 12 0 0 - -R Az 1989 o - O 29 0 1 S -R Az 1990 1992 - Mar Sun>=1 0 0 - -R Az 1990 1991 - O Sun>=21 0 1 S -R Az 1992 o - O 18 0 1 S +R Az 1968 o - May 27 0 0:30 - +R Az 1968 o - D 1 0 0 - +R Az 1970 o - Ap 25 0 1 - +R Az 1970 o - Jun 14 0 0 - +R Az 1972 o - Ap 23 0 1 - +R Az 1972 o - Jul 16 0 0 - +R Az 1974 o - Ja 13 0 1:30 - +R Az 1974 o - Mar 10 0 0:30 - +R Az 1974 o - S 1 0 0 - +R Az 1974 o - D 22 0 1 - +R Az 1975 o - Mar 30 0 0 - +R Az 1976 o - D 19 0 1 - +R Az 1977 o - Mar 6 0 0 - +R Az 1977 o - D 4 0 1 - +R Az 1978 1979 - Mar Sun>=1 0 0 - +R Az 1978 o - D 17 0 1 - +R Az 1979 o - Ap 29 0 1 - +R Az 1980 o - Mar 16 0 0 - +R Az 1987 o - D 14 0 1 - +R Az 1988 o - F 28 0 0 - +R Az 1988 o - D 11 0 1 - +R Az 1989 o - Mar 5 0 0 - +R Az 1989 o - O 29 0 1 - +R Az 1990 o - F 25 0 0 - +R Az 1990 1991 - O Sun>=21 0 1 - +R Az 1991 1992 - Mar Sun>=1 0 0 - +R Az 1992 o - O 18 0 1 - R Az 1993 o - F 28 0 0 - -R Az 2004 o - S 19 0 1 S +R Az 2004 o - S 19 0 1 - R Az 2005 o - Mar 27 2 0 - -R Az 2005 o - O 9 2 1 S -R Az 2006 o - Mar 12 2 0 - -R Az 2006 2014 - O Sun>=1 2 1 S -R Az 2007 2015 - Mar Sun>=8 2 0 - -Z America/Montevideo -3:44:44 - LMT 1898 Jun 28 --3:44:44 - MMT 1920 May +R Az 2005 o - O 9 2 1 - +R Az 2006 2015 - Mar Sun>=8 2 0 - +R Az 2006 2014 - O Sun>=1 2 1 - +Z America/Montevideo -3:44:51 - LMT 1908 Jun 10 +-3:44:51 - MMT 1920 May +-4 - -04 1923 O -3:30 Az -0330/-03 1942 D 14 +-3 Az -03/-0230 1960 -3 Az -03/-02 1968 --3 Az -03/-0230 1971 +-3 Az -03/-0230 1970 -3 Az -03/-02 1974 +-3 Az -03/-0130 1974 Mar 10 -3 Az -03/-0230 1974 D 22 -3 Az -03/-02 Z America/Caracas -4:27:44 - LMT 1890 diff --git a/lib/pytz/zoneinfo/zone.tab b/lib/pytz/zoneinfo/zone.tab index e1bfdee2ecae9904cf18659f40ba9dc71684e40e..f92c919b8a1e79ff60d4a5fbe47f3384b75a8b17 100644 --- a/lib/pytz/zoneinfo/zone.tab +++ b/lib/pytz/zoneinfo/zone.tab @@ -429,7 +429,7 @@ US +593249-1394338 America/Yakutat Alaska - Yakutat US +643004-1652423 America/Nome Alaska (west) US +515248-1763929 America/Adak Aleutian Islands US +211825-1575130 Pacific/Honolulu Hawaii -UY -3453-05611 America/Montevideo +UY -345433-0561245 America/Montevideo UZ +3940+06648 Asia/Samarkand Uzbekistan (west) UZ +4120+06918 Asia/Tashkent Uzbekistan (east) VA +415408+0122711 Europe/Vatican diff --git a/lib/pytz/zoneinfo/zone1970.tab b/lib/pytz/zoneinfo/zone1970.tab index 4ee8ce519d9ab1fdab6f782e8df0bafff3472e8b..2d90ed72f1c647da6e97ac0f70315baa5c8e2b0b 100644 --- a/lib/pytz/zoneinfo/zone1970.tab +++ b/lib/pytz/zoneinfo/zone1970.tab @@ -12,7 +12,7 @@ # 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, +# 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.html file for how zone names are chosen. @@ -371,7 +371,7 @@ US +593249-1394338 America/Yakutat Alaska - Yakutat US +643004-1652423 America/Nome Alaska (west) US +515248-1763929 America/Adak Aleutian Islands US,UM +211825-1575130 Pacific/Honolulu Hawaii -UY -3453-05611 America/Montevideo +UY -345433-0561245 America/Montevideo UZ +3940+06648 Asia/Samarkand Uzbekistan (west) UZ +4120+06918 Asia/Tashkent Uzbekistan (east) VE +1030-06656 America/Caracas diff --git a/lib/subliminal/core.py b/lib/subliminal/core.py index 1f715ea1fd2ec2f48dc57243c18b9a14c1a1d5e2..e879eb80f270e3da39897c5774d40c3347e4090e 100644 --- a/lib/subliminal/core.py +++ b/lib/subliminal/core.py @@ -388,7 +388,7 @@ def search_external_subtitles(path, directory=None): subtitles = {} for p in os.listdir(directory or dirpath): # keep only valid subtitle filenames - if not p.startswith(fileroot) or not p.endswith(SUBTITLE_EXTENSIONS): + if not p.startswith(fileroot) or not p.lower().endswith(SUBTITLE_EXTENSIONS): continue # extract the potential language code @@ -420,7 +420,7 @@ def scan_video(path): raise ValueError('Path does not exist') # check video extension - if not path.endswith(VIDEO_EXTENSIONS): + if not path.lower().endswith(VIDEO_EXTENSIONS): raise ValueError('%r is not a valid video extension' % os.path.splitext(path)[1]) dirpath, filename = os.path.split(path) @@ -468,7 +468,7 @@ def scan_archive(path): rar = RarFile(path) # filter on video extensions - rar_filenames = [f for f in rar.namelist() if f.endswith(VIDEO_EXTENSIONS)] + rar_filenames = [f for f in rar.namelist() if f.lower().endswith(VIDEO_EXTENSIONS)] # no video found if not rar_filenames: @@ -521,17 +521,26 @@ def scan_videos(path, age=None, archives=True): if dirname.startswith('.'): logger.debug('Skipping hidden dirname %r in %r', dirname, dirpath) dirnames.remove(dirname) + # Skip Sample folder + if dirname.lower() == 'sample': + logger.debug('Skipping sample dirname %r in %r', dirname, dirpath) + dirnames.remove(dirname) # scan for videos for filename in filenames: # filter on videos and archives - if not (filename.endswith(VIDEO_EXTENSIONS) or archives and filename.endswith(ARCHIVE_EXTENSIONS)): + if not (filename.lower().endswith(VIDEO_EXTENSIONS) or + archives and filename.lower().endswith(ARCHIVE_EXTENSIONS)): continue # skip hidden files if filename.startswith('.'): logger.debug('Skipping hidden filename %r in %r', filename, dirpath) continue + # skip 'sample' media files + if os.path.splitext(filename)[0].lower() == 'sample': + logger.debug('Skipping sample filename %r in %r', filename, dirpath) + continue # reconstruct the file path filepath = os.path.join(dirpath, filename) @@ -553,13 +562,13 @@ def scan_videos(path, age=None, archives=True): continue # scan - if filename.endswith(VIDEO_EXTENSIONS): # video + if filename.lower().endswith(VIDEO_EXTENSIONS): # video try: video = scan_video(filepath) except ValueError: # pragma: no cover logger.exception('Error scanning video') continue - elif archives and filename.endswith(ARCHIVE_EXTENSIONS): # archive + elif archives and filename.lower().endswith(ARCHIVE_EXTENSIONS): # archive try: video = scan_archive(filepath) except (NotRarFile, RarCannotExec, ValueError): # pragma: no cover diff --git a/lib/subliminal/providers/addic7ed.py b/lib/subliminal/providers/addic7ed.py index 2926081e0d5644343d839c20dfd8276d66d42b83..1832cf92c88fb122f4cdb483ab58c0c9d6fe07ae 100644 --- a/lib/subliminal/providers/addic7ed.py +++ b/lib/subliminal/providers/addic7ed.py @@ -179,7 +179,7 @@ class Addic7edProvider(Provider): # make the search logger.info('Searching show ids with %r', params) - r = self.session.get(self.server_url + 'search.php', params=params, timeout=10) + r = self.session.get(self.server_url + 'srch.php', params=params, timeout=10) r.raise_for_status() soup = ParserBeautifulSoup(r.content, ['lxml', 'html.parser']) diff --git a/lib/subliminal/providers/legendastv.py b/lib/subliminal/providers/legendastv.py index 925bb9ead723e21420a0bdcf898333dc311c692f..3468c65c1c82c62f1e7befa2226599d1d3c4d1d0 100644 --- a/lib/subliminal/providers/legendastv.py +++ b/lib/subliminal/providers/legendastv.py @@ -170,7 +170,7 @@ class LegendasTVProvider(Provider): # Provider needs UNRAR installed. If not available raise ConfigurationError try: - rarfile.custom_check(rarfile.UNRAR_TOOL) + rarfile.custom_check([rarfile.UNRAR_TOOL], True) except rarfile.RarExecError: raise ConfigurationError('UNRAR tool not available') diff --git a/lib/subliminal/subtitle.py b/lib/subliminal/subtitle.py index 726b28e3731eb74b557ef22666a7931300ea3c1d..83beab63a6c7494d81c9f30655ea34110dfb939d 100644 --- a/lib/subliminal/subtitle.py +++ b/lib/subliminal/subtitle.py @@ -238,7 +238,10 @@ def guess_matches(video, guess, partial=False): if video.resolution and 'screen_size' in guess and guess['screen_size'] == video.resolution: matches.add('resolution') # format - if video.format and 'format' in guess and guess['format'].lower() == video.format.lower(): + # Guessit may return a list for `format`, which indicates a conflict in the guessing. + # We should match `format` only when it returns single value to avoid false `format` matches + if video.format and guess.get('format') and not isinstance(guess['format'], list) \ + and guess['format'].lower() == video.format.lower(): matches.add('format') # video_codec if video.video_codec and 'video_codec' in guess and guess['video_codec'] == video.video_codec: