Hello community, here is the log from the commit of package python-certbot-nginx for openSUSE:Factory checked in at 2020-05-14 23:27:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-certbot-nginx (Old) and /work/SRC/openSUSE:Factory/.python-certbot-nginx.new.2738 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-certbot-nginx" Thu May 14 23:27:09 2020 rev:19 rq:805545 version:1.4.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-certbot-nginx/python-certbot-nginx.changes 2020-03-11 18:56:42.159711268 +0100 +++ /work/SRC/openSUSE:Factory/.python-certbot-nginx.new.2738/python-certbot-nginx.changes 2020-05-14 23:27:11.701295301 +0200 @@ -1,0 +2,7 @@ +Thu May 14 08:51:38 UTC 2020 - Marketa Calabkova <mcalabk...@suse.com> + +- update to version 1.4.0 + * Fix nginx plugin crash when non-ASCII configuration file is being read (instead, + the user will be warned that UTF-8 must be used). + +------------------------------------------------------------------- Old: ---- certbot-nginx-1.3.0.tar.gz New: ---- certbot-nginx-1.4.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-certbot-nginx.spec ++++++ --- /var/tmp/diff_new_pack.u4X5he/_old 2020-05-14 23:27:12.373296767 +0200 +++ /var/tmp/diff_new_pack.u4X5he/_new 2020-05-14 23:27:12.373296767 +0200 @@ -18,14 +18,13 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-certbot-nginx -Version: 1.3.0 +Version: 1.4.0 Release: 0 Summary: Nginx plugin for Certbot License: Apache-2.0 URL: https://github.com/letsencrypt/letsencrypt Source: https://files.pythonhosted.org/packages/source/c/certbot-nginx/certbot-nginx-%{version}.tar.gz -BuildRequires: %{python_module certbot >= 1.1.0} -BuildRequires: %{python_module mock} +BuildRequires: %{python_module certbot >= 1.4.0} BuildRequires: %{python_module pyOpenSSL} BuildRequires: %{python_module pyparsing >= 1.5.5} BuildRequires: %{python_module pytest} @@ -34,8 +33,8 @@ BuildRequires: nginx BuildRequires: python-rpm-macros Requires: nginx -Requires: python-acme >= 1.0.0 -Requires: python-certbot >= 1.1.0 +Requires: python-acme >= 1.4.0 +Requires: python-certbot >= 1.4.0 Requires: python-pyOpenSSL Requires: python-pyparsing >= 1.5.5 Requires: python-zope.interface ++++++ certbot-nginx-1.3.0.tar.gz -> certbot-nginx-1.4.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/PKG-INFO new/certbot-nginx-1.4.0/PKG-INFO --- old/certbot-nginx-1.3.0/PKG-INFO 2020-03-03 21:36:47.000000000 +0100 +++ new/certbot-nginx-1.4.0/PKG-INFO 2020-05-05 21:37:47.727920800 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: certbot-nginx -Version: 1.3.0 +Version: 1.4.0 Summary: Nginx plugin for Certbot Home-page: https://github.com/letsencrypt/letsencrypt Author: Certbot Project diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/certbot_nginx/_internal/configurator.py new/certbot-nginx-1.4.0/certbot_nginx/_internal/configurator.py --- old/certbot-nginx-1.3.0/certbot_nginx/_internal/configurator.py 2020-03-03 21:36:36.000000000 +0100 +++ new/certbot-nginx-1.4.0/certbot_nginx/_internal/configurator.py 2020-05-05 21:37:33.000000000 +0200 @@ -1,5 +1,4 @@ """Nginx Configuration""" -# https://github.com/PyCQA/pylint/issues/73 from distutils.version import LooseVersion import logging import re @@ -749,7 +748,7 @@ # if there is no separate SSL block, break the block into two and # choose the SSL block. - if vhost.ssl and any([not addr.ssl for addr in vhost.addrs]): + if vhost.ssl and any(not addr.ssl for addr in vhost.addrs): _, vhost = self._split_block(vhost) header_directives = [ @@ -984,7 +983,7 @@ logger.warning("NGINX derivative %s is not officially supported by" " certbot", product_name) - nginx_version = tuple([int(i) for i in product_version.split(".")]) + nginx_version = tuple(int(i) for i in product_version.split(".")) # nginx < 0.8.48 uses machine hostname as default server_name instead of # the empty string diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/certbot_nginx/_internal/display_ops.py new/certbot-nginx-1.4.0/certbot_nginx/_internal/display_ops.py --- old/certbot-nginx-1.3.0/certbot_nginx/_internal/display_ops.py 2020-03-03 21:36:36.000000000 +0100 +++ new/certbot-nginx-1.4.0/certbot_nginx/_internal/display_ops.py 2020-05-05 21:37:33.000000000 +0200 @@ -17,7 +17,7 @@ :rtype: :class:`list`of type `~obj.Vhost` """ if not vhosts: - return list() + return [] tags_list = [vhost.display_repr()+"\n" for vhost in vhosts] # Remove the extra newline from the last entry if tags_list: @@ -33,7 +33,7 @@ def _reversemap_vhosts(names, vhosts): """Helper function for select_vhost_multiple for mapping string representations back to actual vhost objects""" - return_vhosts = list() + return_vhosts = [] for selection in names: for vhost in vhosts: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/certbot_nginx/_internal/parser.py new/certbot-nginx-1.4.0/certbot_nginx/_internal/parser.py --- old/certbot-nginx-1.3.0/certbot_nginx/_internal/parser.py 2020-03-03 21:36:36.000000000 +0100 +++ new/certbot-nginx-1.4.0/certbot_nginx/_internal/parser.py 2020-05-05 21:37:33.000000000 +0200 @@ -2,6 +2,7 @@ import copy import functools import glob +import io import logging import re @@ -205,12 +206,16 @@ if item in self.parsed and not override: continue try: - with open(item) as _file: + with io.open(item, "r", encoding="utf-8") as _file: parsed = nginxparser.load(_file) self.parsed[item] = parsed trees.append(parsed) except IOError: logger.warning("Could not open file: %s", item) + except UnicodeDecodeError: + logger.warning("Could not read file: %s due to invalid " + "character. Only UTF-8 encoding is " + "supported.", item) except pyparsing.ParseException as err: logger.debug("Could not parse file: %s due to %s", item, err) return trees @@ -399,9 +404,9 @@ if directive and directive[0] == 'listen': # Exclude one-time use parameters which will cause an error if repeated. # https://nginx.org/en/docs/http/ngx_http_core_module.html#listen - exclude = set(('default_server', 'default', 'setfib', 'fastopen', 'backlog', + exclude = {'default_server', 'default', 'setfib', 'fastopen', 'backlog', 'rcvbuf', 'sndbuf', 'accept_filter', 'deferred', 'bind', - 'ipv6only', 'reuseport', 'so_keepalive')) + 'ipv6only', 'reuseport', 'so_keepalive'} for param in exclude: # See: github.com/certbot/certbot/pull/6223#pullrequestreview-143019225 @@ -414,10 +419,13 @@ def _parse_ssl_options(ssl_options): if ssl_options is not None: try: - with open(ssl_options) as _file: + with io.open(ssl_options, "r", encoding="utf-8") as _file: return nginxparser.load(_file) except IOError: logger.warning("Missing NGINX TLS options file: %s", ssl_options) + except UnicodeDecodeError: + logger.warning("Could not read file: %s due to invalid character. " + "Only UTF-8 encoding is supported.", ssl_options) except pyparsing.ParseBaseException as err: logger.debug("Could not parse file: %s due to %s", ssl_options, err) return [] @@ -570,7 +578,7 @@ INCLUDE = 'include' -REPEATABLE_DIRECTIVES = set(['server_name', 'listen', INCLUDE, 'rewrite', 'add_header']) +REPEATABLE_DIRECTIVES = {'server_name', 'listen', INCLUDE, 'rewrite', 'add_header'} COMMENT = ' managed by Certbot' COMMENT_BLOCK = [' ', '#', COMMENT] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/certbot_nginx/_internal/parser_obj.py new/certbot-nginx-1.4.0/certbot_nginx/_internal/parser_obj.py --- old/certbot-nginx-1.3.0/certbot_nginx/_internal/parser_obj.py 2020-03-03 21:36:36.000000000 +0100 +++ new/certbot-nginx-1.4.0/certbot_nginx/_internal/parser_obj.py 2020-05-05 21:37:33.000000000 +0200 @@ -206,7 +206,7 @@ :returns: whether this lists is parseable by `Sentence`. """ return isinstance(lists, list) and len(lists) > 0 and \ - all([isinstance(elem, six.string_types) for elem in lists]) + all(isinstance(elem, six.string_types) for elem in lists) def parse(self, raw_list, add_spaces=False): """ Parses a list of string types into this object. @@ -214,7 +214,7 @@ if add_spaces: raw_list = _space_list(raw_list) if not isinstance(raw_list, list) or \ - any([not isinstance(elem, six.string_types) for elem in raw_list]): + any(not isinstance(elem, six.string_types) for elem in raw_list): raise errors.MisconfigurationError("Sentence parsing expects a list of string types.") self._data = raw_list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/certbot_nginx.egg-info/PKG-INFO new/certbot-nginx-1.4.0/certbot_nginx.egg-info/PKG-INFO --- old/certbot-nginx-1.3.0/certbot_nginx.egg-info/PKG-INFO 2020-03-03 21:36:47.000000000 +0100 +++ new/certbot-nginx-1.4.0/certbot_nginx.egg-info/PKG-INFO 2020-05-05 21:37:47.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: certbot-nginx -Version: 1.3.0 +Version: 1.4.0 Summary: Nginx plugin for Certbot Home-page: https://github.com/letsencrypt/letsencrypt Author: Certbot Project diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/certbot_nginx.egg-info/SOURCES.txt new/certbot-nginx-1.4.0/certbot_nginx.egg-info/SOURCES.txt --- old/certbot-nginx-1.3.0/certbot_nginx.egg-info/SOURCES.txt 2020-03-03 21:36:47.000000000 +0100 +++ new/certbot-nginx-1.4.0/certbot_nginx.egg-info/SOURCES.txt 2020-05-05 21:37:47.000000000 +0200 @@ -31,16 +31,19 @@ tests/obj_test.py tests/parser_obj_test.py tests/parser_test.py +tests/test_log_util.py tests/test_util.py tests/testdata/etc_nginx/broken.conf tests/testdata/etc_nginx/comment_in_file.conf tests/testdata/etc_nginx/edge_cases.conf tests/testdata/etc_nginx/foo.conf +tests/testdata/etc_nginx/invalid_unicode_comments.conf tests/testdata/etc_nginx/mime.types tests/testdata/etc_nginx/minimalistic_comments.conf tests/testdata/etc_nginx/multiline_quotes.conf tests/testdata/etc_nginx/nginx.conf tests/testdata/etc_nginx/server.conf +tests/testdata/etc_nginx/valid_unicode_comments.conf tests/testdata/etc_nginx/sites-enabled/default tests/testdata/etc_nginx/sites-enabled/example.com tests/testdata/etc_nginx/sites-enabled/example.net diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/certbot_nginx.egg-info/requires.txt new/certbot-nginx-1.4.0/certbot_nginx.egg-info/requires.txt --- old/certbot-nginx-1.3.0/certbot_nginx.egg-info/requires.txt 2020-03-03 21:36:47.000000000 +0100 +++ new/certbot-nginx-1.4.0/certbot_nginx.egg-info/requires.txt 2020-05-05 21:37:47.000000000 +0200 @@ -1,7 +1,9 @@ -acme>=1.0.0 -certbot>=1.1.0 -mock +acme>=1.4.0 +certbot>=1.4.0 PyOpenSSL pyparsing>=1.5.5 setuptools zope.interface + +[:python_version < "3.3"] +mock diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/setup.py new/certbot-nginx-1.4.0/setup.py --- old/certbot-nginx-1.3.0/setup.py 2020-03-03 21:36:38.000000000 +0100 +++ new/certbot-nginx-1.4.0/setup.py 2020-05-05 21:37:34.000000000 +0200 @@ -1,23 +1,33 @@ +from distutils.version import StrictVersion import sys +from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup from setuptools.command.test import test as TestCommand -version = '1.3.0' +version = '1.4.0' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ - 'acme>=1.0.0', - 'certbot>=1.1.0', - 'mock', + 'acme>=1.4.0', + 'certbot>=1.4.0', 'PyOpenSSL', 'pyparsing>=1.5.5', # Python3 support 'setuptools', 'zope.interface', ] +setuptools_known_environment_markers = (StrictVersion(setuptools_version) >= StrictVersion('36.2')) +if setuptools_known_environment_markers: + install_requires.append('mock ; python_version < "3.3"') +elif 'bdist_wheel' in sys.argv[1:]: + raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' + 'of setuptools. Version 36.2+ of setuptools is required.') +elif sys.version_info < (3,3): + install_requires.append('mock') + class PyTest(TestCommand): user_options = [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/tests/configurator_test.py new/certbot-nginx-1.4.0/tests/configurator_test.py --- old/certbot-nginx-1.3.0/tests/configurator_test.py 2020-03-03 21:36:36.000000000 +0100 +++ new/certbot-nginx-1.4.0/tests/configurator_test.py 2020-05-05 21:37:33.000000000 +0200 @@ -1,7 +1,10 @@ """Test for certbot_nginx._internal.configurator.""" import unittest -import mock +try: + import mock +except ImportError: # pragma: no cover + from unittest import mock # type: ignore import OpenSSL from acme import challenges @@ -104,7 +107,7 @@ filep = self.config.parser.abs_path('sites-enabled/example.com') mock_vhost = obj.VirtualHost(filep, None, None, None, - set(['.example.com', 'example.*']), + {'.example.com', 'example.*'}, None, [0]) self.config.parser.add_server_directives( mock_vhost, @@ -150,11 +153,11 @@ self._test_choose_vhosts_common('ipv6.com', 'ipv6_conf') def _test_choose_vhosts_common(self, name, conf): - conf_names = {'localhost_conf': set(['localhost', r'~^(www\.)?(example|bar)\.']), - 'server_conf': set(['somename', 'another.alias', 'alias']), - 'example_conf': set(['.example.com', 'example.*']), - 'foo_conf': set(['*.www.foo.com', '*.www.example.com']), - 'ipv6_conf': set(['ipv6.com'])} + conf_names = {'localhost_conf': {'localhost', r'~^(www\.)?(example|bar)\.'}, + 'server_conf': {'somename', 'another.alias', 'alias'}, + 'example_conf': {'.example.com', 'example.*'}, + 'foo_conf': {'*.www.foo.com', '*.www.example.com'}, + 'ipv6_conf': {'ipv6.com'}} conf_path = {'localhost': "etc_nginx/nginx.conf", 'alias': "etc_nginx/nginx.conf", @@ -177,7 +180,7 @@ self.assertTrue(vhost.ipv6_enabled()) # Make sure that we have SSL enabled also for IPv6 addr self.assertTrue( - any([True for x in vhost.addrs if x.ssl and x.ipv6])) + any(True for x in vhost.addrs if x.ssl and x.ipv6)) def test_choose_vhosts_bad(self): bad_results = ['www.foo.com', 'example', 't.www.bar.co', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/tests/http_01_test.py new/certbot-nginx-1.4.0/tests/http_01_test.py --- old/certbot-nginx-1.3.0/tests/http_01_test.py 2020-03-03 21:36:36.000000000 +0100 +++ new/certbot-nginx-1.4.0/tests/http_01_test.py 2020-05-05 21:37:33.000000000 +0200 @@ -2,7 +2,10 @@ import unittest import josepy as jose -import mock +try: + import mock +except ImportError: # pragma: no cover + from unittest import mock # type: ignore import six from acme import challenges diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/tests/obj_test.py new/certbot-nginx-1.4.0/tests/obj_test.py --- old/certbot-nginx-1.3.0/tests/obj_test.py 2020-03-03 21:36:36.000000000 +0100 +++ new/certbot-nginx-1.4.0/tests/obj_test.py 2020-05-05 21:37:33.000000000 +0200 @@ -98,10 +98,10 @@ def test_set_inclusion(self): from certbot_nginx._internal.obj import Addr - set_a = set([self.addr1, self.addr2]) + set_a = {self.addr1, self.addr2} addr1b = Addr.fromstring("192.168.1.1") addr2b = Addr.fromstring("192.168.1.1:* ssl") - set_b = set([addr1b, addr2b]) + set_b = {addr1b, addr2b} self.assertEqual(set_a, set_b) @@ -120,8 +120,8 @@ ] self.vhost1 = VirtualHost( "filep", - set([Addr.fromstring("localhost")]), False, False, - set(['localhost']), raw1, []) + {Addr.fromstring("localhost")}, False, False, + {'localhost'}, raw1, []) raw2 = [ ['listen', '69.50.225.155:9000'], [['if', '($scheme', '!=', '"https") '], @@ -130,24 +130,24 @@ ] self.vhost2 = VirtualHost( "filep", - set([Addr.fromstring("localhost")]), False, False, - set(['localhost']), raw2, []) + {Addr.fromstring("localhost")}, False, False, + {'localhost'}, raw2, []) raw3 = [ ['listen', '69.50.225.155:9000'], ['rewrite', '^(.*)$', '$scheme://www.domain.com$1', 'permanent'] ] self.vhost3 = VirtualHost( "filep", - set([Addr.fromstring("localhost")]), False, False, - set(['localhost']), raw3, []) + {Addr.fromstring("localhost")}, False, False, + {'localhost'}, raw3, []) raw4 = [ ['listen', '69.50.225.155:9000'], ['server_name', 'return.com'] ] self.vhost4 = VirtualHost( "filp", - set([Addr.fromstring("localhost")]), False, False, - set(['localhost']), raw4, []) + {Addr.fromstring("localhost")}, False, False, + {'localhost'}, raw4, []) raw_has_hsts = [ ['listen', '69.50.225.155:9000'], ['server_name', 'return.com'], @@ -155,16 +155,16 @@ ] self.vhost_has_hsts = VirtualHost( "filep", - set([Addr.fromstring("localhost")]), False, False, - set(['localhost']), raw_has_hsts, []) + {Addr.fromstring("localhost")}, False, False, + {'localhost'}, raw_has_hsts, []) def test_eq(self): from certbot_nginx._internal.obj import Addr from certbot_nginx._internal.obj import VirtualHost vhost1b = VirtualHost( "filep", - set([Addr.fromstring("localhost blah")]), False, False, - set(['localhost']), [], []) + {Addr.fromstring("localhost blah")}, False, False, + {'localhost'}, [], []) self.assertEqual(vhost1b, self.vhost1) self.assertEqual(str(vhost1b), str(self.vhost1)) @@ -203,8 +203,8 @@ ['#', ' managed by Certbot'], []] vhost_haystack = VirtualHost( "filp", - set([Addr.fromstring("localhost")]), False, False, - set(['localhost']), test_haystack, []) + {Addr.fromstring("localhost")}, False, False, + {'localhost'}, test_haystack, []) test_bad_haystack = [['listen', '80'], ['root', '/var/www/html'], ['index', 'index.html index.htm index.nginx-debian.html'], ['server_name', 'two.functorkitten.xyz'], ['listen', '443 ssl'], @@ -219,8 +219,8 @@ ['#', ' managed by Certbot'], []] vhost_bad_haystack = VirtualHost( "filp", - set([Addr.fromstring("localhost")]), False, False, - set(['localhost']), test_bad_haystack, []) + {Addr.fromstring("localhost")}, False, False, + {'localhost'}, test_bad_haystack, []) self.assertTrue(vhost_haystack.contains_list(test_needle)) self.assertFalse(vhost_bad_haystack.contains_list(test_needle)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/tests/parser_obj_test.py new/certbot-nginx-1.4.0/tests/parser_obj_test.py --- old/certbot-nginx-1.3.0/tests/parser_obj_test.py 2020-03-03 21:36:36.000000000 +0100 +++ new/certbot-nginx-1.4.0/tests/parser_obj_test.py 2020-05-05 21:37:33.000000000 +0200 @@ -2,7 +2,10 @@ import unittest -import mock +try: + import mock +except ImportError: # pragma: no cover + from unittest import mock # type: ignore from certbot_nginx._internal.parser_obj import COMMENT_BLOCK from certbot_nginx._internal.parser_obj import parse_raw @@ -80,7 +83,7 @@ fake_parser1.should_parse = lambda x: False parsing_hooks.return_value = (fake_parser1,) self.assertRaises(errors.MisconfigurationError, parse_raw, []) - parsing_hooks.return_value = tuple() + parsing_hooks.return_value = () self.assertRaises(errors.MisconfigurationError, parse_raw, []) def test_parse_raw_passes_add_spaces(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/tests/parser_test.py new/certbot-nginx-1.4.0/tests/parser_test.py --- old/certbot-nginx-1.3.0/tests/parser_test.py 2020-03-03 21:36:36.000000000 +0100 +++ new/certbot-nginx-1.4.0/tests/parser_test.py 2020-05-05 21:37:33.000000000 +0200 @@ -4,7 +4,6 @@ import shutil import unittest -from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module from certbot import errors from certbot.compat import os from certbot_nginx._internal import nginxparser @@ -127,7 +126,7 @@ vhost = obj.VirtualHost(nparser.abs_path('sites-enabled/globalssl.com'), [obj.Addr('4.8.2.6', '57', True, False, False, False)], - True, True, set(['globalssl.com']), [], [0]) + True, True, {'globalssl.com'}, [], [0]) globalssl_com = [x for x in vhosts if 'globalssl.com' in x.filep][0] self.assertEqual(vhost, globalssl_com) @@ -140,8 +139,8 @@ [obj.Addr('', '8080', False, False, False, False)], False, True, - set(['localhost', - r'~^(www\.)?(example|bar)\.']), + {'localhost', + r'~^(www\.)?(example|bar)\.'}, [], [10, 1, 9]) vhost2 = obj.VirtualHost(nparser.abs_path('nginx.conf'), [obj.Addr('somename', '8080', False, False, @@ -149,7 +148,7 @@ obj.Addr('', '8000', False, False, False, False)], False, True, - set(['somename', 'another.alias', 'alias']), + {'somename', 'another.alias', 'alias'}, [], [10, 1, 12]) vhost3 = obj.VirtualHost(nparser.abs_path('sites-enabled/example.com'), [obj.Addr('69.50.225.155', '9000', @@ -157,19 +156,19 @@ obj.Addr('127.0.0.1', '', False, False, False, False)], False, True, - set(['.example.com', 'example.*']), [], [0]) + {'.example.com', 'example.*'}, [], [0]) vhost4 = obj.VirtualHost(nparser.abs_path('sites-enabled/default'), [obj.Addr('myhost', '', False, True, False, False), obj.Addr('otherhost', '', False, True, False, False)], - False, True, set(['www.example.org']), + False, True, {'www.example.org'}, [], [0]) vhost5 = obj.VirtualHost(nparser.abs_path('foo.conf'), [obj.Addr('*', '80', True, True, False, False)], - True, True, set(['*.www.foo.com', - '*.www.example.com']), + True, True, {'*.www.foo.com', + '*.www.example.com'}, [], [2, 1, 0]) self.assertEqual(14, len(vhosts)) @@ -209,11 +208,11 @@ nparser = parser.NginxParser(self.config_path) mock_vhost = obj.VirtualHost(nparser.abs_path('nginx.conf'), None, None, None, - set(['localhost', - r'~^(www\.)?(example|bar)\.']), + {'localhost', + r'~^(www\.)?(example|bar)\.'}, None, [10, 1, 9]) example_com = nparser.abs_path('sites-enabled/example.com') - names = set(['.example.com', 'example.*']) + names = {'.example.com', 'example.*'} mock_vhost.filep = example_com mock_vhost.names = names mock_vhost.path = [0] @@ -233,8 +232,8 @@ nparser = parser.NginxParser(self.config_path) mock_vhost = obj.VirtualHost(nparser.abs_path('nginx.conf'), None, None, None, - set(['localhost', - r'~^(www\.)?(example|bar)\.']), + {'localhost', + r'~^(www\.)?(example|bar)\.'}, None, [10, 1, 9]) nparser.add_server_directives(mock_vhost, [['foo', 'bar'], ['\n ', 'ssl_certificate', ' ', @@ -244,7 +243,7 @@ self.assertEqual(1, len(re.findall(ssl_re, dump))) example_com = nparser.abs_path('sites-enabled/example.com') - names = set(['.example.com', 'example.*']) + names = {'.example.com', 'example.*'} mock_vhost.filep = example_com mock_vhost.names = names mock_vhost.path = [0] @@ -265,7 +264,7 @@ ]]]) server_conf = nparser.abs_path('server.conf') - names = set(['alias', 'another.alias', 'somename']) + names = {'alias', 'another.alias', 'somename'} mock_vhost.filep = server_conf mock_vhost.names = names mock_vhost.path = [] @@ -280,7 +279,7 @@ example_com = nparser.abs_path('sites-enabled/example.com') mock_vhost = obj.VirtualHost(example_com, None, None, None, - set(['.example.com', 'example.*']), + {'.example.com', 'example.*'}, None, [0]) nparser.add_server_directives(mock_vhost, [['\n ', '#', ' ', 'what a nice comment']]) @@ -302,7 +301,7 @@ def test_replace_server_directives(self): nparser = parser.NginxParser(self.config_path) - target = set(['.example.com', 'example.*']) + target = {'.example.com', 'example.*'} filep = nparser.abs_path('sites-enabled/example.com') mock_vhost = obj.VirtualHost(filep, None, None, None, target, None, [0]) nparser.update_or_add_server_directives( @@ -315,7 +314,7 @@ ['server_name', 'foobar.com'], ['#', COMMENT], ['server_name', 'example.*'], [] ]]]) - mock_vhost.names = set(['foobar.com', 'example.*']) + mock_vhost.names = {'foobar.com', 'example.*'} nparser.update_or_add_server_directives( mock_vhost, [['ssl_certificate', 'cert.pem']]) self.assertEqual( @@ -329,19 +328,19 @@ def test_get_best_match(self): target_name = 'www.eff.org' - names = [set(['www.eff.org', 'irrelevant.long.name.eff.org', '*.org']), - set(['eff.org', 'ww2.eff.org', 'test.www.eff.org']), - set(['*.eff.org', '.www.eff.org']), - set(['.eff.org', '*.org']), - set(['www.eff.', 'www.eff.*', '*.www.eff.org']), - set(['example.com', r'~^(www\.)?(eff.+)', '*.eff.*']), - set(['*', r'~^(www\.)?(eff.+)']), - set(['www.*', r'~^(www\.)?(eff.+)', '.test.eff.org']), - set(['*.org', r'*.eff.org', 'www.eff.*']), - set(['*.www.eff.org', 'www.*']), - set(['*.org']), - set([]), - set(['example.com'])] + names = [{'www.eff.org', 'irrelevant.long.name.eff.org', '*.org'}, + {'eff.org', 'ww2.eff.org', 'test.www.eff.org'}, + {'*.eff.org', '.www.eff.org'}, + {'.eff.org', '*.org'}, + {'www.eff.', 'www.eff.*', '*.www.eff.org'}, + {'example.com', r'~^(www\.)?(eff.+)', '*.eff.*'}, + {'*', r'~^(www\.)?(eff.+)'}, + {'www.*', r'~^(www\.)?(eff.+)', '.test.eff.org'}, + {'*.org', r'*.eff.org', 'www.eff.*'}, + {'*.www.eff.org', 'www.*'}, + {'*.org'}, + set(), + {'example.com'}] winners = [('exact', 'www.eff.org'), (None, None), ('exact', '.www.eff.org'), @@ -482,7 +481,43 @@ called = True self.assertTrue(called) - + def test_valid_unicode_characters(self): + nparser = parser.NginxParser(self.config_path) + path = nparser.abs_path('valid_unicode_comments.conf') + parsed = nparser._parse_files(path) # pylint: disable=protected-access + self.assertEqual(['server'], parsed[0][2][0]) + self.assertEqual(['listen', '80'], parsed[0][2][1][3]) + + def test_invalid_unicode_characters(self): + with self.assertLogs() as log: + nparser = parser.NginxParser(self.config_path) + path = nparser.abs_path('invalid_unicode_comments.conf') + parsed = nparser._parse_files(path) # pylint: disable=protected-access + + self.assertEqual([], parsed) + self.assertTrue(any( + ('invalid character' in output) and ('UTF-8' in output) + for output in log.output + )) + + def test_valid_unicode_characters_in_ssl_options(self): + nparser = parser.NginxParser(self.config_path) + path = nparser.abs_path('valid_unicode_comments.conf') + parsed = parser._parse_ssl_options(path) # pylint: disable=protected-access + self.assertEqual(['server'], parsed[2][0]) + self.assertEqual(['listen', '80'], parsed[2][1][3]) + + def test_invalid_unicode_characters_in_ssl_options(self): + with self.assertLogs() as log: + nparser = parser.NginxParser(self.config_path) + path = nparser.abs_path('invalid_unicode_comments.conf') + parsed = parser._parse_ssl_options(path) # pylint: disable=protected-access + + self.assertEqual([], parsed) + self.assertTrue(any( + ('invalid character' in output) and ('UTF-8' in output) + for output in log.output + )) if __name__ == "__main__": unittest.main() # pragma: no cover diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/tests/test_log_util.py new/certbot-nginx-1.4.0/tests/test_log_util.py --- old/certbot-nginx-1.3.0/tests/test_log_util.py 1970-01-01 01:00:00.000000000 +0100 +++ new/certbot-nginx-1.4.0/tests/test_log_util.py 2020-05-05 21:37:33.000000000 +0200 @@ -0,0 +1,125 @@ +"""Backport for `TestCase.assertLogs()`. + +Most of the idea and code are from CPython implementation. +https://github.com/python/cpython/blob/b76518d43fb82ed9e5d27025d18c90a23d525c90/Lib/unittest/case.py +""" +import logging +import collections + +__all__ = ['AssertLogsMixin'] + +LoggingWatcher = collections.namedtuple('LoggingWatcher', ['records', 'output']) + + +class CapturingHandler(logging.Handler): + """ + A logging handler capturing all (raw and formatted) logging output. + """ + + def __init__(self): + super(CapturingHandler, self).__init__() + self.watcher = LoggingWatcher([], []) + + def flush(self): + pass + + def emit(self, record): + self.watcher.records.append(record) + self.watcher.output.append(self.format(record)) + + + +class AssertLogsContext(object): + """ + A context manager used to implement `TestCase.assertLogs()`. + """ + + LOGGING_FORMAT = '%(levelname)s:%(name)s:%(message)s' + + def __init__(self, test_case, logger_name, level): + self.test_case = test_case + + self.logger_name = logger_name + self.logger_states = None + self.logger = None + + if level: + # pylint: disable=protected-access,no-member + try: + # In Python 3.x + name_to_level = logging._nameToLevel # type: ignore + except AttributeError: + # In Python 2.7 + name_to_level = logging._levelNames # type: ignore + + self.level = name_to_level.get(level, level) + else: + self.level = logging.INFO + + self.watcher = None + + def _save_logger_states(self): + self.logger_states = (self.logger.handlers[:], self.logger.level, self.logger.propagate) + + def _restore_logger_states(self): + self.logger.handlers, self.logger.level, self.logger.propagate = self.logger_states + + def __enter__(self): + if isinstance(self.logger_name, logging.Logger): + self.logger = self.logger_name + else: + self.logger = logging.getLogger(self.logger_name) + + formatter = logging.Formatter(self.LOGGING_FORMAT) + + handler = CapturingHandler() + handler.setFormatter(formatter) + + self._save_logger_states() + self.logger.handlers = [handler] + self.logger.setLevel(self.level) + self.logger.propagate = False + + self.watcher = handler.watcher + return handler.watcher + + def __exit__(self, exc_type, exc_value, tb): + self._restore_logger_states() + + if exc_type is not None: + # let unexpected exceptions pass through + return + + if not self.watcher.records: + self._raiseFailure( + "no logs of level {} or higher triggered on {}" + .format(logging.getLevelName(self.level), self.logger.name)) + + def _raiseFailure(self, message): + message = self.test_case._formatMessage(None, message) # pylint: disable=protected-access + raise self.test_case.failureException(message) + + +class AssertLogsMixin(object): + """ + A mixin that implements `TestCase.assertLogs()`. + """ + + def assertLogs(self, logger=None, level=None): + """Fail unless a log message of level *level* or higher is emitted + on *logger_name* or its children. If omitted, *level* defaults to + INFO and *logger* defaults to the root logger. + This method must be used as a context manager, and will yield + a recording object with two attributes: `output` and `records`. + At the end of the context manager, the `output` attribute will + be a list of the matching formatted log messages and the + `records` attribute will be a list of the corresponding LogRecord + objects. + Example:: + with self.assertLogs('foo', level='INFO') as cm: + logging.getLogger('foo').info('first message') + logging.getLogger('foo.bar').error('second message') + self.assertEqual(cm.output, ['INFO:foo:first message', + 'ERROR:foo.bar:second message']) + """ + return AssertLogsContext(self, logger, level) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/tests/test_util.py new/certbot-nginx-1.4.0/tests/test_util.py --- old/certbot-nginx-1.3.0/tests/test_util.py 2020-03-03 21:36:36.000000000 +0100 +++ new/certbot-nginx-1.4.0/tests/test_util.py 2020-05-05 21:37:33.000000000 +0200 @@ -4,7 +4,10 @@ import tempfile import josepy as jose -import mock +try: + import mock +except ImportError: # pragma: no cover + from unittest import mock # type: ignore import pkg_resources import zope.component @@ -14,9 +17,10 @@ from certbot.tests import util as test_util from certbot_nginx._internal import configurator from certbot_nginx._internal import nginxparser +import test_log_util -class NginxTest(test_util.ConfigTestCase): +class NginxTest(test_log_util.AssertLogsMixin, test_util.ConfigTestCase): def setUp(self): super(NginxTest, self).setUp() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/tests/testdata/etc_nginx/invalid_unicode_comments.conf new/certbot-nginx-1.4.0/tests/testdata/etc_nginx/invalid_unicode_comments.conf --- old/certbot-nginx-1.3.0/tests/testdata/etc_nginx/invalid_unicode_comments.conf 1970-01-01 01:00:00.000000000 +0100 +++ new/certbot-nginx-1.4.0/tests/testdata/etc_nginx/invalid_unicode_comments.conf 2020-05-05 21:37:33.000000000 +0200 @@ -0,0 +1,7 @@ +# This configuration file is saved with EUC-KR (a.k.a. cp949) encoding, +# including some Korean letters. + +server { + # �ȳ��ϼ���. 80�� ��Ʈ���� ��û�� ��ٸ���. + listen 80; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/certbot-nginx-1.3.0/tests/testdata/etc_nginx/valid_unicode_comments.conf new/certbot-nginx-1.4.0/tests/testdata/etc_nginx/valid_unicode_comments.conf --- old/certbot-nginx-1.3.0/tests/testdata/etc_nginx/valid_unicode_comments.conf 1970-01-01 01:00:00.000000000 +0100 +++ new/certbot-nginx-1.4.0/tests/testdata/etc_nginx/valid_unicode_comments.conf 2020-05-05 21:37:33.000000000 +0200 @@ -0,0 +1,9 @@ +# This configuration file is saved with valid UTF-8 encoding, +# including some CJK alphabets. + +server { + # 안녕하세요. 80번 포트에서 요청을 기다린다. + # こんにちは。80番ポートからリクエストを待つ。 + # 你好。等待端口80上的请求。 + listen 80; +}