New Upstream Release - transip

Ready changes

Summary

Merged new upstream version: 2.1.2 (was: 2.0.0).

Resulting package

Built on 2022-05-21T02:39 (took 1m59s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-releases python3-transipapt install -t fresh-releases transip

Lintian Result

Diff

diff --git a/.travis.yml b/.travis.yml
index 14a36a4..8d0ebee 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,10 @@
-sudo: no
+sudo: false
 language: python
 cache: pip
 
 python:
+  - "3.8"
+  - "3.7"
   - "3.6"
   - "3.5"
   - "3.4"
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index a1ade4e..3e85ca3 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -5,6 +5,24 @@ Changelog
 This document records all notable changes to `transip-api <https://github.com/benkonrath/transip-api>`_.
 This project adheres to `Semantic Versioning <http://semver.org/>`_.
 
+`2.1.2`_ (2020-03-29)
+---------------------
+
+* Fix --api-key CLI argument.
+* Test on Python 3.7 & 3.8.
+
+`2.1.1`_ (2020-03-15)
+---------------------
+
+* Fixed syntax problem in README.rst.
+
+`2.1.0`_ (2020-03-15)
+---------------------
+
+* Added a workaround for backwards incompatible change in the TransIP SOAP API.
+* Fixed bug in `DomainService.get_info`.
+* Add `remove_dns_entries` and `add_dns_entries` functions on DomainService.
+
 `2.0.0`_ (2019-03-17)
 ---------------------
 
@@ -46,3 +64,5 @@ This project adheres to `Semantic Versioning <http://semver.org/>`_.
 .. _1.0.0: https://github.com/benkonrath/transip-api/compare/0.4.1...v1.0.0
 .. _1.0.1: https://github.com/benkonrath/transip-api/compare/v1.0.0...v1.0.1
 .. _2.0.0: https://github.com/benkonrath/transip-api/compare/v1.0.1...v2.0.0
+.. _2.1.0: https://github.com/benkonrath/transip-api/compare/v2.0.0...v2.1.0
+.. _2.1.1: https://github.com/benkonrath/transip-api/compare/v2.1.0...v2.1.1
diff --git a/README.rst b/README.rst
index 50ca662..18a8782 100644
--- a/README.rst
+++ b/README.rst
@@ -29,10 +29,11 @@ Prerequisite
 Setup
 -----
 
-.. code-block::
+You can get the library directly from PyPi:
 
-	$ python setup.py install
+.. code-block::
 
+    $ pip install transip
 
 Example
 -------
@@ -108,7 +109,7 @@ Question:
 Answer:
 
     The `suds` library has fairly limited SSL support which is dependent on the Python version, to work around this the `suds_requests` library can be used which replaces `urllib2` with the `requests` library. Additionally the `requests` library automatically pools connections which makes the library slightly faster to use.
-   To install:
+    To install:
 
     .. code-block::
 
diff --git a/debian/changelog b/debian/changelog
index f4f73da..85e0af2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+transip (2.1.2-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Sat, 21 May 2022 02:37:59 -0000
+
 transip (2.0.0-3) unstable; urgency=high
 
   * Team upload.
diff --git a/dev_requirements.txt b/dev_requirements.txt
index 6ec2858..1aa190a 100644
--- a/dev_requirements.txt
+++ b/dev_requirements.txt
@@ -6,5 +6,7 @@ coverage
 sphinx
 suds-jurko
 rsa
-pylint==1.9.2
+# colorama dropped Python 3.4 in releases >= 0.4.2
+colorama==0.4.1
+pylint==2.4.4
 -e .
diff --git a/docs/index.rst b/docs/index.rst
index 45da1eb..b1279fc 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -24,9 +24,9 @@ Here is an example of a simple Python program:
    # Order a Vps without addons:
    client.order_vps('vps-bladevps-x1', None, 'ubuntu-18.04', 'vps-name')
 
-You can get the library directly from PyPI::
+You can get the library directly from PyPi::
 
-   pip install transip-api
+   pip install transip
 
 Documentation
 -------------
diff --git a/setup.py b/setup.py
index bf92d96..30ecf8f 100644
--- a/setup.py
+++ b/setup.py
@@ -56,6 +56,8 @@ setup(
         'Programming Language :: Python :: 3.4',
         'Programming Language :: Python :: 3.5',
         'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: 3.7',
+        'Programming Language :: Python :: 3.8',
         'Topic :: Utilities',
     ],
 )
diff --git a/tests/service_tests/test_dns.py b/tests/service_tests/test_dns.py
index 1aa47b8..00b6a3d 100644
--- a/tests/service_tests/test_dns.py
+++ b/tests/service_tests/test_dns.py
@@ -12,5 +12,7 @@ class TestDnsEntry(unittest.TestCase):
         dns_entry_two.expire = 600
         self.assertEqual(dns_entry_one, dns_entry_two)
 
+        self.assertNotEqual(dns_entry_one, [dns_entry_two])
+
         dns_entry_two.content = '127.0.0.1'
         self.assertNotEqual(dns_entry_one, dns_entry_two)
diff --git a/tests/service_tests/test_domain.py b/tests/service_tests/test_domain.py
index 1c54d0a..ffc1b4c 100644
--- a/tests/service_tests/test_domain.py
+++ b/tests/service_tests/test_domain.py
@@ -102,6 +102,70 @@ class TestDomainService(unittest.TestCase):
         ds.update_cookie.assert_called_with({"cookie": "value"})
         i.service.setDnsEntries.assert_called_with('domain1', [dns_entry, ])
 
+    @patch('transip.client.SudsClient')
+    def test_add_dns_entries(self, mock_client):
+        ds = DomainService('sundayafternoon')
+        ds.build_cookie = Mock(return_value={'cookie': 'value'})
+        ds.update_cookie = Mock()
+        getinfo_result = Mock()
+        dns_entry1 = DnsEntry(
+            'testentry1',
+            86400,
+            DnsEntry.TYPE_A,
+            '127.0.0.1',
+        )
+        dns_entry2 = DnsEntry(
+            'testentry2',
+            86400,
+            DnsEntry.TYPE_A,
+            '127.0.0.1',
+        )
+        getinfo_result.dnsEntries = [
+            dns_entry1,
+            dns_entry2,
+        ]
+        mock_client.return_value.service.getInfo.return_value = getinfo_result
+        dns_entry3 = DnsEntry(
+            'testentry3',
+            86400,
+            DnsEntry.TYPE_A,
+            '127.0.0.1',
+        )
+        ds.add_dns_entries('domain1', [dns_entry3])
+        mock_client.return_value.service.setDnsEntries.assert_called_with(
+            'domain1',
+            [dns_entry1, dns_entry2, dns_entry3],
+        )
+
+    @patch('transip.client.SudsClient')
+    def test_remove_dns_entries(self, mock_client):
+        ds = DomainService('sundayafternoon')
+        ds.build_cookie = Mock(return_value={'cookie': 'value'})
+        ds.update_cookie = Mock()
+        getinfo_result = Mock()
+        dns_entry1 = DnsEntry(
+            'testentry1',
+            86400,
+            DnsEntry.TYPE_A,
+            '127.0.0.1',
+        )
+        dns_entry2 = DnsEntry(
+            'testentry2',
+            86400,
+            DnsEntry.TYPE_A,
+            '127.0.0.1',
+        )
+        getinfo_result.dnsEntries = [
+            dns_entry1,
+            dns_entry2,
+        ]
+        mock_client.return_value.service.getInfo.return_value = getinfo_result
+        ds.remove_dns_entries('domain1', [dns_entry1])
+        mock_client.return_value.service.setDnsEntries.assert_called_with(
+            'domain1',
+            [dns_entry2],
+        )
+
     def test_batch_check_availability(self):
         self._generic_test(
             soap_method='batchCheckAvailability',
@@ -305,4 +369,4 @@ class TestDomainService(unittest.TestCase):
             result='string',
             parameters=('example.com',),
             mode=MODE_RO
-        )
\ No newline at end of file
+        )
diff --git a/transip/__init__.py b/transip/__init__.py
index 5cb1616..9028e9f 100644
--- a/transip/__init__.py
+++ b/transip/__init__.py
@@ -6,4 +6,4 @@
     For usage of the API itself, please see https://www.transip.eu/transip/api/
 """
 
-__version__ = '2.0.0'
+__version__ = '2.1.2'
diff --git a/transip/client.py b/transip/client.py
index 44d5fc3..30d1b37 100644
--- a/transip/client.py
+++ b/transip/client.py
@@ -17,6 +17,7 @@ from cryptography.hazmat.primitives.asymmetric import padding
 from suds.client import Client as SudsClient
 from suds.sudsobject import Object as SudsObject
 from suds.xsd.doctor import Import, ImportDoctor
+from suds.plugin import DocumentPlugin
 
 from . import __version__
 
@@ -53,7 +54,22 @@ def convert_value(value):
     return value
 
 
+class WSDLFixPlugin(DocumentPlugin):
+    # pylint: disable=W0232
+    """
+    A SudsFilter to fix wsdl document before it is parsed.
+    """
+
+    def loaded(self, context):
+        # pylint: disable=R0201
+        """
+        Replaces an invalid type in the wsdl document with a validy type.
+        """
+        context.document = context.document.replace(b'xsd:array', b'soapenc:Array')
+
+
 class Client(object):
+    # pylint: disable=R0205
     """
     A client-base class, for other classes to base their service implementation
     on. Contains methods to set and sign cookie and to retrieve the correct
