SENSSOFT-103 Supporting pylint, coverage and unit test reports.
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 4cd8b2b..78bc943 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -11,7 +11,7 @@
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
-# limitations under the License. 
+# limitations under the License.
 
 # Apache UserALE documentation build configuration file, created by
 # sphinx-quickstart on Fri Jun 24 16:58:43 2016.
@@ -25,14 +25,15 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys, os
+import sys
+import os
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
 # sys.path.insert(0, os.path.abspath('../../'))
 # sys.path.insert (0, '../..')
-# 
+
 sys.path.insert(0, os.path.abspath('../..'))
 
 from userale.version import __version__
@@ -64,7 +65,7 @@
 source_suffix = '.rst'
 
 # The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
 
 # The master toctree document.
 master_doc = 'index'
@@ -92,9 +93,9 @@
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
-#today = ''
+# today = ''
 # Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
+# today_fmt = '%B %d, %Y'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
@@ -103,27 +104,27 @@
 
 # The reST default role (used for this markup: `text`) to use for all
 # documents.
-#default_role = None
+# default_role = None
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
 
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
-#show_authors = False
+# show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
 pygments_style = 'sphinx'
 
 # A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
 
 # If true, keep warnings as "system message" paragraphs in the built documents.
-#keep_warnings = False
+# keep_warnings = False
 
 # If true, `todo` and `todoList` produce output, else they produce nothing.
 todo_include_todos = True
@@ -138,26 +139,26 @@
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
-#html_theme_options = {}
+# html_theme_options = {}
 
 # Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
 
 # The name for this set of Sphinx documents.
 # "<project> v<release> documentation" by default.
-#html_title = u'UserAle v1.0'
+# html_title = u'UserAle v1.0'
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
 
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
-#html_logo = None
+# html_logo = None
 
 # The name of an image file (relative to this directory) to use as a favicon of
-# the docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
-#html_favicon = None
+# html_favicon = None
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
@@ -167,23 +168,23 @@
 # Add any extra paths that contain custom files (such as robots.txt or
 # .htaccess) here, relative to this directory. These files are copied
 # directly to the root of the documentation.
-#html_extra_path = []
+# html_extra_path = []
 
 # If not None, a 'Last updated on:' timestamp is inserted at every page
 # bottom, using the given strftime format.
 # The empty string is equivalent to '%b %d, %Y'.
-#html_last_updated_fmt = None
+# html_last_updated_fmt = None
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# html_sidebars = {}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
 
 # If false, no module index is generated.
 html_domain_indices = False
@@ -192,86 +193,88 @@
 html_use_index = False
 
 # If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
 
 # If true, links to the reST sources are added to the pages.
 html_show_sourcelink = False
 
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+# html_show_sphinx = True
 
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
 
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
 
 # Language to be used for generating the HTML full-text search index.
 # Sphinx supports the following languages:
 #   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
 #   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
-#html_search_language = 'en'
+# html_search_language = 'en'
 
 # A dictionary with options for the search language support, empty by default.
 # 'ja' uses this config value.
 # 'zh' user can custom change `jieba` dictionary path.
-#html_search_options = {'type': 'default'}
+# html_search_options = {'type': 'default'}
 
 # The name of a javascript file (relative to the configuration directory) that
 # implements a search results scorer. If empty, the default will be used.
-#html_search_scorer = 'scorer.js'
+# html_search_scorer = 'scorer.js'
 
 # Output file base name for HTML help builder.
 htmlhelp_basename = 'ApacheUserALE.PyQt5.doc'
 
 # -- Options for LaTeX output ---------------------------------------------
 
-latex_elements = {
+# latex_elements = {
 # The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
+# 'papersize': 'letterpaper',
 
 # The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
+# 'pointsize': '10pt',
 
 # Additional stuff for the LaTeX preamble.
-#'preamble': '',
+# 'preamble': '',
 
 # Latex figure (float) alignment
-#'figure_align': 'htbp',
-}
+# 'figure_align': 'htbp',
+# }
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-    (master_doc, 'ApacheUserALE.PyQt5.tex', u'Apache UserALE.PyQt5 Documentation',
-     u'Michelle Beard \\textless{}msbeard@apache.dot.org\\textgreater{}', 'manual'),
+    (master_doc,
+        'UserALE.PyQt5.tex', u'Apache UserALE.PyQt5 Documentation',
+        u'Michelle Beard \\textless{}msbeard@apache.dot.org\\textgreater{}',
+        'manual')
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
-#latex_logo = None
+# latex_logo = None
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
 
 # If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
 
 # If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
 
 # Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
 
 # If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
 
 
 # -- Options for manual page output ---------------------------------------
