Hello community,

here is the log from the commit of package python-certbot-dns-cloudflare for 
openSUSE:Factory checked in at 2020-01-03 17:38:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-certbot-dns-cloudflare (Old)
 and      /work/SRC/openSUSE:Factory/.python-certbot-dns-cloudflare.new.6675 
(New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-certbot-dns-cloudflare"

Fri Jan  3 17:38:57 2020 rev:14 rq:760650 version:1.0.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-certbot-dns-cloudflare/python-certbot-dns-cloudflare.changes
      2019-11-15 00:22:24.127906286 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-certbot-dns-cloudflare.new.6675/python-certbot-dns-cloudflare.changes
    2020-01-03 17:39:10.731363255 +0100
@@ -1,0 +2,6 @@
+Fri Jan  3 11:37:04 UTC 2020 - Marketa Calabkova <[email protected]>
+
+- update to version 1.0.0
+  * sync with main certbot package
+
+-------------------------------------------------------------------

Old:
----
  certbot-dns-cloudflare-0.40.1.tar.gz

New:
----
  certbot-dns-cloudflare-1.0.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-certbot-dns-cloudflare.spec ++++++
--- /var/tmp/diff_new_pack.UDJmyE/_old  2020-01-03 17:39:11.311363553 +0100
+++ /var/tmp/diff_new_pack.UDJmyE/_new  2020-01-03 17:39:11.335363566 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-certbot-dns-cloudflare
 #
-# Copyright (c) 2019 SUSE LLC.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,24 +18,24 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-certbot-dns-cloudflare
-Version:        0.40.1
+Version:        1.0.0
 Release:        0
 Summary:        Cloudflare Authenticator plugin for Certbot
 License:        Apache-2.0
 URL:            https://github.com/certbot/certbot
 Source:         
https://files.pythonhosted.org/packages/source/c/certbot-dns-cloudflare/certbot-dns-cloudflare-%{version}.tar.gz
 BuildRequires:  %{python_module acme >= 0.29.0}
-BuildRequires:  %{python_module certbot >= 0.34.0}
-BuildRequires:  %{python_module cloudflare}
+BuildRequires:  %{python_module certbot >= 1.0.0}
+BuildRequires:  %{python_module cloudflare >= 1.5.1}
 BuildRequires:  %{python_module mock}
+BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  %{python_module zope.interface}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-Requires:       python-acme >= 0.25.0
-Requires:       python-certbot >= 0.34.0
-Requires:       python-cloudflare
-Requires:       python-dns-lexicon >= 2.2.1
+Requires:       python-acme >= 0.29.0
+Requires:       python-certbot >= 1.0.0
+Requires:       python-cloudflare >= 1.5.1
 Requires:       python-zope.interface
 BuildArch:      noarch
 %python_subpackages

++++++ certbot-dns-cloudflare-0.40.1.tar.gz -> 
certbot-dns-cloudflare-1.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/certbot-dns-cloudflare-0.40.1/MANIFEST.in 
new/certbot-dns-cloudflare-1.0.0/MANIFEST.in
--- old/certbot-dns-cloudflare-0.40.1/MANIFEST.in       2019-11-06 
03:24:51.000000000 +0100
+++ new/certbot-dns-cloudflare-1.0.0/MANIFEST.in        2019-12-03 
18:20:30.000000000 +0100
@@ -1,3 +1,6 @@
 include LICENSE.txt
 include README.rst
 recursive-include docs *
+recursive-include tests *
+global-exclude __pycache__
+global-exclude *.py[cod]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/certbot-dns-cloudflare-0.40.1/PKG-INFO 
new/certbot-dns-cloudflare-1.0.0/PKG-INFO
--- old/certbot-dns-cloudflare-0.40.1/PKG-INFO  2019-11-06 03:25:01.000000000 
+0100
+++ new/certbot-dns-cloudflare-1.0.0/PKG-INFO   2019-12-03 18:20:49.000000000 
+0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: certbot-dns-cloudflare
-Version: 0.40.1
+Version: 1.0.0
 Summary: Cloudflare DNS Authenticator plugin for Certbot
 Home-page: https://github.com/certbot/certbot
 Author: Certbot Project
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare/_internal/__init__.py 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare/_internal/__init__.py
--- 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare/_internal/__init__.py  
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare/_internal/__init__.py   
    2019-12-03 18:20:30.000000000 +0100
@@ -0,0 +1 @@
+"""Internal implementation of `~certbot_dns_cloudflare.dns_cloudflare` 
plugin."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare/_internal/dns_cloudflare.py
 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare/_internal/dns_cloudflare.py
--- 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare/_internal/dns_cloudflare.py
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare/_internal/dns_cloudflare.py
 2019-12-03 18:20:30.000000000 +0100
@@ -0,0 +1,199 @@
+"""DNS Authenticator for Cloudflare."""
+import logging
+
+import CloudFlare
+import zope.interface
+
+from certbot import errors
+from certbot import interfaces
+from certbot.plugins import dns_common
+
+logger = logging.getLogger(__name__)
+
+ACCOUNT_URL = 'https://dash.cloudflare.com/profile/api-tokens'
+
+
[email protected](interfaces.IAuthenticator)
[email protected](interfaces.IPluginFactory)
+class Authenticator(dns_common.DNSAuthenticator):
+    """DNS Authenticator for Cloudflare
+
+    This Authenticator uses the Cloudflare API to fulfill a dns-01 challenge.
+    """
+
+    description = ('Obtain certificates using a DNS TXT record (if you are 
using Cloudflare for '
+                   'DNS).')
+    ttl = 120
+
+    def __init__(self, *args, **kwargs):
+        super(Authenticator, self).__init__(*args, **kwargs)
+        self.credentials = None
+
+    @classmethod
+    def add_parser_arguments(cls, add):  # pylint: disable=arguments-differ
+        super(Authenticator, cls).add_parser_arguments(add)
+        add('credentials', help='Cloudflare credentials INI file.')
+
+    def more_info(self):  # pylint: disable=missing-docstring,no-self-use
+        return 'This plugin configures a DNS TXT record to respond to a dns-01 
challenge using ' + \
+               'the Cloudflare API.'
+
+    def _setup_credentials(self):
+        self.credentials = self._configure_credentials(
+            'credentials',
+            'Cloudflare credentials INI file',
+            {
+                'email': 'email address associated with Cloudflare account',
+                'api-key': 'API key for Cloudflare account, obtained from 
{0}'.format(ACCOUNT_URL)
+            }
+        )
+
+    def _perform(self, domain, validation_name, validation):
+        self._get_cloudflare_client().add_txt_record(domain, validation_name, 
validation, self.ttl)
+
+    def _cleanup(self, domain, validation_name, validation):
+        self._get_cloudflare_client().del_txt_record(domain, validation_name, 
validation)
+
+    def _get_cloudflare_client(self):
+        return _CloudflareClient(self.credentials.conf('email'), 
self.credentials.conf('api-key'))
+
+
+class _CloudflareClient(object):
+    """
+    Encapsulates all communication with the Cloudflare API.
+    """
+
+    def __init__(self, email, api_key):
+        self.cf = CloudFlare.CloudFlare(email, api_key)
+
+    def add_txt_record(self, domain, record_name, record_content, record_ttl):
+        """
+        Add a TXT record using the supplied information.
+
+        :param str domain: The domain to use to look up the Cloudflare zone.
+        :param str record_name: The record name (typically beginning with 
'_acme-challenge.').
+        :param str record_content: The record content (typically the challenge 
validation).
+        :param int record_ttl: The record TTL (number of seconds that the 
record may be cached).
+        :raises certbot.errors.PluginError: if an error occurs communicating 
with the Cloudflare API
+        """
+
+        zone_id = self._find_zone_id(domain)
+
+        data = {'type': 'TXT',
+                'name': record_name,
+                'content': record_content,
+                'ttl': record_ttl}
+
+        try:
+            logger.debug('Attempting to add record to zone %s: %s', zone_id, 
data)
+            self.cf.zones.dns_records.post(zone_id, data=data)  # zones | 
pylint: disable=no-member
+        except CloudFlare.exceptions.CloudFlareAPIError as e:
+            logger.error('Encountered CloudFlareAPIError adding TXT record: %d 
%s', e, e)
+            raise errors.PluginError('Error communicating with the Cloudflare 
API: {0}'.format(e))
+
+        record_id = self._find_txt_record_id(zone_id, record_name, 
record_content)
+        logger.debug('Successfully added TXT record with record_id: %s', 
record_id)
+
+    def del_txt_record(self, domain, record_name, record_content):
+        """
+        Delete a TXT record using the supplied information.
+
+        Note that both the record's name and content are used to ensure that 
similar records
+        created concurrently (e.g., due to concurrent invocations of this 
plugin) are not deleted.
+
+        Failures are logged, but not raised.
+
+        :param str domain: The domain to use to look up the Cloudflare zone.
+        :param str record_name: The record name (typically beginning with 
'_acme-challenge.').
+        :param str record_content: The record content (typically the challenge 
validation).
+        """
+
+        try:
+            zone_id = self._find_zone_id(domain)
+        except errors.PluginError as e:
+            logger.debug('Encountered error finding zone_id during deletion: 
%s', e)
+            return
+
+        if zone_id:
+            record_id = self._find_txt_record_id(zone_id, record_name, 
record_content)
+            if record_id:
+                try:
+                    # zones | pylint: disable=no-member
+                    self.cf.zones.dns_records.delete(zone_id, record_id)
+                    logger.debug('Successfully deleted TXT record.')
+                except CloudFlare.exceptions.CloudFlareAPIError as e:
+                    logger.warning('Encountered CloudFlareAPIError deleting 
TXT record: %s', e)
+            else:
+                logger.debug('TXT record not found; no cleanup needed.')
+        else:
+            logger.debug('Zone not found; no cleanup needed.')
+
+    def _find_zone_id(self, domain):
+        """
+        Find the zone_id for a given domain.
+
+        :param str domain: The domain for which to find the zone_id.
+        :returns: The zone_id, if found.
+        :rtype: str
+        :raises certbot.errors.PluginError: if no zone_id is found.
+        """
+
+        zone_name_guesses = dns_common.base_domain_name_guesses(domain)
+
+        for zone_name in zone_name_guesses:
+            params = {'name': zone_name,
+                      'per_page': 1}
+
+            try:
+                zones = self.cf.zones.get(params=params)  # zones | pylint: 
disable=no-member
+            except CloudFlare.exceptions.CloudFlareAPIError as e:
+                code = int(e)
+                hint = None
+
+                if code == 6003:
+                    hint = 'Did you copy your entire API key?'
+                elif code == 9103:
+                    hint = 'Did you enter the correct email address?'
+
+                raise errors.PluginError('Error determining zone_id: {0} {1}. 
Please confirm that '
+                                         'you have supplied valid Cloudflare 
API credentials.{2}'
+                                         .format(code, e, ' 
({0})'.format(hint) if hint else ''))
+
+            if zones:
+                zone_id = zones[0]['id']
+                logger.debug('Found zone_id of %s for %s using name %s', 
zone_id, domain, zone_name)
+                return zone_id
+
+        raise errors.PluginError('Unable to determine zone_id for {0} using 
zone names: {1}. '
+                                 'Please confirm that the domain name has been 
entered correctly '
+                                 'and is already associated with the supplied 
Cloudflare account.'
+                                 .format(domain, zone_name_guesses))
+
+    def _find_txt_record_id(self, zone_id, record_name, record_content):
+        """
+        Find the record_id for a TXT record with the given name and content.
+
+        :param str zone_id: The zone_id which contains the record.
+        :param str record_name: The record name (typically beginning with 
'_acme-challenge.').
+        :param str record_content: The record content (typically the challenge 
validation).
+        :returns: The record_id, if found.
+        :rtype: str
+        """
+
+        params = {'type': 'TXT',
+                  'name': record_name,
+                  'content': record_content,
+                  'per_page': 1}
+        try:
+            # zones | pylint: disable=no-member
+            records = self.cf.zones.dns_records.get(zone_id, params=params)
+        except CloudFlare.exceptions.CloudFlareAPIError as e:
+            logger.debug('Encountered CloudFlareAPIError getting TXT 
record_id: %s', e)
+            records = []
+
+        if records:
+            # Cleanup is returning the system to the state we found it. If, 
for some reason,
+            # there are multiple matching records, we only delete one because 
we only added one.
+            return records[0]['id']
+        logger.debug('Unable to find TXT record.')
+        return None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare/dns_cloudflare.py 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare/dns_cloudflare.py
--- old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare/dns_cloudflare.py  
2019-11-06 03:24:51.000000000 +0100
+++ new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare/dns_cloudflare.py   
1970-01-01 01:00:00.000000000 +0100
@@ -1,199 +0,0 @@
-"""DNS Authenticator for Cloudflare."""
-import logging
-
-import CloudFlare
-import zope.interface
-
-from certbot import errors
-from certbot import interfaces
-from certbot.plugins import dns_common
-
-logger = logging.getLogger(__name__)
-
-ACCOUNT_URL = 'https://dash.cloudflare.com/profile/api-tokens'
-
-
[email protected](interfaces.IAuthenticator)
[email protected](interfaces.IPluginFactory)
-class Authenticator(dns_common.DNSAuthenticator):
-    """DNS Authenticator for Cloudflare
-
-    This Authenticator uses the Cloudflare API to fulfill a dns-01 challenge.
-    """
-
-    description = ('Obtain certificates using a DNS TXT record (if you are 
using Cloudflare for '
-                   'DNS).')
-    ttl = 120
-
-    def __init__(self, *args, **kwargs):
-        super(Authenticator, self).__init__(*args, **kwargs)
-        self.credentials = None
-
-    @classmethod
-    def add_parser_arguments(cls, add):  # pylint: disable=arguments-differ
-        super(Authenticator, cls).add_parser_arguments(add)
-        add('credentials', help='Cloudflare credentials INI file.')
-
-    def more_info(self):  # pylint: disable=missing-docstring,no-self-use
-        return 'This plugin configures a DNS TXT record to respond to a dns-01 
challenge using ' + \
-               'the Cloudflare API.'
-
-    def _setup_credentials(self):
-        self.credentials = self._configure_credentials(
-            'credentials',
-            'Cloudflare credentials INI file',
-            {
-                'email': 'email address associated with Cloudflare account',
-                'api-key': 'API key for Cloudflare account, obtained from 
{0}'.format(ACCOUNT_URL)
-            }
-        )
-
-    def _perform(self, domain, validation_name, validation):
-        self._get_cloudflare_client().add_txt_record(domain, validation_name, 
validation, self.ttl)
-
-    def _cleanup(self, domain, validation_name, validation):
-        self._get_cloudflare_client().del_txt_record(domain, validation_name, 
validation)
-
-    def _get_cloudflare_client(self):
-        return _CloudflareClient(self.credentials.conf('email'), 
self.credentials.conf('api-key'))
-
-
-class _CloudflareClient(object):
-    """
-    Encapsulates all communication with the Cloudflare API.
-    """
-
-    def __init__(self, email, api_key):
-        self.cf = CloudFlare.CloudFlare(email, api_key)
-
-    def add_txt_record(self, domain, record_name, record_content, record_ttl):
-        """
-        Add a TXT record using the supplied information.
-
-        :param str domain: The domain to use to look up the Cloudflare zone.
-        :param str record_name: The record name (typically beginning with 
'_acme-challenge.').
-        :param str record_content: The record content (typically the challenge 
validation).
-        :param int record_ttl: The record TTL (number of seconds that the 
record may be cached).
-        :raises certbot.errors.PluginError: if an error occurs communicating 
with the Cloudflare API
-        """
-
-        zone_id = self._find_zone_id(domain)
-
-        data = {'type': 'TXT',
-                'name': record_name,
-                'content': record_content,
-                'ttl': record_ttl}
-
-        try:
-            logger.debug('Attempting to add record to zone %s: %s', zone_id, 
data)
-            self.cf.zones.dns_records.post(zone_id, data=data)  # zones | 
pylint: disable=no-member
-        except CloudFlare.exceptions.CloudFlareAPIError as e:
-            logger.error('Encountered CloudFlareAPIError adding TXT record: %d 
%s', e, e)
-            raise errors.PluginError('Error communicating with the Cloudflare 
API: {0}'.format(e))
-
-        record_id = self._find_txt_record_id(zone_id, record_name, 
record_content)
-        logger.debug('Successfully added TXT record with record_id: %s', 
record_id)
-
-    def del_txt_record(self, domain, record_name, record_content):
-        """
-        Delete a TXT record using the supplied information.
-
-        Note that both the record's name and content are used to ensure that 
similar records
-        created concurrently (e.g., due to concurrent invocations of this 
plugin) are not deleted.
-
-        Failures are logged, but not raised.
-
-        :param str domain: The domain to use to look up the Cloudflare zone.
-        :param str record_name: The record name (typically beginning with 
'_acme-challenge.').
-        :param str record_content: The record content (typically the challenge 
validation).
-        """
-
-        try:
-            zone_id = self._find_zone_id(domain)
-        except errors.PluginError as e:
-            logger.debug('Encountered error finding zone_id during deletion: 
%s', e)
-            return
-
-        if zone_id:
-            record_id = self._find_txt_record_id(zone_id, record_name, 
record_content)
-            if record_id:
-                try:
-                    # zones | pylint: disable=no-member
-                    self.cf.zones.dns_records.delete(zone_id, record_id)
-                    logger.debug('Successfully deleted TXT record.')
-                except CloudFlare.exceptions.CloudFlareAPIError as e:
-                    logger.warning('Encountered CloudFlareAPIError deleting 
TXT record: %s', e)
-            else:
-                logger.debug('TXT record not found; no cleanup needed.')
-        else:
-            logger.debug('Zone not found; no cleanup needed.')
-
-    def _find_zone_id(self, domain):
-        """
-        Find the zone_id for a given domain.
-
-        :param str domain: The domain for which to find the zone_id.
-        :returns: The zone_id, if found.
-        :rtype: str
-        :raises certbot.errors.PluginError: if no zone_id is found.
-        """
-
-        zone_name_guesses = dns_common.base_domain_name_guesses(domain)
-
-        for zone_name in zone_name_guesses:
-            params = {'name': zone_name,
-                      'per_page': 1}
-
-            try:
-                zones = self.cf.zones.get(params=params)  # zones | pylint: 
disable=no-member
-            except CloudFlare.exceptions.CloudFlareAPIError as e:
-                code = int(e)
-                hint = None
-
-                if code == 6003:
-                    hint = 'Did you copy your entire API key?'
-                elif code == 9103:
-                    hint = 'Did you enter the correct email address?'
-
-                raise errors.PluginError('Error determining zone_id: {0} {1}. 
Please confirm that '
-                                         'you have supplied valid Cloudflare 
API credentials.{2}'
-                                         .format(code, e, ' 
({0})'.format(hint) if hint else ''))
-
-            if zones:
-                zone_id = zones[0]['id']
-                logger.debug('Found zone_id of %s for %s using name %s', 
zone_id, domain, zone_name)
-                return zone_id
-
-        raise errors.PluginError('Unable to determine zone_id for {0} using 
zone names: {1}. '
-                                 'Please confirm that the domain name has been 
entered correctly '
-                                 'and is already associated with the supplied 
Cloudflare account.'
-                                 .format(domain, zone_name_guesses))
-
-    def _find_txt_record_id(self, zone_id, record_name, record_content):
-        """
-        Find the record_id for a TXT record with the given name and content.
-
-        :param str zone_id: The zone_id which contains the record.
-        :param str record_name: The record name (typically beginning with 
'_acme-challenge.').
-        :param str record_content: The record content (typically the challenge 
validation).
-        :returns: The record_id, if found.
-        :rtype: str
-        """
-
-        params = {'type': 'TXT',
-                  'name': record_name,
-                  'content': record_content,
-                  'per_page': 1}
-        try:
-            # zones | pylint: disable=no-member
-            records = self.cf.zones.dns_records.get(zone_id, params=params)
-        except CloudFlare.exceptions.CloudFlareAPIError as e:
-            logger.debug('Encountered CloudFlareAPIError getting TXT 
record_id: %s', e)
-            records = []
-
-        if records:
-            # Cleanup is returning the system to the state we found it. If, 
for some reason,
-            # there are multiple matching records, we only delete one because 
we only added one.
-            return records[0]['id']
-        logger.debug('Unable to find TXT record.')
-        return None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare/dns_cloudflare_test.py 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare/dns_cloudflare_test.py
--- 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare/dns_cloudflare_test.py 
    2019-11-06 03:24:51.000000000 +0100
+++ 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare/dns_cloudflare_test.py  
    1970-01-01 01:00:00.000000000 +0100
@@ -1,174 +0,0 @@
-"""Tests for certbot_dns_cloudflare.dns_cloudflare."""
-
-import unittest
-
-import CloudFlare
-import mock
-
-from certbot import errors
-from certbot.compat import os
-from certbot.plugins import dns_test_common
-from certbot.plugins.dns_test_common import DOMAIN
-from certbot.tests import util as test_util
-
-API_ERROR = CloudFlare.exceptions.CloudFlareAPIError(1000, '', '')
-API_KEY = 'an-api-key'
-EMAIL = '[email protected]'
-
-
-class AuthenticatorTest(test_util.TempDirTestCase, 
dns_test_common.BaseAuthenticatorTest):
-
-    def setUp(self):
-        from certbot_dns_cloudflare.dns_cloudflare import Authenticator
-
-        super(AuthenticatorTest, self).setUp()
-
-        path = os.path.join(self.tempdir, 'file.ini')
-        dns_test_common.write({"cloudflare_email": EMAIL, 
"cloudflare_api_key": API_KEY}, path)
-
-        self.config = mock.MagicMock(cloudflare_credentials=path,
-                                     cloudflare_propagation_seconds=0)  # 
don't wait during tests
-
-        self.auth = Authenticator(self.config, "cloudflare")
-
-        self.mock_client = mock.MagicMock()
-        # _get_cloudflare_client | pylint: disable=protected-access
-        self.auth._get_cloudflare_client = 
mock.MagicMock(return_value=self.mock_client)
-
-    def test_perform(self):
-        self.auth.perform([self.achall])
-
-        expected = [mock.call.add_txt_record(DOMAIN, 
'_acme-challenge.'+DOMAIN, mock.ANY, mock.ANY)]
-        self.assertEqual(expected, self.mock_client.mock_calls)
-
-    def test_cleanup(self):
-        # _attempt_cleanup | pylint: disable=protected-access
-        self.auth._attempt_cleanup = True
-        self.auth.cleanup([self.achall])
-
-        expected = [mock.call.del_txt_record(DOMAIN, 
'_acme-challenge.'+DOMAIN, mock.ANY)]
-        self.assertEqual(expected, self.mock_client.mock_calls)
-
-
-class CloudflareClientTest(unittest.TestCase):
-    record_name = "foo"
-    record_content = "bar"
-    record_ttl = 42
-    zone_id = 1
-    record_id = 2
-
-    def setUp(self):
-        from certbot_dns_cloudflare.dns_cloudflare import _CloudflareClient
-
-        self.cloudflare_client = _CloudflareClient(EMAIL, API_KEY)
-
-        self.cf = mock.MagicMock()
-        self.cloudflare_client.cf = self.cf
-
-    def test_add_txt_record(self):
-        self.cf.zones.get.return_value = [{'id': self.zone_id}]
-
-        self.cloudflare_client.add_txt_record(DOMAIN, self.record_name, 
self.record_content,
-                                              self.record_ttl)
-
-        self.cf.zones.dns_records.post.assert_called_with(self.zone_id, 
data=mock.ANY)
-
-        post_data = self.cf.zones.dns_records.post.call_args[1]['data']
-
-        self.assertEqual('TXT', post_data['type'])
-        self.assertEqual(self.record_name, post_data['name'])
-        self.assertEqual(self.record_content, post_data['content'])
-        self.assertEqual(self.record_ttl, post_data['ttl'])
-
-    def test_add_txt_record_error(self):
-        self.cf.zones.get.return_value = [{'id': self.zone_id}]
-
-        self.cf.zones.dns_records.post.side_effect = API_ERROR
-
-        self.assertRaises(
-            errors.PluginError,
-            self.cloudflare_client.add_txt_record,
-            DOMAIN, self.record_name, self.record_content, self.record_ttl)
-
-    def test_add_txt_record_error_during_zone_lookup(self):
-        self.cf.zones.get.side_effect = API_ERROR
-
-        self.assertRaises(
-            errors.PluginError,
-            self.cloudflare_client.add_txt_record,
-            DOMAIN, self.record_name, self.record_content, self.record_ttl)
-
-    def test_add_txt_record_zone_not_found(self):
-        self.cf.zones.get.return_value = []
-
-        self.assertRaises(
-            errors.PluginError,
-            self.cloudflare_client.add_txt_record,
-            DOMAIN, self.record_name, self.record_content, self.record_ttl)
-
-    def test_del_txt_record(self):
-        self.cf.zones.get.return_value = [{'id': self.zone_id}]
-        self.cf.zones.dns_records.get.return_value = [{'id': self.record_id}]
-
-        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
-
-        expected = [mock.call.zones.get(params=mock.ANY),
-                    mock.call.zones.dns_records.get(self.zone_id, 
params=mock.ANY),
-                    mock.call.zones.dns_records.delete(self.zone_id, 
self.record_id)]
-
-        self.assertEqual(expected, self.cf.mock_calls)
-
-        get_data = self.cf.zones.dns_records.get.call_args[1]['params']
-
-        self.assertEqual('TXT', get_data['type'])
-        self.assertEqual(self.record_name, get_data['name'])
-        self.assertEqual(self.record_content, get_data['content'])
-
-    def test_del_txt_record_error_during_zone_lookup(self):
-        self.cf.zones.get.side_effect = API_ERROR
-
-        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
-
-    def test_del_txt_record_error_during_delete(self):
-        self.cf.zones.get.return_value = [{'id': self.zone_id}]
-        self.cf.zones.dns_records.get.return_value = [{'id': self.record_id}]
-        self.cf.zones.dns_records.delete.side_effect = API_ERROR
-
-        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
-        expected = [mock.call.zones.get(params=mock.ANY),
-                    mock.call.zones.dns_records.get(self.zone_id, 
params=mock.ANY),
-                    mock.call.zones.dns_records.delete(self.zone_id, 
self.record_id)]
-
-        self.assertEqual(expected, self.cf.mock_calls)
-
-    def test_del_txt_record_error_during_get(self):
-        self.cf.zones.get.return_value = [{'id': self.zone_id}]
-        self.cf.zones.dns_records.get.side_effect = API_ERROR
-
-        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
-        expected = [mock.call.zones.get(params=mock.ANY),
-                    mock.call.zones.dns_records.get(self.zone_id, 
params=mock.ANY)]
-
-        self.assertEqual(expected, self.cf.mock_calls)
-
-    def test_del_txt_record_no_record(self):
-        self.cf.zones.get.return_value = [{'id': self.zone_id}]
-        self.cf.zones.dns_records.get.return_value = []
-
-        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
-        expected = [mock.call.zones.get(params=mock.ANY),
-                    mock.call.zones.dns_records.get(self.zone_id, 
params=mock.ANY)]
-
-        self.assertEqual(expected, self.cf.mock_calls)
-
-    def test_del_txt_record_no_zone(self):
-        self.cf.zones.get.return_value = [{'id': None}]
-
-        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
-        expected = [mock.call.zones.get(params=mock.ANY)]
-
-        self.assertEqual(expected, self.cf.mock_calls)
-
-
-if __name__ == "__main__":
-    unittest.main()  # pragma: no cover
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare.egg-info/PKG-INFO 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare.egg-info/PKG-INFO
--- old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare.egg-info/PKG-INFO  
2019-11-06 03:25:01.000000000 +0100
+++ new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare.egg-info/PKG-INFO   
2019-12-03 18:20:49.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: certbot-dns-cloudflare
-Version: 0.40.1
+Version: 1.0.0
 Summary: Cloudflare DNS Authenticator plugin for Certbot
 Home-page: https://github.com/certbot/certbot
 Author: Certbot Project
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare.egg-info/SOURCES.txt 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare.egg-info/SOURCES.txt
--- 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare.egg-info/SOURCES.txt   
    2019-11-06 03:25:01.000000000 +0100
+++ 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare.egg-info/SOURCES.txt    
    2019-12-03 18:20:49.000000000 +0100
@@ -4,18 +4,18 @@
 setup.cfg
 setup.py
 certbot_dns_cloudflare/__init__.py
-certbot_dns_cloudflare/dns_cloudflare.py
-certbot_dns_cloudflare/dns_cloudflare_test.py
 certbot_dns_cloudflare.egg-info/PKG-INFO
 certbot_dns_cloudflare.egg-info/SOURCES.txt
 certbot_dns_cloudflare.egg-info/dependency_links.txt
 certbot_dns_cloudflare.egg-info/entry_points.txt
 certbot_dns_cloudflare.egg-info/requires.txt
 certbot_dns_cloudflare.egg-info/top_level.txt
+certbot_dns_cloudflare/_internal/__init__.py
+certbot_dns_cloudflare/_internal/dns_cloudflare.py
 docs/.gitignore
 docs/Makefile
 docs/api.rst
 docs/conf.py
 docs/index.rst
 docs/make.bat
-docs/api/dns_cloudflare.rst
\ No newline at end of file
+tests/dns_cloudflare_test.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare.egg-info/entry_points.txt
 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare.egg-info/entry_points.txt
--- 
old/certbot-dns-cloudflare-0.40.1/certbot_dns_cloudflare.egg-info/entry_points.txt
  2019-11-06 03:25:01.000000000 +0100
+++ 
new/certbot-dns-cloudflare-1.0.0/certbot_dns_cloudflare.egg-info/entry_points.txt
   2019-12-03 18:20:49.000000000 +0100
@@ -1,3 +1,3 @@
 [certbot.plugins]
-dns-cloudflare = certbot_dns_cloudflare.dns_cloudflare:Authenticator
+dns-cloudflare = certbot_dns_cloudflare._internal.dns_cloudflare:Authenticator
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/certbot-dns-cloudflare-0.40.1/docs/api/dns_cloudflare.rst 
new/certbot-dns-cloudflare-1.0.0/docs/api/dns_cloudflare.rst
--- old/certbot-dns-cloudflare-0.40.1/docs/api/dns_cloudflare.rst       
2019-11-06 03:24:51.000000000 +0100
+++ new/certbot-dns-cloudflare-1.0.0/docs/api/dns_cloudflare.rst        
1970-01-01 01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-:mod:`certbot_dns_cloudflare.dns_cloudflare`
---------------------------------------------
-
-.. automodule:: certbot_dns_cloudflare.dns_cloudflare
-   :members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/certbot-dns-cloudflare-0.40.1/docs/api.rst 
new/certbot-dns-cloudflare-1.0.0/docs/api.rst
--- old/certbot-dns-cloudflare-0.40.1/docs/api.rst      2019-11-06 
03:24:51.000000000 +0100
+++ new/certbot-dns-cloudflare-1.0.0/docs/api.rst       2019-12-03 
18:20:30.000000000 +0100
@@ -2,7 +2,4 @@
 API Documentation
 =================
 
-.. toctree::
-   :glob:
-
-   api/**
+Certbot plugins implement the Certbot plugins API, and do not otherwise have 
an external API.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/certbot-dns-cloudflare-0.40.1/setup.py 
new/certbot-dns-cloudflare-1.0.0/setup.py
--- old/certbot-dns-cloudflare-0.40.1/setup.py  2019-11-06 03:24:52.000000000 
+0100
+++ new/certbot-dns-cloudflare-1.0.0/setup.py   2019-12-03 18:20:32.000000000 
+0100
@@ -1,8 +1,10 @@
 from setuptools import setup
 from setuptools import find_packages
+from setuptools.command.test import test as TestCommand
+import sys
 
 
-version = '0.40.1'
+version = '1.0.0'
 
 # Remember to update local-oldest-requirements.txt when changing the minimum
 # acme/certbot version.
@@ -20,6 +22,20 @@
     'sphinx_rtd_theme',
 ]
 
+class PyTest(TestCommand):
+    user_options = []
+
+    def initialize_options(self):
+        TestCommand.initialize_options(self)
+        self.pytest_args = ''
+
+    def run_tests(self):
+        import shlex
+        # import here, cause outside the eggs aren't loaded
+        import pytest
+        errno = pytest.main(shlex.split(self.pytest_args))
+        sys.exit(errno)
+
 setup(
     name='certbot-dns-cloudflare',
     version=version,
@@ -60,8 +76,10 @@
     },
     entry_points={
         'certbot.plugins': [
-            'dns-cloudflare = 
certbot_dns_cloudflare.dns_cloudflare:Authenticator',
+            'dns-cloudflare = 
certbot_dns_cloudflare._internal.dns_cloudflare:Authenticator',
         ],
     },
+    tests_require=["pytest"],
     test_suite='certbot_dns_cloudflare',
+    cmdclass={"test": PyTest},
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/certbot-dns-cloudflare-0.40.1/tests/dns_cloudflare_test.py 
new/certbot-dns-cloudflare-1.0.0/tests/dns_cloudflare_test.py
--- old/certbot-dns-cloudflare-0.40.1/tests/dns_cloudflare_test.py      
1970-01-01 01:00:00.000000000 +0100
+++ new/certbot-dns-cloudflare-1.0.0/tests/dns_cloudflare_test.py       
2019-12-03 18:20:30.000000000 +0100
@@ -0,0 +1,174 @@
+"""Tests for certbot_dns_cloudflare._internal.dns_cloudflare."""
+
+import unittest
+
+import CloudFlare
+import mock
+
+from certbot import errors
+from certbot.compat import os
+from certbot.plugins import dns_test_common
+from certbot.plugins.dns_test_common import DOMAIN
+from certbot.tests import util as test_util
+
+API_ERROR = CloudFlare.exceptions.CloudFlareAPIError(1000, '', '')
+API_KEY = 'an-api-key'
+EMAIL = '[email protected]'
+
+
+class AuthenticatorTest(test_util.TempDirTestCase, 
dns_test_common.BaseAuthenticatorTest):
+
+    def setUp(self):
+        from certbot_dns_cloudflare._internal.dns_cloudflare import 
Authenticator
+
+        super(AuthenticatorTest, self).setUp()
+
+        path = os.path.join(self.tempdir, 'file.ini')
+        dns_test_common.write({"cloudflare_email": EMAIL, 
"cloudflare_api_key": API_KEY}, path)
+
+        self.config = mock.MagicMock(cloudflare_credentials=path,
+                                     cloudflare_propagation_seconds=0)  # 
don't wait during tests
+
+        self.auth = Authenticator(self.config, "cloudflare")
+
+        self.mock_client = mock.MagicMock()
+        # _get_cloudflare_client | pylint: disable=protected-access
+        self.auth._get_cloudflare_client = 
mock.MagicMock(return_value=self.mock_client)
+
+    def test_perform(self):
+        self.auth.perform([self.achall])
+
+        expected = [mock.call.add_txt_record(DOMAIN, 
'_acme-challenge.'+DOMAIN, mock.ANY, mock.ANY)]
+        self.assertEqual(expected, self.mock_client.mock_calls)
+
+    def test_cleanup(self):
+        # _attempt_cleanup | pylint: disable=protected-access
+        self.auth._attempt_cleanup = True
+        self.auth.cleanup([self.achall])
+
+        expected = [mock.call.del_txt_record(DOMAIN, 
'_acme-challenge.'+DOMAIN, mock.ANY)]
+        self.assertEqual(expected, self.mock_client.mock_calls)
+
+
+class CloudflareClientTest(unittest.TestCase):
+    record_name = "foo"
+    record_content = "bar"
+    record_ttl = 42
+    zone_id = 1
+    record_id = 2
+
+    def setUp(self):
+        from certbot_dns_cloudflare._internal.dns_cloudflare import 
_CloudflareClient
+
+        self.cloudflare_client = _CloudflareClient(EMAIL, API_KEY)
+
+        self.cf = mock.MagicMock()
+        self.cloudflare_client.cf = self.cf
+
+    def test_add_txt_record(self):
+        self.cf.zones.get.return_value = [{'id': self.zone_id}]
+
+        self.cloudflare_client.add_txt_record(DOMAIN, self.record_name, 
self.record_content,
+                                              self.record_ttl)
+
+        self.cf.zones.dns_records.post.assert_called_with(self.zone_id, 
data=mock.ANY)
+
+        post_data = self.cf.zones.dns_records.post.call_args[1]['data']
+
+        self.assertEqual('TXT', post_data['type'])
+        self.assertEqual(self.record_name, post_data['name'])
+        self.assertEqual(self.record_content, post_data['content'])
+        self.assertEqual(self.record_ttl, post_data['ttl'])
+
+    def test_add_txt_record_error(self):
+        self.cf.zones.get.return_value = [{'id': self.zone_id}]
+
+        self.cf.zones.dns_records.post.side_effect = API_ERROR
+
+        self.assertRaises(
+            errors.PluginError,
+            self.cloudflare_client.add_txt_record,
+            DOMAIN, self.record_name, self.record_content, self.record_ttl)
+
+    def test_add_txt_record_error_during_zone_lookup(self):
+        self.cf.zones.get.side_effect = API_ERROR
+
+        self.assertRaises(
+            errors.PluginError,
+            self.cloudflare_client.add_txt_record,
+            DOMAIN, self.record_name, self.record_content, self.record_ttl)
+
+    def test_add_txt_record_zone_not_found(self):
+        self.cf.zones.get.return_value = []
+
+        self.assertRaises(
+            errors.PluginError,
+            self.cloudflare_client.add_txt_record,
+            DOMAIN, self.record_name, self.record_content, self.record_ttl)
+
+    def test_del_txt_record(self):
+        self.cf.zones.get.return_value = [{'id': self.zone_id}]
+        self.cf.zones.dns_records.get.return_value = [{'id': self.record_id}]
+
+        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
+
+        expected = [mock.call.zones.get(params=mock.ANY),
+                    mock.call.zones.dns_records.get(self.zone_id, 
params=mock.ANY),
+                    mock.call.zones.dns_records.delete(self.zone_id, 
self.record_id)]
+
+        self.assertEqual(expected, self.cf.mock_calls)
+
+        get_data = self.cf.zones.dns_records.get.call_args[1]['params']
+
+        self.assertEqual('TXT', get_data['type'])
+        self.assertEqual(self.record_name, get_data['name'])
+        self.assertEqual(self.record_content, get_data['content'])
+
+    def test_del_txt_record_error_during_zone_lookup(self):
+        self.cf.zones.get.side_effect = API_ERROR
+
+        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
+
+    def test_del_txt_record_error_during_delete(self):
+        self.cf.zones.get.return_value = [{'id': self.zone_id}]
+        self.cf.zones.dns_records.get.return_value = [{'id': self.record_id}]
+        self.cf.zones.dns_records.delete.side_effect = API_ERROR
+
+        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
+        expected = [mock.call.zones.get(params=mock.ANY),
+                    mock.call.zones.dns_records.get(self.zone_id, 
params=mock.ANY),
+                    mock.call.zones.dns_records.delete(self.zone_id, 
self.record_id)]
+
+        self.assertEqual(expected, self.cf.mock_calls)
+
+    def test_del_txt_record_error_during_get(self):
+        self.cf.zones.get.return_value = [{'id': self.zone_id}]
+        self.cf.zones.dns_records.get.side_effect = API_ERROR
+
+        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
+        expected = [mock.call.zones.get(params=mock.ANY),
+                    mock.call.zones.dns_records.get(self.zone_id, 
params=mock.ANY)]
+
+        self.assertEqual(expected, self.cf.mock_calls)
+
+    def test_del_txt_record_no_record(self):
+        self.cf.zones.get.return_value = [{'id': self.zone_id}]
+        self.cf.zones.dns_records.get.return_value = []
+
+        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
+        expected = [mock.call.zones.get(params=mock.ANY),
+                    mock.call.zones.dns_records.get(self.zone_id, 
params=mock.ANY)]
+
+        self.assertEqual(expected, self.cf.mock_calls)
+
+    def test_del_txt_record_no_zone(self):
+        self.cf.zones.get.return_value = [{'id': None}]
+
+        self.cloudflare_client.del_txt_record(DOMAIN, self.record_name, 
self.record_content)
+        expected = [mock.call.zones.get(params=mock.ANY)]
+
+        self.assertEqual(expected, self.cf.mock_calls)
+
+
+if __name__ == "__main__":
+    unittest.main()  # pragma: no cover


Reply via email to