@@ -87,7 +103,7 @@ class Client(object):
         if suds_requests:
             suds_kwargs['transport'] = suds_requests.RequestsTransport()
 
-        self.soap_client = SudsClient(self.url, doctor=doc, **suds_kwargs)
+        self.soap_client = SudsClient(self.url, doctor=doc, plugins=[WSDLFixPlugin()], **suds_kwargs)
 
     def _sign(self, message):
         """ Uses the decrypted private key to sign the message. """
diff --git a/transip/service/domain.py b/transip/service/domain.py
index 171e18e..1d83221 100644
--- a/transip/service/domain.py
+++ b/transip/service/domain.py
@@ -152,6 +152,29 @@ class DomainService(Client):
         """
         return self._simple_request('setDnsEntries', domain_name, dns_entries, mode=MODE_RW)
 
+    def add_dns_entries(self, domain_name, dns_entries):
+        """
+        Adds the given DnsEntries to the domain.
+        :type domain_name: str
+        :type dns_entries: list of transip.service.objects.DnsEntry
+        """
+        old_dns_entries = self.get_info(domain_name).dnsEntries
+        return self.set_dns_entries(domain_name, old_dns_entries + dns_entries)
+
+    def remove_dns_entries(self, domain_name, dns_entries):
+        """
+        Removes the given DnsEntries from the domain.
+        :type domain_name: str
+        :type dns_entries: list of transip.service.objects.DnsEntry to remove, cannot be empty
+        """
+        if not dns_entries:
+            raise ValueError('dns_entries cannot be empty.')
+        old_dns_entries = self.get_info(domain_name).dnsEntries
+        # Remove the DNS entries from the existing DNS entries
+        for entry in dns_entries:
+            old_dns_entries.remove(entry)
+        return self.set_dns_entries(domain_name, old_dns_entries)
+
     def set_owner(self, domain_name, registrant_whois_contact):
         """
         Transip_DomainService::batchGetInfo