@@ -284,7 +287,7 @@
 ]
 
 # If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
 
 
 # -- Options for Texinfo output -------------------------------------------
@@ -294,21 +297,22 @@
 #  dir menu entry, description, category)
 texinfo_documents = [
     (master_doc, 'ApacheUserALE.PyQt5', u'Apache UserALE.PyQt5 Documentation',
-     author, 'ApacheUserAle.PyQt5', 'Apache UserALE.PyQt5 provides an easy way to generate highly detailed log streams from a PyQt5 application.',
+     author, 'ApacheUserAle.PyQt5', 'Apache UserALE.PyQt5 provides an easy way \
+      to generate highly detailed log streams from a PyQt5 application.',
      'Instrumentation'),
 ]
 
 # Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
 
 # If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
 
 # If true, do not generate a @detailmenu in the "Top" node's menu.
-#texinfo_no_detailmenu = False
+# texinfo_no_detailmenu = False
 
 # Example configuration for intersphinx: refer to the Python standard library.
 intersphinx_mapping = {'https://docs.python.org/': None}
diff --git a/setup.cfg b/setup.cfg
index 10bbb43..390dda1 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -14,11 +14,15 @@
 # limitations under the License.
 
 [egg_info]
+tag_build = 0.1.6
 tag_svn_revision = false
 
-[pytest]
-addopts = --ignore=setup.py --ignore=build --ignore=dist --doctest-modules
-norecursedirs=*.egg
+[aliases]
+test=pytest
+
+[tool:pytest]
+addopts = --ignore=setup.py --ignore=build --ignore=dist --junitxml=test-report.xml --cov-report xml --cov=userale userale/.
+norecursedirs=*.eggs *env .igt
 
 [build_sphinx]
 source-dir = docs
diff --git a/setup.py b/setup.py
index d54ed46..10b4290 100644
--- a/setup.py
+++ b/setup.py
@@ -14,67 +14,59 @@
 # limitations under the License.
 
 from setuptools import setup, find_packages
-from setuptools.command.test import test as TestCommand
-import io, os, sys
+import os
+import sys
+
 
 if sys.version_info[:2] < (3, 5):
     m = "Python 3.5 or later is required for UserAle (%d.%d detected)."
-    raise ImportError (m % sys.version_info[:2])
+    raise ImportError(m % sys.version_info[:2])
 
 if sys.argv[-1] == 'setup.py':
     print ("To install, run 'python3 setup.py install'")
     print ()
-    
-# This is a plug-in for setuptools that will invoke py.test
-# when you run python setup.py test
-class PyTest (TestCommand):
-    def finalize_options (self):
-        TestCommand.finalize_options (self)
-        self.test_args = []
-        self.test_suite = True
 
-    def run_tests (self):
-        import pytest  # import here, because outside the required eggs aren't loaded yet
-        sys.exit (pytest.main (self.test_args))
 
 # Get the version string
-def get_version ():
-    basedir = os.path.dirname (__file__)
-    with open (os.path.join (basedir, 'userale/version.py')) as f:
+def get_version():
+    basedir = os.path.dirname(__file__)
+    with open(os.path.join(basedir, 'userale/version.py')) as f:
         version = {}
-        exec (f.read (), version)
+        exec(f.read(), version)
         return version['__version__']
-    raise RuntimeError ('No version info found.')
+    raise RuntimeError('No version info found.')
 
