Repository: paragbaxi/qualysapi

Issue:
Drop support for Python 2.x
Since Python 2.7 is EOL January 1, 2020 and is currently failing in CI, can it be officially dropped from this project? I would be happy to make a PR.

Discussion:

Patch:
diff --git a/.travis.yml b/.travis.yml
index 120e5d2..21d3840 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,21 +2,14 @@ group: travis_latest
 language: python
 cache: pip
 python:
-    - 2.7
     - 3.5
     - 3.6
-# Enable newer 3.7 without globally enabling sudo and dist: xenial for other build jobs
+    - 3.7
+    - 3.8
+#    - 3.9-dev  # need to find out if Travis CI supports Py3.9
 matrix:
   allow_failures:
-    - python: 3.8-dev
-    - python: 3.5
-  include:
-    - python: 3.7
-      dist: xenial
-      sudo: true
-    - python: 3.8-dev
-      dist: xenial
-      sudo: true
+    - python: 3.9-dev
 install: "make"
 before_script:
     - make lint
diff --git a/README.md b/README.md
index ca560f7..2bb5e5a 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ qualysapi
 [![Coverage Status](https://coveralls.io/repos/github/paragbaxi/qualysapi/badge.svg?branch=master)](https://coveralls.io/github/paragbaxi/qualysapi?branch=master)
 
 Python package, qualysapi, that makes calling any Qualys API very simple. Qualys API versions v1, v2, & WAS & AM (asset management) are all supported.
- 
+
 My focus was making the API super easy to use. The only parameters the user needs to provide is the call, and data (optional). It automates the following:
 * Automatically identifies API version through the call requested.
 * Automatically identifies url from the above step.
@@ -21,7 +21,7 @@ There are currenty three methods of connecting to Qualys APIs
 
 * `qualysapi.connect()` will prompt the user for credentials at runtime.
 * `qualysapi.connect('/path/to/config.ini')` will parse the config file for credentials (see below).
-* `qualysapi.connect(username='username', password='password')` will use the provided credentials. 
+* `qualysapi.connect(username='username', password='password')` will use the provided credentials.
 
 
 Example
@@ -34,7 +34,7 @@ Sample example below.
 >>> import qualysapi
 >>> a = qualysapi.connect()
 QualysGuard Username: my_username
-QualysGuard Password: 
+QualysGuard Password:
 >>> print a.request('about.php')
 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE ABOUT SYSTEM "https://qualysapi.qualys.com/about.dtd">
@@ -45,7 +45,7 @@ QualysGuard Password:
   <VULNSIGS-VERSION>2.2.475-2</VULNSIGS-VERSION>
 </ABOUT>
 <!-- Generated for username="my_username" date="2013-07-03T10:31:57Z" -->
-<!-- CONFIDENTIAL AND PROPRIETARY INFORMATION. Qualys provides the QualysGuard Service "As Is," without any warranty of any kind. Qualys makes no warranty that the information contained in this report is complete or error-free. Copyright 2013, Qualys, Inc. //--> 
+<!-- CONFIDENTIAL AND PROPRIETARY INFORMATION. Qualys provides the QualysGuard Service "As Is," without any warranty of any kind. Qualys makes no warranty that the information contained in this report is complete or error-free. Copyright 2013, Qualys, Inc. //-->
 ```
 
 Installation
@@ -64,8 +64,6 @@ Requirements
 * requests (http://docs.python-requests.org)
 * lxml (http://lxml.de/)
 
-Tested successfully on Python 2.7.
-
 Configuration
 =============
 
diff --git a/qualysapi/__init__.py b/qualysapi/__init__.py
index f72cab3..1a9e736 100644
--- a/qualysapi/__init__.py
+++ b/qualysapi/__init__.py
@@ -3,7 +3,6 @@
 # setup.py install
 
 # Ownership and Copyright Information.
-from __future__ import absolute_import
 __author__ = "Parag Baxi <parag.baxi@gmail.com>"
 __copyright__ = "Copyright 2011-2013, Parag Baxi"
 __license__ = "BSD-new"
diff --git a/qualysapi/api_actions.py b/qualysapi/api_actions.py
index 81859a9..97ab3df 100644
--- a/qualysapi/api_actions.py
+++ b/qualysapi/api_actions.py
@@ -1,5 +1,4 @@
 # -*- coding: future_fstrings -*-
-from __future__ import absolute_import
 from qualysapi.api_objects import *
 from lxml import objectify
 
diff --git a/qualysapi/api_methods.py b/qualysapi/api_methods.py
index cda44b0..ae38256 100644
--- a/qualysapi/api_methods.py
+++ b/qualysapi/api_methods.py
@@ -1,5 +1,4 @@
 # -*- coding: future_fstrings -*-
-from __future__ import absolute_import
 
 __author__ = 'pbaxi'
 
diff --git a/qualysapi/api_objects.py b/qualysapi/api_objects.py
index 4fac751..850b83d 100644
--- a/qualysapi/api_objects.py
+++ b/qualysapi/api_objects.py
@@ -1,10 +1,9 @@
 # -*- coding: future_fstrings -*-
-from __future__ import absolute_import
 import datetime
 from lxml import objectify
 
 
-class Host(object):
+class Host:
     def __init__(self, dns, id, ip, last_scan, netbios, os, tracking_method):
         self.dns = str(dns)
         self.id = int(id)
@@ -25,7 +24,7 @@ class Host(object):
         return f"ip: {self.ip}, qualys_id: {self.id}, dns: {self.dns}"
 
 
-class VirtualHost(object):
+class VirtualHost:
     def __init__(self, fqdn, ip, network_id, port):
         self.fqdn = fqdn
         self.ip = ip
@@ -36,7 +35,7 @@ class VirtualHost(object):
         return f"vhost: {self.fqdn}, ip: {self.ip}, network_id: {self.network_id}, port: {self.port}"
 
 
-class AssetGroup(object):
+class AssetGroup:
     def __init__(self, business_impact, id, last_update, scanips, scandns, scanner_appliances, title):
         self.business_impact = str(business_impact)
         self.id = int(id)
@@ -61,7 +60,7 @@ class AssetGroup(object):
         return f"qualys_id: {self.id}, title: {self.title}"
 
 
-class ReportTemplate(object):
+class ReportTemplate:
     def __init__(self, isGlobal, id, last_update, template_type, title, type, user):
         self.isGlobal = int(isGlobal)
         self.id = int(id)
@@ -75,7 +74,7 @@ class ReportTemplate(object):
         return f"qualys_id: {self.id}, title: {self.title}"
 
 
-class Report(object):
+class Report:
     def __init__(self, expiration_datetime, id, launch_datetime, output_format, size, status, type, user_login,
                  title=''):
         self.expiration_datetime = str(expiration_datetime).replace('T', ' ').replace('Z', '').split(' ')
@@ -98,7 +97,7 @@ class Report(object):
             return conn.request(call, parameters)
 
 
-class Scan(object):
+class Scan:
     def __init__(self, assetgroups, duration, launch_datetime, option_profile, processed, ref, status, target, title,
                  type, user_login):
         self.assetgroups = assetgroups
diff --git a/qualysapi/config.py b/qualysapi/config.py
index 0f59d1c..02f770b 100644
--- a/qualysapi/config.py
+++ b/qualysapi/config.py
@@ -2,14 +2,11 @@
 """ Module providing a single class (QualysConnectConfig) that parses a config
 file and provides the information required to build QualysGuard sessions.
 """
-from __future__ import absolute_import
-from __future__ import print_function
 import os
 import stat
 import getpass
 import logging
-from six.moves import input
-from six.moves.configparser import *
+from configparser import ConfigParser
 
 import qualysapi.settings as qcs
 
diff --git a/qualysapi/connector.py b/qualysapi/connector.py
index 4adb514..7193f90 100644
--- a/qualysapi/connector.py
+++ b/qualysapi/connector.py
@@ -1,6 +1,4 @@
 # -*- coding: future_fstrings -*-
-from __future__ import absolute_import
-from __future__ import print_function
 
 __author__ = 'Parag Baxi <parag.baxi@gmail.com>'
 __copyright__ = 'Copyright 2013, Parag Baxi'
diff --git a/qualysapi/settings.py b/qualysapi/settings.py
index 0aa7a12..a05180f 100644
--- a/qualysapi/settings.py
+++ b/qualysapi/settings.py
@@ -1,7 +1,6 @@
 # -*- coding: future_fstrings -*-
 ''' Module to hold global settings reused throughout qualysapi. '''
 
-from __future__ import absolute_import
 __author__ = "Colin Bell <colin.bell@uwaterloo.ca>"
 __copyright__ = "Copyright 2011-2013, University of Waterloo"
 __license__ = "BSD-new"
diff --git a/qualysapi/util.py b/qualysapi/util.py
index d102d41..1fd4772 100644
--- a/qualysapi/util.py
+++ b/qualysapi/util.py
@@ -1,6 +1,5 @@
 # -*- coding: future_fstrings -*-
 """ A set of utility functions for QualysConnect module. """
-from __future__ import absolute_import
 import logging
 
 import qualysapi.config as qcconf
diff --git a/reqs/requirements.txt b/reqs/requirements.txt
index 416b461..c13d49e 100644
--- a/reqs/requirements.txt
+++ b/reqs/requirements.txt
@@ -1,4 +1,3 @@
 requests
 lxml
 future-fstrings
-pathlib2;python_version == '2.7'
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
index cd36fb7..deb66ba 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -2,11 +2,3 @@
 # This includes the license file in the wheel.
 license_file = license
 
-[bdist_wheel]
-# This flag says to generate wheels that support both Python 2 and Python
-# 3. If your code will not run unchanged on both Python 2 and 3, you will
-# need to generate separate wheels for each Python version that you
-# support. Removing this line (or setting universal to 0) will prevent
-# bdist_wheel from trying to make a universal wheel. For more see:
-# https://packaging.python.org/tutorials/distributing-packages/#wheels
-universal=1
diff --git a/setup.py b/setup.py
index 6fbe27a..3ece0d1 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,5 @@
 # -*- coding: future_fstrings -*-
 #!/usr/bin/env python
-from __future__ import absolute_import
 import os
 import setuptools
 
@@ -28,7 +27,6 @@ REQUIREMENTS = [
     "requests",
     "lxml",
     "future-fstrings",
-    "pathlib2 ; python_version == '2.7'",
 ]
 
 
@@ -59,10 +57,10 @@ setup(name=__pkgname__,
           'Topic :: Utilities',
           'License :: OSI Approved :: Apache Software License',
           'Intended Audience :: Developers',
-          'Programming Language :: Python :: 2.7',
-          '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',
     ],
     install_requires=REQUIREMENTS,
 )


Test patch:
diff --git a/tests/test_smoke.py b/tests/test_smoke.py
index 228271c..d8fd6c3 100644
--- a/tests/test_smoke.py
+++ b/tests/test_smoke.py
@@ -1,13 +1,5 @@
 # -*- coding: future_fstrings -*-
-from sys import version_info
-import importlib
-
-PYTHON_VER = (version_info.major, version_info.minor)
-
-if PYTHON_VER == (2, 7):
-    import pathlib2 as pathlib
-else:
-    import pathlib
+import pathlib
 
 import pytest