diff --git a/transip/service/objects.py b/transip/service/objects.py
index 7336fb3..5bfee1b 100644
--- a/transip/service/objects.py
+++ b/transip/service/objects.py
@@ -50,7 +50,7 @@ class DnsEntry(SudsObject):
 
     def __eq__(self, other):
         # other can be a list. This check ensures that other is a DnsEntry.
-        if not hasattr(self, 'name') or not hasattr(self, 'type') or not hasattr(self, 'content'):
+        if isinstance(other, list):
             return False
 
         # expire is intentionally not used for equality.
diff --git a/transip/transip_cli.py b/transip/transip_cli.py
index 7d790a0..cbc57db 100644
--- a/transip/transip_cli.py
+++ b/transip/transip_cli.py
@@ -5,6 +5,7 @@ from __future__ import print_function
 
 import argparse
 import logging
+import sys
 
 from suds import WebFault
 
@@ -26,7 +27,7 @@ def show_dns_entries(domain_service, domain_name):
         dns_entries = domain_service.get_info(domain_name).dnsEntries
     except WebFault as err:
         print(err)
-        exit(1)
+        sys.exit(1)
     print(dns_entries)
 
 
@@ -41,14 +42,14 @@ def update_dns(domain_service, args):
         dns_entries = domain_service.get_info(args.domain_name).dnsEntries
     except WebFault as err:
         print(err)