-setup (
-    name = 'Apache UserALE.PyQt5',
-    version = get_version (),
-    url = 'https://github.com/draperlaboratory/userale.pyqt5',
-    license = 'Apache Software License 2.0',
-    author = 'Michelle Beard',
-    author_email = 'mbeard@draper.com',
-    description = 'Apache UserALE.PyQt5 provides an easy way to generate highly detailed log streams from a PyQt5 application.',
-    long_description = __doc__,
-    classifiers = [
-      'Development Status :: 4 - Beta',
-      'Programming Language :: Python',
-      'Programming Language :: Python :: 3.5',
-      'Natural Language :: English',
-      'Environment :: Desktop Environment',
-      'Intended Audience :: Developers',
-      'License :: OSI Approved :: Apache Software License',
-      'Operating System :: OS Independent'
+
+setup(
+    name='Apache UserALE.PyQt5',
+    version=get_version(),
+    url='https://github.com/apache/incubator-senssoft-userale-pyqt5',
+    license='Apache Software License 2.0',
+    author='Michelle Beard',
+    author_email='msbeard@apache.org',
+    description='Apache UserALE.PyQt5 provides an easy way to generate highly\
+     detailed log streams from a PyQt5 application.',
+    long_description=__doc__,
+    classifiers=[
+        'Development Status :: 4 - Beta',
+        'Intended Audience :: Developers',
+        'Intended Audience :: Science/Research',
+        'License :: OSI Approved :: Apache Software License',
+        'Natural Language :: English',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python :: 3 :: Only',
+        'Programming Language :: Python :: 3.5',
+        'Programming Language :: Python :: 3.6',
+        'Topic :: Desktop Environment',
+        'Topic :: Scientific/Engineering :: Information Analysis'
     ],
-    keywords = 'logs users interactions', # Separate with spaces
-    packages = find_packages (exclude=['examples', 'tests']),
-    include_package_data = True,
-    zip_safe = False,
-    tests_require = ['pytest'],
-    cmdclass = {'test': PyTest},
-    install_requires = ['pyqt5==5.6', 
-                        'requests>=2.0.0'
-                        ],
-    entry_points = {
+    keywords='logs users interactions',
+    packages=find_packages(exclude=['examples', 'tests']),
+    include_package_data=True,
+    zip_safe=False,
+    tests_require=['pytest>=3.0.0', 'pytest-pylint', 'coverage'],
+    install_requires=['pyqt5==5.6', 'requests>=2.0.0'],
+    entry_points={
         'console_scripts': [
             'mouse = userale.examples.testapp:test_app',
             'drag = userale.examples.testdragndrop:test_drag',
diff --git a/test_requirements.txt b/test_requirements.txt
new file mode 100644
index 0000000..3201881
--- /dev/null
+++ b/test_requirements.txt
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+pylint==1.6.4
+pytest==3.0.3
+pytest-cov==2.4.0
+pytest-runner==2.9
+pytest-pylint
+coverage==4.2
diff --git a/userale/ale.py b/userale/ale.py
index b196e4b..e82a916 100644
--- a/userale/ale.py
+++ b/userale/ale.py
@@ -16,8 +16,7 @@
 from userale.version import __version__
 from userale.format import JsonFormatter
 from PyQt5.QtCore import QObject, QEvent, QTimer
-from collections import Counter
-import datetime, time
+import time
 import logging
 import uuid
 import atexit
@@ -25,12 +24,12 @@
 
 _ = JsonFormatter
 
+
 class Ale (QObject):
     """
     ALE Library
     """
-
-    def __init__(self, 
+    def __init__(self,
                  output="userale.log",
                  user=None,
                  session=None,
@@ -38,19 +37,23 @@
                  toolversion=None,
                  keylog=False,
                  interval=5000,
-                 resolution=100,   
+                 resolution=100,
                  shutoff=[]):
         """
         :param output: [str] The file or url path to which logs will be sent.
         :param user: [str] Identifier for the user of the application.
-        :param session: [str] Session tag to track same user with multiple sessions. If a session is not provided, one will be created.
+        :param session: [str] Session tag to track same user with \
+         multiple sessions. If a session is not provided, one will be created.
         :param toolname: [str] The application name.
         :param toolversion: [str] The application version.
-        :param keylog: [bool] Should detailed key logs be recorded. Default is False.
-        :param interval: [int] The minimum time interval in ms between batch transmission of logs. Default is 5000ms.
-        :param resolution: [int] Delay in ms between instances of high frequency logs like mousemoves, scrolls, etc. Default is 100ms (10Hz). Entering 0 disables it.
+        :param keylog: [bool] Enable logging of keystrokes.
+        :param interval: [int] The minimum time interval in ms between
+        \batch transmission of logs. Default is 5000ms.
+        :param resolution: [int] Delay in ms between instances of high \
+        frequency logs like mousemoves, scrolls, etc. Default is 100ms \
+        (10Hz). Entering 0 disables it.
         :param shutoff: [list] Turn off logging for specific events.
-    
+
         An example log will appear like this:
 
         .. code-block:: python
@@ -76,7 +79,7 @@
         self.output = output
         self.user = user
         # Autogenerate session id if session is not configured
-        self.session = session if session is not None else str (uuid.uuid4 ())
+        self.session = session if session is not None else str(uuid.uuid4())
         self.toolname = toolname
         self.toolversion = toolversion
         self.keylog = keylog
@@ -85,11 +88,11 @@
         self.shutoff = shutoff
 
         # Configure logging
-        self.logger = logging.getLogger ('userale')
+        self.logger = logging.getLogger('userale')
         self.logger.propagate = False
-        self.logger.setLevel (logging.INFO)
-        handler = logging.FileHandler (self.output)
-        self.logger.addHandler (handler)
+        self.logger.setLevel(logging.INFO)
+        handler = logging.FileHandler(self.output)
+        self.logger.addHandler(handler)
 
         # Mapping of all events to methods
         self.map = {
@@ -110,76 +113,80 @@
         }
 
         # Turn on/off keylogging & remove specific filters
-        for key in list (self.map):
-            name = list (self.map[key]) [0]
-            if name in self.shutoff or (not self.keylog and (name == 'keypress' or name == 'keyrelease')):
-                del self.map [key]
+        for key in list(self.map):
+            name = list(self.map[key])[0]
+            if (name in self.shutoff or
+                    (not self.keylog and
+                        (name == 'keypress' or name == 'keyrelease'))):
+                del self.map[key]
 
-        # Sample rate 
+        # Sample rate
         self.hfreq = [QEvent.MouseMove, QEvent.DragMove, QEvent.Scroll]
 
         # Sample Timer
         if self.resolution > 0:
-            self.timer = QTimer ()
-            self.timer.timeout.connect (self.aggregate)
-            self.timer.start (self.resolution)
+            self.timer = QTimer()
+            self.timer.timeout.connect(self.aggregate)
+            self.timer.start(self.resolution)
 
         # Batch transmission of logs
-        self.intervalID = self.startTimer (self.interval)
+        self.intervalID = self.startTimer(self.interval)
 
         # Temporary storage for logs
         self.logs = []
         self.hlogs = []
 
         # Register Exit hanldler
-        atexit.register (self.cleanup)
+        atexit.register(self.cleanup)
 
-    def eventFilter (self, object, event):
+    def eventFilter(self, object, event):
         '''
         :param object: [QObject] The object being watched.
         :param event: [QEvent] The event triggered by a user action.
-        :return: [bool] Propagate filter up if other objects needs to be handled
-        
+        :return: [bool] Propagate filter up if other events need to be handled
+
         Filters events for the watched widget.
         '''
 
         data = None
-        t = event.type ()
+        t = event.type()
 
-        if t in self.map:        
-            # Handle leaf node 
-            if len(object.children ()) == 0:
-            # if object.isWidgetType () and len(object.children ()) == 0:
-                name = list (self.map [t].keys())[0]
-                method = list (self.map [t].values())[0]
-                data = method (name, event, object)
+        if t in self.map:
+            # Handle leaf node
+            if len(object.children()) == 0:
+                # if object.isWidgetType () and len(object.children ()) == 0:
+                name = list(self.map[t].keys())[0]
+                method = list(self.map[t].values())[0]
+                data = method(name, event, object)
 
             # Handle window object
             else:
-                # How to handle events on windows? It comes before the child widgets in window? 
-                # Either an event actually ocurred on window or is an effect of event propagation. 
+                # How to handle events on windows?
+                # It comes before the child widgets in window?
+                # Either an event actually ocurred on window or
+                # is an effect of event propagation.
                 pass
 
         # Filter data to higher or lower priority list
         if data is not None:
             print (_(data))
-            if self.resolution > 0 and t in self.hfreq and t in self.map:   # data is in watched list and is a high frequency log
-                self.hlogs.append (data)
+            # data is in watched list and is a high frequency log
+            if self.resolution > 0 and t in self.hfreq and t in self.map:
+                self.hlogs.append(data)
             else:
-                self.logs.append (data)
+                self.logs.append(data)
 
+        return super(Ale, self).eventFilter(object, event)
 
-        return super (Ale, self).eventFilter (object, event)
-
-    def cleanup (self):
+    def cleanup(self):
         '''
         Clean up any dangling logs in self.logs or self.hlogs
         '''
         if self.resolution > 0:
-            self.aggregate ()
-        self.dump ()
+            self.aggregate()
+        self.dump()
 
-    def timerEvent (self, event):
+    def timerEvent(self, event):
         '''
         :param object: [list] List of events
         :return: [void] Emit events to file
@@ -187,201 +194,199 @@
         Routinely dump data to file or send over the network
         '''
 
-        self.dump ()
+        self.dump()
 
-    def dump (self):
+    def dump(self):
         '''
         Write log data to file
         '''
 
-        if len (self.logs) > 0:
+        if len(self.logs) > 0:
             # print ("dumping {} logs".format (len (self.logs)))
-            self.logger.info (_(self.logs))
-            self.logs = [] # Reset logs
+            self.logger.info(_(self.logs))
+            self.logs = []  # Reset logs
 
-    def aggregate (self):
+    def aggregate(self):
         '''
-        Sample high frequency logs at self.resolution. High frequency logs are consolidated down to a single log event 
+        Sample high frequency logs at self.resolution.
+        High frequency logs are consolidated down to a single log event
         to be emitted later
         '''
-        
-        if len (self.hlogs) > 0:
-            # print ("agging {} logs".format (len (self.hlogs)))
-            # Given target, path, location [median], return aggregate
-            # agg_events = Counter (self.hlogs)
-            # # Iterate over collapsed collection to generate a single log per event
-            # # Location information is lost due to consolidation. 
-            # # @todo develop hashing funciton or new counter to generate avg x and avg y location
-            # for event, counter in agg_events.items ():
-            #     # aggdata = self.__create_msg (event[0], event[1], event[2], details={"count" : counter}) 
-            #     aggdata = {"target": event[0], "type" : event[1], "details": {"count": counter}}
-            #     print (aggdata)
-            #     self.logs.append (aggdata)
-            self.logs.append (random.choice (self.hlogs))
+
+        if len(self.hlogs) > 0:
+            self.logs.append(random.choice(self.hlogs))
             self.hlogs = []
-        
-    def getSender (self, object):
+
+    def getSender(self, object):
         '''
         :param object: [QObject] The object being watched.
-        :return: [QObject] The QObject 
+        :return: [QObject] The QObject
 
         Fetch the QObject who triggered the event
         '''
 
         sender = None
         try:
-            sender = object.sender () if object.sender() is not None else None   
+            sender = object.sender() if object.sender() is not None else None
         except:
             pass
         return sender
 
-    def getSelector (self, object):
+    def getSelector(self, object):
         """
         :param object: [QObject] The base class for all Qt objects.
         :return: [str] The Qt object's name
 
-        Get target object's name (object defined by user or object's meta class name). If object is null, return "Undefined".
+        Get target object's name. If object is null, return "Undefined".
         """
         try:
-            return object.objectName () if object.objectName () else object.staticMetaObject.className ()
+            return object.objectName() if object.objectName() else object.staticMetaObject.className()
         except:
             return "Undefined"
 
-    def getLocation (self, event):
+    def getLocation(self, event):
         """
         :param event: [QEvent] The base class for all event classes.
-        :return: [dict] A dictionary representation of the x and y positions of the mouse cursor.
+        :return: [dict] A dict of the x and y positions of the mouse cursor.
 
-        Grab the x and y position of the mouse cursor, relative to the widget that received the event.
+        Grab the x and y position of the mouse cursor,
+        relative to the widget that received the event.
         """
 
-        try: 
-            return {"x" : event.pos ().x (), "y" : event.pos ().y ()}
+        try:
+            return {"x": event.pos().x(), "y": event.pos().y()}
         except:
             return None
 
-    def getPath (self, object):
+    def getPath(self, object):
         """
         :param object: [QObject] The base class for all Qt objects.
         :return: [list] List of QObjects.
 
-        Generate the entire object hierachy from root to leaf node. 
+        Generate the entire object hierachy from root to leaf node.
         """
 
         try:
             if object.parent() is not None:
-                return self.getPath (object.parent()) + [self.getSelector (object)]
+                return self.getPath(object.parent()) + [self.getSelector(object)]
             else:
-                return [self.getSelector (object)]
+                return [self.getSelector(object)]
         except:
             return "Undefined"
-        
-    def getClientTime (self):
+
+    def getClientTime(self):
         """
-        :return: [str] String representation of the time the event was captured.
-        
-        Capture the time the event was captured in milliseconds since the UNIX epoch (January 1, 1970 00:00:00 UTC)
+        :return: [str] Time the event was captured.
+
+        Capture the time the event was captured in milliseconds
+        since the UNIX epoch (January 1, 1970 00:00:00 UTC)
         """
 
-        return int (time.time() * 1000)
+        return int(time.time() * 1000)
 
-    def handleMouseEvents (self, event_type, event, object):
+    def handleMouseEvents(self, event_type, event, object):
         """
-        :param event_type: [str] The string representation of the type of event being triggered by the user.
+        :param event_type: [str] The type of event being triggered by the user.
         :param event: [QEvent] The base class for all event classes.
         :param object: [QObject] The base class for all Qt objects.
         :return: [dict] A userale log describing a mouse event.
 
-        Returns the userale log representing all mouse event data. 
+        Returns the userale log representing all mouse event data.
         """
 
         details = {}
-        return self.__create_msg (event_type, event, object, details=details)
+        return self.__create_msg(event_type, event, object, details=details)
 
-    def handleKeyEvents (self, event_type, event, object):
+    def handleKeyEvents(self, event_type, event, object):
         """
-        :param event_type: [str] The string representation of the type of event being triggered by the user.
+        :param event_type: [str] The type of event being triggered by the user.
         :param event: [QEvent] The base class for all event classes.
         :param object: [QObject] The base class for all Qt objects.
         :return: [dict] A userale log describing a key event.
 
-        Returns the userale log representing all key events, including key name and key code.
+        Returns the userale log representing all key events,
+        including key name and key code.
         """
 
-        details = {"key" : event.text (), "keycode" : event.key ()}
-        return self.__create_msg (event_type, event, object, details=details)
+        details = {"key": event.text(), "keycode": event.key()}
+        return self.__create_msg(event_type, event, object, details=details)
 
-    def handleDragEvents (self, event_type, event, object):
+    def handleDragEvents(self, event_type, event, object):
         """
-        :param event_type: [str] The string representation of the type of event being triggered by the user.
+        :param event_type: [str] The type of event being triggered by the user.
         :param event: [QEvent] The base class for all event classes.
         :param object: [QObject] The base class for all Qt objects.
         :return: [dict] A userale log describing a drag event.
 
-        Returns the userale log representing all drag events. 
+        Returns the userale log representing all drag events.
         """
 
         details = {}
 
         try:
-            details ["source"] = self.getSelector (event.source ())      
+            details["source"] = self.getSelector(event.source())
         except:
-            details ["source"] = None
+            details["source"] = None
 
-        return self.__create_msg (event_type, event, object, details=details)
+        return self.__create_msg(event_type, event, object, details=details)
 
-    def handleMoveEvents (self, event_type, event, object):
+    def handleMoveEvents(self, event_type, event, object):
         """
-        :param event_type: [str] The string representation of the type of event being triggered by the user.
+        :param event_type: [str] The type of event being triggered by the user.
         :param event: [QEvent] The base class for all event classes.
         :param object: [QObject] The base class for all Qt objects.
         :return: [dict] A userale log describing a drag event.
 
-        Returns the userale log representing all move events. 
+        Returns the userale log representing all move events.
         """
 
-        details = {"oldPos" : {"x" : event.oldPos ().x (), "y" : event.oldPos ().y ()}}
-        return self.__create_msg (event_type, event, object, details=details)
-        
-    def handleResizeEvents (self, event_type, event, object):
+        details = {"oldPos": {"x": event.oldPos().x(),
+                              "y": event.oldPos().y()}}
+
+        return self.__create_msg(event_type, event, object, details=details)
+
+    def handleResizeEvents(self, event_type, event, object):
         """
-        :param event_type: [str] The string representation of the type of event being triggered by the user.
+        :param event_type: [str] The type of event being triggered by the user.
         :param event: [QEvent] The base class for all event classes.
         :param object: [QObject] The base class for all Qt objects.
         :return: [dict] A userale log describing a resize event.
 
-        Returns the userale log representing all resize events. 
+        Returns the userale log representing all resize events.
         """
 
-        details = {"size" : {"height" : event.size ().height (), "width" : event.size ().width ()},
-                   "oldSize":  {"height" : event.oldSize ().height (), "width" : event.oldSize ().width ()}}
-        return self.__create_msg (event_type, event, object, details=details)
+        details = {"size": {"height": event.size().height(),
+                            "width": event.size().width()},
+                   "oldSize": {"height": event.oldSize().height(),
+                               "width": event.oldSize().width()}}
 
-    def handleScrollEvents (self, event_type, event, object):
+        return self.__create_msg(event_type, event, object, details=details)
+
+    def handleScrollEvents(self, event_type, event, object):
         """
-        :param event_type: [str] The string representation of the type of event being triggered by the user.
+        :param event_type: [str] The type of event being triggered by the user.
         :param event: [QEvent] The base class for all event classes.
         :param object: [QObject] The base class for all Qt objects.
         :return: [dict] A userale log describing a scroll event.
 
-        Returns the userale log representing all scroll events. 
+        Returns the userale log representing all scroll events.
         """
 
-        return self.__create_msg (event_type, event, object)
+        return self.__create_msg(event_type, event, object)
 
-    def __create_msg (self, event_type, event, object, details={}):
+    def __create_msg(self, event_type, event, object, details={}):
         """
         Geneate UserAle log describing an event.
         """
 
         data = {
-            "target": self.getSelector (object),
-            "path": self.getPath (object),
-            "clientTime": self.getClientTime (),    
-            "location": self.getLocation (event),
-            "type": event_type ,
+            "target": self.getSelector(object),
+            "path": self.getPath(object),
+            "clientTime": self.getClientTime(),
+            "location": self.getLocation(event),
+            "type": event_type,
             "userAction": True,   # legacy field
-            "details" : details,
+            "details": details,
             "userId": self.user,
             "session": self.session,
             "toolName": self.toolname,
diff --git a/userale/format.py b/userale/format.py
index 7b1c750..abf138d 100644
--- a/userale/format.py
+++ b/userale/format.py
@@ -13,20 +13,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import requests
-from requests.auth import HTTPBasicAuth, HTTPDigestAuth
-from requests.auth import AuthBase
-
 import json
 
-# Logger will need to optinally handle authorization 
-# through basic http auth, proxy, and SOCKS
 
 class JsonFormatter (object):
-	"""
-	"""
-	def __init__(self, data):
-		self.data = data
+    def __init__(self, data):
+        self.data = data
 
-	def __str__(self):
-		return "%s" % (json.dumps (self.data, sort_keys=False))
+    def __str__(self):
+        return "%s" % (json.dumps(self.data, sort_keys=False))
diff --git a/userale/version.py b/userale/version.py
index 48782d9..2071510 100644
--- a/userale/version.py
+++ b/userale/version.py
@@ -19,4 +19,4 @@
 and parsed by ``setup.py``.
 """
 
-__version__ = "0.1.5"
\ No newline at end of file
+__version__ = "0.1.6"