-        exit(1)
+        sys.exit(1)
 
     number_of_entries = len(dns_entries)
     for entry in dns_entries:
         if args.add_dns_entry and entry.name == args.entry_name and entry.type == args.entry_type and \
                 entry.content == args.entry_content:
             print('The DNS entry already exists.')
-            exit(1)
+            sys.exit(1)
 
         elif args.update_dns_entry and entry.name == args.entry_name and entry.type == args.entry_type:
             dns_entries.remove(entry)
@@ -60,7 +61,7 @@ def update_dns(domain_service, args):
     if args.update_dns_entry or args.delete_dns_entry:
         if number_of_entries == len(dns_entries):
             print('The DNS entry was not found.')
-            exit(1)
+            sys.exit(1)
 
     if args.add_dns_entry or args.update_dns_entry:
         dns_entries.append(DnsEntry(args.entry_name, args.entry_expire, args.entry_type, args.entry_content))
@@ -69,7 +70,7 @@ def update_dns(domain_service, args):
         result = domain_service.set_dns_entries(args.domain_name, dns_entries)
     except WebFault as err:
         print(err)
-        exit(1)
+        sys.exit(1)
     if result is None:
         print('Request finished successfully.')
     else:
@@ -94,30 +95,30 @@ def main():
 
     if not args.loginname:
         print('Please provide your TransIP username.')
-        exit(1)
+        sys.exit(1)
 
     if not args.api_key_file:
         args.api_key_file = 'decrypted_key'
 
-    domain_service = DomainService(args.loginname, args.api_key_file)
+    domain_service = DomainService(args.loginname, private_key_file=args.api_key_file)
 
     if args.add_dns_entry or args.update_dns_entry or args.delete_dns_entry:
         if [args.add_dns_entry, args.update_dns_entry, args.delete_dns_entry].count(True) > 1:
             print('Please use only one of the options: '
                   '-a/--add-dns-entry, -u/--update-dns-entry, -d/--delete-dns-entry')
-            exit(1)
+            sys.exit(1)
 
         if args.domain_name and args.entry_name and args.entry_expire and args.entry_type and args.entry_content:
             update_dns(domain_service, args)
         else:
             print('Please provide the details of the DNS entry.')
-            exit(1)
+            sys.exit(1)
     elif args.show_dns_entries:
         if args.domain_name:
             show_dns_entries(domain_service, args.domain_name)
         else:
             print('Please provide the domain name.')
-            exit(1)
+            sys.exit(1)
     else:
         names = domain_service.get_domain_names()
         print(names)

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.1.2.egg-info/PKG-INFO
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.1.2.egg-info/dependency_links.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.1.2.egg-info/entry_points.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.1.2.egg-info/not-zip-safe
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.1.2.egg-info/requires.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.1.2.egg-info/top_level.txt

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.0.0.egg-info/PKG-INFO
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.0.0.egg-info/dependency_links.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.0.0.egg-info/entry_points.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.0.0.egg-info/not-zip-safe
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.0.0.egg-info/requires.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/transip-2.0.0.egg-info/top_level.txt

No differences were encountered between the control files of package python3-transip

No differences were encountered between the control files of package transip

More details

Full run details