Repository: tarantool/tarantool-python (language: python)

Issue:
Lint Python code
Add some linter (`pylint`, `flake8`) to CI runs.

The task itself is rather simple, yet before merging this we should resolve any conflicts. And pylint yielded a couple of hundreds of them (not counting missing docstring ones).
Lint Python code
Add some linter (`pylint`, `flake8`) to CI runs.

The task itself is rather simple, yet before merging this we should resolve any conflicts. And pylint yielded a couple of hundreds of them (not counting missing docstring ones).
Lint Python code
Add some linter (`pylint`, `flake8`) to CI runs.

The task itself is rather simple, yet before merging this we should resolve any conflicts. And pylint yielded a couple of hundreds of them (not counting missing docstring ones).


Discussion / hints:

Fix patch:
diff --git a/.codespellrc b/.codespellrc
new file mode 100644
index 00000000..fe94c2d8
--- /dev/null
+++ b/.codespellrc
@@ -0,0 +1,3 @@
+[codespell]
+skip = tarantool/msgpack_ext/types/timezones/timezones.py
+ignore-words-list = ans,gost,ro
diff --git a/.flake8 b/.flake8
new file mode 100644
index 00000000..4425b53d
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,3 @@
+[flake8]
+# Use pylint for lines length check
+ignore=E501,W503
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 00000000..3fd8b942
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,8 @@
+[BASIC]
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_,ok,t,tz
+
+[FORMAT]
+# Allow links in docstings, allow tables
+ignore-long-lines=^(?:\s*(# )?(?:\.\.\s.+?:)?\s*<?https?://\S+>?)|(\s\+.+\+)|(\s\|.+\|)$
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 957c2312..aab01e84 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,10 +4,18 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## Unreleased
+
+### Changed
+- **Breaking**: Allow only named `on_push` and `on_push_ctx` for `insert` and `replace`.
+- Migrate to built-in `Warning` instead of a custom one.
+- Migrate to built-in `RecursionError` instead of a custom one.
+- Collect full exception traceback.
+
 ## 0.12.1 - 2023-02-28
 
 ### Changed
-- Discovery iproto features only for Tarantools since version 2.10.0 (#283). 
+- Discovery iproto features only for Tarantools since version 2.10.0 (#283).
 
 ### Fixed
 - Schema fetch for spaces with foreign keys (#282).
@@ -352,7 +360,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Various improvements and fixes in README (PR #210, PR #215).
 
 ### Fixed
-- json.dumps compatibility with Python 2 (PR #186). 
+- json.dumps compatibility with Python 2 (PR #186).
 - Unix socket support in mesh_connection (PR #189, #111).
 - Various fixes in tests (PR #189, #111, PR #195, #194).
 
diff --git a/Makefile b/Makefile
index 1ab6441b..25809cd8 100644
--- a/Makefile
+++ b/Makefile
@@ -3,8 +3,17 @@ install:
 	pip3 install --editable .
 
 
+PYTHON_FILES=tarantool test setup.py docs/source/conf.py
+TEXT_FILES=README.rst docs/source/*.rst
+.PHONY: lint
+lint:
+	python3 -m pylint --recursive=y $(PYTHON_FILES)
+	python3 -m flake8 $(PYTHON_FILES)
+	codespell $(PYTHON_FILES) $(TEXT_FILES)
+
+
 .PHONY: test
-test:
+test: lint
 	python3 setup.py test
 
 .PHONY: test-pure-install
diff --git a/README.rst b/README.rst
index 41aa6a62..7e95ec3a 100644
--- a/README.rst
+++ b/README.rst
@@ -86,7 +86,7 @@ You can also install the development version of the package using ``pip``.
 What is Tarantool?
 ------------------
 
-`Tarantool`_ is an in-memory computing platform originally designed by 
+`Tarantool`_ is an in-memory computing platform originally designed by
 `VK`_ and released under the terms of `BSD license`_.
 
 Features
diff --git a/debian/changelog b/debian/changelog
index d6d83b6a..c85ff501 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -290,7 +290,7 @@ tarantool-python (0.9.0-0) unstable; urgency=medium
         transport="ssl",
         ssl_ca_file=client_ca_file)
     ```
-    
+   
     If the server authenticates clients using certificates issued by
     given CA, you must provide private SSL key file with `ssl_key_file`
     parameter and SSL certificate file with `ssl_cert_file` parameter.
@@ -351,7 +351,7 @@ tarantool-python (0.9.0-0) unstable; urgency=medium
     ```
 
     See [Tarantool Enterprise Edition manual](https://www.tarantool.io/en/enterprise_doc/security/#enterprise-iproto-encryption)
-    for details. 
+    for details.
 
     ## Breaking changes
 
diff --git a/debian/rules b/debian/rules
index 658c3ceb..b55a2b66 100755
--- a/debian/rules
+++ b/debian/rules
@@ -14,7 +14,7 @@ override_dh_auto_build:
 	python3 setup.py build --force
 
 override_dh_auto_install:
-	python3 setup.py install --force --root=debian/python3-tarantool --no-compile -O0 --install-layout=deb --prefix=/usr 
+	python3 setup.py install --force --root=debian/python3-tarantool --no-compile -O0 --install-layout=deb --prefix=/usr
 
 override_dh_python2:
 	dh_python2 --no-guessing-versions
diff --git a/docs/source/conf.py b/docs/source/conf.py
index cea15f49..e9db5edb 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -1,15 +1,19 @@
-# Tarantool python client library documentation build configuration file, created by
-# sphinx-quickstart on Tue Nov 29 06:29:57 2011.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import sys, os
+"""
+Tarantool python client library documentation build configuration file, created by
+sphinx-quickstart on Tue Nov 29 06:29:57 2011.
+
+This file is execfile()d with the current directory set to its containing dir.
+
+Note that not all possible configuration values are present in this
+autogenerated file.
+
+All configuration values have a default; values that are commented out
+serve to show the default.
+"""
+# pylint: disable=invalid-name,redefined-builtin,duplicate-code
+# flake8: noqa: E265
+
+import tarantool
 
 # 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
@@ -45,15 +49,13 @@
 master_doc = 'index'
 
 # General information about the project.
-project = u'Tarantool python client library'
-copyright = u'2011-2022, tarantool-python AUTHORS'
+project = 'Tarantool python client library'
+copyright = '2011-2022, tarantool-python AUTHORS'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 
-import tarantool
-
 # The short X.Y version.
 version = tarantool.__version__
 # The full version, including alpha/beta/rc tags.
@@ -126,7 +128,7 @@
 # pixels large.
 #html_favicon = None
 
-# Set up favicons with sphinx_favicon. 
+# Set up favicons with sphinx_favicon.
 favicons = [
     {
         "rel": "icon",
@@ -279,8 +281,8 @@
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-  ('index', 'Tarantoolpythonclientlibrary.tex', u'Tarantool python client library Documentation',
-   u'tarantool-python AUTHORS', 'manual'),
+  ('index', 'Tarantoolpythonclientlibrary.tex', 'Tarantool python client library Documentation',
+   'tarantool-python AUTHORS', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
@@ -309,8 +311,8 @@
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    ('index', 'tarantoolpythonclientlibrary', u'Tarantool python client library Documentation',
-     [u'tarantool-python AUTHORS'], 1)
+    ('index', 'tarantoolpythonclientlibrary', 'Tarantool python client library Documentation',
+     ['tarantool-python AUTHORS'], 1)
 ]
 
 # If true, show URL addresses after external links.
@@ -323,8 +325,8 @@
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-  ('index', 'Tarantoolpythonclientlibrary', u'Tarantool python client library Documentation',
-   u'tarantool-python AUTHORS', 'Tarantoolpythonclientlibrary', 'One line description of project.',
+  ('index', 'Tarantoolpythonclientlibrary', 'Tarantool python client library Documentation',
+   'tarantool-python AUTHORS', 'Tarantoolpythonclientlibrary', 'One line description of project.',
    'Miscellaneous'),
 ]
 
diff --git a/docs/source/index.rst b/docs/source/index.rst
index b2d31cd7..60a264fe 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -5,7 +5,7 @@ Python client library for Tarantool
 
 :Version: |version|
 
-`Tarantool`_ is an in-memory computing platform originally designed by 
+`Tarantool`_ is an in-memory computing platform originally designed by
 `VK`_ and released under the terms of `BSD license`_.
 
 Install Tarantool Python connector with ``pip`` (`PyPI`_ page):
@@ -78,7 +78,7 @@ API Reference
 
 .. Indices and tables
 .. ==================
-.. 
+..
 .. * :ref:`genindex`
 .. * :ref:`modindex`
 .. * :ref:`search`
diff --git a/docs/source/quick-start.rst b/docs/source/quick-start.rst
index 81526276..20dec4db 100644
--- a/docs/source/quick-start.rst
+++ b/docs/source/quick-start.rst
@@ -56,7 +56,7 @@ Throws an error if there is already a tuple with the same primary key.
     ...     conn.insert('demo', ('BBBB', 'Bravo'))
     ... except Exception as exc:
     ...     print(exc)
-    ... 
+    ...
     (3, 'Duplicate key exists in unique index "pk" in space "demo" with old tuple - ["BBBB", "Bravo"] and new tuple - ["BBBB", "Bravo"]')
 
 Replace
@@ -125,7 +125,7 @@ Creating a space instance
 An instance of :class:`~tarantool.space.Space` is a named object to access
 the key space.
 
-Create a ``demo`` object that will be used to access the space 
+Create a ``demo`` object that will be used to access the space
 with id ``'demo'``:
 
 .. code-block:: python
@@ -205,26 +205,26 @@ read-write and read-only pool instances:
 Receiving out-of-band messages
 ----------------------------------
 
-Receiving out-of-band messages from a server that uses box.session.push 
-call is supported for methods: :meth:`~tarantool.Connection.call`, 
-:meth:`~tarantool.Connection.eval`, :meth:`~tarantool.Connection.select`, 
-:meth:`~tarantool.Connection.insert`, :meth:`~tarantool.Connection.replace`, 
-:meth:`~tarantool.Connection.update`, :meth:`~tarantool.Connection.upsert`, 
+Receiving out-of-band messages from a server that uses box.session.push
+call is supported for methods: :meth:`~tarantool.Connection.call`,
+:meth:`~tarantool.Connection.eval`, :meth:`~tarantool.Connection.select`,
+:meth:`~tarantool.Connection.insert`, :meth:`~tarantool.Connection.replace`,
+:meth:`~tarantool.Connection.update`, :meth:`~tarantool.Connection.upsert`,
 :meth:`~tarantool.Connection.delete`.
 
-To work with out-of-band messages, 2 optional arguments are used in 
+To work with out-of-band messages, 2 optional arguments are used in
 the methods listed above:
 
  * `on_push` - callback, launched with the received data for each out-of-band message. Two arguments for this callback are expected:
-   
+  
     * the first is the received from an out-of-band message data.
 
     * the second is `on_push_ctx`, variable for working with callback context (for example, recording the result or pass data to callback).
  * `on_push_ctx` - result of the `on_push` work can be written to this variable, or through this variable you can pass data to `on_push` callback.
 
-Below is an example of the proposed API with method :meth:`~tarantool.Connection.call` 
-and :meth:`~tarantool.Connection.insert`. In the described example, before the end 
-of the :meth:`~tarantool.Connection.call` and :meth:`~tarantool.Connection.insert`, 
+Below is an example of the proposed API with method :meth:`~tarantool.Connection.call`
+and :meth:`~tarantool.Connection.insert`. In the described example, before the end
+of the :meth:`~tarantool.Connection.call` and :meth:`~tarantool.Connection.insert`,
 out-of-band messages are processed via specified callback.
 
 In the example below, two shells are used, in the first we will configure the server:
@@ -249,7 +249,7 @@ In the example below, two shells are used, in the first we will configure the se
         return x
     end
 
-In the second shell, we will execute a :meth:`~tarantool.Connection.call` 
+In the second shell, we will execute a :meth:`~tarantool.Connection.call`
 with receiving out-of-band messages from the server:
 
 .. code-block:: python
@@ -266,11 +266,11 @@ with receiving out-of-band messages from the server:
     conn = tarantool.Connection(port=3301)
     res = conn.call(
         'server_function',
-        on_push=callback, 
+        on_push=callback,
         on_push_ctx=callback_res
     )
 
-    # receiving out-of-band messages, 
+    # receiving out-of-band messages,
     # the conn.call is not finished yet.
 
     >>> run callback with data:  [[1, 0]]
@@ -285,7 +285,7 @@ with receiving out-of-band messages from the server:
     print(callback_res)
     >>> [[[1, 1]], [[2, 1]], [[3, 1]]]
 
-Let's go back to the first shell with the server and 
+Let's go back to the first shell with the server and
 create a space and a trigger for it:
 
 .. code-block:: lua
@@ -315,7 +315,7 @@ create a space and a trigger for it:
         on_replace_callback
     )
 
-Now, in the second shell, we will execute an :meth:`~tarantool.ConnectionPool.insert` 
+Now, in the second shell, we will execute an :meth:`~tarantool.ConnectionPool.insert`
 with out-of-band message processing:
 
 .. code-block:: python
@@ -333,7 +333,7 @@ with out-of-band message processing:
         on_push_ctx=callback_res,
     )
 
-    # receiving out-of-band messages, 
+    # receiving out-of-band messages,
     # the conn_pool.insert is not finished yet.
 
     >>> run callback with data:  [[100, 0]]
@@ -352,7 +352,7 @@ with out-of-band message processing:
 Interaction with the crud module
 ----------------------------------
 
-Through the :class:`~tarantool.Connection` object, you can access 
+Through the :class:`~tarantool.Connection` object, you can access
 `crud module <https://github.com/tarantool/crud>`_ methods:
 
 .. code-block:: python
@@ -362,16 +362,16 @@ Through the :class:`~tarantool.Connection` object, you can access
     >>> conn = tarantool.Connection(host='localhost',port=3301,fetch_schema=False)
 
     >>> conn.crud_
-    conn.crud_count(                conn.crud_insert(               conn.crud_insert_object_many(   
-    conn.crud_min(                  conn.crud_replace_object(       conn.crud_stats(                
-    conn.crud_unflatten_rows(       conn.crud_upsert_many(          conn.crud_delete(               
-    conn.crud_insert_many(          conn.crud_len(                  conn.crud_replace(              
-    conn.crud_replace_object_many(  conn.crud_storage_info(         conn.crud_update(               
-    conn.crud_upsert_object(        conn.crud_get(                  conn.crud_insert_object(        
-    conn.crud_max(                  conn.crud_replace_many(         conn.crud_select(               
+    conn.crud_count(                conn.crud_insert(               conn.crud_insert_object_many(  
+    conn.crud_min(                  conn.crud_replace_object(       conn.crud_stats(               
+    conn.crud_unflatten_rows(       conn.crud_upsert_many(          conn.crud_delete(              
+    conn.crud_insert_many(          conn.crud_len(                  conn.crud_replace(             
+    conn.crud_replace_object_many(  conn.crud_storage_info(         conn.crud_update(              
+    conn.crud_upsert_object(        conn.crud_get(                  conn.crud_insert_object(       
+    conn.crud_max(                  conn.crud_replace_many(         conn.crud_select(              
     conn.crud_truncate(             conn.crud_upsert(               conn.crud_upsert_object_many(
 
-As an example, consider :meth:`~tarantool.Connection.crud_insert` and :meth:`~tarantool.Connection.crud_insert_object_many`. 
+As an example, consider :meth:`~tarantool.Connection.crud_insert` and :meth:`~tarantool.Connection.crud_insert_object_many`.
 It is recommended to enclose calls in the try-except construction as follows:
 
 .. code-block:: python
@@ -392,13 +392,13 @@ It is recommended to enclose calls in the try-except construction as follows:
     ...     res = conn.crud_insert('tester', (3500,300,'Rob'))
     ... except CrudModuleError as e:
     ...     exc_crud = e
-    ... 
+    ...
     >>> exc_crud
     CrudModuleError(0, 'Failed to insert: Duplicate key exists in unique index "primary_index" in space "tester" with old tuple - [3500, 300, "Rob"] and new tuple - [3500, 300, "Rob"]')
     >>> exc_crud.extra_info_error
     <tarantool.crud.CrudError object at 0x10a276950>
     >>> exc_crud.extra_info_error.
-    exc_crud.extra_info_error.class_name  exc_crud.extra_info_error.err         exc_crud.extra_info_error.file        exc_crud.extra_info_error.line        exc_crud.extra_info_error.str       
+    exc_crud.extra_info_error.class_name  exc_crud.extra_info_error.err         exc_crud.extra_info_error.file        exc_crud.extra_info_error.line        exc_crud.extra_info_error.str      
     >>> exc_crud.extra_info_error.class_name
     'InsertError'
     >>> exc_crud.extra_info_error.str
@@ -409,7 +409,7 @@ It is recommended to enclose calls in the try-except construction as follows:
     ...     res = conn.crud_insert_object_many('tester', ({'id':3,'bucket_id':100,'name':'Ann'}, {'id':4,'bucket_id':100,'name':'Sam'}), {'timeout':100, 'rollback_on_error':False})
     ... except CrudModuleManyError as e:
     ...     exc_crud = e
-    ... 
+    ...
     >>> exc_crud
     CrudModuleManyError(0, 'Got multiple errors, see errors_list')
     >>> exc_crud.success_list # some of the rows were inserted.
@@ -422,7 +422,7 @@ It is recommended to enclose calls in the try-except construction as follows:
     'CallError: Failed for 037adb3a-b9e3-4f78-a6d1-9f0cdb6cbefc: Function returned an error: Duplicate key exists in unique index "primary_index" in space "tester" with old tuple - [3500, 300, "Rob"] and new tuple - [3500, 100, "Mike"]'
     >>> exc_crud.errors_list[1].str
     'InsertManyError: Failed to flatten object: FlattenError: Object is specified in bad format: FlattenError: Unknown field "second_name" is specified'
-    
+   
     # If there are no problems with any rows, the entire response will be contained in the res variable.
     >>> res = conn.crud_insert_object_many('tester', ({'id':3,'bucket_id':100,'name':'Ann'}, {'id':4,'bucket_id':100,'name':'Sam'}), {'timeout':100, 'rollback_on_error':False})
     >>> res.rows
@@ -436,7 +436,7 @@ If module crud not found on the router or user has not sufficient grants:
     ...     res = conn.crud_insert('tester', (22221,300,'Rob'))
     ... except DatabaseError as e:
     ...     exc_db = e
-    ... 
+    ...
     >>> exc_db
     DatabaseError(33, "Procedure 'crud.insert' is not defined. Ensure that you're calling crud.router and user has sufficient grants")
     >>> exc_db.extra_info
diff --git a/setup.py b/setup.py
index 1c565e79..4ee0797c 100755
--- a/setup.py
+++ b/setup.py
@@ -1,37 +1,46 @@
 #!/usr/bin/env python
+"""
+Package setup commands.
+"""
+# pylint: disable=bad-option-value,too-many-ancestors
 
 import codecs
 import os
-import re
 
-try:
-    from setuptools import setup, find_packages
-    from setuptools.command.build_py import build_py
-except ImportError:
-    from distutils.core import setup, find_packages
-    from distutils.command.build_py import build_py
+from setuptools import setup, find_packages
+from setuptools.command.build_py import build_py
 
 # Extra commands for documentation management
 cmdclass = {}
 command_options = {}
 
-# Build the package
-# python setup.py build_py
-# builds the package with generating correspondent VERSION file
+
 class BuildPyCommand(build_py):
+    """
+    Build the package
+    python setup.py build_py
+    builds the package with generating correspondent VERSION file
+    """
+
     def run(self):
+        """
+        Run the command.
+        """
+
         # Import here to allow to run commands
         # like `python setup.py test` without setuptools_scm.
+        # pylint: disable=import-outside-toplevel,import-error
         from setuptools_scm import get_version
         version = get_version()
 
         package_dir = self.get_package_dir('tarantool')
         version_file = os.path.join(package_dir, 'version.py')
-        with open(version_file, 'w') as file:
+        with open(version_file, 'w', encoding='utf-8') as file:
             file.write(f"__version__ = '{version}'")
 
         return super().run()
 
+
 cmdclass["build_py"] = BuildPyCommand
 
 # Build Sphinx documentation (html)
@@ -47,33 +56,34 @@ def run(self):
 # Test runner
 # python setup.py test
 try:
-    from test.setup_command import test
-    cmdclass["test"] = test
+    from test.setup_command import Test
+    cmdclass["test"] = Test
 except ImportError:
     pass
 
 
 def read(*parts):
+    """
+    Read the file.
+    """
+
     filename = os.path.join(os.path.dirname(__file__), *parts)
-    with codecs.open(filename, encoding='utf-8') as fp:
-        return fp.read()
+    with codecs.open(filename, encoding='utf-8') as file:
+        return file.read()
+
+
+def get_dependencies(filename):
+    """
+    Get package dependencies from the `requirements.txt`.
+    """
 
-def get_dependencies(file):
     root = os.path.dirname(os.path.realpath(__file__))
-    requirements = os.path.join(root, file)
-    result = []
+    requirements = os.path.join(root, filename)
     if os.path.isfile(requirements):
-        with open(requirements) as f:
-            return f.read().splitlines()
-    raise RuntimeError("Unable to get dependencies from file " + file)
-
-def find_version(*file_paths):
-    version_file = read(*file_paths)
-    version_match = re.search(r"""^__version__\s*=\s*(['"])(.+)\1""",
-                              version_file, re.M)
-    if version_match:
-        return version_match.group(2)
-    raise RuntimeError("Unable to find version string.")
+        with open(requirements, encoding='utf-8') as file:
+            return file.read().splitlines()
+    raise RuntimeError("Unable to get dependencies from file " + filename)
+
 
 packages = [item for item in find_packages('.') if item.startswith('tarantool')]
 
diff --git a/tarantool/__init__.py b/tarantool/__init__.py
index 915961fd..91f80e10 100644
--- a/tarantool/__init__.py
+++ b/tarantool/__init__.py
@@ -1,6 +1,7 @@
-# pylint: disable=C0301,W0105,W0401,W0614
-
-import sys
+"""
+This package provides API for interaction with a Tarantool server.
+"""
+# pylint: disable=too-many-arguments
 
 from tarantool.connection import Connection
 from tarantool.mesh_connection import MeshConnection
@@ -141,4 +142,4 @@ def connectmesh(addrs=({'host': 'localhost', 'port': 3301},), user=None,
 __all__ = ['connect', 'Connection', 'connectmesh', 'MeshConnection', 'Schema',
            'Error', 'DatabaseError', 'NetworkError', 'NetworkWarning',
            'SchemaError', 'dbapi', 'Datetime', 'Interval', 'IntervalAdjust',
-           'ConnectionPool', 'Mode', 'BoxError',]
+           'ConnectionPool', 'Mode', 'BoxError']
diff --git a/tarantool/connection.py b/tarantool/connection.py
index cd1329c6..ca7109de 100644
--- a/tarantool/connection.py
+++ b/tarantool/connection.py
@@ -1,23 +1,25 @@
-# pylint: disable=C0301,W0105,W0401,W0614
 """
 This module provides API for interaction with a Tarantool server.
 """
+# pylint: disable=too-many-lines,duplicate-code
 
 import os
 import time
 import errno
+from enum import Enum
 import socket
 try:
     import ssl
-    is_ssl_supported = True
+    IS_SSL_SUPPORTED = True
 except ImportError:
-    is_ssl_supported = False
+    IS_SSL_SUPPORTED = False
 import sys
 import abc
 
 import ctypes
 import ctypes.util
 from ctypes import c_ssize_t
+from typing import Optional, Union
 
 import msgpack
 
@@ -69,7 +71,6 @@
     IPROTO_FEATURE_TRANSACTIONS,
     IPROTO_FEATURE_ERROR_EXTENSION,
     IPROTO_FEATURE_WATCHERS,
-    IPROTO_AUTH_TYPE,
     IPROTO_CHUNK,
     AUTH_TYPE_CHAP_SHA1,
     AUTH_TYPE_PAP_SHA256,
@@ -93,7 +94,6 @@
     CrudModuleError,
     CrudModuleManyError,
     SchemaReloadException,
-    Warning,
     warn
 )
 from tarantool.schema import Schema
@@ -108,7 +108,10 @@
     CrudError,
     call_crud,
 )
-from typing import Union
+
+WWSAEWOULDBLOCK = 10035
+ER_UNKNOWN_REQUEST_TYPE = 48
+
 
 # Based on https://realpython.com/python-interface/
 class ConnectionInterface(metaclass=abc.ABCMeta):
@@ -120,36 +123,37 @@ class ConnectionInterface(metaclass=abc.ABCMeta):
     Lua code on server, make simple data manipulations and execute SQL
     queries.
     """
+    # pylint: disable=too-many-public-methods
 
     @classmethod
     def __subclasshook__(cls, subclass):
-        return (hasattr(subclass, 'close') and
-                callable(subclass.close) and
-                hasattr(subclass, 'is_closed') and
-                callable(subclass.is_closed) and
-                hasattr(subclass, 'connect') and
-                callable(subclass.connect) and
-                hasattr(subclass, 'call') and
-                callable(subclass.call) and
-                hasattr(subclass, 'eval') and
-                callable(subclass.eval) and
-                hasattr(subclass, 'replace') and
-                callable(subclass.replace) and
-                hasattr(subclass, 'insert') and
-                callable(subclass.insert) and
-                hasattr(subclass, 'delete') and
-                callable(subclass.delete) and
-                hasattr(subclass, 'upsert') and
-                callable(subclass.upsert) and
-                hasattr(subclass, 'update') and
-                callable(subclass.update) and
-                hasattr(subclass, 'ping') and
-                callable(subclass.ping) and
-                hasattr(subclass, 'select') and
-                callable(subclass.select) and
-                hasattr(subclass, 'execute') and
-                callable(subclass.execute) or
-                NotImplemented)
+        return (hasattr(subclass, 'close')
+                and callable(subclass.close)
+                and hasattr(subclass, 'is_closed')
+                and callable(subclass.is_closed)
+                and hasattr(subclass, 'connect')
+                and callable(subclass.connect)
+                and hasattr(subclass, 'call')
+                and callable(subclass.call)
+                and hasattr(subclass, 'eval')
+                and callable(subclass.eval)
+                and hasattr(subclass, 'replace')
+                and callable(subclass.replace)
+                and hasattr(subclass, 'insert')
+                and callable(subclass.insert)
+                and hasattr(subclass, 'delete')
+                and callable(subclass.delete)
+                and hasattr(subclass, 'upsert')
+                and callable(subclass.upsert)
+                and hasattr(subclass, 'update')
+                and callable(subclass.update)
+                and hasattr(subclass, 'ping')
+                and callable(subclass.ping)
+                and hasattr(subclass, 'select')
+                and callable(subclass.select)
+                and hasattr(subclass, 'execute')
+                and callable(subclass.execute)
+                or NotImplemented)
 
     @abc.abstractmethod
     def close(self):
@@ -193,7 +197,7 @@ def eval(self, expr, *args, on_push=None, on_push_ctx=None):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def replace(self, space_name, values, on_push=None, on_push_ctx=None):
+    def replace(self, space_name, values, *, on_push=None, on_push_ctx=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.replace`.
         """
@@ -201,7 +205,7 @@ def replace(self, space_name, values, on_push=None, on_push_ctx=None):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def insert(self, space_name, values, on_push=None, on_push_ctx=None):
+    def insert(self, space_name, values, *, on_push=None, on_push_ctx=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.insert`.
         """
@@ -217,7 +221,7 @@ def delete(self, space_name, key, *, index=None, on_push=None, on_push_ctx=None)
         raise NotImplementedError
 
     @abc.abstractmethod
-    def upsert(self, space_name, tuple_value, op_list, *, index=None, 
+    def upsert(self, space_name, tuple_value, op_list, *, index=None,
                on_push=None, on_push_ctx=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.upsert`.
@@ -259,7 +263,7 @@ def execute(self, query, params):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_insert(self, space_name, values, opts={}):
+    def crud_insert(self, space_name, values, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_insert`.
         """
@@ -267,7 +271,7 @@ def crud_insert(self, space_name, values, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_insert_object(self, space_name, values, opts={}):
+    def crud_insert_object(self, space_name, values, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_insert_object`.
         """
@@ -275,7 +279,7 @@ def crud_insert_object(self, space_name, values, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_insert_many(self, space_name, values, opts={}):
+    def crud_insert_many(self, space_name, values, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_insert_many`.
         """
@@ -283,7 +287,7 @@ def crud_insert_many(self, space_name, values, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_insert_object_many(self, space_name, values, opts={}):
+    def crud_insert_object_many(self, space_name, values, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_insert_object_many`.
         """
@@ -291,7 +295,7 @@ def crud_insert_object_many(self, space_name, values, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_get(self, space_name, key, opts={}):
+    def crud_get(self, space_name, key, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_get`.
         """
@@ -299,7 +303,7 @@ def crud_get(self, space_name, key, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_update(self, space_name, key, operations=[], opts={}):
+    def crud_update(self, space_name, key, operations=None, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_update`.
         """
@@ -307,7 +311,7 @@ def crud_update(self, space_name, key, operations=[], opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_delete(self, space_name, key, opts={}):
+    def crud_delete(self, space_name, key, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_delete`.
         """
@@ -315,7 +319,7 @@ def crud_delete(self, space_name, key, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_replace(self, space_name, values, opts={}):
+    def crud_replace(self, space_name, values, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_replace`.
         """
@@ -323,7 +327,7 @@ def crud_replace(self, space_name, values, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_replace_object(self, space_name, values, opts={}):
+    def crud_replace_object(self, space_name, values, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_replace_object`.
         """
@@ -331,7 +335,7 @@ def crud_replace_object(self, space_name, values, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_replace_many(self, space_name, values, opts={}):
+    def crud_replace_many(self, space_name, values, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_replace_many`.
         """
@@ -339,7 +343,7 @@ def crud_replace_many(self, space_name, values, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_replace_object_many(self, space_name, values, opts={}):
+    def crud_replace_object_many(self, space_name, values, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_replace_object_many`.
         """
@@ -347,7 +351,7 @@ def crud_replace_object_many(self, space_name, values, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_upsert(self, space_name, values, operations=[], opts={}):
+    def crud_upsert(self, space_name, values, operations=None, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_upsert`.
         """
@@ -355,7 +359,7 @@ def crud_upsert(self, space_name, values, operations=[], opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_upsert_object(self, space_name, values, operations=[], opts={}):
+    def crud_upsert_object(self, space_name, values, operations=None, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_upsert_object`.
         """
@@ -363,7 +367,7 @@ def crud_upsert_object(self, space_name, values, operations=[], opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_upsert_many(self, space_name, values_operation, opts={}):
+    def crud_upsert_many(self, space_name, values_operation, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_upsert_many`.
         """
@@ -371,7 +375,7 @@ def crud_upsert_many(self, space_name, values_operation, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_upsert_object_many(self, space_name, values_operation, opts={}):
+    def crud_upsert_object_many(self, space_name, values_operation, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_upsert_object_many`.
         """
@@ -379,7 +383,7 @@ def crud_upsert_object_many(self, space_name, values_operation, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_select(self, space_name: str, conditions=[], opts={}):
+    def crud_select(self, space_name: str, conditions=None, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_select`.
         """
@@ -387,7 +391,7 @@ def crud_select(self, space_name: str, conditions=[], opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_min(self, space_name, index_name, opts={}):
+    def crud_min(self, space_name, index_name, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_min`.
         """
@@ -395,7 +399,7 @@ def crud_min(self, space_name, index_name, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_max(self, space_name, index_name, opts={}):
+    def crud_max(self, space_name, index_name, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_max`.
         """
@@ -403,7 +407,7 @@ def crud_max(self, space_name, index_name, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_truncate(self, space_name, opts={}):
+    def crud_truncate(self, space_name, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_truncate`.
         """
@@ -411,7 +415,7 @@ def crud_truncate(self, space_name, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_len(self, space_name, opts={}):
+    def crud_len(self, space_name, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_len`.
         """
@@ -419,7 +423,7 @@ def crud_len(self, space_name, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_storage_info(self, opts={}):
+    def crud_storage_info(self, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_storage_info`.
         """
@@ -427,7 +431,7 @@ def crud_storage_info(self, opts={}):
         raise NotImplementedError
 
     @abc.abstractmethod
-    def crud_count(self, space_name, conditions=[], opts={}):
+    def crud_count(self, space_name, conditions=None, opts=None):
         """
         Reference implementation: :meth:`~tarantool.Connection.crud_count`.
         """
@@ -451,6 +455,34 @@ def crud_unflatten_rows(self, rows, metadata):
         raise NotImplementedError
 
 
+class JoinState(Enum):
+    """
+    Current replication join state. See `join protocol`_ for more info.
+
+    .. _join protocol: https://www.tarantool.io/en/doc/latest/dev_guide/internals/iproto/replication/#box-protocol-join
+    """
+
+    HANDSHAKE = 1
+    """
+    Sent the join request.
+    """
+
+    INITIAL = 2
+    """
+    Received initial vclock.
+    """
+
+    FINAL = 3
+    """
+    Received current vclock.
+    """
+
+    DONE = 4
+    """
+    No more messages expected.
+    """
+
+
 class Connection(ConnectionInterface):
     """
     Represents a connection to the Tarantool server.
@@ -459,6 +491,7 @@ class Connection(ConnectionInterface):
     check its status, call procedures and evaluate Lua code on server,
     make simple data manipulations and execute SQL queries.
     """
+    # pylint: disable=too-many-instance-attributes,too-many-public-methods,bad-option-value,no-self-use
 
     # DBAPI Extension: supply exceptions as attributes on the connection
     Error = Error
@@ -757,10 +790,11 @@ def __init__(self, host, port,
         .. _mp_bin: https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family
         .. _mp_array: https://github.com/msgpack/msgpack/blob/master/spec.md#array-format-family
         """
+        # pylint: disable=too-many-arguments,too-many-locals
 
         if msgpack.version >= (1, 0, 0) and encoding not in (None, 'utf-8'):
-            raise ConfigurationError("msgpack>=1.0.0 only supports None and " +
-                                     "'utf-8' encoding option values")
+            raise ConfigurationError("msgpack>=1.0.0 only supports None and "
+                                     + "'utf-8' encoding option values")
 
         if os.name == 'nt':
             libc = ctypes.WinDLL(
@@ -807,6 +841,9 @@ def __init__(self, host, port,
         self._unpacker_factory_impl = unpacker_factory
         self._client_auth_type = auth_type
         self._server_auth_type = None
+        self.version_id = None
+        self.uuid = None
+        self._salt = None
 
         if connect_now:
             self.connect()
@@ -863,9 +900,9 @@ def connect_tcp(self):
                 (self.host, self.port), timeout=self.connection_timeout)
             self._socket.settimeout(self.socket_timeout)
             self._socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
-        except socket.error as e:
+        except socket.error as exc:
             self.connected = False
-            raise NetworkError(e)
+            raise NetworkError(exc) from exc
 
     def connect_unix(self):
         """
@@ -876,6 +913,7 @@ def connect_unix(self):
 
         :meta private:
         """
+        # pylint: disable=no-member
 
         try:
             # If old socket already exists - close it and re-create
@@ -886,9 +924,9 @@ def connect_unix(self):
             self._socket.settimeout(self.connection_timeout)
             self._socket.connect(self.port)
             self._socket.settimeout(self.socket_timeout)
-        except socket.error as e:
+        except socket.error as exc:
             self.connected = False
-            raise NetworkError(e)
+            raise NetworkError(exc) from exc
 
     def wrap_socket_ssl(self):
         """
@@ -899,17 +937,17 @@ def wrap_socket_ssl(self):
         :meta private:
         """
 
-        if not is_ssl_supported:
+        if not IS_SSL_SUPPORTED:
             raise SslError("Your version of Python doesn't support SSL")
 
         ver = sys.version_info
         if ver[0] < 3 or (ver[0] == 3 and ver[1] < 5):
-            raise SslError("SSL transport is supported only since " +
+            raise SslError("SSL transport is supported only since "
                            "python 3.5")
 
         if ((self.ssl_cert_file is None and self.ssl_key_file is not None)
            or (self.ssl_cert_file is not None and self.ssl_key_file is None)):
-            raise SslError("Both ssl_cert_file and ssl_key_file should be " +
+            raise SslError("Both ssl_cert_file and ssl_key_file should be "
                            "configured or unconfigured")
 
         try:
@@ -940,10 +978,10 @@ def wrap_socket_ssl(self):
                 context.set_ciphers(self.ssl_ciphers)
 
             self._socket = context.wrap_socket(self._socket)
-        except SslError as e:
-            raise e
-        except Exception as e:
-            raise SslError(e)
+        except SslError as exc:
+            raise exc
+        except Exception as exc:
+            raise SslError(exc) from exc
 
     def _ssl_load_cert_chain(self, context):
         """
@@ -968,34 +1006,32 @@ def _ssl_load_cert_chain(self, context):
                                         keyfile=self.ssl_key_file,
                                         password=self.ssl_password)
                 return
-            except Exception as e:
-                exc_list.append(e)
-
+            except Exception as exc:  # pylint: disable=bad-option-value,broad-exception-caught,broad-except
+                exc_list.append(exc)
 
         if self.ssl_password_file is not None:
-            with open(self.ssl_password_file) as file:
+            with open(self.ssl_password_file, encoding=self.encoding) as file:
                 for line in file:
                     try:
                         context.load_cert_chain(certfile=self.ssl_cert_file,
                                                 keyfile=self.ssl_key_file,
                                                 password=line.rstrip())
                         return
-                    except Exception as e:
-                        exc_list.append(e)
-
+                    except Exception as exc:  # pylint: disable=bad-option-value,broad-exception-caught,broad-except
+                        exc_list.append(exc)
 
         try:
             def password_raise_error():
-                raise SslError("Password prompt for decrypting the private " +
-                               "key is unsupported, use ssl_password or " +
+                raise SslError("Password prompt for decrypting the private "
+                               "key is unsupported, use ssl_password or "
                                "ssl_password_file")
             context.load_cert_chain(certfile=self.ssl_cert_file,
                                     keyfile=self.ssl_key_file,
                                     password=password_raise_error)
 
             return
-        except Exception as e:
-            exc_list.append(e)
+        except Exception as exc:  # pylint: disable=bad-option-value,broad-exception-caught,broad-except
+            exc_list.append(exc)
 
         raise SslError(exc_list)
 
@@ -1043,11 +1079,11 @@ def connect(self):
                 self.load_schema()
             else:
                 self.schema = None
-        except SslError as e:
-            raise e
-        except Exception as e:
+        except SslError as exc:
+            raise exc
+        except Exception as exc:
             self.connected = False
-            raise NetworkError(e)
+            raise NetworkError(exc) from exc
 
     def _recv(self, to_read):
         """
@@ -1066,28 +1102,28 @@ def _recv(self, to_read):
         while to_read > 0:
             try:
                 tmp = self._socket.recv(to_read)
-            except OverflowError:
+            except OverflowError as exc:
                 self._socket.close()
                 err = socket.error(
                     errno.ECONNRESET,
                     "Packet too large. Closing connection to server"
                 )
-                raise NetworkError(err)
-            except socket.error:
+                raise NetworkError(err) from exc
+            except socket.error as exc:
+                err = socket.error(
+                    errno.ECONNRESET,
+                    "Lost connection to server during query"
+                )
+                raise NetworkError(err) from exc
+
+            if len(tmp) == 0:
                 err = socket.error(
                     errno.ECONNRESET,
                     "Lost connection to server during query"
                 )
                 raise NetworkError(err)
-            else:
-                if len(tmp) == 0:
-                    err = socket.error(
-                        errno.ECONNRESET,
-                        "Lost connection to server during query"
-                    )
-                    raise NetworkError(err)
-                to_read -= len(tmp)
-                buf += tmp
+            to_read -= len(tmp)
+            buf += tmp
         return buf
 
     def _read_response(self):
@@ -1136,14 +1172,14 @@ def _send_request_wo_reconnect(self, request, on_push=None, on_push_ctx=None):
                 self._socket.sendall(bytes(request))
                 response = request.response_class(self, self._read_response())
                 break
-            except SchemaReloadException as e:
+            except SchemaReloadException as exc:
                 if self.schema is not None:
-                    self.update_schema(e.schema_version)
+                    self.update_schema(exc.schema_version)
                 continue
 
-        while response._code == IPROTO_CHUNK:
-            if on_push is not None: 
-                on_push(response._data, on_push_ctx)
+        while response.code == IPROTO_CHUNK:
+            if on_push is not None:
+                on_push(response.data, on_push_ctx)
             response = request.response_class(self, self._read_response())
 
         return response
@@ -1158,42 +1194,41 @@ def _opt_reconnect(self):
 
         :meta private:
         """
+        # pylint: disable=no-member
 
         # **Bug in Python: timeout is an internal Python construction (???).
         if not self._socket:
-            return self.connect()
+            self.connect()
+            return
 
         def check():  # Check that connection is alive
             buf = ctypes.create_string_buffer(2)
             try:
                 sock_fd = self._socket.fileno()
-            except socket.error as e:
-                if e.errno == errno.EBADF:
+            except socket.error as exc:
+                if exc.errno == errno.EBADF:
                     return errno.ECONNRESET
+                return exc.errno
+
+            if os.name == 'nt':
+                flag = socket.MSG_PEEK
+                self._socket.setblocking(False)
             else:
-                if os.name == 'nt':
-                    flag = socket.MSG_PEEK
-                    self._socket.setblocking(False)
-                else:
-                    flag = socket.MSG_DONTWAIT | socket.MSG_PEEK
-                retbytes = self._sys_recv(sock_fd, buf, 1, flag)
-
-                err = 0
-                if os.name!= 'nt':
-                    err = ctypes.get_errno()
-                else:
-                    err = ctypes.get_last_error()
-                    self._socket.setblocking(True)
-
-
-                WWSAEWOULDBLOCK = 10035
-                if (retbytes < 0) and (err == errno.EAGAIN or
-                                       err == errno.EWOULDBLOCK or
-                                       err == WWSAEWOULDBLOCK):
-                    ctypes.set_errno(0)
-                    return errno.EAGAIN
-                else:
-                    return errno.ECONNRESET
+                flag = socket.MSG_DONTWAIT | socket.MSG_PEEK
+            retbytes = self._sys_recv(sock_fd, buf, 1, flag)
+
+            err = 0
+            if os.name != 'nt':
+                err = ctypes.get_errno()
+            else:
+                err = ctypes.get_last_error()
+                self._socket.setblocking(True)
+
+            if (retbytes < 0) and err in (errno.EAGAIN, errno.EWOULDBLOCK, WWSAEWOULDBLOCK):
+                ctypes.set_errno(0)
+                return errno.EAGAIN
+
+            return errno.ECONNRESET
 
         last_errno = check()
         if self.connected and last_errno == errno.EAGAIN:
@@ -1210,8 +1245,8 @@ def check():  # Check that connection is alive
             else:
                 if self.connected:
                     break
-            warn("Reconnecting, attempt %d of %d" %
-                 (attempt, self.reconnect_max_attempts), NetworkWarning)
+            warn(f"Reconnecting, attempt {attempt} of {self.reconnect_max_attempts}",
+                 NetworkWarning)
             if attempt == self.reconnect_max_attempts:
                 raise NetworkError(
                     socket.error(last_errno, errno.errorcode[last_errno]))
@@ -1302,7 +1337,7 @@ def _schemaful_connection_check(self):
         :raise: :exc:`~tarantool.error.NotSupportedError`
         """
         if self.schema is None:
-            raise NotSupportedError('This method is not available in ' +
+            raise NotSupportedError('This method is not available in '
                                     'connection opened with fetch_schema=False')
 
     def call(self, func_name, *args, on_push=None, on_push_ctx=None):
@@ -1378,7 +1413,7 @@ def eval(self, expr, *args, on_push=None, on_push_ctx=None):
         response = self._send_request(request, on_push, on_push_ctx)
         return response
 
-    def replace(self, space_name, values, on_push=None, on_push_ctx=None):
+    def replace(self, space_name, values, *, on_push=None, on_push_ctx=None):
         """
         Execute a REPLACE request: `replace`_ a tuple in the space.
         Doesn't throw an error if there is no tuple with the specified
@@ -1444,11 +1479,12 @@ def authenticate(self, user, password):
         if not self._socket:
             return self._opt_reconnect()
 
-        request = RequestAuthenticate(self,
-                              salt=self._salt,
-                              user=self.user,
-                              password=self.password,
-                              auth_type=self._get_auth_type())
+        request = RequestAuthenticate(
+            self,
+            salt=self._salt,
+            user=self.user,
+            password=self.password,
+            auth_type=self._get_auth_type())
         auth_response = self._send_request_wo_reconnect(request)
         if auth_response.return_code == 0 and self.schema is not None:
             self.flush_schema()
@@ -1470,11 +1506,13 @@ def _get_auth_type(self):
                 auth_type = AUTH_TYPE_CHAP_SHA1
             else:
                 if self._server_auth_type not in AUTH_TYPES:
-                    raise ConfigurationError(f'Unknown server authentication type {self._server_auth_type}')
+                    raise ConfigurationError('Unknown server authentication type '
+                                             + str(self._server_auth_type))
                 auth_type = self._server_auth_type
         else:
             if self._client_auth_type not in AUTH_TYPES:
-                raise ConfigurationError(f'Unknown client authentication type {self._client_auth_type}')
+                raise ConfigurationError('Unknown client authentication type '
+                                         + str(self._client_auth_type))
             auth_type = self._client_auth_type
 
         if auth_type == AUTH_TYPE_PAP_SHA256 and self.transport != SSL_TRANSPORT:
@@ -1520,29 +1558,30 @@ def _join_v17(self, server_uuid):
             :exc:`~tarantool.error.SslError`
         """
 
-        class JoinState:
-            Handshake, Initial, Final, Done = range(4)
-
         request = RequestJoin(self, server_uuid)
         self._socket.sendall(bytes(request))
-        state = JoinState.Handshake
+        state = JoinState.HANDSHAKE
         while True:
             resp = Response(self, self._read_response())
             yield resp
             if resp.code >= REQUEST_TYPE_ERROR:
                 return
-            elif resp.code == REQUEST_TYPE_OK:
-                state = state + 1
-                if state == JoinState.Done:
+            if resp.code == REQUEST_TYPE_OK:
+                if state == JoinState.HANDSHAKE:
+                    state = JoinState.INITIAL
+                elif state == JoinState.INITIAL:
+                    state = JoinState.FINAL
+                elif state == JoinState.FINAL:
+                    state = JoinState.DONE
                     return
 
     def _ops_process(self, space, update_ops):
         new_ops = []
-        for op in update_ops:
-            if isinstance(op[1], str):
-                op = list(op)
-                op[1] = self.schema.get_field(space, op[1])['id']
-            new_ops.append(op)
+        for operation in update_ops:
+            if isinstance(operation[1], str):
+                operation = list(operation)
+                operation[1] = self.schema.get_field(space, operation[1])['id']
+            new_ops.append(operation)
         return new_ops
 
     def join(self, server_uuid):
@@ -1599,7 +1638,7 @@ def subscribe(self, cluster_uuid, server_uuid, vclock=None):
                 return
         self.close()  # close connection after SUBSCRIBE
 
-    def insert(self, space_name, values, on_push=None, on_push_ctx=None):
+    def insert(self, space_name, values, *, on_push=None, on_push_ctx=None):
         """
         Execute an INSERT request: `insert`_ a tuple to the space.
         Throws an error if there is already a tuple with the same
@@ -1858,15 +1897,16 @@ def ping(self, notime=False):
         """
 
         request = RequestPing(self)
-        t0 = time.time()
+        start_time = time.time()
         self._send_request(request)
-        t1 = time.time()
+        finish_time = time.time()
 
         if notime:
             return "Success"
-        return t1 - t0
+        return finish_time - start_time
 
-    def select(self, space_name, key=None, *, offset=0, limit=0xffffffff, index=0, iterator=None, on_push=None, on_push_ctx=None):
+    def select(self, space_name, key=None, *, offset=0, limit=0xffffffff, index=0, iterator=None,
+               on_push=None, on_push_ctx=None):
         """
         Execute a SELECT request: `select`_ a tuple from the space.
 
@@ -2000,7 +2040,7 @@ def select(self, space_name, key=None, *, offset=0, limit=0xffffffff, index=0, i
 
         :param on_push_ctx: Сontext for working with on_push callback.
         :type on_push_ctx: optional
-        
+
         :rtype: :class:`~tarantool.response.Response`
 
         :raise: :exc:`~AssertionError`,
@@ -2017,8 +2057,8 @@ def select(self, space_name, key=None, *, offset=0, limit=0xffffffff, index=0, i
 
         if iterator is None:
             iterator = ITERATOR_EQ
-            if key is None or (isinstance(key, (list, tuple)) and
-                               len(key) == 0):
+            if key is None or (isinstance(key, (list, tuple))
+                               and len(key) == 0):
                 iterator = ITERATOR_ALL
 
         # Perform smart type checking (scalar / list of scalars / list of
@@ -2141,7 +2181,6 @@ def _check_features(self):
             server_features = response.features
             server_auth_type = response.auth_type
         except DatabaseError as exc:
-            ER_UNKNOWN_REQUEST_TYPE = 48
             if exc.code == ER_UNKNOWN_REQUEST_TYPE:
                 server_protocol_version = None
                 server_features = []
@@ -2166,9 +2205,10 @@ def _packer_factory(self):
     def _unpacker_factory(self):
         return self._unpacker_factory_impl(self)
 
-    def crud_insert(self, space_name: str, values: Union[tuple, list], opts: dict={}) -> CrudResult:
+    def crud_insert(self, space_name: str, values: Union[tuple, list],
+                    opts: Optional[dict] = None) -> CrudResult:
         """
-        Inserts row through the 
+        Inserts row through the
         `crud <https://github.com/tarantool/crud#insert>`__.
 
         :param space_name: The name of the target space.
@@ -2188,6 +2228,8 @@ def crud_insert(self, space_name: str, values: Union[tuple, list], opts: dict={}
 
         assert isinstance(space_name, str)
         assert isinstance(values, (tuple, list))
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.insert", space_name, values, opts)
@@ -2197,9 +2239,10 @@ def crud_insert(self, space_name: str, values: Union[tuple, list], opts: dict={}
 
         return CrudResult(crud_resp[0])
 
-    def crud_insert_object(self, space_name: str, values: dict, opts: dict={}) -> CrudResult:
+    def crud_insert_object(self, space_name: str, values: dict,
+                           opts: Optional[dict] = None) -> CrudResult:
         """
-        Inserts object row through the 
+        Inserts object row through the
         `crud <https://github.com/tarantool/crud#insert>`__.
 
         :param space_name: The name of the target space.
@@ -2219,6 +2262,8 @@ def crud_insert_object(self, space_name: str, values: dict, opts: dict={}) -> Cr
 
         assert isinstance(space_name, str)
         assert isinstance(values, dict)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.insert_object", space_name, values, opts)
@@ -2228,9 +2273,10 @@ def crud_insert_object(self, space_name: str, values: dict, opts: dict={}) -> Cr
 
         return CrudResult(crud_resp[0])
 
-    def crud_insert_many(self, space_name: str, values: Union[tuple, list], opts: dict={}) -> CrudResult:
+    def crud_insert_many(self, space_name: str, values: Union[tuple, list],
+                         opts: Optional[dict] = None) -> CrudResult:
         """
-        Inserts batch rows through the 
+        Inserts batch rows through the
         `crud <https://github.com/tarantool/crud#insert-many>`__.
 
         :param space_name: The name of the target space.
@@ -2250,6 +2296,8 @@ def crud_insert_many(self, space_name: str, values: Union[tuple, list], opts: di
 
         assert isinstance(space_name, str)
         assert isinstance(values, (tuple, list))
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.insert_many", space_name, values, opts)
@@ -2259,16 +2307,17 @@ def crud_insert_many(self, space_name: str, values: Union[tuple, list], opts: di
             res = CrudResult(crud_resp[0])
 
         if crud_resp[1] is not None:
-            errs = list()
+            errs = []
             for err in crud_resp[1]:
                 errs.append(CrudError(err))
             raise CrudModuleManyError(res, errs)
 
         return res
 
-    def crud_insert_object_many(self, space_name: str, values: Union[tuple, list], opts: dict={}) -> CrudResult:
+    def crud_insert_object_many(self, space_name: str, values: Union[tuple, list],
+                                opts: Optional[dict] = None) -> CrudResult:
         """
-        Inserts batch object rows through the 
+        Inserts batch object rows through the
         `crud <https://github.com/tarantool/crud#insert-many>`__.
 
         :param space_name: The name of the target space.
@@ -2288,6 +2337,8 @@ def crud_insert_object_many(self, space_name: str, values: Union[tuple, list], o
 
         assert isinstance(space_name, str)
         assert isinstance(values, (tuple, list))
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.insert_object_many", space_name, values, opts)
@@ -2297,16 +2348,16 @@ def crud_insert_object_many(self, space_name: str, values: Union[tuple, list], o
             res = CrudResult(crud_resp[0])
 
         if crud_resp[1] is not None:
-            errs = list()
+            errs = []
             for err in crud_resp[1]:
                 errs.append(CrudError(err))
             raise CrudModuleManyError(res, errs)
 
         return res
 
-    def crud_get(self, space_name: str, key: int, opts: dict={}) -> CrudResult:
+    def crud_get(self, space_name: str, key: int, opts: Optional[dict] = None) -> CrudResult:
         """
-        Gets row through the 
+        Gets row through the
         `crud <https://github.com/tarantool/crud#get>`__.
 
         :param space_name: The name of the target space.
@@ -2325,6 +2376,8 @@ def crud_get(self, space_name: str, key: int, opts: dict={}) -> CrudResult:
         """
 
         assert isinstance(space_name, str)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.get", space_name, key, opts)
@@ -2334,9 +2387,10 @@ def crud_get(self, space_name: str, key: int, opts: dict={}) -> CrudResult:
 
         return CrudResult(crud_resp[0])
 
-    def crud_update(self, space_name: str, key: int, operations: list=[], opts: dict={}) -> CrudResult:
+    def crud_update(self, space_name: str, key: int, operations: Optional[list] = None,
+                    opts: Optional[dict] = None) -> CrudResult:
         """
-        Updates row through the 
+        Updates row through the
         `crud <https://github.com/tarantool/crud#update>`__.
 
         :param space_name: The name of the target space.
@@ -2358,7 +2412,11 @@ def crud_update(self, space_name: str, key: int, operations: list=[], opts: dict
         """
 
         assert isinstance(space_name, str)
+        if operations is None:
+            operations = []
         assert isinstance(operations, list)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.update", space_name, key, operations, opts)
@@ -2368,9 +2426,9 @@ def crud_update(self, space_name: str, key: int, operations: list=[], opts: dict
 
         return CrudResult(crud_resp[0])
 
-    def crud_delete(self, space_name: str, key: int, opts: dict={}) -> CrudResult:
+    def crud_delete(self, space_name: str, key: int, opts: Optional[dict] = None) -> CrudResult:
         """
-        Deletes row through the 
+        Deletes row through the
         `crud <https://github.com/tarantool/crud#delete>`__.
 
         :param space_name: The name of the target space.
@@ -2389,6 +2447,8 @@ def crud_delete(self, space_name: str, key: int, opts: dict={}) -> CrudResult:
         """
 
         assert isinstance(space_name, str)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.delete", space_name, key, opts)
@@ -2398,9 +2458,10 @@ def crud_delete(self, space_name: str, key: int, opts: dict={}) -> CrudResult:
 
         return CrudResult(crud_resp[0])
 
-    def crud_replace(self, space_name: str, values: Union[tuple, list], opts: dict={}) -> CrudResult:
+    def crud_replace(self, space_name: str, values: Union[tuple, list],
+                     opts: Optional[dict] = None) -> CrudResult:
         """
-        Replaces row through the 
+        Replaces row through the
         `crud <https://github.com/tarantool/crud#replace>`__.
 
         :param space_name: The name of the target space.
@@ -2420,6 +2481,8 @@ def crud_replace(self, space_name: str, values: Union[tuple, list], opts: dict={
 
         assert isinstance(space_name, str)
         assert isinstance(values, (tuple, list))
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.replace", space_name, values, opts)
@@ -2429,9 +2492,10 @@ def crud_replace(self, space_name: str, values: Union[tuple, list], opts: dict={
 
         return CrudResult(crud_resp[0])
 
-    def crud_replace_object(self, space_name: str, values: dict, opts: dict={}) -> CrudResult:
+    def crud_replace_object(self, space_name: str, values: dict,
+                            opts: Optional[dict] = None) -> CrudResult:
         """
-        Replaces object row through the 
+        Replaces object row through the
         `crud <https://github.com/tarantool/crud#replace>`__.
 
         :param space_name: The name of the target space.
@@ -2451,6 +2515,8 @@ def crud_replace_object(self, space_name: str, values: dict, opts: dict={}) -> C
 
         assert isinstance(space_name, str)
         assert isinstance(values, dict)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.replace_object", space_name, values, opts)
@@ -2460,9 +2526,10 @@ def crud_replace_object(self, space_name: str, values: dict, opts: dict={}) -> C
 
         return CrudResult(crud_resp[0])
 
-    def crud_replace_many(self, space_name: str, values: Union[tuple, list], opts: dict={}) -> CrudResult:
+    def crud_replace_many(self, space_name: str, values: Union[tuple, list],
+                          opts: Optional[dict] = None) -> CrudResult:
         """
-        Replaces batch rows through the 
+        Replaces batch rows through the
         `crud <https://github.com/tarantool/crud#replace-many>`__.
 
         :param space_name: The name of the target space.
@@ -2482,6 +2549,8 @@ def crud_replace_many(self, space_name: str, values: Union[tuple, list], opts: d
 
         assert isinstance(space_name, str)
         assert isinstance(values, (tuple, list))
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.replace_many", space_name, values, opts)
@@ -2491,16 +2560,17 @@ def crud_replace_many(self, space_name: str, values: Union[tuple, list], opts: d
             res = CrudResult(crud_resp[0])
 
         if crud_resp[1] is not None:
-            errs = list()
+            errs = []
             for err in crud_resp[1]:
                 errs.append(CrudError(err))
             raise CrudModuleManyError(res, errs)
 
         return res
 
-    def crud_replace_object_many(self, space_name: str, values: Union[tuple, list], opts: dict={}) -> CrudResult:
+    def crud_replace_object_many(self, space_name: str, values: Union[tuple, list],
+                                 opts: Optional[dict] = None) -> CrudResult:
         """
-        Replaces batch object rows through the 
+        Replaces batch object rows through the
         `crud <https://github.com/tarantool/crud#replace-many>`__.
 
         :param space_name: The name of the target space.
@@ -2520,6 +2590,8 @@ def crud_replace_object_many(self, space_name: str, values: Union[tuple, list],
 
         assert isinstance(space_name, str)
         assert isinstance(values, (tuple, list))
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.replace_object_many", space_name, values, opts)
@@ -2529,16 +2601,17 @@ def crud_replace_object_many(self, space_name: str, values: Union[tuple, list],
             res = CrudResult(crud_resp[0])
 
         if crud_resp[1] is not None:
-            errs = list()
+            errs = []
             for err in crud_resp[1]:
                 errs.append(CrudError(err))
             raise CrudModuleManyError(res, errs)
 
         return res
 
-    def crud_upsert(self, space_name: str, values: Union[tuple, list], operations: list=[], opts: dict={}) -> CrudResult:
+    def crud_upsert(self, space_name: str, values: Union[tuple, list],
+                    operations: Optional[list] = None, opts: Optional[dict] = None) -> CrudResult:
         """
-        Upserts row through the 
+        Upserts row through the
         `crud <https://github.com/tarantool/crud#upsert>`__.
 
         :param space_name: The name of the target space.
@@ -2561,7 +2634,11 @@ def crud_upsert(self, space_name: str, values: Union[tuple, list], operations: l
 
         assert isinstance(space_name, str)
         assert isinstance(values, (tuple, list))
+        if operations is None:
+            operations = []
         assert isinstance(operations, list)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.upsert", space_name, values, operations, opts)
@@ -2571,9 +2648,11 @@ def crud_upsert(self, space_name: str, values: Union[tuple, list], operations: l
 
         return CrudResult(crud_resp[0])
 
-    def crud_upsert_object(self, space_name: str, values: dict, operations: list=[], opts: dict={}) -> CrudResult:
+    def crud_upsert_object(self, space_name: str, values: dict,
+                           operations: Optional[list] = None,
+                           opts: Optional[dict] = None) -> CrudResult:
         """
-        Upserts object row through the 
+        Upserts object row through the
         `crud <https://github.com/tarantool/crud#upsert>`__.
 
         :param space_name: The name of the target space.
@@ -2596,19 +2675,24 @@ def crud_upsert_object(self, space_name: str, values: dict, operations: list=[],
 
         assert isinstance(space_name, str)
         assert isinstance(values, dict)
+        if operations is None:
+            operations = []
         assert isinstance(operations, list)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.upsert_object", space_name, values, operations, opts)
-        
+
         if crud_resp[1] is not None:
             raise CrudModuleError(None, CrudError(crud_resp[1]))
 
         return CrudResult(crud_resp[0])
 
-    def crud_upsert_many(self, space_name: str, values_operation: Union[tuple, list], opts: dict={}) -> CrudResult:
+    def crud_upsert_many(self, space_name: str, values_operation: Union[tuple, list],
+                         opts: Optional[dict] = None) -> CrudResult:
         """
-        Upserts batch rows through the 
+        Upserts batch rows through the
         `crud <https://github.com/tarantool/crud#upsert-many>`__.
 
         :param space_name: The name of the target space.
@@ -2628,6 +2712,8 @@ def crud_upsert_many(self, space_name: str, values_operation: Union[tuple, list]
 
         assert isinstance(space_name, str)
         assert isinstance(values_operation, (tuple, list))
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.upsert_many", space_name, values_operation, opts)
@@ -2637,16 +2723,17 @@ def crud_upsert_many(self, space_name: str, values_operation: Union[tuple, list]
             res = CrudResult(crud_resp[0])
 
         if crud_resp[1] is not None:
-            errs = list()
+            errs = []
             for err in crud_resp[1]:
                 errs.append(CrudError(err))
             raise CrudModuleManyError(res, errs)
 
         return res
 
-    def crud_upsert_object_many(self, space_name: str, values_operation: Union[tuple, list], opts: dict={}) -> CrudResult:
+    def crud_upsert_object_many(self, space_name: str, values_operation: Union[tuple, list],
+                                opts: Optional[dict] = None) -> CrudResult:
         """
-        Upserts batch object rows through the 
+        Upserts batch object rows through the
         `crud <https://github.com/tarantool/crud#upsert-many>`__.
 
         :param space_name: The name of the target space.
@@ -2666,6 +2753,8 @@ def crud_upsert_object_many(self, space_name: str, values_operation: Union[tuple
 
         assert isinstance(space_name, str)
         assert isinstance(values_operation, (tuple, list))
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.upsert_object_many", space_name, values_operation, opts)
@@ -2675,16 +2764,17 @@ def crud_upsert_object_many(self, space_name: str, values_operation: Union[tuple
             res = CrudResult(crud_resp[0])
 
         if crud_resp[1] is not None:
-            errs = list()
+            errs = []
             for err in crud_resp[1]:
                 errs.append(CrudError(err))
             raise CrudModuleManyError(res, errs)
 
         return res
 
-    def crud_select(self, space_name: str, conditions: list=[], opts: dict={}) -> CrudResult:
+    def crud_select(self, space_name: str, conditions: Optional[list] = None,
+                    opts: Optional[dict] = None) -> CrudResult:
         """
-        Selects rows through the 
+        Selects rows through the
         `crud <https://github.com/tarantool/crud#select>`__.
 
         :param space_name: The name of the target space.
@@ -2703,7 +2793,11 @@ def crud_select(self, space_name: str, conditions: list=[], opts: dict={}) -> Cr
         """
 
         assert isinstance(space_name, str)
-        assert isinstance(conditions, (tuple, list))
+        if conditions is None:
+            conditions = []
+        assert isinstance(conditions, list)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.select", space_name, conditions, opts)
@@ -2713,9 +2807,9 @@ def crud_select(self, space_name: str, conditions: list=[], opts: dict={}) -> Cr
 
         return CrudResult(crud_resp[0])
 
-    def crud_min(self, space_name: str, index_name: str, opts: dict={}) -> CrudResult:
+    def crud_min(self, space_name: str, index_name: str, opts: Optional[dict] = None) -> CrudResult:
         """
-        Gets rows with minimum value in the specified index through 
+        Gets rows with minimum value in the specified index through
         the `crud <https://github.com/tarantool/crud#min-and-max>`__.
 
         :param space_name: The name of the target space.
@@ -2734,6 +2828,8 @@ def crud_min(self, space_name: str, index_name: str, opts: dict={}) -> CrudResul
         """
 
         assert isinstance(space_name, str)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.min", space_name, index_name, opts)
@@ -2743,9 +2839,9 @@ def crud_min(self, space_name: str, index_name: str, opts: dict={}) -> CrudResul
 
         return CrudResult(crud_resp[0])
 
-    def crud_max(self, space_name: str, index_name: str, opts: dict={}) -> CrudResult:
+    def crud_max(self, space_name: str, index_name: str, opts: Optional[dict] = None) -> CrudResult:
         """
-        Gets rows with maximum value in the specified index through 
+        Gets rows with maximum value in the specified index through
         the `crud <https://github.com/tarantool/crud#min-and-max>`__.
 
         :param space_name: The name of the target space.
@@ -2764,6 +2860,8 @@ def crud_max(self, space_name: str, index_name: str, opts: dict={}) -> CrudResul
         """
 
         assert isinstance(space_name, str)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.max", space_name, index_name, opts)
@@ -2773,9 +2871,9 @@ def crud_max(self, space_name: str, index_name: str, opts: dict={}) -> CrudResul
 
         return CrudResult(crud_resp[0])
 
-    def crud_truncate(self, space_name: str, opts: dict={}) -> bool:
+    def crud_truncate(self, space_name: str, opts: Optional[dict] = None) -> bool:
         """
-        Truncate rows through 
+        Truncate rows through
         the `crud <https://github.com/tarantool/crud#truncate>`__.
 
         :param space_name: The name of the target space.
@@ -2791,20 +2889,22 @@ def crud_truncate(self, space_name: str, opts: dict={}) -> bool:
         """
 
         assert isinstance(space_name, str)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.truncate", space_name, opts)
 
-        # In absence of an error, crud does not give 
+        # In absence of an error, crud does not give
         # variable err as nil (as in most cases).
         if len(crud_resp) != 1:
             raise CrudModuleError(None, CrudError(crud_resp[1]))
 
         return crud_resp[0]
-    
-    def crud_len(self, space_name: str, opts: dict={}) -> int:
+
+    def crud_len(self, space_name: str, opts: Optional[dict] = None) -> int:
         """
-        Gets the number of tuples in the space through 
+        Gets the number of tuples in the space through
         the `crud <https://github.com/tarantool/crud#len>`__.
 
         :param space_name: The name of the target space.
@@ -2820,20 +2920,22 @@ def crud_len(self, space_name: str, opts: dict={}) -> int:
         """
 
         assert isinstance(space_name, str)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.len", space_name, opts)
 
-        # In absence of an error, crud does not give 
+        # In absence of an error, crud does not give
         # variable err as nil (as in most cases).
         if len(crud_resp) != 1:
             raise CrudModuleError(None, CrudError(crud_resp[1]))
 
         return crud_resp[0]
 
-    def crud_storage_info(self, opts: dict={}) -> dict:
+    def crud_storage_info(self, opts: Optional[dict] = None) -> dict:
         """
-        Gets storages status through the 
+        Gets storages status through the
         `crud <https://github.com/tarantool/crud#storage-info>`__.
 
         :param opts: The opts for the crud module.
@@ -2845,20 +2947,23 @@ def crud_storage_info(self, opts: dict={}) -> dict:
             :exc:`~tarantool.error.DatabaseError`
         """
 
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.storage_info", opts)
 
-        # In absence of an error, crud does not give 
+        # In absence of an error, crud does not give
         # variable err as nil (as in most cases).
         if len(crud_resp) != 1:
             raise CrudModuleError(None, CrudError(crud_resp[1]))
 
         return crud_resp[0]
 
-    def crud_count(self, space_name: str, conditions: list=[], opts: dict={}) -> int:
+    def crud_count(self, space_name: str, conditions: Optional[list] = None,
+                   opts: Optional[dict] = None) -> int:
         """
-        Gets rows count through the 
+        Gets rows count through the
         `crud <https://github.com/tarantool/crud#count>`__.
 
         :param space_name: The name of the target space.
@@ -2877,7 +2982,11 @@ def crud_count(self, space_name: str, conditions: list=[], opts: dict={}) -> int
         """
 
         assert isinstance(space_name, str)
-        assert isinstance(conditions, (tuple, list))
+        if conditions is None:
+            conditions = []
+        assert isinstance(conditions, list)
+        if opts is None:
+            opts = {}
         assert isinstance(opts, dict)
 
         crud_resp = call_crud(self, "crud.count", space_name, conditions, opts)
@@ -2887,9 +2996,9 @@ def crud_count(self, space_name: str, conditions: list=[], opts: dict={}) -> int
 
         return crud_resp[0]
 
-    def crud_stats(self, space_name: str=None) -> CrudResult:
+    def crud_stats(self, space_name: str = None) -> CrudResult:
         """
-        Gets statistics from the 
+        Gets statistics from the
         `crud <https://github.com/tarantool/crud#statistics>`__.
 
         :param space_name: The name of the target space.
@@ -2913,7 +3022,7 @@ def crud_stats(self, space_name: str=None) -> CrudResult:
 
     def crud_unflatten_rows(self, rows: list, metadata: list) -> list:
         """
-        Makes rows unflatten through the 
+        Makes rows unflatten through the
         `crud <https://github.com/tarantool/crud#api>`__.
 
         :param rows: The rows to unflatten.
diff --git a/tarantool/connection_pool.py b/tarantool/connection_pool.py
index b5e5f4f4..1008991f 100644
--- a/tarantool/connection_pool.py
+++ b/tarantool/connection_pool.py
@@ -1,6 +1,7 @@
 """
 This module provides API for interaction with Tarantool servers cluster.
 """
+# pylint: disable=too-many-lines,duplicate-code
 
 import abc
 import itertools
@@ -18,8 +19,6 @@
     POOL_INSTANCE_RECONNECT_MAX_ATTEMPTS,
     POOL_REFRESH_DELAY,
     SOCKET_TIMEOUT,
-    DEFAULT_SSL_PASSWORD,
-    DEFAULT_SSL_PASSWORD_FILE,
 )
 from tarantool.error import (
     ClusterConnectWarning,
@@ -93,13 +92,13 @@ class InstanceState():
     """
     :type: :class:`~tarantool.connection_pool.Status`
     """
-    ro: typing.Optional[bool] = None
+    read_only: typing.Optional[bool] = None
     """
     :type: :obj:`bool`, optional
     """
 
 
-def QueueFactory():
+def queue_factory():
     """
     Build a queue-based channel.
     """
@@ -126,14 +125,14 @@ class PoolUnit():
     :type: :class:`~tarantool.Connection`
     """
 
-    input_queue: queue.Queue = field(default_factory=QueueFactory)
+    input_queue: queue.Queue = field(default_factory=queue_factory)
     """
     Channel to pass requests for the server thread.
 
     :type: :obj:`queue.Queue`
     """
 
-    output_queue: queue.Queue = field(default_factory=QueueFactory)
+    output_queue: queue.Queue = field(default_factory=queue_factory)
     """
     Channel to receive responses from the server thread.
 
@@ -162,21 +161,23 @@ class PoolUnit():
     :type: :obj:`bool`
     """
 
+
 # Based on https://realpython.com/python-interface/
 class StrategyInterface(metaclass=abc.ABCMeta):
     """
     Defines strategy to choose a pool server based on a request mode.
     """
+    # pylint: disable=bad-option-value,super-init-not-called
 
     @classmethod
     def __subclasshook__(cls, subclass):
-        return (hasattr(subclass, '__init__') and
-                callable(subclass.__init__) and
-                hasattr(subclass, 'update') and
-                callable(subclass.update) and
-                hasattr(subclass, 'getnext') and
-                callable(subclass.getnext) or
-                NotImplemented)
+        return (hasattr(subclass, '__init__')
+                and callable(subclass.__init__)
+                and hasattr(subclass, 'update')
+                and callable(subclass.update)
+                and hasattr(subclass, 'getnext')
+                and callable(subclass.getnext)
+                or NotImplemented)
 
     @abc.abstractmethod
     def __init__(self, pool):
@@ -205,10 +206,12 @@ def getnext(self, mode):
 
         raise NotImplementedError
 
+
 class RoundRobinStrategy(StrategyInterface):
     """
     Simple round-robin pool servers rotation.
     """
+    # pylint: disable=bad-option-value,no-self-use,super-init-not-called
 
     def __init__(self, pool):
         """
@@ -216,9 +219,9 @@ def __init__(self, pool):
             :class:`~tarantool.connection_pool.PoolUnit` objects
         """
 
-        self.ANY_iter = None
-        self.RW_iter = None
-        self.RO_iter = None
+        self.any_iter = None
+        self.rw_iter = None
+        self.ro_iter = None
         self.pool = pool
         self.rebuild_needed = True
 
@@ -228,9 +231,9 @@ def build(self):
         based on `box.info.ro`_ state.
         """
 
-        ANY_pool = []
-        RW_pool = []
-        RO_pool = []
+        any_pool = []
+        rw_pool = []
+        ro_pool = []
 
         for key in self.pool:
             state = self.pool[key].state
@@ -238,27 +241,27 @@ def build(self):
             if state.status == Status.UNHEALTHY:
                 continue
 
-            ANY_pool.append(key)
+            any_pool.append(key)
 
-            if state.ro == False:
-                RW_pool.append(key)
+            if state.read_only is False:
+                rw_pool.append(key)
             else:
-                RO_pool.append(key)
+                ro_pool.append(key)
 
-        if len(ANY_pool) > 0:
-            self.ANY_iter = itertools.cycle(ANY_pool)
+        if len(any_pool) > 0:
+            self.any_iter = itertools.cycle(any_pool)
         else:
-            self.ANY_iter = None
+            self.any_iter = None
 
-        if len(RW_pool) > 0:
-            self.RW_iter = itertools.cycle(RW_pool)
+        if len(rw_pool) > 0:
+            self.rw_iter = itertools.cycle(rw_pool)
         else:
-            self.RW_iter = None
+            self.rw_iter = None
 
-        if len(RO_pool) > 0:
-            self.RO_iter = itertools.cycle(RO_pool)
+        if len(ro_pool) > 0:
+            self.ro_iter = itertools.cycle(ro_pool)
         else:
-            self.RO_iter = None
+            self.ro_iter = None
 
         self.rebuild_needed = False
 
@@ -271,6 +274,27 @@ def update(self):
 
         self.rebuild_needed = True
 
+    def _getnext_by_mode(self, *iters, err_msg="Can't find healthy instance in pool"):
+        """
+        Get server from prioritized list of iterators.
+
+        :param iters: list of iterators
+        :type iters: :obj:`list`
+
+        :param err_msg: Error message to raise in case of error.
+        :type err_msg: :obj:`str`
+
+        :rtype: :class:`~tarantool.connection_pool.PoolUnit`
+
+        :raise: :exc:`~tarantool.error.PoolTolopogyError`
+
+        :meta private:
+        """
+        for itr in iters:
+            if itr is not None:
+                return next(itr)
+        raise PoolTolopogyError(err_msg)
+
     def getnext(self, mode):
         """
         Get server based on the request mode.
@@ -287,34 +311,19 @@ def getnext(self, mode):
             self.build()
 
         if mode == Mode.ANY:
-            if self.ANY_iter is not None:
-                return next(self.ANY_iter)
-            else:
-                raise PoolTolopogyError("Can't find healthy instance in pool")
-        elif mode == Mode.RW:
-            if self.RW_iter is not None:
-                return next(self.RW_iter)
-            else:
-                raise PoolTolopogyError("Can't find healthy rw instance in pool")
-        elif mode == Mode.RO:
-            if self.RO_iter is not None:
-                return next(self.RO_iter)
-            else:
-                raise PoolTolopogyError("Can't find healthy ro instance in pool")
-        elif mode == Mode.PREFER_RO:
-            if self.RO_iter is not None:
-                return next(self.RO_iter)
-            elif self.RW_iter is not None:
-                return next(self.RW_iter)
-            else:
-                raise PoolTolopogyError("Can't find healthy instance in pool")
-        elif mode == Mode.PREFER_RW:
-            if self.RW_iter is not None:
-                return next(self.RW_iter)
-            elif self.RO_iter is not None:
-                return next(self.RO_iter)
-            else:
-                raise PoolTolopogyError("Can't find healthy instance in pool")
+            return self._getnext_by_mode(self.any_iter)
+        if mode == Mode.RW:
+            return self._getnext_by_mode(self.rw_iter,
+                                         err_msg="Can't find healthy rw instance in pool")
+        if mode == Mode.RO:
+            return self._getnext_by_mode(self.ro_iter,
+                                         err_msg="Can't find healthy ro instance in pool")
+        if mode == Mode.PREFER_RO:
+            return self._getnext_by_mode(self.ro_iter, self.rw_iter)
+        if mode == Mode.PREFER_RW:
+            return self._getnext_by_mode(self.rw_iter, self.ro_iter)
+
+        raise ValueError(f"Unexpected mode {mode}")
 
 
 @dataclass
@@ -365,6 +374,7 @@ class ConnectionPool(ConnectionInterface):
         >>> resp
         - ['AAAA', 'Alpha']
     """
+    # pylint: disable=too-many-public-methods,duplicate-code,bad-option-value,no-self-use
 
     def __init__(self,
                  addrs,
@@ -463,6 +473,7 @@ def __init__(self,
         .. _box.info.status:
         .. _box.info: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_info/
         """
+        # pylint: disable=too-many-arguments,too-many-locals
 
         if not isinstance(addrs, list) or len(addrs) == 0:
             raise ConfigurationError("addrs must be non-empty list")
@@ -493,7 +504,7 @@ def __init__(self,
                     socket_timeout=socket_timeout,
                     reconnect_max_attempts=reconnect_max_attempts,
                     reconnect_delay=reconnect_delay,
-                    connect_now=False, # Connect in ConnectionPool.connect()
+                    connect_now=False,  # Connect in ConnectionPool.connect()
                     encoding=encoding,
                     call_16=call_16,
                     connection_timeout=connection_timeout,
@@ -526,7 +537,7 @@ def _make_key(self, addr):
         :meta private:
         """
 
-        return '{0}:{1}'.format(addr['host'], addr['port'])
+        return f"{addr['host']}:{addr['port']}"
 
     def _get_new_state(self, unit):
         """
@@ -545,25 +556,25 @@ def _get_new_state(self, unit):
         if conn.is_closed():
             try:
                 conn.connect()
-            except NetworkError as e:
-                msg = "Failed to connect to {0}:{1}".format(
-                    unit.addr['host'], unit.addr['port'])
+            except NetworkError as exc:
+                msg = (f"Failed to connect to {unit.addr['host']}:{unit.addr['port']}, "
+                       f"reason: {repr(exc)}")
                 warn(msg, ClusterConnectWarning)
                 return InstanceState(Status.UNHEALTHY)
 
         try:
             resp = conn.call('box.info')
-        except NetworkError as e:
-            msg = "Failed to get box.info for {0}:{1}, reason: {2}".format(
-                unit.addr['host'], unit.addr['port'], repr(e))
+        except NetworkError as exc:
+            msg = (f"Failed to get box.info for {unit.addr['host']}:{unit.addr['port']}, "
+                   f"reason: {repr(exc)}")
             warn(msg, PoolTolopogyWarning)
             return InstanceState(Status.UNHEALTHY)
 
         try:
-            ro = resp.data[0]['ro']
-        except (IndexError, KeyError) as e:
-            msg = "Incorrect box.info response from {0}:{1}".format(
-                unit.addr['host'], unit.addr['port'])
+            read_only = resp.data[0]['ro']
+        except (IndexError, KeyError) as exc:
+            msg = (f"Incorrect box.info response from {unit.addr['host']}:{unit.addr['port']}"
+                   f"reason: {repr(exc)}")
             warn(msg, PoolTolopogyWarning)
             return InstanceState(Status.UNHEALTHY)
 
@@ -571,17 +582,16 @@ def _get_new_state(self, unit):
             status = resp.data[0]['status']
 
             if status != 'running':
-                msg = "{0}:{1} instance status is not 'running'".format(
-                    unit.addr['host'], unit.addr['port'])
+                msg = f"{unit.addr['host']}:{unit.addr['port']} instance status is not 'running'"
                 warn(msg, PoolTolopogyWarning)
                 return InstanceState(Status.UNHEALTHY)
-        except (IndexError, KeyError) as e:
-            msg = "Incorrect box.info response from {0}:{1}".format(
-                unit.addr['host'], unit.addr['port'])
+        except (IndexError, KeyError) as exc:
+            msg = (f"Incorrect box.info response from {unit.addr['host']}:{unit.addr['port']}"
+                   f"reason: {repr(exc)}")
             warn(msg, PoolTolopogyWarning)
             return InstanceState(Status.UNHEALTHY)
 
-        return InstanceState(Status.HEALTHY, ro)
+        return InstanceState(Status.HEALTHY, read_only)
 
     def _refresh_state(self, key):
         """
@@ -620,7 +630,7 @@ def is_closed(self):
         :rtype: :obj:`bool`
         """
 
-        return all(unit.request_processing_enabled == False for unit in self.pool.values())
+        return all(unit.request_processing_enabled is False for unit in self.pool.values())
 
     def _request_process_loop(self, key, unit, last_refresh):
         """
@@ -644,8 +654,8 @@ def _request_process_loop(self, key, unit, last_refresh):
                 method = getattr(Connection, task.method_name)
                 try:
                     resp = method(unit.conn, *task.args, **task.kwargs)
-                except Exception as e:
-                    unit.output_queue.put(e)
+                except Exception as exc:  # pylint: disable=bad-option-value,broad-exception-caught,broad-except
+                    unit.output_queue.put(exc)
                 else:
                     unit.output_queue.put(resp)
 
@@ -668,9 +678,7 @@ def connect(self):
         and refresh the info would be processed in the background.
         """
 
-        for key in self.pool:
-            unit = self.pool[key]
-
+        for key, unit in self.pool.items():
             self._refresh_state(key)
             last_refresh = time.time()
 
@@ -813,7 +821,8 @@ def replace(self, space_name, values, *, mode=Mode.RW, on_push=None, on_push_ctx
         .. _replace: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/replace/
         """
 
-        return self._send(mode, 'replace', space_name, values, on_push=on_push, on_push_ctx=on_push_ctx)
+        return self._send(mode, 'replace', space_name, values,
+                          on_push=on_push, on_push_ctx=on_push_ctx)
 
     def insert(self, space_name, values, *, mode=Mode.RW, on_push=None, on_push_ctx=None):
         """
@@ -842,7 +851,8 @@ def insert(self, space_name, values, *, mode=Mode.RW, on_push=None, on_push_ctx=
         .. _insert: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/insert/
         """
 
-        return self._send(mode, 'insert', space_name, values, on_push=on_push, on_push_ctx=on_push_ctx)
+        return self._send(mode, 'insert', space_name, values,
+                          on_push=on_push, on_push_ctx=on_push_ctx)
 
     def delete(self, space_name, key, *, index=0, mode=Mode.RW, on_push=None, on_push_ctx=None):
         """
@@ -874,9 +884,11 @@ def delete(self, space_name, key, *, index=0, mode=Mode.RW, on_push=None, on_pus
         .. _delete: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/delete/
         """
 
-        return self._send(mode, 'delete', space_name, key, index=index, on_push=on_push, on_push_ctx=on_push_ctx)
+        return self._send(mode, 'delete', space_name, key, index=index,
+                          on_push=on_push, on_push_ctx=on_push_ctx)
 
-    def upsert(self, space_name, tuple_value, op_list, *, index=0, mode=Mode.RW, on_push=None, on_push_ctx=None):
+    def upsert(self, space_name, tuple_value, op_list, *, index=0, mode=Mode.RW,
+               on_push=None, on_push_ctx=None):
         """
         Execute an UPSERT request on the pool server: `upsert`_ a tuple to
         the space. Refer to :meth:`~tarantool.Connection.upsert`.
@@ -910,9 +922,10 @@ def upsert(self, space_name, tuple_value, op_list, *, index=0, mode=Mode.RW, on_
         """
 
         return self._send(mode, 'upsert', space_name, tuple_value,
-            op_list, index=index, on_push=on_push, on_push_ctx=on_push_ctx)
+                          op_list, index=index, on_push=on_push, on_push_ctx=on_push_ctx)
 
-    def update(self, space_name, key, op_list, *, index=0, mode=Mode.RW, on_push=None, on_push_ctx=None):
+    def update(self, space_name, key, op_list, *, index=0, mode=Mode.RW,
+               on_push=None, on_push_ctx=None):
         """
         Execute an UPDATE request on the pool server: `update`_ a tuple
         in the space. Refer to :meth:`~tarantool.Connection.update`.
@@ -945,8 +958,8 @@ def update(self, space_name, key, op_list, *, index=0, mode=Mode.RW, on_push=Non
         .. _update: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/update/
         """
 
-        return self._send(mode, 'update', space_name, key, 
-            op_list, index=index, on_push=on_push, on_push_ctx=on_push_ctx)
+        return self._send(mode, 'update', space_name, key,
+                          op_list, index=index, on_push=on_push, on_push_ctx=on_push_ctx)
 
     def ping(self, notime=False, *, mode=None):
         """
@@ -1039,10 +1052,10 @@ def execute(self, query, params=None, *, mode=None):
 
         return self._send(mode, 'execute', query, params)
 
-    def crud_insert(self, space_name, values, opts={}, *, mode=Mode.ANY):
+    def crud_insert(self, space_name, values, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_insert request on the pool server: 
-        inserts row through the 
+        Execute an crud_insert request on the pool server:
+        inserts row through the
         `crud <https://github.com/tarantool/crud#insert>`__.
         Refer to :meth:`~tarantool.Connection.crud_insert`.
 
@@ -1066,10 +1079,10 @@ def crud_insert(self, space_name, values, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_insert', space_name, values, opts)
 
-    def crud_insert_object(self, space_name, values, opts={}, *, mode=Mode.ANY):
+    def crud_insert_object(self, space_name, values, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_insert_object request on the pool server: 
-        inserts object row through the 
+        Execute an crud_insert_object request on the pool server:
+        inserts object row through the
         `crud <https://github.com/tarantool/crud#insert>`__.
         Refer to :meth:`~tarantool.Connection.crud_insert_object`.
 
@@ -1093,10 +1106,10 @@ def crud_insert_object(self, space_name, values, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_insert_object', space_name, values, opts)
 
-    def crud_insert_many(self, space_name, values, opts={}, *, mode=Mode.ANY):
+    def crud_insert_many(self, space_name, values, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_insert_many request on the pool server: 
-        inserts batch rows through the 
+        Execute an crud_insert_many request on the pool server:
+        inserts batch rows through the
         `crud <https://github.com/tarantool/crud#insert-many>`__.
         Refer to :meth:`~tarantool.Connection.crud_insert_many`.
 
@@ -1120,9 +1133,9 @@ def crud_insert_many(self, space_name, values, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_insert_many', space_name, values, opts)
 
-    def crud_insert_object_many(self, space_name, values, opts={}, *, mode=Mode.ANY):
+    def crud_insert_object_many(self, space_name, values, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_insert_object_many request on the pool server: 
+        Execute an crud_insert_object_many request on the pool server:
         inserts batch object rows through the
         `crud <https://github.com/tarantool/crud#insert-many>`__.
         Refer to :meth:`~tarantool.Connection.crud_insert_object_many`.
@@ -1147,10 +1160,10 @@ def crud_insert_object_many(self, space_name, values, opts={}, *, mode=Mode.ANY)
 
         return self._send(mode, 'crud_insert_object_many', space_name, values, opts)
 
-    def crud_get(self, space_name, key, opts={}, *, mode=Mode.ANY):
+    def crud_get(self, space_name, key, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_get request on the pool server: 
-        gets row through the 
+        Execute an crud_get request on the pool server:
+        gets row through the
         `crud <https://github.com/tarantool/crud#get>`__.
         Refer to :meth:`~tarantool.Connection.crud_get`.
 
@@ -1174,10 +1187,10 @@ def crud_get(self, space_name, key, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_get', space_name, key, opts)
 
-    def crud_update(self, space_name, key, operations=[], opts={}, *, mode=Mode.ANY):
+    def crud_update(self, space_name, key, operations=None, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_update request on the pool server: 
-        updates row through the 
+        Execute an crud_update request on the pool server:
+        updates row through the
         `crud <https://github.com/tarantool/crud#update>`__.
         Refer to :meth:`~tarantool.Connection.crud_update`.
 
@@ -1204,10 +1217,10 @@ def crud_update(self, space_name, key, operations=[], opts={}, *, mode=Mode.ANY)
 
         return self._send(mode, 'crud_update', space_name, key, operations, opts)
 
-    def crud_delete(self, space_name, key, opts={}, *, mode=Mode.ANY):
+    def crud_delete(self, space_name, key, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_delete request on the pool server: 
-        deletes row through the 
+        Execute an crud_delete request on the pool server:
+        deletes row through the
         `crud <https://github.com/tarantool/crud#delete>`__.
         Refer to :meth:`~tarantool.Connection.crud_delete`.
 
@@ -1231,10 +1244,10 @@ def crud_delete(self, space_name, key, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_delete', space_name, key, opts)
 
-    def crud_replace(self, space_name, values, opts={}, *, mode=Mode.ANY):
+    def crud_replace(self, space_name, values, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_replace request on the pool server: 
-        replaces row through the 
+        Execute an crud_replace request on the pool server:
+        replaces row through the
         `crud <https://github.com/tarantool/crud#replace>`__.
         Refer to :meth:`~tarantool.Connection.crud_replace`.
 
@@ -1258,10 +1271,10 @@ def crud_replace(self, space_name, values, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_replace', space_name, values, opts)
 
-    def crud_replace_object(self, space_name, values, opts={}, *, mode=Mode.ANY):
+    def crud_replace_object(self, space_name, values, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_replace_object request on the pool server: 
-        replaces object row through the 
+        Execute an crud_replace_object request on the pool server:
+        replaces object row through the
         `crud <https://github.com/tarantool/crud#replace>`__.
         Refer to :meth:`~tarantool.Connection.crud_replace_object`.
 
@@ -1285,10 +1298,10 @@ def crud_replace_object(self, space_name, values, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_replace_object', space_name, values, opts)
 
-    def crud_replace_many(self, space_name, values, opts={}, *, mode=Mode.ANY):
+    def crud_replace_many(self, space_name, values, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_replace_many request on the pool server: 
-        replaces batch rows through the 
+        Execute an crud_replace_many request on the pool server:
+        replaces batch rows through the
         `crud <https://github.com/tarantool/crud#replace-many>`__.
         Refer to :meth:`~tarantool.Connection.crud_replace_many`.
 
@@ -1312,10 +1325,10 @@ def crud_replace_many(self, space_name, values, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_replace_many', space_name, values, opts)
 
-    def crud_replace_object_many(self, space_name, values, opts={}, *, mode=Mode.ANY):
+    def crud_replace_object_many(self, space_name, values, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_replace_object_many request on the pool server: 
-        replaces batch object rows through the 
+        Execute an crud_replace_object_many request on the pool server:
+        replaces batch object rows through the
         `crud <https://github.com/tarantool/crud#replace-many>`__.
         Refer to :meth:`~tarantool.Connection.crud_replace_object_many`.
 
@@ -1339,10 +1352,10 @@ def crud_replace_object_many(self, space_name, values, opts={}, *, mode=Mode.ANY
 
         return self._send(mode, 'crud_replace_object_many', space_name, values, opts)
 
-    def crud_upsert(self, space_name, values, operations=[], opts={}, *, mode=Mode.ANY):
+    def crud_upsert(self, space_name, values, operations=None, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_upsert request on the pool server: 
-        upserts row through the 
+        Execute an crud_upsert request on the pool server:
+        upserts row through the
         `crud <https://github.com/tarantool/crud#upsert>`__.
         Refer to :meth:`~tarantool.Connection.crud_upsert`.
 
@@ -1369,10 +1382,10 @@ def crud_upsert(self, space_name, values, operations=[], opts={}, *, mode=Mode.A
 
         return self._send(mode, 'crud_upsert', space_name, values, operations, opts)
 
-    def crud_upsert_object(self, space_name, values, operations=[], opts={}, *, mode=Mode.ANY):
+    def crud_upsert_object(self, space_name, values, operations=None, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_upsert_object request on the pool server: 
-        upserts object row through the 
+        Execute an crud_upsert_object request on the pool server:
+        upserts object row through the
         `crud <https://github.com/tarantool/crud#upsert>`__.
         Refer to :meth:`~tarantool.Connection.crud_upsert_object`.
 
@@ -1399,10 +1412,10 @@ def crud_upsert_object(self, space_name, values, operations=[], opts={}, *, mode
 
         return self._send(mode, 'crud_upsert_object', space_name, values, operations, opts)
 
-    def crud_upsert_many(self, space_name, values_operation, opts={}, *, mode=Mode.ANY):
+    def crud_upsert_many(self, space_name, values_operation, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_upsert_many request on the pool server: 
-        upserts batch rows through the 
+        Execute an crud_upsert_many request on the pool server:
+        upserts batch rows through the
         `crud <https://github.com/tarantool/crud#upsert-many>`__.
         Refer to :meth:`~tarantool.Connection.crud_upsert_many`.
 
@@ -1426,10 +1439,10 @@ def crud_upsert_many(self, space_name, values_operation, opts={}, *, mode=Mode.A
 
         return self._send(mode, 'crud_upsert_many', space_name, values_operation, opts)
 
-    def crud_upsert_object_many(self, space_name, values_operation, opts={}, *, mode=Mode.ANY):
+    def crud_upsert_object_many(self, space_name, values_operation, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_upsert_object_many request on the pool server: 
-        upserts batch object rows through the 
+        Execute an crud_upsert_object_many request on the pool server:
+        upserts batch object rows through the
         `crud <https://github.com/tarantool/crud#upsert-many>`__.
         Refer to :meth:`~tarantool.Connection.crud_upsert_object_many`.
 
@@ -1453,10 +1466,10 @@ def crud_upsert_object_many(self, space_name, values_operation, opts={}, *, mode
 
         return self._send(mode, 'crud_upsert_object_many', space_name, values_operation, opts)
 
-    def crud_select(self, space_name, conditions=[], opts={}, *, mode=Mode.ANY):
+    def crud_select(self, space_name, conditions=None, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_select request on the pool server: 
-        selects rows through the 
+        Execute an crud_select request on the pool server:
+        selects rows through the
         `crud <https://github.com/tarantool/crud#select>`__.
         Refer to :meth:`~tarantool.Connection.crud_select`.
 
@@ -1480,10 +1493,10 @@ def crud_select(self, space_name, conditions=[], opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_select', space_name, conditions, opts)
 
-    def crud_min(self, space_name, index_name, opts={}, *, mode=Mode.ANY):
+    def crud_min(self, space_name, index_name, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_min request on the pool server: 
-        gets rows with minimum value in the specified index through 
+        Execute an crud_min request on the pool server:
+        gets rows with minimum value in the specified index through
         `crud <https://github.com/tarantool/crud#min-and-max>`__.
         Refer to :meth:`~tarantool.Connection.crud_min`.
 
@@ -1507,10 +1520,10 @@ def crud_min(self, space_name, index_name, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_min', space_name, index_name, opts)
 
-    def crud_max(self, space_name, index_name, opts={}, *, mode=Mode.ANY):
+    def crud_max(self, space_name, index_name, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_max request on the pool server: 
-        gets rows with maximum value in the specified index through 
+        Execute an crud_max request on the pool server:
+        gets rows with maximum value in the specified index through
         `crud <https://github.com/tarantool/crud#min-and-max>`__.
         Refer to :meth:`~tarantool.Connection.crud_max`.
 
@@ -1534,10 +1547,10 @@ def crud_max(self, space_name, index_name, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_max', space_name, index_name, opts)
 
-    def crud_len(self, space_name, opts={}, *, mode=Mode.ANY):
+    def crud_len(self, space_name, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_len request on the pool server: 
-        gets the number of tuples in the space through 
+        Execute an crud_len request on the pool server:
+        gets the number of tuples in the space through
         `crud <https://github.com/tarantool/crud#len>`__.
         Refer to :meth:`~tarantool.Connection.crud_len`.
 
@@ -1558,10 +1571,10 @@ def crud_len(self, space_name, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_len', space_name, opts)
 
-    def crud_storage_info(self, opts={}, *, mode=Mode.ANY):
+    def crud_storage_info(self, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_storage_info request on the pool server: 
-        gets storages status through the 
+        Execute an crud_storage_info request on the pool server:
+        gets storages status through the
         `crud <https://github.com/tarantool/crud#storage-info>`__.
         Refer to :meth:`~tarantool.Connection.crud_storage_info`.
 
@@ -1579,10 +1592,10 @@ def crud_storage_info(self, opts={}, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_storage_info', opts)
 
-    def crud_count(self, space_name, conditions=[], opts={}, *, mode=Mode.ANY):
+    def crud_count(self, space_name, conditions=None, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_count request on the pool server: 
-        gets rows count through the 
+        Execute an crud_count request on the pool server:
+        gets rows count through the
         `crud <https://github.com/tarantool/crud#count>`__.
         Refer to :meth:`~tarantool.Connection.crud_count`.
 
@@ -1608,8 +1621,8 @@ def crud_count(self, space_name, conditions=[], opts={}, *, mode=Mode.ANY):
 
     def crud_stats(self, space_name=None, *, mode=Mode.ANY):
         """
-        Execute an crud_stats request on the pool server: 
-        gets statistics through the 
+        Execute an crud_stats request on the pool server:
+        gets statistics through the
         `crud <https://github.com/tarantool/crud#statistics>`__.
         Refer to :meth:`~tarantool.Connection.crud_stats`.
 
@@ -1629,7 +1642,7 @@ def crud_stats(self, space_name=None, *, mode=Mode.ANY):
 
     def crud_unflatten_rows(self, rows, metadata, *, mode=Mode.ANY):
         """
-        Makes rows unflatten through the 
+        Makes rows unflatten through the
         `crud <https://github.com/tarantool/crud#api>`__.
         Refer to :meth:`~tarantool.Connection.crud_unflatten_rows`.
 
@@ -1650,10 +1663,10 @@ def crud_unflatten_rows(self, rows, metadata, *, mode=Mode.ANY):
 
         return self._send(mode, 'crud_unflatten_rows', rows, metadata)
 
-    def crud_truncate(self, space_name, opts={}, *, mode=Mode.ANY):
+    def crud_truncate(self, space_name, opts=None, *, mode=Mode.ANY):
         """
-        Execute an crud_truncate request on the pool server: 
-        truncates rows through 
+        Execute an crud_truncate request on the pool server:
+        truncates rows through
         `crud <https://github.com/tarantool/crud#truncate>`__.
         Refer to :meth:`~tarantool.Connection.crud_truncate`.
 
diff --git a/tarantool/const.py b/tarantool/const.py
index 6b12598d..21a3c8a9 100644
--- a/tarantool/const.py
+++ b/tarantool/const.py
@@ -1,4 +1,6 @@
-# pylint: disable=C0301,W0105,W0401,W0614
+"""
+This module a set of constants for the package.
+"""
 
 IPROTO_REQUEST_TYPE = 0x00
 IPROTO_SYNC = 0x01
@@ -134,7 +136,7 @@
 # Tarantool 2.10 protocol version is 3
 CONNECTOR_IPROTO_VERSION = 3
 # List of connector-supported features
-CONNECTOR_FEATURES = [IPROTO_FEATURE_ERROR_EXTENSION,]
+CONNECTOR_FEATURES = [IPROTO_FEATURE_ERROR_EXTENSION]
 
 # Authenticate with CHAP-SHA1 (Tarantool CE and EE)
 AUTH_TYPE_CHAP_SHA1 = "chap-sha1"
diff --git a/tarantool/crud.py b/tarantool/crud.py
index dee1be36..d10726c5 100644
--- a/tarantool/crud.py
+++ b/tarantool/crud.py
@@ -7,13 +7,14 @@
 from tarantool.error import DatabaseError, ER_NO_SUCH_PROC, ER_ACCESS_DENIED
 
 
-class CrudResponse(object):
+class CrudResponse():
     """
-    Contains response fields from the `crud`_ module that correspond 
+    Contains response fields from the `crud`_ module that correspond
     to the Lua implementation.
 
     .. _crud: https://github.com/tarantool/crud/
     """
+    # pylint: disable=too-few-public-methods
 
     def __init__(self, response):
         """
@@ -33,16 +34,16 @@ def __init__(self, response):
             raise RuntimeError('Unable to decode response to object due to unknown type')
 
 
-class CrudResult(CrudResponse):
+class CrudResult(CrudResponse):  # pylint: disable=too-few-public-methods
     """
-    Contains result's fields from result variable 
+    Contains result's fields from result variable
     of crud module operation.
     """
 
 
-class CrudError(CrudResponse):
+class CrudError(CrudResponse):  # pylint: disable=too-few-public-methods
     """
-    Contains error's fields from error variable 
+    Contains error's fields from error variable
     of crud module operation.
     """
 
@@ -64,9 +65,9 @@ def call_crud(conn, *args):
 
     try:
         crud_resp = conn.call(*args)
-    except DatabaseError as e:
-        if e.code == ER_NO_SUCH_PROC or e.code == ER_ACCESS_DENIED:
+    except DatabaseError as exc:
+        if exc.code in (ER_NO_SUCH_PROC, ER_ACCESS_DENIED):
             exc_msg = ". Ensure that you're calling crud.router and user has sufficient grants"
-            raise DatabaseError(e.code, e.message + exc_msg, extra_info=e.extra_info) from e
+            raise DatabaseError(exc.code, exc.message + exc_msg, extra_info=exc.extra_info) from exc
 
     return crud_resp
diff --git a/tarantool/dbapi.py b/tarantool/dbapi.py
index f6f5d2ab..3b4d1013 100644
--- a/tarantool/dbapi.py
+++ b/tarantool/dbapi.py
@@ -3,11 +3,24 @@
 
 .. _PEP-249: http://www.python.org/dev/peps/pep-0249/
 """
+# pylint: disable=fixme,unused-import,bad-option-value,no-self-use
+# flake8: noqa: F401
 
 from tarantool.connection import Connection as BaseConnection
-from tarantool.error import *
-
-
+from tarantool.error import (
+    Error,
+    InterfaceError,
+    DatabaseError,
+    OperationalError,
+    IntegrityError,
+    InternalError,
+    ProgrammingError,
+    NotSupportedError,
+)
+
+Warning = Warning  # pylint: disable=redefined-builtin,self-assigning-variable
+
+# pylint: disable=invalid-name
 paramstyle = 'named'
 apilevel = "2.0"
 threadsafety = 1
@@ -50,6 +63,11 @@ def callproc(self, procname, *params):
 
     @property
     def rows(self):
+        """
+        Returns the current count of rows in cursor.
+
+        :type: :obj:`int`
+        """
         return self._rows
 
     @property
@@ -278,7 +296,7 @@ def __init__(self, *args, **kwargs):
         :raise: :class:`~tarantool.Connection` exceptions
         """
 
-        super(Connection, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self._set_autocommit(kwargs.get('autocommit', True))
 
     def _set_autocommit(self, autocommit):
@@ -291,7 +309,7 @@ def _set_autocommit(self, autocommit):
 
         if not isinstance(autocommit, bool):
             raise InterfaceError("autocommit parameter must be boolean, "
-                                 "not %s" % autocommit.__class__.__name__)
+                                 f"not {autocommit.__class__.__name__}")
         if autocommit is False:
             raise NotSupportedError("The connector supports "
                                     "only autocommit mode")
@@ -337,7 +355,7 @@ def close(self):
         """
 
         self._check_not_closed("The closed connector can not be closed again.")
-        super(Connection, self).close()
+        super().close()
 
     def commit(self):
         """
diff --git a/tarantool/error.py b/tarantool/error.py
index 29c2430f..85e30c03 100644
--- a/tarantool/error.py
+++ b/tarantool/error.py
@@ -1,4 +1,3 @@
-# pylint: disable=C0301,W0105,W0401,W0614
 """
 Python DB API compatible exceptions, see `PEP-249`_.
 
@@ -7,22 +6,10 @@
 
 import os
 import socket
-try:
-    import ssl
-    is_ssl_supported = True
-except ImportError:
-    is_ssl_supported = False
 import sys
 import warnings
 
 
-
-class Warning(Exception):
-    """
-    Exception raised for important warnings
-    like data truncations while inserting, etc.
-    """
-
 class Error(Exception):
     """
     Base class for error exceptions.
@@ -124,6 +111,7 @@ class ConfigurationError(Error):
     Error of initialization with a user-provided configuration.
     """
 
+
 class MsgpackError(Error):
     """
     Error with encoding or decoding of `MP_EXT`_ types.
@@ -131,11 +119,13 @@ class MsgpackError(Error):
     .. _MP_EXT: https://www.tarantool.io/en/doc/latest/dev_guide/internals/msgpack_extensions/
     """
 
+
 class MsgpackWarning(UserWarning):
     """
     Warning with encoding or decoding of `MP_EXT`_ types.
     """
 
+
 # Monkey patch os.strerror for win32
 if sys.platform == "win32":
     # Windows Sockets Error Codes (not all, but related on network errors)
@@ -194,8 +184,8 @@ def os_strerror_patched(code):
         message = os_strerror_orig(code)
         if not message.startswith("Unknown"):
             return message
-        else:
-            return _code2str.get(code, "Unknown error %s" % code)
+
+        return _code2str.get(code, f"Unknown error {code}")
 
     os.strerror = os_strerror_patched
     del os_strerror_patched
@@ -211,7 +201,7 @@ def __init__(self, value):
         :param value: Error value.
         """
 
-        super(SchemaError, self).__init__(0, value)
+        super().__init__(0, value)
         self.value = value
 
     def __str__(self):
@@ -232,7 +222,7 @@ def __init__(self, message, schema_version):
         :type schema_version: :obj:`int`
         """
 
-        super(SchemaReloadException, self).__init__(109, message)
+        super().__init__(109, message)
         self.schema_version = schema_version
 
     def __str__(self):
@@ -244,72 +234,79 @@ class NetworkError(DatabaseError):
     Error related to network.
     """
 
-    def __init__(self, orig_exception=None, *args, **kwargs):
+    def __init__(self, *args, **kwargs):
         """
-        :param orig_exception: Exception to wrap.
-        :type orig_exception: optional
+        :param args: Exception arguments. If the first argument is
+           a socket exception, it is wrapped.
+        :type args: :obj:`tuple`, optional
 
-        :param args: Wrapped exception arguments.
-        :type args: :obj:`tuple`
+        :param kwargs: Exception to wrap.
+        :type args: :obj:`dict`, optional
         """
 
         self.errno = 0
-        if hasattr(orig_exception, 'errno'):
-            self.errno = orig_exception.errno
-        if orig_exception:
+
+        if len(args) > 0:
+            orig_exception = args[0]
+
+            if hasattr(orig_exception, 'errno'):
+                self.errno = orig_exception.errno
+
             if isinstance(orig_exception, socket.timeout):
                 self.message = "Socket timeout"
-                super(NetworkError, self).__init__(0, self.message)
-            elif isinstance(orig_exception, socket.error):
+                super().__init__(0, self.message)
+                return
+
+            if isinstance(orig_exception, socket.error):
                 self.message = os.strerror(orig_exception.errno)
-                super(NetworkError, self).__init__(
-                    orig_exception.errno, self.message)
-            else:
-                super(NetworkError, self).__init__(orig_exception, *args, **kwargs)
+                super().__init__(orig_exception.errno, self.message)
+                return
+
+        super().__init__(*args, **kwargs)
 
 
 class NetworkWarning(UserWarning):
     """
     Warning related to network.
     """
-    pass
+
 
 class SslError(DatabaseError):
     """
     Error related to SSL.
     """
 
-    def __init__(self, orig_exception=None, *args):
+    def __init__(self, *args, **kwargs):
         """
-        :param orig_exception: Exception to wrap.
-        :type orig_exception: optional
+        :param args: Exception arguments. If the first argument is
+           a socket exception, it is wrapped.
+        :type args: :obj:`tuple`, optional
 
-        :param args: Wrapped exception arguments.
-        :type args: :obj:`tuple`
+        :param kwargs: Exception to wrap.
+        :type args: :obj:`dict`, optional
         """
 
         self.errno = 0
-        if hasattr(orig_exception, 'errno'):
-            self.errno = orig_exception.errno
-        if orig_exception:
-            if is_ssl_supported and isinstance(orig_exception, ssl.SSLError):
-                super(SslError, self).__init__(orig_exception, *args)
-            else:
-                super(SslError, self).__init__(orig_exception, *args)
+
+        if len(args) > 0:
+            orig_exception = args[0]
+
+            if hasattr(orig_exception, 'errno'):
+                self.errno = orig_exception.errno
+
+        super().__init__(*args, **kwargs)
 
 
 class ClusterDiscoveryWarning(UserWarning):
     """
     Warning related to cluster discovery.
     """
-    pass
 
 
 class ClusterConnectWarning(UserWarning):
     """
     Warning related to cluster pool connection.
     """
-    pass
 
 
 class PoolTolopogyWarning(UserWarning):
@@ -317,7 +314,6 @@ class PoolTolopogyWarning(UserWarning):
     Warning related to unsatisfying `box.info.ro`_ state of
     pool instances.
     """
-    pass
 
 
 class PoolTolopogyError(DatabaseError):
@@ -327,7 +323,6 @@ class PoolTolopogyError(DatabaseError):
 
     .. _box.info.ro: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_info/
     """
-    pass
 
 
 class CrudModuleError(DatabaseError):
@@ -341,12 +336,12 @@ class CrudModuleError(DatabaseError):
     def __init__(self, _, error):
         """
         Sets fields with result and errors.
-        
+
         :param args: The tuple from the crud module with result and errors.
         :type args: :obj:`tuple`
         """
 
-        super(CrudModuleError, self).__init__(0, error.err)
+        super().__init__(0, error.err)
         # Sets tarantool.crud.CrudError object.
         self.extra_info_error = error
 
@@ -362,13 +357,13 @@ class CrudModuleManyError(DatabaseError):
     def __init__(self, success, error):
         """
         Sets fields with result and errors.
-        
+
         :param args: The tuple from the crud module with result and errors.
         :type args: :obj:`tuple`
         """
 
         exc_msg = "Got multiple errors, see errors_list and success_list"
-        super(CrudModuleManyError, self).__init__(0, exc_msg)
+        super().__init__(0, exc_msg)
         # Sets list of tarantool.crud.CrudResult objects.
         self.success_list = success
         # Sets list of tarantool.crud.CrudError objects.
@@ -390,8 +385,9 @@ def warn(message, warning_class):
     :param warning_class: Warning class.
     :type warning_class: :class:`~tarantool.error.Warning`
     """
+    # pylint: disable=protected-access
 
-    frame = sys._getframe(2)  # pylint: disable=W0212
+    frame = sys._getframe(2)
     module_name = frame.f_globals.get("__name__")
     line_no = frame.f_lineno
     warnings.warn_explicit(message, warning_class, module_name, line_no)
diff --git a/tarantool/mesh_connection.py b/tarantool/mesh_connection.py
index 2cb44ee3..ebbc1a40 100644
--- a/tarantool/mesh_connection.py
+++ b/tarantool/mesh_connection.py
@@ -1,6 +1,7 @@
 """
 This module provides API for interaction with Tarantool servers cluster.
 """
+# pylint: disable=fixme,duplicate-code
 
 import time
 
@@ -58,10 +59,11 @@ def parse_uri(uri):
     :rtype: first value: :obj:`dict` or ``None``,
         second value: ``None`` or :obj:`str`
     """
+    # pylint: disable=too-many-branches
 
     # TODO: Support Unix sockets.
     def parse_error(uri, msg):
-        msg = 'URI "%s": %s' % (uri, msg)
+        msg = f'URI "{uri}": {msg}'
         return None, msg
 
     if not uri:
@@ -88,17 +90,17 @@ def parse_error(uri, msg):
     except ValueError:
         return parse_error(uri, 'port should be a number')
 
-    for k, v in default_addr_opts.items():
-        result[k] = v
+    for key, val in default_addr_opts.items():
+        result[key] = val
 
     if opts_str != "":
         for opt_str in opts_str.split('&'):
             opt = opt_str.split('=')
             if len(opt) != 2:
                 continue
-            for k in default_addr_opts:
-                if k == opt[0]:
-                    result[k] = opt[1]
+            for key in default_addr_opts:
+                if key == opt[0]:
+                    result[key] = opt[1]
 
     return result, None
 
@@ -117,9 +119,10 @@ def prepare_address(address):
     :rtype: first value: :obj:`dict` or ``None``,
         second value: ``None`` or :obj:`str`
     """
+    # pylint: disable=too-many-return-statements,too-many-branches
 
     def format_error(address, err):
-        return None, 'Address %s: %s' % (str(address), err)
+        return None, f'Address {str(address)}: {err}'
 
     if not isinstance(address, dict):
         return format_error(address, 'address must be a dict')
@@ -128,12 +131,12 @@ def format_error(address, err):
         return format_error(address, 'port is not set or None')
 
     result = {}
-    for k, v in address.items():
-        result[k] = v
+    for key, val in address.items():
+        result[key] = val
     # Set default values.
-    for k, v in default_addr_opts.items():
-        if k not in result:
-            result[k] = v
+    for key, val in default_addr_opts.items():
+        if key not in result:
+            result[key] = val
 
     if isinstance(result['port'], int):
         # Looks like an inet address.
@@ -152,11 +155,12 @@ def format_error(address, err):
                                 'port must be an int for an inet result')
         if result['port'] < 1 or result['port'] > 65535:
             return format_error(result, 'port must be in range [1, 65535] '
-                                         'for an inet result')
+                                        'for an inet result')
 
         # Looks okay.
         return result, None
-    elif isinstance(result['port'], str):
+
+    if isinstance(result['port'], str):
         # Looks like a unix address.
 
         # Expect no host.
@@ -198,7 +202,7 @@ def update_connection(conn, address):
     conn.auth_type = address['auth_type']
 
 
-class RoundRobinStrategy(object):
+class RoundRobinStrategy():
     """
     Defines strategy to choose next pool server after fail.
     """
@@ -209,6 +213,8 @@ def __init__(self, addrs):
             :paramref:`~tarantool.ConnectionPool.params.addrs`.
         :type addrs: :obj:`list` of :obj:`dict`
         """
+        self.pos = None
+        self.addrs = []
         self.update(addrs)
 
     def update(self, new_addrs):
@@ -230,7 +236,7 @@ def update(self, new_addrs):
         new_addrs = new_addrs_unique
 
         # Save a current address if any.
-        if 'pos' in self.__dict__ and 'addrs' in self.__dict__:
+        if self.pos is not None:
             current_addr = self.addrs[self.pos]
         else:
             current_addr = None
@@ -433,6 +439,7 @@ def __init__(self, host=None, port=None,
             :class:`~tarantool.Connection` exceptions,
             :class:`~tarantool.MeshConnection.connect` exceptions
         """
+        # pylint: disable=too-many-arguments,too-many-locals
 
         if addrs is None:
             addrs = []
@@ -474,7 +481,7 @@ def __init__(self, host=None, port=None,
         self.cluster_discovery_delay = cluster_discovery_delay
         self.last_nodes_refresh = 0
 
-        super(MeshConnection, self).__init__(
+        super().__init__(
             host=addr['host'],
             port=addr['port'],
             user=user,
@@ -508,7 +515,7 @@ def connect(self):
             :exc:`~tarantool.error.NetworkError`,
             :class:`~tarantool.Connection.connect` exceptions
         """
-        super(MeshConnection, self).connect()
+        super().connect()
         if self.connected and self.cluster_discovery_function:
             self._opt_refresh_instances()
 
@@ -524,11 +531,11 @@ def _opt_reconnect(self):
         last_error = None
         for _ in range(len(self.strategy.addrs)):
             try:
-                super(MeshConnection, self)._opt_reconnect()
+                super()._opt_reconnect()
                 last_error = None
                 break
-            except NetworkError as e:
-                last_error = e
+            except NetworkError as exc:
+                last_error = exc
                 addr = self.strategy.getnext()
                 update_connection(self, addr)
 
@@ -558,8 +565,8 @@ def _opt_refresh_instances(self):
                               self.call_16)
         try:
             resp = self._send_request_wo_reconnect(request)
-        except DatabaseError as e:
-            msg = 'got "%s" error, skipped address updates' % str(e)
+        except DatabaseError as exc:
+            msg = f'got "{str(exc)}" error, skipped address updates'
             warn(msg, ClusterDiscoveryWarning)
             return
 
@@ -626,4 +633,4 @@ def _send_request(self, request, on_push=None, on_push_ctx=None):
         """
 
         self._opt_refresh_instances()
-        return super(MeshConnection, self)._send_request(request, on_push, on_push_ctx)
+        return super()._send_request(request, on_push, on_push_ctx)
diff --git a/tarantool/msgpack_ext/datetime.py b/tarantool/msgpack_ext/datetime.py
index 64422f5d..f7323c5f 100644
--- a/tarantool/msgpack_ext/datetime.py
+++ b/tarantool/msgpack_ext/datetime.py
@@ -40,7 +40,6 @@
 
 from tarantool.msgpack_ext.types.datetime import (
     NSEC_IN_SEC,
-    SEC_IN_MIN,
     Datetime,
 )
 import tarantool.msgpack_ext.types.timezones as tt_timezones
@@ -54,10 +53,10 @@
 
 BYTEORDER = 'little'
 
-SECONDS_SIZE_BYTES  = 8
-NSEC_SIZE_BYTES     = 4
+SECONDS_SIZE_BYTES = 8
+NSEC_SIZE_BYTES = 4
 TZOFFSET_SIZE_BYTES = 2
-TZINDEX_SIZE_BYTES  = 2
+TZINDEX_SIZE_BYTES = 2
 
 
 def get_int_as_bytes(data, size):
@@ -78,6 +77,7 @@ def get_int_as_bytes(data, size):
 
     return data.to_bytes(size, byteorder=BYTEORDER, signed=True)
 
+
 def encode(obj, _):
     """
     Encode a datetime object.
@@ -95,9 +95,9 @@ def encode(obj, _):
     nsec = obj.nsec
     tzoffset = obj.tzoffset
 
-    tz = obj.tz
-    if tz != '':
-        tzindex = tt_timezones.timezoneToIndex[tz]
+    timezone = obj.tz
+    if timezone != '':
+        tzindex = tt_timezones.timezoneToIndex[timezone]
     else:
         tzindex = 0
 
@@ -134,6 +134,7 @@ def get_bytes_as_int(data, cursor, size):
     part = data[cursor:cursor + size]
     return int.from_bytes(part, BYTEORDER, signed=True), cursor + size
 
+
 def decode(data, _):
     """
     Decode a datetime object.
@@ -152,11 +153,11 @@ def decode(data, _):
     seconds, cursor = get_bytes_as_int(data, cursor, SECONDS_SIZE_BYTES)
 
     data_len = len(data)
-    if data_len == (SECONDS_SIZE_BYTES + NSEC_SIZE_BYTES + \
-                    TZOFFSET_SIZE_BYTES + TZINDEX_SIZE_BYTES):
-        nsec, cursor     = get_bytes_as_int(data, cursor, NSEC_SIZE_BYTES)
+    if data_len == (SECONDS_SIZE_BYTES + NSEC_SIZE_BYTES
+                    + TZOFFSET_SIZE_BYTES + TZINDEX_SIZE_BYTES):
+        nsec, cursor = get_bytes_as_int(data, cursor, NSEC_SIZE_BYTES)
         tzoffset, cursor = get_bytes_as_int(data, cursor, TZOFFSET_SIZE_BYTES)
-        tzindex, cursor  = get_bytes_as_int(data, cursor, TZINDEX_SIZE_BYTES)
+        tzindex, cursor = get_bytes_as_int(data, cursor, TZINDEX_SIZE_BYTES)
     elif data_len == SECONDS_SIZE_BYTES:
         nsec = 0
         tzoffset = 0
@@ -170,9 +171,9 @@ def decode(data, _):
         tz = tt_timezones.indexToTimezone[tzindex]
         return Datetime(timestamp=seconds, nsec=nsec, tz=tz,
                         timestamp_since_utc_epoch=True)
-    elif tzoffset != 0:
+    if tzoffset != 0:
         return Datetime(timestamp=seconds, nsec=nsec, tzoffset=tzoffset,
                         timestamp_since_utc_epoch=True)
-    else:
-        return Datetime(timestamp=seconds, nsec=nsec,
-                        timestamp_since_utc_epoch=True)
+
+    return Datetime(timestamp=seconds, nsec=nsec,
+                    timestamp_since_utc_epoch=True)
diff --git a/tarantool/msgpack_ext/decimal.py b/tarantool/msgpack_ext/decimal.py
index bad947fb..545ee07d 100644
--- a/tarantool/msgpack_ext/decimal.py
+++ b/tarantool/msgpack_ext/decimal.py
@@ -65,6 +65,7 @@
 
 TARANTOOL_DECIMAL_MAX_DIGITS = 38
 
+
 def get_mp_sign(sign):
     """
     Parse decimal sign to a nibble.
@@ -88,6 +89,7 @@ def get_mp_sign(sign):
 
     raise RuntimeError
 
+
 def add_mp_digit(digit, bytes_reverted, digit_count):
     """
     Append decimal digit to a binary data array.
@@ -109,6 +111,7 @@ def add_mp_digit(digit, bytes_reverted, digit_count):
     else:
         bytes_reverted.append(digit)
 
+
 def check_valid_tarantool_decimal(str_repr, scale, first_digit_ind):
     """
     Decimal numbers have 38 digits of precision, that is, the total
@@ -183,21 +186,21 @@ def check_valid_tarantool_decimal(str_repr, scale, first_digit_ind):
         return True
 
     if (digit_count - scale) > TARANTOOL_DECIMAL_MAX_DIGITS:
-        raise MsgpackError('Decimal cannot be encoded: Tarantool decimal ' + \
+        raise MsgpackError('Decimal cannot be encoded: Tarantool decimal '
                            'supports a maximum of 38 digits.')
 
     starts_with_zero = str_repr[first_digit_ind] == '0'
 
-    if (    (digit_count > TARANTOOL_DECIMAL_MAX_DIGITS + 1) or \
-            (digit_count == TARANTOOL_DECIMAL_MAX_DIGITS + 1 \
-            and not starts_with_zero)):
-        warn('Decimal encoded with loss of precision: ' + \
+    if (digit_count > TARANTOOL_DECIMAL_MAX_DIGITS + 1) or \
+            (digit_count == TARANTOOL_DECIMAL_MAX_DIGITS + 1 and not starts_with_zero):
+        warn('Decimal encoded with loss of precision: '
              'Tarantool decimal supports a maximum of 38 digits.',
              MsgpackWarning)
         return False
 
     return True
 
+
 def strip_decimal_str(str_repr, scale, first_digit_ind):
     """
     Strip decimal digits after the decimal point if decimal cannot be
@@ -225,6 +228,7 @@ def strip_decimal_str(str_repr, scale, first_digit_ind):
     # Do not strips zeroes before the decimal point
     return str_repr
 
+
 def encode(obj, _):
     """
     Encode a decimal object.
@@ -244,8 +248,7 @@ def encode(obj, _):
     bytes_reverted = bytearray()
 
     scale = 0
-    for i in range(len(str_repr)):
-        str_digit = str_repr[i]
+    for i, str_digit in enumerate(str_repr):
         if str_digit == '.':
             scale = len(str_repr) - i - 1
             break
@@ -263,7 +266,7 @@ def encode(obj, _):
     bytes_reverted.append(get_mp_sign(sign))
 
     digit_count = 0
-    # We need to update the scale after possible strip_decimal_str() 
+    # We need to update the scale after possible strip_decimal_str()
     scale = 0
 
     for i in range(len(str_repr) - 1, first_digit_ind - 1, -1):
@@ -301,14 +304,15 @@ def get_str_sign(nibble):
     :meta private:
     """
 
-    if nibble == 0x0a or nibble == 0x0c or nibble == 0x0e or nibble == 0x0f:
+    if nibble in (0x0a, 0x0c, 0x0e, 0x0f):
         return '+'
 
-    if nibble == 0x0b or nibble == 0x0d:
+    if nibble in (0x0b, 0x0d):
         return '-'
 
     raise MsgpackError('Unexpected MP_DECIMAL sign nibble')
 
+
 def add_str_digit(digit, digits_reverted, scale):
     """
     Append decimal digit to a binary data array.
@@ -327,7 +331,7 @@ def add_str_digit(digit, digits_reverted, scale):
     :meta private:
     """
 
-    if not (0 <= digit <= 9):
+    if not 0 <= digit <= 9:
         raise MsgpackError('Unexpected MP_DECIMAL digit nibble')
 
     if len(digits_reverted) == scale:
@@ -335,6 +339,7 @@ def add_str_digit(digit, digits_reverted, scale):
 
     digits_reverted.append(str(digit))
 
+
 def decode(data, _):
     """
     Decode a decimal object.
@@ -348,7 +353,7 @@ def decode(data, _):
     :raise: :exc:`~tarantool.error.MsgpackError`
     """
 
-    scale = data[0] 
+    scale = data[0]
 
     sign = get_str_sign(data[-1] & 0x0f)
 
diff --git a/tarantool/msgpack_ext/error.py b/tarantool/msgpack_ext/error.py
index a3f13a04..ef322d58 100644
--- a/tarantool/msgpack_ext/error.py
+++ b/tarantool/msgpack_ext/error.py
@@ -16,6 +16,7 @@
 `error`_ type id.
 """
 
+
 def encode(obj, packer):
     """
     Encode an error object.
@@ -33,6 +34,7 @@ def encode(obj, packer):
     err_map = encode_box_error(obj)
     return packer.pack(err_map)
 
+
 def decode(data, unpacker):
     """
     Decode an error object.
diff --git a/tarantool/msgpack_ext/interval.py b/tarantool/msgpack_ext/interval.py
index cd7ab16d..12136772 100644
--- a/tarantool/msgpack_ext/interval.py
+++ b/tarantool/msgpack_ext/interval.py
@@ -51,6 +51,7 @@
 `datetime.interval`_ type id.
 """
 
+
 def encode(obj, _):
     """
     Encode an interval object.
@@ -65,8 +66,7 @@ def encode(obj, _):
     buf = bytes()
 
     count = 0
-    for field_id in id_map.keys():
-        field_name = id_map[field_id]
+    for field_id, field_name in id_map.items():
         value = getattr(obj, field_name)
 
         if field_name == 'adjust':
@@ -80,6 +80,7 @@ def encode(obj, _):
 
     return buf
 
+
 def decode(data, unpacker):
     """
     Decode an interval object.
@@ -127,8 +128,8 @@ def decode(data, unpacker):
             if field_name == 'adjust':
                 try:
                     value = Adjust(value)
-                except ValueError as e:
-                    raise MsgpackError(e)
+                except ValueError as exc:
+                    raise MsgpackError(exc) from exc
 
             kwargs[id_map[field_id]] = value
 
diff --git a/tarantool/msgpack_ext/packer.py b/tarantool/msgpack_ext/packer.py
index 12faa29e..e2c03b8b 100644
--- a/tarantool/msgpack_ext/packer.py
+++ b/tarantool/msgpack_ext/packer.py
@@ -3,6 +3,7 @@
 
 .. _extension: https://www.tarantool.io/en/doc/latest/dev_guide/internals/msgpack_extensions/
 """
+# pylint: disable=duplicate-code
 
 from decimal import Decimal
 from uuid import UUID
@@ -19,13 +20,14 @@
 import tarantool.msgpack_ext.interval as ext_interval
 
 encoders = [
-    {'type': Decimal,  'ext': ext_decimal },
-    {'type': UUID,     'ext': ext_uuid    },
-    {'type': BoxError, 'ext': ext_error   },
+    {'type': Decimal, 'ext': ext_decimal},
+    {'type': UUID, 'ext': ext_uuid},
+    {'type': BoxError, 'ext': ext_error},
     {'type': Datetime, 'ext': ext_datetime},
     {'type': Interval, 'ext': ext_interval},
 ]
 
+
 def default(obj, packer=None):
     """
     :class:`msgpack.Packer` encoder.
@@ -48,4 +50,4 @@ def default(obj, packer=None):
     for encoder in encoders:
         if isinstance(obj, encoder['type']):
             return ExtType(encoder['ext'].EXT_ID, encoder['ext'].encode(obj, packer))
-    raise TypeError("Unknown type: %r" % (obj,))
+    raise TypeError(f"Unknown type: {repr(obj)}")
diff --git a/tarantool/msgpack_ext/types/datetime.py b/tarantool/msgpack_ext/types/datetime.py
index d2e4b903..79c669b9 100644
--- a/tarantool/msgpack_ext/types/datetime.py
+++ b/tarantool/msgpack_ext/types/datetime.py
@@ -1,6 +1,7 @@
 """
 Tarantool `datetime`_ extension type implementation module.
 """
+# pylint: disable=line-too-long
 
 from copy import deepcopy
 
@@ -16,6 +17,7 @@
 SEC_IN_MIN = 60
 MONTH_IN_YEAR = 12
 
+
 def compute_offset(timestamp):
     """
     Compute timezone offset. Offset is computed each time and not stored
@@ -41,6 +43,7 @@ def compute_offset(timestamp):
     # There is no precision loss since offset is in minutes
     return int(utc_offset.total_seconds()) // SEC_IN_MIN
 
+
 def get_python_tzinfo(tz):
     """
     All non-abbreviated Tarantool timezones are represented as pytz
@@ -71,6 +74,7 @@ def get_python_tzinfo(tz):
 
     return pytz.FixedOffset(tt_tzinfo['offset'])
 
+
 class Datetime():
     """
     Class representing Tarantool `datetime`_ info. Internals are based
@@ -207,7 +211,7 @@ def __init__(self, *, timestamp=None, year=None, month=None,
         :type tz: :obj:`str`, optional
 
         :param timestamp_since_utc_epoch: Parameter to set timestamp
-            convertion behavior for timezone-aware datetimes.
+            conversion behavior for timezone-aware datetimes.
 
             If ``False`` (default), behaves similar to Tarantool
             `datetime.new()`_:
@@ -228,7 +232,7 @@ def __init__(self, *, timestamp=None, year=None, month=None,
 
             Thus, if ``False``, datetime is computed from timestamp
             since epoch and then timezone is applied without any
-            convertion. In that case,
+            conversion. In that case,
             :attr:`~tarantool.Datetime.timestamp` won't be equal to
             initialization
             :paramref:`~tarantool.Datetime.params.timestamp` for all
@@ -261,6 +265,7 @@ def __init__(self, *, timestamp=None, year=None, month=None,
 
         .. _datetime.new(): https://www.tarantool.io/en/doc/latest/reference/reference_lua/datetime/new/
         """
+        # pylint: disable=too-many-branches,too-many-locals
 
         tzinfo = None
         if tz != '':
@@ -275,10 +280,11 @@ def __init__(self, *, timestamp=None, year=None, month=None,
         # The logic is same as in Tarantool, refer to datetime API.
         # https://www.tarantool.io/en/doc/latest/reference/reference_lua/datetime/new/
         if timestamp is not None:
-            if ((year is not None) or (month is not None) or \
-                    (day is not None) or (hour is not None) or \
-                    (minute is not None) or (sec is not None)):
-                raise ValueError('Cannot provide both timestamp and year, month, ' +
+            # pylint: disable=too-many-boolean-expressions
+            if ((year is not None) or (month is not None)
+                    or (day is not None) or (hour is not None)
+                    or (minute is not None) or (sec is not None)):
+                raise ValueError('Cannot provide both timestamp and year, month, '
                                  'day, hour, minute, sec')
 
             if nsec is not None:
@@ -330,24 +336,24 @@ def _interval_operation(self, other, sign=1):
         # https://github.com/tarantool/tarantool/wiki/Datetime-Internals#date-adjustions-and-leap-years
         months = other.year * MONTH_IN_YEAR + other.month
 
-        res = self_dt + pandas.DateOffset(months = sign * months)
+        res = self_dt + pandas.DateOffset(months=sign * months)
 
         # pandas.DateOffset works exactly like Adjust.NONE
         if other.adjust == Adjust.EXCESS:
             if self_dt.day > res.day:
-                res = res + pandas.DateOffset(days = self_dt.day - res.day)
+                res = res + pandas.DateOffset(days=self_dt.day - res.day)
         elif other.adjust == Adjust.LAST:
             if self_dt.is_month_end:
                 # day replaces days
-                res = res.replace(day = res.days_in_month)
+                res = res.replace(day=res.days_in_month)
 
-        res = res + pandas.Timedelta(weeks = sign * other.week,
-                                     days = sign * other.day,
-                                     hours = sign * other.hour,
-                                     minutes = sign * other.minute,
-                                     seconds = sign * other.sec,
-                                     microseconds = sign * (other.nsec // NSEC_IN_MKSEC),
-                                     nanoseconds = sign * (other.nsec % NSEC_IN_MKSEC))
+        res = res + pandas.Timedelta(weeks=sign * other.week,
+                                     days=sign * other.day,
+                                     hours=sign * other.hour,
+                                     minutes=sign * other.minute,
+                                     seconds=sign * other.sec,
+                                     microseconds=sign * (other.nsec // NSEC_IN_MKSEC),
+                                     nanoseconds=sign * (other.nsec % NSEC_IN_MKSEC))
 
         if res.tzinfo is not None:
             tzoffset = compute_offset(res)
@@ -421,7 +427,8 @@ def __add__(self, other):
         """
 
         if not isinstance(other, Interval):
-            raise TypeError(f"unsupported operand type(s) for +: '{type(self)}' and '{type(other)}'")
+            raise TypeError("unsupported operand type(s) for +: "
+                            f"'{type(self)}' and '{type(other)}'")
 
         return self._interval_operation(other, sign=1)
 
@@ -470,18 +477,18 @@ def __sub__(self, other):
             other_nsec = other_dt.microsecond * NSEC_IN_MKSEC + other_dt.nanosecond
 
             return Interval(
-                year = self_dt.year - other_dt.year,
-                month = self_dt.month - other_dt.month,
-                day = self_dt.day - other_dt.day,
-                hour = self_dt.hour - other_dt.hour,
-                minute = self_dt.minute - other_dt.minute,
-                sec = self_dt.second - other_dt.second,
-                nsec = self_nsec - other_nsec,
+                year=self_dt.year - other_dt.year,
+                month=self_dt.month - other_dt.month,
+                day=self_dt.day - other_dt.day,
+                hour=self_dt.hour - other_dt.hour,
+                minute=self_dt.minute - other_dt.minute,
+                sec=self_dt.second - other_dt.second,
+                nsec=self_nsec - other_nsec,
             )
-        elif isinstance(other, Interval):
+        if isinstance(other, Interval):
             return self._interval_operation(other, sign=-1)
-        else:
-            raise TypeError(f"unsupported operand type(s) for -: '{type(self)}' and '{type(other)}'")
+
+        raise TypeError(f"unsupported operand type(s) for -: '{type(self)}' and '{type(other)}'")
 
     def __eq__(self, other):
         """
@@ -496,10 +503,9 @@ def __eq__(self, other):
 
         if isinstance(other, Datetime):
             return self._datetime == other._datetime
-        elif isinstance(other, pandas.Timestamp):
+        if isinstance(other, pandas.Timestamp):
             return self._datetime == other
-        else:
-            return False
+        return False
 
     def __str__(self):
         return self._datetime.__str__()
@@ -517,8 +523,8 @@ def __deepcopy__(self, memo):
         cls = self.__class__
         result = cls.__new__(cls)
         memo[id(self)] = result
-        for k, v in self.__dict__.items():
-            setattr(result, k, deepcopy(v, memo))
+        for key, val in self.__dict__.items():
+            setattr(result, key, deepcopy(val, memo))
         return result
 
     @property
diff --git a/tarantool/msgpack_ext/types/interval.py b/tarantool/msgpack_ext/types/interval.py
index e90ff0a0..10dc4847 100644
--- a/tarantool/msgpack_ext/types/interval.py
+++ b/tarantool/msgpack_ext/types/interval.py
@@ -16,6 +16,7 @@
     8: 'adjust',
 }
 
+
 # https://github.com/tarantool/c-dt/blob/cec6acebb54d9e73ea0b99c63898732abd7683a6/dt_arithmetic.h#L34
 class Adjust(Enum):
     """
@@ -38,6 +39,7 @@ class Adjust(Enum):
     Mode when day snaps to the end of month, if it happens.
     """
 
+
 class Interval():
     """
     Class representing Tarantool `datetime.interval`_ info.
@@ -57,6 +59,7 @@ class Interval():
 
     .. _datetime.interval: https://www.tarantool.io/en/doc/latest/dev_guide/internals/msgpack_extensions/#the-interval-type
     """
+    # pylint: disable=too-many-instance-attributes
 
     def __init__(self, *, year=0, month=0, week=0,
                  day=0, hour=0, minute=0, sec=0,
@@ -90,7 +93,7 @@ def __init__(self, *, year=0, month=0, week=0,
             :meth:`~tarantool.Datetime.__add__`.
         :type adjust: :class:`~tarantool.IntervalAdjust`, optional
         """
-        
+
         self.year = year
         self.month = month
         self.week = week
@@ -119,7 +122,8 @@ def __add__(self, other):
         """
 
         if not isinstance(other, Interval):
-            raise TypeError(f"unsupported operand type(s) for +: '{type(self)}' and '{type(other)}'")
+            raise TypeError("unsupported operand type(s) for +: "
+                            f"'{type(self)}' and '{type(other)}'")
 
         # Tarantool saves adjust of the first argument
         #
@@ -139,14 +143,14 @@ def __add__(self, other):
         # ...
 
         return Interval(
-            year = self.year + other.year,
-            month = self.month + other.month,
-            day = self.day + other.day,
-            hour = self.hour + other.hour,
-            minute = self.minute + other.minute,
-            sec = self.sec + other.sec,
-            nsec = self.nsec + other.nsec,
-            adjust = self.adjust,
+            year=self.year + other.year,
+            month=self.month + other.month,
+            day=self.day + other.day,
+            hour=self.hour + other.hour,
+            minute=self.minute + other.minute,
+            sec=self.sec + other.sec,
+            nsec=self.nsec + other.nsec,
+            adjust=self.adjust,
         )
 
     def __sub__(self, other):
@@ -167,7 +171,8 @@ def __sub__(self, other):
         """
 
         if not isinstance(other, Interval):
-            raise TypeError(f"unsupported operand type(s) for -: '{type(self)}' and '{type(other)}'")
+            raise TypeError("unsupported operand type(s) for -: "
+                            f"'{type(self)}' and '{type(other)}'")
 
         # Tarantool saves adjust of the first argument
         #
@@ -187,14 +192,14 @@ def __sub__(self, other):
         # ...
 
         return Interval(
-            year = self.year - other.year,
-            month = self.month - other.month,
-            day = self.day - other.day,
-            hour = self.hour - other.hour,
-            minute = self.minute - other.minute,
-            sec = self.sec - other.sec,
-            nsec = self.nsec - other.nsec,
-            adjust = self.adjust,
+            year=self.year - other.year,
+            month=self.month - other.month,
+            day=self.day - other.day,
+            hour=self.hour - other.hour,
+            minute=self.minute - other.minute,
+            sec=self.sec - other.sec,
+            nsec=self.nsec - other.nsec,
+            adjust=self.adjust,
         )
 
     def __eq__(self, other):
@@ -219,8 +224,7 @@ def __eq__(self, other):
         # - false
         # ...
 
-        for field_id in id_map.keys():
-            field_name = id_map[field_id]
+        for _, field_name in id_map.items():
             if getattr(self, field_name) != getattr(other, field_name):
                 return False
 
diff --git a/tarantool/msgpack_ext/types/timezones/__init__.py b/tarantool/msgpack_ext/types/timezones/__init__.py
index c0c4ce7e..47a9edf9 100644
--- a/tarantool/msgpack_ext/types/timezones/__init__.py
+++ b/tarantool/msgpack_ext/types/timezones/__init__.py
@@ -3,10 +3,10 @@
 """
 
 from tarantool.msgpack_ext.types.timezones.timezones import (
-	TZ_AMBIGUOUS,
-	indexToTimezone,
-	timezoneToIndex,
-	timezoneAbbrevInfo,
+    TZ_AMBIGUOUS,
+    indexToTimezone,
+    timezoneToIndex,
+    timezoneAbbrevInfo,
 )
 
 __all__ = ['TZ_AMBIGUOUS', 'indexToTimezone', 'timezoneToIndex',
diff --git a/tarantool/msgpack_ext/types/timezones/gen-timezones.sh b/tarantool/msgpack_ext/types/timezones/gen-timezones.sh
index 5de5a51a..bca568b0 100755
--- a/tarantool/msgpack_ext/types/timezones/gen-timezones.sh
+++ b/tarantool/msgpack_ext/types/timezones/gen-timezones.sh
@@ -26,23 +26,24 @@ cat <<EOF > ${DST_FILE}
 Tarantool timezone info. Automatically generated by
 \`\`gen-timezones.sh\`\`.
 """
+# pylint: disable=too-many-lines
 
-TZ_UTC       = 0x01
-TZ_RFC       = 0x02
-TZ_MILITARY  = 0x04
+TZ_UTC = 0x01
+TZ_RFC = 0x02
+TZ_MILITARY = 0x04
 TZ_AMBIGUOUS = 0x08
-TZ_NYI       = 0x10
-TZ_OLSON     = 0x20
-TZ_ALIAS     = 0x40
-TZ_DST       = 0x80
+TZ_NYI = 0x10
+TZ_OLSON = 0x20
+TZ_ALIAS = 0x40
+TZ_DST = 0x80
 
 indexToTimezone = {
 EOF
 
 grep ZONE_ABBREV ${SRC_FILE} | sed "s/ZONE_ABBREV( *//g" | sed "s/[),]//g" \
-	| awk '{printf("\t%s : %s,\n", $1, $3)}' >> ${DST_FILE}
+	| awk '{printf("    %s: %s,\n", $1, $3)}' >> ${DST_FILE}
 grep ZONE_UNIQUE ${SRC_FILE} | sed "s/ZONE_UNIQUE( *//g" | sed "s/[),]//g" \
-	| awk '{printf("\t%s : %s,\n", $1, $2)}' >> ${DST_FILE}
+	| awk '{printf("    %s: %s,\n", $1, $2)}' >> ${DST_FILE}
 
 cat <<EOF >> ${DST_FILE}
 }
@@ -51,11 +52,11 @@ timezoneToIndex = {
 EOF
 
 grep ZONE_ABBREV ${SRC_FILE} | sed "s/ZONE_ABBREV( *//g" | sed "s/[),]//g" \
-	| awk '{printf("\t%s : %s,\n", $3, $1)}' >> ${DST_FILE}
+	| awk '{printf("    %s: %s,\n", $3, $1)}' >> ${DST_FILE}
 grep ZONE_UNIQUE ${SRC_FILE} | sed "s/ZONE_UNIQUE( *//g" | sed "s/[),]//g" \
-	| awk '{printf("\t%s : %s,\n", $2, $1)}' >> ${DST_FILE}
+	| awk '{printf("    %s: %s,\n", $2, $1)}' >> ${DST_FILE}
 grep ZONE_ALIAS  ${SRC_FILE} | sed "s/ZONE_ALIAS( *//g"  | sed "s/[),]//g" \
-	| awk '{printf("\t%s : %s,\n", $2, $1)}' >> ${DST_FILE}
+	| awk '{printf("    %s: %s,\n", $2, $1)}' >> ${DST_FILE}
 
 cat <<EOF >> ${DST_FILE}
 }
@@ -63,10 +64,23 @@ cat <<EOF >> ${DST_FILE}
 timezoneAbbrevInfo = {
 EOF
 
-grep ZONE_ABBREV ${SRC_FILE} | sed "s/ZONE_ABBREV( *//g" | sed "s/[),]//g" \
-	| awk '{printf("\t%s : {\"offset\" : %d, \"category\" : %s},\n", $3, $2, $4)}' >> ${DST_FILE}
+grep ZONE_ABBREV ${SRC_FILE} | sed "s/ZONE_ABBREV( *//g" | sed "s/[),]//g"  \
+	| awk '{printf("    %s: {\"offset\": %d, \"category\": %s},\n", $3, $2, $4)}' | sed "s/|/ | /g" >> ${DST_FILE}
 echo "}" >> ${DST_FILE}
 
 rm timezones.h
 
-python validate_timezones.py
+python <<EOF
+import pytz
+from timezones import timezoneToIndex, timezoneAbbrevInfo
+
+if __name__ != '__main__':
+    raise RuntimeError('Import not expected')
+
+for timezone in timezoneToIndex.keys():
+    if timezone in pytz.all_timezones:
+        continue
+
+    if not timezone in timezoneAbbrevInfo:
+        raise KeyError(f'Unknown Tarantool timezone {timezone}')
+EOF
diff --git a/tarantool/msgpack_ext/types/timezones/timezones.py b/tarantool/msgpack_ext/types/timezones/timezones.py
index 0e3ff770..082ee356 100644
--- a/tarantool/msgpack_ext/types/timezones/timezones.py
+++ b/tarantool/msgpack_ext/types/timezones/timezones.py
@@ -2,1786 +2,1787 @@
 Tarantool timezone info. Automatically generated by
 ``gen-timezones.sh``.
 """
+# pylint: disable=too-many-lines
 
-TZ_UTC       = 0x01
-TZ_RFC       = 0x02
-TZ_MILITARY  = 0x04
+TZ_UTC = 0x01
+TZ_RFC = 0x02
+TZ_MILITARY = 0x04
 TZ_AMBIGUOUS = 0x08
-TZ_NYI       = 0x10
-TZ_OLSON     = 0x20
-TZ_ALIAS     = 0x40
-TZ_DST       = 0x80
+TZ_NYI = 0x10
+TZ_OLSON = 0x20
+TZ_ALIAS = 0x40
+TZ_DST = 0x80
 
 indexToTimezone = {
-	1 : "A",
-	2 : "B",
-	3 : "C",
-	4 : "D",
-	5 : "E",
-	6 : "F",
-	7 : "G",
-	8 : "H",
-	9 : "I",
-	10 : "K",
-	11 : "L",
-	12 : "M",
-	13 : "N",
-	14 : "O",
-	15 : "P",
-	16 : "Q",
-	17 : "R",
-	18 : "S",
-	19 : "T",
-	20 : "U",
-	21 : "V",
-	22 : "W",
-	23 : "X",
-	24 : "Y",
-	25 : "Z",
-	32 : "AT",
-	40 : "BT",
-	48 : "CT",
-	56 : "ET",
-	64 : "GT",
-	72 : "IT",
-	80 : "KT",
-	88 : "MT",
-	96 : "PT",
-	104 : "ST",
-	112 : "UT",
-	120 : "WT",
-	128 : "ACT",
-	129 : "ADT",
-	130 : "AET",
-	131 : "AFT",
-	132 : "AMT",
-	133 : "AoE",
-	134 : "ART",
-	135 : "AST",
-	136 : "AZT",
-	144 : "BDT",
-	145 : "BNT",
-	146 : "BOT",
-	147 : "BRT",
-	148 : "BST",
-	149 : "BTT",
-	152 : "CAT",
-	153 : "CCT",
-	154 : "CDT",
-	155 : "CET",
-	156 : "CIT",
-	157 : "CKT",
-	158 : "CLT",
-	159 : "COT",
-	160 : "CST",
-	161 : "CVT",
-	162 : "CXT",
-	168 : "EAT",
-	169 : "ECT",
-	170 : "EDT",
-	171 : "EET",
-	172 : "EGT",
-	173 : "EST",
-	176 : "FET",
-	177 : "FJT",
-	178 : "FKT",
-	179 : "FNT",
-	184 : "GET",
-	185 : "GFT",
-	186 : "GMT",
-	187 : "GST",
-	188 : "GYT",
-	192 : "HAA",
-	193 : "HAC",
-	194 : "HAE",
-	195 : "HAP",
-	196 : "HAR",
-	197 : "HAT",
-	198 : "HDT",
-	199 : "HKT",
-	200 : "HLV",
-	201 : "HNA",
-	202 : "HNC",
-	203 : "HNE",
-	204 : "HNP",
-	205 : "HNR",
-	206 : "HNT",
-	207 : "HST",
-	208 : "ICT",
-	209 : "IDT",
-	210 : "IOT",
-	211 : "IST",
-	216 : "JST",
-	224 : "KGT",
-	225 : "KIT",
-	226 : "KST",
-	232 : "MCK",
-	233 : "MDT",
-	234 : "MEZ",
-	235 : "MHT",
-	236 : "MMT",
-	237 : "MSD",
-	238 : "MSK",
-	239 : "MST",
-	240 : "MUT",
-	241 : "MVT",
-	242 : "MYT",
-	248 : "NCT",
-	249 : "NDT",
-	250 : "NFT",
-	251 : "NPT",
-	252 : "NRT",
-	253 : "NST",
-	254 : "NUT",
-	256 : "OEZ",
-	264 : "PDT",
-	265 : "PET",
-	266 : "PGT",
-	267 : "PHT",
-	268 : "PKT",
-	269 : "PST",
-	270 : "PWT",
-	271 : "PYT",
-	272 : "RET",
-	280 : "SBT",
-	281 : "SCT",
-	282 : "SGT",
-	283 : "SRT",
-	284 : "SST",
-	288 : "TFT",
-	289 : "TJT",
-	290 : "TKT",
-	291 : "TLT",
-	292 : "TMT",
-	293 : "TOT",
-	294 : "TRT",
-	295 : "TVT",
-	296 : "UTC",
-	297 : "UYT",
-	298 : "UZT",
-	304 : "VET",
-	305 : "VUT",
-	312 : "WAT",
-	313 : "WDT",
-	314 : "WET",
-	315 : "WEZ",
-	316 : "WFT",
-	317 : "WGT",
-	318 : "WIB",
-	319 : "WIT",
-	320 : "WST",
-	328 : "ACDT",
-	329 : "ACST",
-	330 : "ADST",
-	331 : "AEDT",
-	332 : "AEST",
-	333 : "AKDT",
-	334 : "AKST",
-	335 : "ALMT",
-	336 : "AMDT",
-	337 : "AMST",
-	338 : "ANAT",
-	339 : "AQTT",
-	340 : "AWDT",
-	341 : "AWST",
-	342 : "AZOT",
-	343 : "AZST",
-	344 : "BDST",
-	345 : "BRST",
-	352 : "CAST",
-	353 : "CDST",
-	354 : "CEDT",
-	355 : "CEST",
-	356 : "CHOT",
-	357 : "ChST",
-	358 : "CHUT",
-	359 : "CIST",
-	360 : "CLDT",
-	361 : "CLST",
-	368 : "DAVT",
-	369 : "DDUT",
-	376 : "EADT",
-	377 : "EAST",
-	378 : "ECST",
-	379 : "EDST",
-	380 : "EEDT",
-	381 : "EEST",
-	382 : "EGST",
-	384 : "FJDT",
-	385 : "FJST",
-	386 : "FKDT",
-	387 : "FKST",
-	392 : "GALT",
-	393 : "GAMT",
-	394 : "GILT",
-	400 : "HADT",
-	401 : "HAST",
-	402 : "HOVT",
-	408 : "IRDT",
-	409 : "IRKT",
-	410 : "IRST",
-	416 : "KOST",
-	417 : "KRAT",
-	418 : "KUYT",
-	424 : "LHDT",
-	425 : "LHST",
-	426 : "LINT",
-	432 : "MAGT",
-	433 : "MART",
-	434 : "MAWT",
-	435 : "MDST",
-	436 : "MESZ",
-	440 : "NFDT",
-	441 : "NOVT",
-	442 : "NZDT",
-	443 : "NZST",
-	448 : "OESZ",
-	449 : "OMST",
-	450 : "ORAT",
-	456 : "PDST",
-	457 : "PETT",
-	458 : "PHOT",
-	459 : "PMDT",
-	460 : "PMST",
-	461 : "PONT",
-	462 : "PYST",
-	464 : "QYZT",
-	472 : "ROTT",
-	480 : "SAKT",
-	481 : "SAMT",
-	482 : "SAST",
-	483 : "SRET",
-	484 : "SYOT",
-	488 : "TAHT",
-	489 : "TOST",
-	496 : "ULAT",
-	497 : "UYST",
-	504 : "VLAT",
-	505 : "VOST",
-	512 : "WAKT",
-	513 : "WAST",
-	514 : "WEDT",
-	515 : "WEST",
-	516 : "WESZ",
-	517 : "WGST",
-	518 : "WITA",
-	520 : "YAKT",
-	521 : "YAPT",
-	522 : "YEKT",
-	528 : "ACWST",
-	529 : "ANAST",
-	530 : "AZODT",
-	531 : "AZOST",
-	536 : "CHADT",
-	537 : "CHAST",
-	538 : "CHODT",
-	539 : "CHOST",
-	540 : "CIDST",
-	544 : "EASST",
-	545 : "EFATE",
-	552 : "HOVDT",
-	553 : "HOVST",
-	560 : "IRKST",
-	568 : "KRAST",
-	576 : "MAGST",
-	584 : "NACDT",
-	585 : "NACST",
-	586 : "NAEDT",
-	587 : "NAEST",
-	588 : "NAMDT",
-	589 : "NAMST",
-	590 : "NAPDT",
-	591 : "NAPST",
-	592 : "NOVST",
-	600 : "OMSST",
-	608 : "PETST",
-	616 : "SAMST",
-	624 : "ULAST",
-	632 : "VLAST",
-	640 : "WARST",
-	648 : "YAKST",
-	649 : "YEKST",
-	656 : "CHODST",
-	664 : "HOVDST",
-	672 : "Africa/Abidjan",
-	673 : "Africa/Algiers",
-	674 : "Africa/Bissau",
-	675 : "Africa/Cairo",
-	676 : "Africa/Casablanca",
-	677 : "Africa/Ceuta",
-	678 : "Africa/El_Aaiun",
-	679 : "Africa/Johannesburg",
-	680 : "Africa/Juba",
-	681 : "Africa/Khartoum",
-	682 : "Africa/Lagos",
-	683 : "Africa/Maputo",
-	684 : "Africa/Monrovia",
-	685 : "Africa/Nairobi",
-	686 : "Africa/Ndjamena",
-	687 : "Africa/Sao_Tome",
-	688 : "Africa/Tripoli",
-	689 : "Africa/Tunis",
-	690 : "Africa/Windhoek",
-	691 : "America/Adak",
-	692 : "America/Anchorage",
-	693 : "America/Araguaina",
-	694 : "America/Argentina/Buenos_Aires",
-	695 : "America/Argentina/Catamarca",
-	696 : "America/Argentina/Cordoba",
-	697 : "America/Argentina/Jujuy",
-	698 : "America/Argentina/La_Rioja",
-	699 : "America/Argentina/Mendoza",
-	700 : "America/Argentina/Rio_Gallegos",
-	701 : "America/Argentina/Salta",
-	702 : "America/Argentina/San_Juan",
-	703 : "America/Argentina/San_Luis",
-	704 : "America/Argentina/Tucuman",
-	705 : "America/Argentina/Ushuaia",
-	706 : "America/Asuncion",
-	707 : "America/Bahia",
-	708 : "America/Bahia_Banderas",
-	709 : "America/Barbados",
-	710 : "America/Belem",
-	711 : "America/Belize",
-	712 : "America/Boa_Vista",
-	713 : "America/Bogota",
-	714 : "America/Boise",
-	715 : "America/Cambridge_Bay",
-	716 : "America/Campo_Grande",
-	717 : "America/Cancun",
-	718 : "America/Caracas",
-	719 : "America/Cayenne",
-	720 : "America/Chicago",
-	721 : "America/Chihuahua",
-	722 : "America/Costa_Rica",
-	723 : "America/Cuiaba",
-	724 : "America/Danmarkshavn",
-	725 : "America/Dawson",
-	726 : "America/Dawson_Creek",
-	727 : "America/Denver",
-	728 : "America/Detroit",
-	729 : "America/Edmonton",
-	730 : "America/Eirunepe",
-	731 : "America/El_Salvador",
-	732 : "America/Fort_Nelson",
-	733 : "America/Fortaleza",
-	734 : "America/Glace_Bay",
-	735 : "America/Goose_Bay",
-	736 : "America/Grand_Turk",
-	737 : "America/Guatemala",
-	738 : "America/Guayaquil",
-	739 : "America/Guyana",
-	740 : "America/Halifax",
-	741 : "America/Havana",
-	742 : "America/Hermosillo",
-	743 : "America/Indiana/Indianapolis",
-	744 : "America/Indiana/Knox",
-	745 : "America/Indiana/Marengo",
-	746 : "America/Indiana/Petersburg",
-	747 : "America/Indiana/Tell_City",
-	748 : "America/Indiana/Vevay",
-	749 : "America/Indiana/Vincennes",
-	750 : "America/Indiana/Winamac",
-	751 : "America/Inuvik",
-	752 : "America/Iqaluit",
-	753 : "America/Jamaica",
-	754 : "America/Juneau",
-	755 : "America/Kentucky/Louisville",
-	756 : "America/Kentucky/Monticello",
-	757 : "America/La_Paz",
-	758 : "America/Lima",
-	759 : "America/Los_Angeles",
-	760 : "America/Maceio",
-	761 : "America/Managua",
-	762 : "America/Manaus",
-	763 : "America/Martinique",
-	764 : "America/Matamoros",
-	765 : "America/Mazatlan",
-	766 : "America/Menominee",
-	767 : "America/Merida",
-	768 : "America/Metlakatla",
-	769 : "America/Mexico_City",
-	770 : "America/Miquelon",
-	771 : "America/Moncton",
-	772 : "America/Monterrey",
-	773 : "America/Montevideo",
-	774 : "America/New_York",
-	775 : "America/Nipigon",
-	776 : "America/Nome",
-	777 : "America/Noronha",
-	778 : "America/North_Dakota/Beulah",
-	779 : "America/North_Dakota/Center",
-	780 : "America/North_Dakota/New_Salem",
-	781 : "America/Nuuk",
-	782 : "America/Ojinaga",
-	783 : "America/Panama",
-	784 : "America/Pangnirtung",
-	785 : "America/Paramaribo",
-	786 : "America/Phoenix",
-	787 : "America/Port-au-Prince",
-	788 : "America/Porto_Velho",
-	789 : "America/Puerto_Rico",
-	790 : "America/Punta_Arenas",
-	791 : "America/Rainy_River",
-	792 : "America/Rankin_Inlet",
-	793 : "America/Recife",
-	794 : "America/Regina",
-	795 : "America/Resolute",
-	796 : "America/Rio_Branco",
-	797 : "America/Santarem",
-	798 : "America/Santiago",
-	799 : "America/Santo_Domingo",
-	800 : "America/Sao_Paulo",
-	801 : "America/Scoresbysund",
-	802 : "America/Sitka",
-	803 : "America/St_Johns",
-	804 : "America/Swift_Current",
-	805 : "America/Tegucigalpa",
-	806 : "America/Thule",
-	807 : "America/Thunder_Bay",
-	808 : "America/Tijuana",
-	809 : "America/Toronto",
-	810 : "America/Vancouver",
-	811 : "America/Whitehorse",
-	812 : "America/Winnipeg",
-	813 : "America/Yakutat",
-	814 : "America/Yellowknife",
-	815 : "Antarctica/Casey",
-	816 : "Antarctica/Davis",
-	817 : "Antarctica/Macquarie",
-	818 : "Antarctica/Mawson",
-	819 : "Antarctica/Palmer",
-	820 : "Antarctica/Rothera",
-	821 : "Antarctica/Troll",
-	822 : "Antarctica/Vostok",
-	823 : "Asia/Almaty",
-	824 : "Asia/Amman",
-	825 : "Asia/Anadyr",
-	826 : "Asia/Aqtau",
-	827 : "Asia/Aqtobe",
-	828 : "Asia/Ashgabat",
-	829 : "Asia/Atyrau",
-	830 : "Asia/Baghdad",
-	831 : "Asia/Baku",
-	832 : "Asia/Bangkok",
-	833 : "Asia/Barnaul",
-	834 : "Asia/Beirut",
-	835 : "Asia/Bishkek",
-	836 : "Asia/Brunei",
-	837 : "Asia/Chita",
-	838 : "Asia/Choibalsan",
-	839 : "Asia/Colombo",
-	840 : "Asia/Damascus",
-	841 : "Asia/Dhaka",
-	842 : "Asia/Dili",
-	843 : "Asia/Dubai",
-	844 : "Asia/Dushanbe",
-	845 : "Asia/Famagusta",
-	846 : "Asia/Gaza",
-	847 : "Asia/Hebron",
-	848 : "Asia/Ho_Chi_Minh",
-	849 : "Asia/Hong_Kong",
-	850 : "Asia/Hovd",
-	851 : "Asia/Irkutsk",
-	852 : "Asia/Jakarta",
-	853 : "Asia/Jayapura",
-	854 : "Asia/Jerusalem",
-	855 : "Asia/Kabul",
-	856 : "Asia/Kamchatka",
-	857 : "Asia/Karachi",
-	858 : "Asia/Kathmandu",
-	859 : "Asia/Khandyga",
-	860 : "Asia/Kolkata",
-	861 : "Asia/Krasnoyarsk",
-	862 : "Asia/Kuala_Lumpur",
-	863 : "Asia/Kuching",
-	864 : "Asia/Macau",
-	865 : "Asia/Magadan",
-	866 : "Asia/Makassar",
-	867 : "Asia/Manila",
-	868 : "Asia/Nicosia",
-	869 : "Asia/Novokuznetsk",
-	870 : "Asia/Novosibirsk",
-	871 : "Asia/Omsk",
-	872 : "Asia/Oral",
-	873 : "Asia/Pontianak",
-	874 : "Asia/Pyongyang",
-	875 : "Asia/Qatar",
-	876 : "Asia/Qostanay",
-	877 : "Asia/Qyzylorda",
-	878 : "Asia/Riyadh",
-	879 : "Asia/Sakhalin",
-	880 : "Asia/Samarkand",
-	881 : "Asia/Seoul",
-	882 : "Asia/Shanghai",
-	883 : "Asia/Singapore",
-	884 : "Asia/Srednekolymsk",
-	885 : "Asia/Taipei",
-	886 : "Asia/Tashkent",
-	887 : "Asia/Tbilisi",
-	888 : "Asia/Tehran",
-	889 : "Asia/Thimphu",
-	890 : "Asia/Tokyo",
-	891 : "Asia/Tomsk",
-	892 : "Asia/Ulaanbaatar",
-	893 : "Asia/Urumqi",
-	894 : "Asia/Ust-Nera",
-	895 : "Asia/Vladivostok",
-	896 : "Asia/Yakutsk",
-	897 : "Asia/Yangon",
-	898 : "Asia/Yekaterinburg",
-	899 : "Asia/Yerevan",
-	900 : "Atlantic/Azores",
-	901 : "Atlantic/Bermuda",
-	902 : "Atlantic/Canary",
-	903 : "Atlantic/Cape_Verde",
-	904 : "Atlantic/Faroe",
-	905 : "Atlantic/Madeira",
-	906 : "Atlantic/Reykjavik",
-	907 : "Atlantic/South_Georgia",
-	908 : "Atlantic/Stanley",
-	909 : "Australia/Adelaide",
-	910 : "Australia/Brisbane",
-	911 : "Australia/Broken_Hill",
-	912 : "Australia/Darwin",
-	913 : "Australia/Eucla",
-	914 : "Australia/Hobart",
-	915 : "Australia/Lindeman",
-	916 : "Australia/Lord_Howe",
-	917 : "Australia/Melbourne",
-	918 : "Australia/Perth",
-	919 : "Australia/Sydney",
-	920 : "Etc/GMT",
-	921 : "Etc/UTC",
-	922 : "Europe/Amsterdam",
-	923 : "Europe/Andorra",
-	924 : "Europe/Astrakhan",
-	925 : "Europe/Athens",
-	926 : "Europe/Belgrade",
-	927 : "Europe/Berlin",
-	928 : "Europe/Brussels",
-	929 : "Europe/Bucharest",
-	930 : "Europe/Budapest",
-	931 : "Europe/Chisinau",
-	932 : "Europe/Copenhagen",
-	933 : "Europe/Dublin",
-	934 : "Europe/Gibraltar",
-	935 : "Europe/Helsinki",
-	936 : "Europe/Istanbul",
-	937 : "Europe/Kaliningrad",
-	938 : "Europe/Kiev",
-	939 : "Europe/Kirov",
-	940 : "Europe/Lisbon",
-	941 : "Europe/London",
-	942 : "Europe/Luxembourg",
-	943 : "Europe/Madrid",
-	944 : "Europe/Malta",
-	945 : "Europe/Minsk",
-	946 : "Europe/Monaco",
-	947 : "Europe/Moscow",
-	948 : "Europe/Oslo",
-	949 : "Europe/Paris",
-	950 : "Europe/Prague",
-	951 : "Europe/Riga",
-	952 : "Europe/Rome",
-	953 : "Europe/Samara",
-	954 : "Europe/Saratov",
-	955 : "Europe/Simferopol",
-	956 : "Europe/Sofia",
-	957 : "Europe/Stockholm",
-	958 : "Europe/Tallinn",
-	959 : "Europe/Tirane",
-	960 : "Europe/Ulyanovsk",
-	961 : "Europe/Uzhgorod",
-	962 : "Europe/Vienna",
-	963 : "Europe/Vilnius",
-	964 : "Europe/Volgograd",
-	965 : "Europe/Warsaw",
-	966 : "Europe/Zaporozhye",
-	967 : "Europe/Zurich",
-	968 : "Indian/Chagos",
-	969 : "Indian/Christmas",
-	970 : "Indian/Cocos",
-	971 : "Indian/Kerguelen",
-	972 : "Indian/Mahe",
-	973 : "Indian/Maldives",
-	974 : "Indian/Mauritius",
-	975 : "Indian/Reunion",
-	976 : "Pacific/Apia",
-	977 : "Pacific/Auckland",
-	978 : "Pacific/Bougainville",
-	979 : "Pacific/Chatham",
-	980 : "Pacific/Chuuk",
-	981 : "Pacific/Easter",
-	982 : "Pacific/Efate",
-	983 : "Pacific/Fakaofo",
-	984 : "Pacific/Fiji",
-	985 : "Pacific/Funafuti",
-	986 : "Pacific/Galapagos",
-	987 : "Pacific/Gambier",
-	988 : "Pacific/Guadalcanal",
-	989 : "Pacific/Guam",
-	990 : "Pacific/Honolulu",
-	991 : "Pacific/Kanton",
-	992 : "Pacific/Kiritimati",
-	993 : "Pacific/Kosrae",
-	994 : "Pacific/Kwajalein",
-	995 : "Pacific/Majuro",
-	996 : "Pacific/Marquesas",
-	997 : "Pacific/Nauru",
-	998 : "Pacific/Niue",
-	999 : "Pacific/Norfolk",
-	1000 : "Pacific/Noumea",
-	1001 : "Pacific/Pago_Pago",
-	1002 : "Pacific/Palau",
-	1003 : "Pacific/Pitcairn",
-	1004 : "Pacific/Pohnpei",
-	1005 : "Pacific/Port_Moresby",
-	1006 : "Pacific/Rarotonga",
-	1007 : "Pacific/Tahiti",
-	1008 : "Pacific/Tarawa",
-	1009 : "Pacific/Tongatapu",
-	1010 : "Pacific/Wake",
-	1011 : "Pacific/Wallis",
+    1: "A",
+    2: "B",
+    3: "C",
+    4: "D",
+    5: "E",
+    6: "F",
+    7: "G",
+    8: "H",
+    9: "I",
+    10: "K",
+    11: "L",
+    12: "M",
+    13: "N",
+    14: "O",
+    15: "P",
+    16: "Q",
+    17: "R",
+    18: "S",
+    19: "T",
+    20: "U",
+    21: "V",
+    22: "W",
+    23: "X",
+    24: "Y",
+    25: "Z",
+    32: "AT",
+    40: "BT",
+    48: "CT",
+    56: "ET",
+    64: "GT",
+    72: "IT",
+    80: "KT",
+    88: "MT",
+    96: "PT",
+    104: "ST",
+    112: "UT",
+    120: "WT",
+    128: "ACT",
+    129: "ADT",
+    130: "AET",
+    131: "AFT",
+    132: "AMT",
+    133: "AoE",
+    134: "ART",
+    135: "AST",
+    136: "AZT",
+    144: "BDT",
+    145: "BNT",
+    146: "BOT",
+    147: "BRT",
+    148: "BST",
+    149: "BTT",
+    152: "CAT",
+    153: "CCT",
+    154: "CDT",
+    155: "CET",
+    156: "CIT",
+    157: "CKT",
+    158: "CLT",
+    159: "COT",
+    160: "CST",
+    161: "CVT",
+    162: "CXT",
+    168: "EAT",
+    169: "ECT",
+    170: "EDT",
+    171: "EET",
+    172: "EGT",
+    173: "EST",
+    176: "FET",
+    177: "FJT",
+    178: "FKT",
+    179: "FNT",
+    184: "GET",
+    185: "GFT",
+    186: "GMT",
+    187: "GST",
+    188: "GYT",
+    192: "HAA",
+    193: "HAC",
+    194: "HAE",
+    195: "HAP",
+    196: "HAR",
+    197: "HAT",
+    198: "HDT",
+    199: "HKT",
+    200: "HLV",
+    201: "HNA",
+    202: "HNC",
+    203: "HNE",
+    204: "HNP",
+    205: "HNR",
+    206: "HNT",
+    207: "HST",
+    208: "ICT",
+    209: "IDT",
+    210: "IOT",
+    211: "IST",
+    216: "JST",
+    224: "KGT",
+    225: "KIT",
+    226: "KST",
+    232: "MCK",
+    233: "MDT",
+    234: "MEZ",
+    235: "MHT",
+    236: "MMT",
+    237: "MSD",
+    238: "MSK",
+    239: "MST",
+    240: "MUT",
+    241: "MVT",
+    242: "MYT",
+    248: "NCT",
+    249: "NDT",
+    250: "NFT",
+    251: "NPT",
+    252: "NRT",
+    253: "NST",
+    254: "NUT",
+    256: "OEZ",
+    264: "PDT",
+    265: "PET",
+    266: "PGT",
+    267: "PHT",
+    268: "PKT",
+    269: "PST",
+    270: "PWT",
+    271: "PYT",
+    272: "RET",
+    280: "SBT",
+    281: "SCT",
+    282: "SGT",
+    283: "SRT",
+    284: "SST",
+    288: "TFT",
+    289: "TJT",
+    290: "TKT",
+    291: "TLT",
+    292: "TMT",
+    293: "TOT",
+    294: "TRT",
+    295: "TVT",
+    296: "UTC",
+    297: "UYT",
+    298: "UZT",
+    304: "VET",
+    305: "VUT",
+    312: "WAT",
+    313: "WDT",
+    314: "WET",
+    315: "WEZ",
+    316: "WFT",
+    317: "WGT",
+    318: "WIB",
+    319: "WIT",
+    320: "WST",
+    328: "ACDT",
+    329: "ACST",
+    330: "ADST",
+    331: "AEDT",
+    332: "AEST",
+    333: "AKDT",
+    334: "AKST",
+    335: "ALMT",
+    336: "AMDT",
+    337: "AMST",
+    338: "ANAT",
+    339: "AQTT",
+    340: "AWDT",
+    341: "AWST",
+    342: "AZOT",
+    343: "AZST",
+    344: "BDST",
+    345: "BRST",
+    352: "CAST",
+    353: "CDST",
+    354: "CEDT",
+    355: "CEST",
+    356: "CHOT",
+    357: "ChST",
+    358: "CHUT",
+    359: "CIST",
+    360: "CLDT",
+    361: "CLST",
+    368: "DAVT",
+    369: "DDUT",
+    376: "EADT",
+    377: "EAST",
+    378: "ECST",
+    379: "EDST",
+    380: "EEDT",
+    381: "EEST",
+    382: "EGST",
+    384: "FJDT",
+    385: "FJST",
+    386: "FKDT",
+    387: "FKST",
+    392: "GALT",
+    393: "GAMT",
+    394: "GILT",
+    400: "HADT",
+    401: "HAST",
+    402: "HOVT",
+    408: "IRDT",
+    409: "IRKT",
+    410: "IRST",
+    416: "KOST",
+    417: "KRAT",
+    418: "KUYT",
+    424: "LHDT",
+    425: "LHST",
+    426: "LINT",
+    432: "MAGT",
+    433: "MART",
+    434: "MAWT",
+    435: "MDST",
+    436: "MESZ",
+    440: "NFDT",
+    441: "NOVT",
+    442: "NZDT",
+    443: "NZST",
+    448: "OESZ",
+    449: "OMST",
+    450: "ORAT",
+    456: "PDST",
+    457: "PETT",
+    458: "PHOT",
+    459: "PMDT",
+    460: "PMST",
+    461: "PONT",
+    462: "PYST",
+    464: "QYZT",
+    472: "ROTT",
+    480: "SAKT",
+    481: "SAMT",
+    482: "SAST",
+    483: "SRET",
+    484: "SYOT",
+    488: "TAHT",
+    489: "TOST",
+    496: "ULAT",
+    497: "UYST",
+    504: "VLAT",
+    505: "VOST",
+    512: "WAKT",
+    513: "WAST",
+    514: "WEDT",
+    515: "WEST",
+    516: "WESZ",
+    517: "WGST",
+    518: "WITA",
+    520: "YAKT",
+    521: "YAPT",
+    522: "YEKT",
+    528: "ACWST",
+    529: "ANAST",
+    530: "AZODT",
+    531: "AZOST",
+    536: "CHADT",
+    537: "CHAST",
+    538: "CHODT",
+    539: "CHOST",
+    540: "CIDST",
+    544: "EASST",
+    545: "EFATE",
+    552: "HOVDT",
+    553: "HOVST",
+    560: "IRKST",
+    568: "KRAST",
+    576: "MAGST",
+    584: "NACDT",
+    585: "NACST",
+    586: "NAEDT",
+    587: "NAEST",
+    588: "NAMDT",
+    589: "NAMST",
+    590: "NAPDT",
+    591: "NAPST",
+    592: "NOVST",
+    600: "OMSST",
+    608: "PETST",
+    616: "SAMST",
+    624: "ULAST",
+    632: "VLAST",
+    640: "WARST",
+    648: "YAKST",
+    649: "YEKST",
+    656: "CHODST",
+    664: "HOVDST",
+    672: "Africa/Abidjan",
+    673: "Africa/Algiers",
+    674: "Africa/Bissau",
+    675: "Africa/Cairo",
+    676: "Africa/Casablanca",
+    677: "Africa/Ceuta",
+    678: "Africa/El_Aaiun",
+    679: "Africa/Johannesburg",
+    680: "Africa/Juba",
+    681: "Africa/Khartoum",
+    682: "Africa/Lagos",
+    683: "Africa/Maputo",
+    684: "Africa/Monrovia",
+    685: "Africa/Nairobi",
+    686: "Africa/Ndjamena",
+    687: "Africa/Sao_Tome",
+    688: "Africa/Tripoli",
+    689: "Africa/Tunis",
+    690: "Africa/Windhoek",
+    691: "America/Adak",
+    692: "America/Anchorage",
+    693: "America/Araguaina",
+    694: "America/Argentina/Buenos_Aires",
+    695: "America/Argentina/Catamarca",
+    696: "America/Argentina/Cordoba",
+    697: "America/Argentina/Jujuy",
+    698: "America/Argentina/La_Rioja",
+    699: "America/Argentina/Mendoza",
+    700: "America/Argentina/Rio_Gallegos",
+    701: "America/Argentina/Salta",
+    702: "America/Argentina/San_Juan",
+    703: "America/Argentina/San_Luis",
+    704: "America/Argentina/Tucuman",
+    705: "America/Argentina/Ushuaia",
+    706: "America/Asuncion",
+    707: "America/Bahia",
+    708: "America/Bahia_Banderas",
+    709: "America/Barbados",
+    710: "America/Belem",
+    711: "America/Belize",
+    712: "America/Boa_Vista",
+    713: "America/Bogota",
+    714: "America/Boise",
+    715: "America/Cambridge_Bay",
+    716: "America/Campo_Grande",
+    717: "America/Cancun",
+    718: "America/Caracas",
+    719: "America/Cayenne",
+    720: "America/Chicago",
+    721: "America/Chihuahua",
+    722: "America/Costa_Rica",
+    723: "America/Cuiaba",
+    724: "America/Danmarkshavn",
+    725: "America/Dawson",
+    726: "America/Dawson_Creek",
+    727: "America/Denver",
+    728: "America/Detroit",
+    729: "America/Edmonton",
+    730: "America/Eirunepe",
+    731: "America/El_Salvador",
+    732: "America/Fort_Nelson",
+    733: "America/Fortaleza",
+    734: "America/Glace_Bay",
+    735: "America/Goose_Bay",
+    736: "America/Grand_Turk",
+    737: "America/Guatemala",
+    738: "America/Guayaquil",
+    739: "America/Guyana",
+    740: "America/Halifax",
+    741: "America/Havana",
+    742: "America/Hermosillo",
+    743: "America/Indiana/Indianapolis",
+    744: "America/Indiana/Knox",
+    745: "America/Indiana/Marengo",
+    746: "America/Indiana/Petersburg",
+    747: "America/Indiana/Tell_City",
+    748: "America/Indiana/Vevay",
+    749: "America/Indiana/Vincennes",
+    750: "America/Indiana/Winamac",
+    751: "America/Inuvik",
+    752: "America/Iqaluit",
+    753: "America/Jamaica",
+    754: "America/Juneau",
+    755: "America/Kentucky/Louisville",
+    756: "America/Kentucky/Monticello",
+    757: "America/La_Paz",
+    758: "America/Lima",
+    759: "America/Los_Angeles",
+    760: "America/Maceio",
+    761: "America/Managua",
+    762: "America/Manaus",
+    763: "America/Martinique",
+    764: "America/Matamoros",
+    765: "America/Mazatlan",
+    766: "America/Menominee",
+    767: "America/Merida",
+    768: "America/Metlakatla",
+    769: "America/Mexico_City",
+    770: "America/Miquelon",
+    771: "America/Moncton",
+    772: "America/Monterrey",
+    773: "America/Montevideo",
+    774: "America/New_York",
+    775: "America/Nipigon",
+    776: "America/Nome",
+    777: "America/Noronha",
+    778: "America/North_Dakota/Beulah",
+    779: "America/North_Dakota/Center",
+    780: "America/North_Dakota/New_Salem",
+    781: "America/Nuuk",
+    782: "America/Ojinaga",
+    783: "America/Panama",
+    784: "America/Pangnirtung",
+    785: "America/Paramaribo",
+    786: "America/Phoenix",
+    787: "America/Port-au-Prince",
+    788: "America/Porto_Velho",
+    789: "America/Puerto_Rico",
+    790: "America/Punta_Arenas",
+    791: "America/Rainy_River",
+    792: "America/Rankin_Inlet",
+    793: "America/Recife",
+    794: "America/Regina",
+    795: "America/Resolute",
+    796: "America/Rio_Branco",
+    797: "America/Santarem",
+    798: "America/Santiago",
+    799: "America/Santo_Domingo",
+    800: "America/Sao_Paulo",
+    801: "America/Scoresbysund",
+    802: "America/Sitka",
+    803: "America/St_Johns",
+    804: "America/Swift_Current",
+    805: "America/Tegucigalpa",
+    806: "America/Thule",
+    807: "America/Thunder_Bay",
+    808: "America/Tijuana",
+    809: "America/Toronto",
+    810: "America/Vancouver",
+    811: "America/Whitehorse",
+    812: "America/Winnipeg",
+    813: "America/Yakutat",
+    814: "America/Yellowknife",
+    815: "Antarctica/Casey",
+    816: "Antarctica/Davis",
+    817: "Antarctica/Macquarie",
+    818: "Antarctica/Mawson",
+    819: "Antarctica/Palmer",
+    820: "Antarctica/Rothera",
+    821: "Antarctica/Troll",
+    822: "Antarctica/Vostok",
+    823: "Asia/Almaty",
+    824: "Asia/Amman",
+    825: "Asia/Anadyr",
+    826: "Asia/Aqtau",
+    827: "Asia/Aqtobe",
+    828: "Asia/Ashgabat",
+    829: "Asia/Atyrau",
+    830: "Asia/Baghdad",
+    831: "Asia/Baku",
+    832: "Asia/Bangkok",
+    833: "Asia/Barnaul",
+    834: "Asia/Beirut",
+    835: "Asia/Bishkek",
+    836: "Asia/Brunei",
+    837: "Asia/Chita",
+    838: "Asia/Choibalsan",
+    839: "Asia/Colombo",
+    840: "Asia/Damascus",
+    841: "Asia/Dhaka",
+    842: "Asia/Dili",
+    843: "Asia/Dubai",
+    844: "Asia/Dushanbe",
+    845: "Asia/Famagusta",
+    846: "Asia/Gaza",
+    847: "Asia/Hebron",
+    848: "Asia/Ho_Chi_Minh",
+    849: "Asia/Hong_Kong",
+    850: "Asia/Hovd",
+    851: "Asia/Irkutsk",
+    852: "Asia/Jakarta",
+    853: "Asia/Jayapura",
+    854: "Asia/Jerusalem",
+    855: "Asia/Kabul",
+    856: "Asia/Kamchatka",
+    857: "Asia/Karachi",
+    858: "Asia/Kathmandu",
+    859: "Asia/Khandyga",
+    860: "Asia/Kolkata",
+    861: "Asia/Krasnoyarsk",
+    862: "Asia/Kuala_Lumpur",
+    863: "Asia/Kuching",
+    864: "Asia/Macau",
+    865: "Asia/Magadan",
+    866: "Asia/Makassar",
+    867: "Asia/Manila",
+    868: "Asia/Nicosia",
+    869: "Asia/Novokuznetsk",
+    870: "Asia/Novosibirsk",
+    871: "Asia/Omsk",
+    872: "Asia/Oral",
+    873: "Asia/Pontianak",
+    874: "Asia/Pyongyang",
+    875: "Asia/Qatar",
+    876: "Asia/Qostanay",
+    877: "Asia/Qyzylorda",
+    878: "Asia/Riyadh",
+    879: "Asia/Sakhalin",
+    880: "Asia/Samarkand",
+    881: "Asia/Seoul",
+    882: "Asia/Shanghai",
+    883: "Asia/Singapore",
+    884: "Asia/Srednekolymsk",
+    885: "Asia/Taipei",
+    886: "Asia/Tashkent",
+    887: "Asia/Tbilisi",
+    888: "Asia/Tehran",
+    889: "Asia/Thimphu",
+    890: "Asia/Tokyo",
+    891: "Asia/Tomsk",
+    892: "Asia/Ulaanbaatar",
+    893: "Asia/Urumqi",
+    894: "Asia/Ust-Nera",
+    895: "Asia/Vladivostok",
+    896: "Asia/Yakutsk",
+    897: "Asia/Yangon",
+    898: "Asia/Yekaterinburg",
+    899: "Asia/Yerevan",
+    900: "Atlantic/Azores",
+    901: "Atlantic/Bermuda",
+    902: "Atlantic/Canary",
+    903: "Atlantic/Cape_Verde",
+    904: "Atlantic/Faroe",
+    905: "Atlantic/Madeira",
+    906: "Atlantic/Reykjavik",
+    907: "Atlantic/South_Georgia",
+    908: "Atlantic/Stanley",
+    909: "Australia/Adelaide",
+    910: "Australia/Brisbane",
+    911: "Australia/Broken_Hill",
+    912: "Australia/Darwin",
+    913: "Australia/Eucla",
+    914: "Australia/Hobart",
+    915: "Australia/Lindeman",
+    916: "Australia/Lord_Howe",
+    917: "Australia/Melbourne",
+    918: "Australia/Perth",
+    919: "Australia/Sydney",
+    920: "Etc/GMT",
+    921: "Etc/UTC",
+    922: "Europe/Amsterdam",
+    923: "Europe/Andorra",
+    924: "Europe/Astrakhan",
+    925: "Europe/Athens",
+    926: "Europe/Belgrade",
+    927: "Europe/Berlin",
+    928: "Europe/Brussels",
+    929: "Europe/Bucharest",
+    930: "Europe/Budapest",
+    931: "Europe/Chisinau",
+    932: "Europe/Copenhagen",
+    933: "Europe/Dublin",
+    934: "Europe/Gibraltar",
+    935: "Europe/Helsinki",
+    936: "Europe/Istanbul",
+    937: "Europe/Kaliningrad",
+    938: "Europe/Kiev",
+    939: "Europe/Kirov",
+    940: "Europe/Lisbon",
+    941: "Europe/London",
+    942: "Europe/Luxembourg",
+    943: "Europe/Madrid",
+    944: "Europe/Malta",
+    945: "Europe/Minsk",
+    946: "Europe/Monaco",
+    947: "Europe/Moscow",
+    948: "Europe/Oslo",
+    949: "Europe/Paris",
+    950: "Europe/Prague",
+    951: "Europe/Riga",
+    952: "Europe/Rome",
+    953: "Europe/Samara",
+    954: "Europe/Saratov",
+    955: "Europe/Simferopol",
+    956: "Europe/Sofia",
+    957: "Europe/Stockholm",
+    958: "Europe/Tallinn",
+    959: "Europe/Tirane",
+    960: "Europe/Ulyanovsk",
+    961: "Europe/Uzhgorod",
+    962: "Europe/Vienna",
+    963: "Europe/Vilnius",
+    964: "Europe/Volgograd",
+    965: "Europe/Warsaw",
+    966: "Europe/Zaporozhye",
+    967: "Europe/Zurich",
+    968: "Indian/Chagos",
+    969: "Indian/Christmas",
+    970: "Indian/Cocos",
+    971: "Indian/Kerguelen",
+    972: "Indian/Mahe",
+    973: "Indian/Maldives",
+    974: "Indian/Mauritius",
+    975: "Indian/Reunion",
+    976: "Pacific/Apia",
+    977: "Pacific/Auckland",
+    978: "Pacific/Bougainville",
+    979: "Pacific/Chatham",
+    980: "Pacific/Chuuk",
+    981: "Pacific/Easter",
+    982: "Pacific/Efate",
+    983: "Pacific/Fakaofo",
+    984: "Pacific/Fiji",
+    985: "Pacific/Funafuti",
+    986: "Pacific/Galapagos",
+    987: "Pacific/Gambier",
+    988: "Pacific/Guadalcanal",
+    989: "Pacific/Guam",
+    990: "Pacific/Honolulu",
+    991: "Pacific/Kanton",
+    992: "Pacific/Kiritimati",
+    993: "Pacific/Kosrae",
+    994: "Pacific/Kwajalein",
+    995: "Pacific/Majuro",
+    996: "Pacific/Marquesas",
+    997: "Pacific/Nauru",
+    998: "Pacific/Niue",
+    999: "Pacific/Norfolk",
+    1000: "Pacific/Noumea",
+    1001: "Pacific/Pago_Pago",
+    1002: "Pacific/Palau",
+    1003: "Pacific/Pitcairn",
+    1004: "Pacific/Pohnpei",
+    1005: "Pacific/Port_Moresby",
+    1006: "Pacific/Rarotonga",
+    1007: "Pacific/Tahiti",
+    1008: "Pacific/Tarawa",
+    1009: "Pacific/Tongatapu",
+    1010: "Pacific/Wake",
+    1011: "Pacific/Wallis",
 }
 
 timezoneToIndex = {
-	"A" : 1,
-	"B" : 2,
-	"C" : 3,
-	"D" : 4,
-	"E" : 5,
-	"F" : 6,
-	"G" : 7,
-	"H" : 8,
-	"I" : 9,
-	"K" : 10,
-	"L" : 11,
-	"M" : 12,
-	"N" : 13,
-	"O" : 14,
-	"P" : 15,
-	"Q" : 16,
-	"R" : 17,
-	"S" : 18,
-	"T" : 19,
-	"U" : 20,
-	"V" : 21,
-	"W" : 22,
-	"X" : 23,
-	"Y" : 24,
-	"Z" : 25,
-	"AT" : 32,
-	"BT" : 40,
-	"CT" : 48,
-	"ET" : 56,
-	"GT" : 64,
-	"IT" : 72,
-	"KT" : 80,
-	"MT" : 88,
-	"PT" : 96,
-	"ST" : 104,
-	"UT" : 112,
-	"WT" : 120,
-	"ACT" : 128,
-	"ADT" : 129,
-	"AET" : 130,
-	"AFT" : 131,
-	"AMT" : 132,
-	"AoE" : 133,
-	"ART" : 134,
-	"AST" : 135,
-	"AZT" : 136,
-	"BDT" : 144,
-	"BNT" : 145,
-	"BOT" : 146,
-	"BRT" : 147,
-	"BST" : 148,
-	"BTT" : 149,
-	"CAT" : 152,
-	"CCT" : 153,
-	"CDT" : 154,
-	"CET" : 155,
-	"CIT" : 156,
-	"CKT" : 157,
-	"CLT" : 158,
-	"COT" : 159,
-	"CST" : 160,
-	"CVT" : 161,
-	"CXT" : 162,
-	"EAT" : 168,
-	"ECT" : 169,
-	"EDT" : 170,
-	"EET" : 171,
-	"EGT" : 172,
-	"EST" : 173,
-	"FET" : 176,
-	"FJT" : 177,
-	"FKT" : 178,
-	"FNT" : 179,
-	"GET" : 184,
-	"GFT" : 185,
-	"GMT" : 186,
-	"GST" : 187,
-	"GYT" : 188,
-	"HAA" : 192,
-	"HAC" : 193,
-	"HAE" : 194,
-	"HAP" : 195,
-	"HAR" : 196,
-	"HAT" : 197,
-	"HDT" : 198,
-	"HKT" : 199,
-	"HLV" : 200,
-	"HNA" : 201,
-	"HNC" : 202,
-	"HNE" : 203,
-	"HNP" : 204,
-	"HNR" : 205,
-	"HNT" : 206,
-	"HST" : 207,
-	"ICT" : 208,
-	"IDT" : 209,
-	"IOT" : 210,
-	"IST" : 211,
-	"JST" : 216,
-	"KGT" : 224,
-	"KIT" : 225,
-	"KST" : 226,
-	"MCK" : 232,
-	"MDT" : 233,
-	"MEZ" : 234,
-	"MHT" : 235,
-	"MMT" : 236,
-	"MSD" : 237,
-	"MSK" : 238,
-	"MST" : 239,
-	"MUT" : 240,
-	"MVT" : 241,
-	"MYT" : 242,
-	"NCT" : 248,
-	"NDT" : 249,
-	"NFT" : 250,
-	"NPT" : 251,
-	"NRT" : 252,
-	"NST" : 253,
-	"NUT" : 254,
-	"OEZ" : 256,
-	"PDT" : 264,
-	"PET" : 265,
-	"PGT" : 266,
-	"PHT" : 267,
-	"PKT" : 268,
-	"PST" : 269,
-	"PWT" : 270,
-	"PYT" : 271,
-	"RET" : 272,
-	"SBT" : 280,
-	"SCT" : 281,
-	"SGT" : 282,
-	"SRT" : 283,
-	"SST" : 284,
-	"TFT" : 288,
-	"TJT" : 289,
-	"TKT" : 290,
-	"TLT" : 291,
-	"TMT" : 292,
-	"TOT" : 293,
-	"TRT" : 294,
-	"TVT" : 295,
-	"UTC" : 296,
-	"UYT" : 297,
-	"UZT" : 298,
-	"VET" : 304,
-	"VUT" : 305,
-	"WAT" : 312,
-	"WDT" : 313,
-	"WET" : 314,
-	"WEZ" : 315,
-	"WFT" : 316,
-	"WGT" : 317,
-	"WIB" : 318,
-	"WIT" : 319,
-	"WST" : 320,
-	"ACDT" : 328,
-	"ACST" : 329,
-	"ADST" : 330,
-	"AEDT" : 331,
-	"AEST" : 332,
-	"AKDT" : 333,
-	"AKST" : 334,
-	"ALMT" : 335,
-	"AMDT" : 336,
-	"AMST" : 337,
-	"ANAT" : 338,
-	"AQTT" : 339,
-	"AWDT" : 340,
-	"AWST" : 341,
-	"AZOT" : 342,
-	"AZST" : 343,
-	"BDST" : 344,
-	"BRST" : 345,
-	"CAST" : 352,
-	"CDST" : 353,
-	"CEDT" : 354,
-	"CEST" : 355,
-	"CHOT" : 356,
-	"ChST" : 357,
-	"CHUT" : 358,
-	"CIST" : 359,
-	"CLDT" : 360,
-	"CLST" : 361,
-	"DAVT" : 368,
-	"DDUT" : 369,
-	"EADT" : 376,
-	"EAST" : 377,
-	"ECST" : 378,
-	"EDST" : 379,
-	"EEDT" : 380,
-	"EEST" : 381,
-	"EGST" : 382,
-	"FJDT" : 384,
-	"FJST" : 385,
-	"FKDT" : 386,
-	"FKST" : 387,
-	"GALT" : 392,
-	"GAMT" : 393,
-	"GILT" : 394,
-	"HADT" : 400,
-	"HAST" : 401,
-	"HOVT" : 402,
-	"IRDT" : 408,
-	"IRKT" : 409,
-	"IRST" : 410,
-	"KOST" : 416,
-	"KRAT" : 417,
-	"KUYT" : 418,
-	"LHDT" : 424,
-	"LHST" : 425,
-	"LINT" : 426,
-	"MAGT" : 432,
-	"MART" : 433,
-	"MAWT" : 434,
-	"MDST" : 435,
-	"MESZ" : 436,
-	"NFDT" : 440,
-	"NOVT" : 441,
-	"NZDT" : 442,
-	"NZST" : 443,
-	"OESZ" : 448,
-	"OMST" : 449,
-	"ORAT" : 450,
-	"PDST" : 456,
-	"PETT" : 457,
-	"PHOT" : 458,
-	"PMDT" : 459,
-	"PMST" : 460,
-	"PONT" : 461,
-	"PYST" : 462,
-	"QYZT" : 464,
-	"ROTT" : 472,
-	"SAKT" : 480,
-	"SAMT" : 481,
-	"SAST" : 482,
-	"SRET" : 483,
-	"SYOT" : 484,
-	"TAHT" : 488,
-	"TOST" : 489,
-	"ULAT" : 496,
-	"UYST" : 497,
-	"VLAT" : 504,
-	"VOST" : 505,
-	"WAKT" : 512,
-	"WAST" : 513,
-	"WEDT" : 514,
-	"WEST" : 515,
-	"WESZ" : 516,
-	"WGST" : 517,
-	"WITA" : 518,
-	"YAKT" : 520,
-	"YAPT" : 521,
-	"YEKT" : 522,
-	"ACWST" : 528,
-	"ANAST" : 529,
-	"AZODT" : 530,
-	"AZOST" : 531,
-	"CHADT" : 536,
-	"CHAST" : 537,
-	"CHODT" : 538,
-	"CHOST" : 539,
-	"CIDST" : 540,
-	"EASST" : 544,
-	"EFATE" : 545,
-	"HOVDT" : 552,
-	"HOVST" : 553,
-	"IRKST" : 560,
-	"KRAST" : 568,
-	"MAGST" : 576,
-	"NACDT" : 584,
-	"NACST" : 585,
-	"NAEDT" : 586,
-	"NAEST" : 587,
-	"NAMDT" : 588,
-	"NAMST" : 589,
-	"NAPDT" : 590,
-	"NAPST" : 591,
-	"NOVST" : 592,
-	"OMSST" : 600,
-	"PETST" : 608,
-	"SAMST" : 616,
-	"ULAST" : 624,
-	"VLAST" : 632,
-	"WARST" : 640,
-	"YAKST" : 648,
-	"YEKST" : 649,
-	"CHODST" : 656,
-	"HOVDST" : 664,
-	"Africa/Abidjan" : 672,
-	"Africa/Algiers" : 673,
-	"Africa/Bissau" : 674,
-	"Africa/Cairo" : 675,
-	"Africa/Casablanca" : 676,
-	"Africa/Ceuta" : 677,
-	"Africa/El_Aaiun" : 678,
-	"Africa/Johannesburg" : 679,
-	"Africa/Juba" : 680,
-	"Africa/Khartoum" : 681,
-	"Africa/Lagos" : 682,
-	"Africa/Maputo" : 683,
-	"Africa/Monrovia" : 684,
-	"Africa/Nairobi" : 685,
-	"Africa/Ndjamena" : 686,
-	"Africa/Sao_Tome" : 687,
-	"Africa/Tripoli" : 688,
-	"Africa/Tunis" : 689,
-	"Africa/Windhoek" : 690,
-	"America/Adak" : 691,
-	"America/Anchorage" : 692,
-	"America/Araguaina" : 693,
-	"America/Argentina/Buenos_Aires" : 694,
-	"America/Argentina/Catamarca" : 695,
-	"America/Argentina/Cordoba" : 696,
-	"America/Argentina/Jujuy" : 697,
-	"America/Argentina/La_Rioja" : 698,
-	"America/Argentina/Mendoza" : 699,
-	"America/Argentina/Rio_Gallegos" : 700,
-	"America/Argentina/Salta" : 701,
-	"America/Argentina/San_Juan" : 702,
-	"America/Argentina/San_Luis" : 703,
-	"America/Argentina/Tucuman" : 704,
-	"America/Argentina/Ushuaia" : 705,
-	"America/Asuncion" : 706,
-	"America/Bahia" : 707,
-	"America/Bahia_Banderas" : 708,
-	"America/Barbados" : 709,
-	"America/Belem" : 710,
-	"America/Belize" : 711,
-	"America/Boa_Vista" : 712,
-	"America/Bogota" : 713,
-	"America/Boise" : 714,
-	"America/Cambridge_Bay" : 715,
-	"America/Campo_Grande" : 716,
-	"America/Cancun" : 717,
-	"America/Caracas" : 718,
-	"America/Cayenne" : 719,
-	"America/Chicago" : 720,
-	"America/Chihuahua" : 721,
-	"America/Costa_Rica" : 722,
-	"America/Cuiaba" : 723,
-	"America/Danmarkshavn" : 724,
-	"America/Dawson" : 725,
-	"America/Dawson_Creek" : 726,
-	"America/Denver" : 727,
-	"America/Detroit" : 728,
-	"America/Edmonton" : 729,
-	"America/Eirunepe" : 730,
-	"America/El_Salvador" : 731,
-	"America/Fort_Nelson" : 732,
-	"America/Fortaleza" : 733,
-	"America/Glace_Bay" : 734,
-	"America/Goose_Bay" : 735,
-	"America/Grand_Turk" : 736,
-	"America/Guatemala" : 737,
-	"America/Guayaquil" : 738,
-	"America/Guyana" : 739,
-	"America/Halifax" : 740,
-	"America/Havana" : 741,
-	"America/Hermosillo" : 742,
-	"America/Indiana/Indianapolis" : 743,
-	"America/Indiana/Knox" : 744,
-	"America/Indiana/Marengo" : 745,
-	"America/Indiana/Petersburg" : 746,
-	"America/Indiana/Tell_City" : 747,
-	"America/Indiana/Vevay" : 748,
-	"America/Indiana/Vincennes" : 749,
-	"America/Indiana/Winamac" : 750,
-	"America/Inuvik" : 751,
-	"America/Iqaluit" : 752,
-	"America/Jamaica" : 753,
-	"America/Juneau" : 754,
-	"America/Kentucky/Louisville" : 755,
-	"America/Kentucky/Monticello" : 756,
-	"America/La_Paz" : 757,
-	"America/Lima" : 758,
-	"America/Los_Angeles" : 759,
-	"America/Maceio" : 760,
-	"America/Managua" : 761,
-	"America/Manaus" : 762,
-	"America/Martinique" : 763,
-	"America/Matamoros" : 764,
-	"America/Mazatlan" : 765,
-	"America/Menominee" : 766,
-	"America/Merida" : 767,
-	"America/Metlakatla" : 768,
-	"America/Mexico_City" : 769,
-	"America/Miquelon" : 770,
-	"America/Moncton" : 771,
-	"America/Monterrey" : 772,
-	"America/Montevideo" : 773,
-	"America/New_York" : 774,
-	"America/Nipigon" : 775,
-	"America/Nome" : 776,
-	"America/Noronha" : 777,
-	"America/North_Dakota/Beulah" : 778,
-	"America/North_Dakota/Center" : 779,
-	"America/North_Dakota/New_Salem" : 780,
-	"America/Nuuk" : 781,
-	"America/Ojinaga" : 782,
-	"America/Panama" : 783,
-	"America/Pangnirtung" : 784,
-	"America/Paramaribo" : 785,
-	"America/Phoenix" : 786,
-	"America/Port-au-Prince" : 787,
-	"America/Porto_Velho" : 788,
-	"America/Puerto_Rico" : 789,
-	"America/Punta_Arenas" : 790,
-	"America/Rainy_River" : 791,
-	"America/Rankin_Inlet" : 792,
-	"America/Recife" : 793,
-	"America/Regina" : 794,
-	"America/Resolute" : 795,
-	"America/Rio_Branco" : 796,
-	"America/Santarem" : 797,
-	"America/Santiago" : 798,
-	"America/Santo_Domingo" : 799,
-	"America/Sao_Paulo" : 800,
-	"America/Scoresbysund" : 801,
-	"America/Sitka" : 802,
-	"America/St_Johns" : 803,
-	"America/Swift_Current" : 804,
-	"America/Tegucigalpa" : 805,
-	"America/Thule" : 806,
-	"America/Thunder_Bay" : 807,
-	"America/Tijuana" : 808,
-	"America/Toronto" : 809,
-	"America/Vancouver" : 810,
-	"America/Whitehorse" : 811,
-	"America/Winnipeg" : 812,
-	"America/Yakutat" : 813,
-	"America/Yellowknife" : 814,
-	"Antarctica/Casey" : 815,
-	"Antarctica/Davis" : 816,
-	"Antarctica/Macquarie" : 817,
-	"Antarctica/Mawson" : 818,
-	"Antarctica/Palmer" : 819,
-	"Antarctica/Rothera" : 820,
-	"Antarctica/Troll" : 821,
-	"Antarctica/Vostok" : 822,
-	"Asia/Almaty" : 823,
-	"Asia/Amman" : 824,
-	"Asia/Anadyr" : 825,
-	"Asia/Aqtau" : 826,
-	"Asia/Aqtobe" : 827,
-	"Asia/Ashgabat" : 828,
-	"Asia/Atyrau" : 829,
-	"Asia/Baghdad" : 830,
-	"Asia/Baku" : 831,
-	"Asia/Bangkok" : 832,
-	"Asia/Barnaul" : 833,
-	"Asia/Beirut" : 834,
-	"Asia/Bishkek" : 835,
-	"Asia/Brunei" : 836,
-	"Asia/Chita" : 837,
-	"Asia/Choibalsan" : 838,
-	"Asia/Colombo" : 839,
-	"Asia/Damascus" : 840,
-	"Asia/Dhaka" : 841,
-	"Asia/Dili" : 842,
-	"Asia/Dubai" : 843,
-	"Asia/Dushanbe" : 844,
-	"Asia/Famagusta" : 845,
-	"Asia/Gaza" : 846,
-	"Asia/Hebron" : 847,
-	"Asia/Ho_Chi_Minh" : 848,
-	"Asia/Hong_Kong" : 849,
-	"Asia/Hovd" : 850,
-	"Asia/Irkutsk" : 851,
-	"Asia/Jakarta" : 852,
-	"Asia/Jayapura" : 853,
-	"Asia/Jerusalem" : 854,
-	"Asia/Kabul" : 855,
-	"Asia/Kamchatka" : 856,
-	"Asia/Karachi" : 857,
-	"Asia/Kathmandu" : 858,
-	"Asia/Khandyga" : 859,
-	"Asia/Kolkata" : 860,
-	"Asia/Krasnoyarsk" : 861,
-	"Asia/Kuala_Lumpur" : 862,
-	"Asia/Kuching" : 863,
-	"Asia/Macau" : 864,
-	"Asia/Magadan" : 865,
-	"Asia/Makassar" : 866,
-	"Asia/Manila" : 867,
-	"Asia/Nicosia" : 868,
-	"Asia/Novokuznetsk" : 869,
-	"Asia/Novosibirsk" : 870,
-	"Asia/Omsk" : 871,
-	"Asia/Oral" : 872,
-	"Asia/Pontianak" : 873,
-	"Asia/Pyongyang" : 874,
-	"Asia/Qatar" : 875,
-	"Asia/Qostanay" : 876,
-	"Asia/Qyzylorda" : 877,
-	"Asia/Riyadh" : 878,
-	"Asia/Sakhalin" : 879,
-	"Asia/Samarkand" : 880,
-	"Asia/Seoul" : 881,
-	"Asia/Shanghai" : 882,
-	"Asia/Singapore" : 883,
-	"Asia/Srednekolymsk" : 884,
-	"Asia/Taipei" : 885,
-	"Asia/Tashkent" : 886,
-	"Asia/Tbilisi" : 887,
-	"Asia/Tehran" : 888,
-	"Asia/Thimphu" : 889,
-	"Asia/Tokyo" : 890,
-	"Asia/Tomsk" : 891,
-	"Asia/Ulaanbaatar" : 892,
-	"Asia/Urumqi" : 893,
-	"Asia/Ust-Nera" : 894,
-	"Asia/Vladivostok" : 895,
-	"Asia/Yakutsk" : 896,
-	"Asia/Yangon" : 897,
-	"Asia/Yekaterinburg" : 898,
-	"Asia/Yerevan" : 899,
-	"Atlantic/Azores" : 900,
-	"Atlantic/Bermuda" : 901,
-	"Atlantic/Canary" : 902,
-	"Atlantic/Cape_Verde" : 903,
-	"Atlantic/Faroe" : 904,
-	"Atlantic/Madeira" : 905,
-	"Atlantic/Reykjavik" : 906,
-	"Atlantic/South_Georgia" : 907,
-	"Atlantic/Stanley" : 908,
-	"Australia/Adelaide" : 909,
-	"Australia/Brisbane" : 910,
-	"Australia/Broken_Hill" : 911,
-	"Australia/Darwin" : 912,
-	"Australia/Eucla" : 913,
-	"Australia/Hobart" : 914,
-	"Australia/Lindeman" : 915,
-	"Australia/Lord_Howe" : 916,
-	"Australia/Melbourne" : 917,
-	"Australia/Perth" : 918,
-	"Australia/Sydney" : 919,
-	"Etc/GMT" : 920,
-	"Etc/UTC" : 921,
-	"Europe/Amsterdam" : 922,
-	"Europe/Andorra" : 923,
-	"Europe/Astrakhan" : 924,
-	"Europe/Athens" : 925,
-	"Europe/Belgrade" : 926,
-	"Europe/Berlin" : 927,
-	"Europe/Brussels" : 928,
-	"Europe/Bucharest" : 929,
-	"Europe/Budapest" : 930,
-	"Europe/Chisinau" : 931,
-	"Europe/Copenhagen" : 932,
-	"Europe/Dublin" : 933,
-	"Europe/Gibraltar" : 934,
-	"Europe/Helsinki" : 935,
-	"Europe/Istanbul" : 936,
-	"Europe/Kaliningrad" : 937,
-	"Europe/Kiev" : 938,
-	"Europe/Kirov" : 939,
-	"Europe/Lisbon" : 940,
-	"Europe/London" : 941,
-	"Europe/Luxembourg" : 942,
-	"Europe/Madrid" : 943,
-	"Europe/Malta" : 944,
-	"Europe/Minsk" : 945,
-	"Europe/Monaco" : 946,
-	"Europe/Moscow" : 947,
-	"Europe/Oslo" : 948,
-	"Europe/Paris" : 949,
-	"Europe/Prague" : 950,
-	"Europe/Riga" : 951,
-	"Europe/Rome" : 952,
-	"Europe/Samara" : 953,
-	"Europe/Saratov" : 954,
-	"Europe/Simferopol" : 955,
-	"Europe/Sofia" : 956,
-	"Europe/Stockholm" : 957,
-	"Europe/Tallinn" : 958,
-	"Europe/Tirane" : 959,
-	"Europe/Ulyanovsk" : 960,
-	"Europe/Uzhgorod" : 961,
-	"Europe/Vienna" : 962,
-	"Europe/Vilnius" : 963,
-	"Europe/Volgograd" : 964,
-	"Europe/Warsaw" : 965,
-	"Europe/Zaporozhye" : 966,
-	"Europe/Zurich" : 967,
-	"Indian/Chagos" : 968,
-	"Indian/Christmas" : 969,
-	"Indian/Cocos" : 970,
-	"Indian/Kerguelen" : 971,
-	"Indian/Mahe" : 972,
-	"Indian/Maldives" : 973,
-	"Indian/Mauritius" : 974,
-	"Indian/Reunion" : 975,
-	"Pacific/Apia" : 976,
-	"Pacific/Auckland" : 977,
-	"Pacific/Bougainville" : 978,
-	"Pacific/Chatham" : 979,
-	"Pacific/Chuuk" : 980,
-	"Pacific/Easter" : 981,
-	"Pacific/Efate" : 982,
-	"Pacific/Fakaofo" : 983,
-	"Pacific/Fiji" : 984,
-	"Pacific/Funafuti" : 985,
-	"Pacific/Galapagos" : 986,
-	"Pacific/Gambier" : 987,
-	"Pacific/Guadalcanal" : 988,
-	"Pacific/Guam" : 989,
-	"Pacific/Honolulu" : 990,
-	"Pacific/Kanton" : 991,
-	"Pacific/Kiritimati" : 992,
-	"Pacific/Kosrae" : 993,
-	"Pacific/Kwajalein" : 994,
-	"Pacific/Majuro" : 995,
-	"Pacific/Marquesas" : 996,
-	"Pacific/Nauru" : 997,
-	"Pacific/Niue" : 998,
-	"Pacific/Norfolk" : 999,
-	"Pacific/Noumea" : 1000,
-	"Pacific/Pago_Pago" : 1001,
-	"Pacific/Palau" : 1002,
-	"Pacific/Pitcairn" : 1003,
-	"Pacific/Pohnpei" : 1004,
-	"Pacific/Port_Moresby" : 1005,
-	"Pacific/Rarotonga" : 1006,
-	"Pacific/Tahiti" : 1007,
-	"Pacific/Tarawa" : 1008,
-	"Pacific/Tongatapu" : 1009,
-	"Pacific/Wake" : 1010,
-	"Pacific/Wallis" : 1011,
-	"Africa/Accra" : 672,
-	"Africa/Addis_Ababa" : 685,
-	"Africa/Asmara" : 685,
-	"Africa/Asmera" : 685,
-	"Africa/Bamako" : 672,
-	"Africa/Bangui" : 682,
-	"Africa/Banjul" : 672,
-	"Africa/Blantyre" : 683,
-	"Africa/Brazzaville" : 682,
-	"Africa/Bujumbura" : 683,
-	"Africa/Conakry" : 672,
-	"Africa/Dakar" : 672,
-	"Africa/Dar_es_Salaam" : 685,
-	"Africa/Djibouti" : 685,
-	"Africa/Douala" : 682,
-	"Africa/Freetown" : 672,
-	"Africa/Gaborone" : 683,
-	"Africa/Harare" : 683,
-	"Africa/Kampala" : 685,
-	"Africa/Kigali" : 683,
-	"Africa/Kinshasa" : 682,
-	"Africa/Libreville" : 682,
-	"Africa/Lome" : 672,
-	"Africa/Luanda" : 682,
-	"Africa/Lubumbashi" : 683,
-	"Africa/Lusaka" : 683,
-	"Africa/Malabo" : 682,
-	"Africa/Maseru" : 679,
-	"Africa/Mbabane" : 679,
-	"Africa/Mogadishu" : 685,
-	"Africa/Niamey" : 682,
-	"Africa/Nouakchott" : 672,
-	"Africa/Ouagadougou" : 672,
-	"Africa/Porto-Novo" : 682,
-	"Africa/Timbuktu" : 672,
-	"America/Anguilla" : 789,
-	"America/Antigua" : 789,
-	"America/Argentina/ComodRivadavia" : 695,
-	"America/Aruba" : 789,
-	"America/Atikokan" : 783,
-	"America/Atka" : 691,
-	"America/Blanc-Sablon" : 789,
-	"America/Buenos_Aires" : 694,
-	"America/Catamarca" : 695,
-	"America/Cayman" : 783,
-	"America/Coral_Harbour" : 783,
-	"America/Cordoba" : 696,
-	"America/Creston" : 786,
-	"America/Curacao" : 789,
-	"America/Dominica" : 789,
-	"America/Ensenada" : 808,
-	"America/Fort_Wayne" : 743,
-	"America/Godthab" : 781,
-	"America/Grenada" : 789,
-	"America/Guadeloupe" : 789,
-	"America/Indianapolis" : 743,
-	"America/Jujuy" : 697,
-	"America/Knox_IN" : 744,
-	"America/Kralendijk" : 789,
-	"America/Louisville" : 755,
-	"America/Lower_Princes" : 789,
-	"America/Marigot" : 789,
-	"America/Mendoza" : 699,
-	"America/Montreal" : 809,
-	"America/Montserrat" : 789,
-	"America/Nassau" : 809,
-	"America/Port_of_Spain" : 789,
-	"America/Porto_Acre" : 796,
-	"America/Rosario" : 696,
-	"America/Santa_Isabel" : 808,
-	"America/Shiprock" : 727,
-	"America/St_Barthelemy" : 789,
-	"America/St_Kitts" : 789,
-	"America/St_Lucia" : 789,
-	"America/St_Thomas" : 789,
-	"America/St_Vincent" : 789,
-	"America/Tortola" : 789,
-	"America/Virgin" : 789,
-	"Antarctica/DumontDUrville" : 1005,
-	"Antarctica/McMurdo" : 977,
-	"Antarctica/South_Pole" : 977,
-	"Antarctica/Syowa" : 878,
-	"Arctic/Longyearbyen" : 948,
-	"Asia/Aden" : 878,
-	"Asia/Ashkhabad" : 828,
-	"Asia/Bahrain" : 875,
-	"Asia/Calcutta" : 860,
-	"Asia/Chongqing" : 882,
-	"Asia/Chungking" : 882,
-	"Asia/Dacca" : 841,
-	"Asia/Harbin" : 882,
-	"Asia/Istanbul" : 936,
-	"Asia/Kashgar" : 893,
-	"Asia/Katmandu" : 858,
-	"Asia/Kuwait" : 878,
-	"Asia/Macao" : 864,
-	"Asia/Muscat" : 843,
-	"Asia/Phnom_Penh" : 832,
-	"Asia/Rangoon" : 897,
-	"Asia/Saigon" : 848,
-	"Asia/Tel_Aviv" : 854,
-	"Asia/Thimbu" : 889,
-	"Asia/Ujung_Pandang" : 866,
-	"Asia/Ulan_Bator" : 892,
-	"Asia/Vientiane" : 832,
-	"Atlantic/Faeroe" : 904,
-	"Atlantic/Jan_Mayen" : 948,
-	"Atlantic/St_Helena" : 672,
-	"Australia/ACT" : 919,
-	"Australia/Canberra" : 919,
-	"Australia/Currie" : 914,
-	"Australia/LHI" : 916,
-	"Australia/NSW" : 919,
-	"Australia/North" : 912,
-	"Australia/Queensland" : 910,
-	"Australia/South" : 909,
-	"Australia/Tasmania" : 914,
-	"Australia/Victoria" : 917,
-	"Australia/West" : 918,
-	"Australia/Yancowinna" : 911,
-	"Brazil/Acre" : 796,
-	"Brazil/DeNoronha" : 777,
-	"Brazil/East" : 800,
-	"Brazil/West" : 762,
-	"Canada/Atlantic" : 740,
-	"Canada/Central" : 812,
-	"Canada/Eastern" : 809,
-	"Canada/Mountain" : 729,
-	"Canada/Newfoundland" : 803,
-	"Canada/Pacific" : 810,
-	"Canada/Saskatchewan" : 794,
-	"Canada/Yukon" : 811,
-	"Chile/Continental" : 798,
-	"Chile/EasterIsland" : 981,
-	"Cuba" : 741,
-	"Egypt" : 675,
-	"Eire" : 933,
-	"Etc/GMT+0" : 920,
-	"Etc/GMT-0" : 920,
-	"Etc/GMT0" : 920,
-	"Etc/Greenwich" : 920,
-	"Etc/UCT" : 921,
-	"Etc/Universal" : 921,
-	"Etc/Zulu" : 921,
-	"Europe/Belfast" : 941,
-	"Europe/Bratislava" : 950,
-	"Europe/Busingen" : 967,
-	"Europe/Guernsey" : 941,
-	"Europe/Isle_of_Man" : 941,
-	"Europe/Jersey" : 941,
-	"Europe/Ljubljana" : 926,
-	"Europe/Mariehamn" : 935,
-	"Europe/Nicosia" : 868,
-	"Europe/Podgorica" : 926,
-	"Europe/San_Marino" : 952,
-	"Europe/Sarajevo" : 926,
-	"Europe/Skopje" : 926,
-	"Europe/Tiraspol" : 931,
-	"Europe/Vaduz" : 967,
-	"Europe/Vatican" : 952,
-	"Europe/Zagreb" : 926,
-	"GB" : 941,
-	"GB-Eire" : 941,
-	"GMT+0" : 920,
-	"GMT-0" : 920,
-	"GMT0" : 920,
-	"Greenwich" : 920,
-	"Hongkong" : 849,
-	"Iceland" : 906,
-	"Indian/Antananarivo" : 685,
-	"Indian/Comoro" : 685,
-	"Indian/Mayotte" : 685,
-	"Iran" : 888,
-	"Israel" : 854,
-	"Jamaica" : 753,
-	"Japan" : 890,
-	"Kwajalein" : 994,
-	"Libya" : 688,
-	"Mexico/BajaNorte" : 808,
-	"Mexico/BajaSur" : 765,
-	"Mexico/General" : 769,
-	"NZ" : 977,
-	"NZ-CHAT" : 979,
-	"Navajo" : 727,
-	"PRC" : 882,
-	"Pacific/Enderbury" : 991,
-	"Pacific/Johnston" : 990,
-	"Pacific/Midway" : 1001,
-	"Pacific/Ponape" : 1004,
-	"Pacific/Saipan" : 989,
-	"Pacific/Samoa" : 1001,
-	"Pacific/Truk" : 980,
-	"Pacific/Yap" : 980,
-	"Poland" : 965,
-	"Portugal" : 940,
-	"ROC" : 885,
-	"ROK" : 881,
-	"Singapore" : 883,
-	"Turkey" : 936,
-	"UCT" : 921,
-	"US/Alaska" : 692,
-	"US/Aleutian" : 691,
-	"US/Arizona" : 786,
-	"US/Central" : 720,
-	"US/East-Indiana" : 743,
-	"US/Eastern" : 774,
-	"US/Hawaii" : 990,
-	"US/Indiana-Starke" : 744,
-	"US/Michigan" : 728,
-	"US/Mountain" : 727,
-	"US/Pacific" : 759,
-	"US/Samoa" : 1001,
-	"Universal" : 921,
-	"W-SU" : 947,
-	"Zulu" : 921,
+    "A": 1,
+    "B": 2,
+    "C": 3,
+    "D": 4,
+    "E": 5,
+    "F": 6,
+    "G": 7,
+    "H": 8,
+    "I": 9,
+    "K": 10,
+    "L": 11,
+    "M": 12,
+    "N": 13,
+    "O": 14,
+    "P": 15,
+    "Q": 16,
+    "R": 17,
+    "S": 18,
+    "T": 19,
+    "U": 20,
+    "V": 21,
+    "W": 22,
+    "X": 23,
+    "Y": 24,
+    "Z": 25,
+    "AT": 32,
+    "BT": 40,
+    "CT": 48,
+    "ET": 56,
+    "GT": 64,
+    "IT": 72,
+    "KT": 80,
+    "MT": 88,
+    "PT": 96,
+    "ST": 104,
+    "UT": 112,
+    "WT": 120,
+    "ACT": 128,
+    "ADT": 129,
+    "AET": 130,
+    "AFT": 131,
+    "AMT": 132,
+    "AoE": 133,
+    "ART": 134,
+    "AST": 135,
+    "AZT": 136,
+    "BDT": 144,
+    "BNT": 145,
+    "BOT": 146,
+    "BRT": 147,
+    "BST": 148,
+    "BTT": 149,
+    "CAT": 152,
+    "CCT": 153,
+    "CDT": 154,
+    "CET": 155,
+    "CIT": 156,
+    "CKT": 157,
+    "CLT": 158,
+    "COT": 159,
+    "CST": 160,
+    "CVT": 161,
+    "CXT": 162,
+    "EAT": 168,
+    "ECT": 169,
+    "EDT": 170,
+    "EET": 171,
+    "EGT": 172,
+    "EST": 173,
+    "FET": 176,
+    "FJT": 177,
+    "FKT": 178,
+    "FNT": 179,
+    "GET": 184,
+    "GFT": 185,
+    "GMT": 186,
+    "GST": 187,
+    "GYT": 188,
+    "HAA": 192,
+    "HAC": 193,
+    "HAE": 194,
+    "HAP": 195,
+    "HAR": 196,
+    "HAT": 197,
+    "HDT": 198,
+    "HKT": 199,
+    "HLV": 200,
+    "HNA": 201,
+    "HNC": 202,
+    "HNE": 203,
+    "HNP": 204,
+    "HNR": 205,
+    "HNT": 206,
+    "HST": 207,
+    "ICT": 208,
+    "IDT": 209,
+    "IOT": 210,
+    "IST": 211,
+    "JST": 216,
+    "KGT": 224,
+    "KIT": 225,
+    "KST": 226,
+    "MCK": 232,
+    "MDT": 233,
+    "MEZ": 234,
+    "MHT": 235,
+    "MMT": 236,
+    "MSD": 237,
+    "MSK": 238,
+    "MST": 239,
+    "MUT": 240,
+    "MVT": 241,
+    "MYT": 242,
+    "NCT": 248,
+    "NDT": 249,
+    "NFT": 250,
+    "NPT": 251,
+    "NRT": 252,
+    "NST": 253,
+    "NUT": 254,
+    "OEZ": 256,
+    "PDT": 264,
+    "PET": 265,
+    "PGT": 266,
+    "PHT": 267,
+    "PKT": 268,
+    "PST": 269,
+    "PWT": 270,
+    "PYT": 271,
+    "RET": 272,
+    "SBT": 280,
+    "SCT": 281,
+    "SGT": 282,
+    "SRT": 283,
+    "SST": 284,
+    "TFT": 288,
+    "TJT": 289,
+    "TKT": 290,
+    "TLT": 291,
+    "TMT": 292,
+    "TOT": 293,
+    "TRT": 294,
+    "TVT": 295,
+    "UTC": 296,
+    "UYT": 297,
+    "UZT": 298,
+    "VET": 304,
+    "VUT": 305,
+    "WAT": 312,
+    "WDT": 313,
+    "WET": 314,
+    "WEZ": 315,
+    "WFT": 316,
+    "WGT": 317,
+    "WIB": 318,
+    "WIT": 319,
+    "WST": 320,
+    "ACDT": 328,
+    "ACST": 329,
+    "ADST": 330,
+    "AEDT": 331,
+    "AEST": 332,
+    "AKDT": 333,
+    "AKST": 334,
+    "ALMT": 335,
+    "AMDT": 336,
+    "AMST": 337,
+    "ANAT": 338,
+    "AQTT": 339,
+    "AWDT": 340,
+    "AWST": 341,
+    "AZOT": 342,
+    "AZST": 343,
+    "BDST": 344,
+    "BRST": 345,
+    "CAST": 352,
+    "CDST": 353,
+    "CEDT": 354,
+    "CEST": 355,
+    "CHOT": 356,
+    "ChST": 357,
+    "CHUT": 358,
+    "CIST": 359,
+    "CLDT": 360,
+    "CLST": 361,
+    "DAVT": 368,
+    "DDUT": 369,
+    "EADT": 376,
+    "EAST": 377,
+    "ECST": 378,
+    "EDST": 379,
+    "EEDT": 380,
+    "EEST": 381,
+    "EGST": 382,
+    "FJDT": 384,
+    "FJST": 385,
+    "FKDT": 386,
+    "FKST": 387,
+    "GALT": 392,
+    "GAMT": 393,
+    "GILT": 394,
+    "HADT": 400,
+    "HAST": 401,
+    "HOVT": 402,
+    "IRDT": 408,
+    "IRKT": 409,
+    "IRST": 410,
+    "KOST": 416,
+    "KRAT": 417,
+    "KUYT": 418,
+    "LHDT": 424,
+    "LHST": 425,
+    "LINT": 426,
+    "MAGT": 432,
+    "MART": 433,
+    "MAWT": 434,
+    "MDST": 435,
+    "MESZ": 436,
+    "NFDT": 440,
+    "NOVT": 441,
+    "NZDT": 442,
+    "NZST": 443,
+    "OESZ": 448,
+    "OMST": 449,
+    "ORAT": 450,
+    "PDST": 456,
+    "PETT": 457,
+    "PHOT": 458,
+    "PMDT": 459,
+    "PMST": 460,
+    "PONT": 461,
+    "PYST": 462,
+    "QYZT": 464,
+    "ROTT": 472,
+    "SAKT": 480,
+    "SAMT": 481,
+    "SAST": 482,
+    "SRET": 483,
+    "SYOT": 484,
+    "TAHT": 488,
+    "TOST": 489,
+    "ULAT": 496,
+    "UYST": 497,
+    "VLAT": 504,
+    "VOST": 505,
+    "WAKT": 512,
+    "WAST": 513,
+    "WEDT": 514,
+    "WEST": 515,
+    "WESZ": 516,
+    "WGST": 517,
+    "WITA": 518,
+    "YAKT": 520,
+    "YAPT": 521,
+    "YEKT": 522,
+    "ACWST": 528,
+    "ANAST": 529,
+    "AZODT": 530,
+    "AZOST": 531,
+    "CHADT": 536,
+    "CHAST": 537,
+    "CHODT": 538,
+    "CHOST": 539,
+    "CIDST": 540,
+    "EASST": 544,
+    "EFATE": 545,
+    "HOVDT": 552,
+    "HOVST": 553,
+    "IRKST": 560,
+    "KRAST": 568,
+    "MAGST": 576,
+    "NACDT": 584,
+    "NACST": 585,
+    "NAEDT": 586,
+    "NAEST": 587,
+    "NAMDT": 588,
+    "NAMST": 589,
+    "NAPDT": 590,
+    "NAPST": 591,
+    "NOVST": 592,
+    "OMSST": 600,
+    "PETST": 608,
+    "SAMST": 616,
+    "ULAST": 624,
+    "VLAST": 632,
+    "WARST": 640,
+    "YAKST": 648,
+    "YEKST": 649,
+    "CHODST": 656,
+    "HOVDST": 664,
+    "Africa/Abidjan": 672,
+    "Africa/Algiers": 673,
+    "Africa/Bissau": 674,
+    "Africa/Cairo": 675,
+    "Africa/Casablanca": 676,
+    "Africa/Ceuta": 677,
+    "Africa/El_Aaiun": 678,
+    "Africa/Johannesburg": 679,
+    "Africa/Juba": 680,
+    "Africa/Khartoum": 681,
+    "Africa/Lagos": 682,
+    "Africa/Maputo": 683,
+    "Africa/Monrovia": 684,
+    "Africa/Nairobi": 685,
+    "Africa/Ndjamena": 686,
+    "Africa/Sao_Tome": 687,
+    "Africa/Tripoli": 688,
+    "Africa/Tunis": 689,
+    "Africa/Windhoek": 690,
+    "America/Adak": 691,
+    "America/Anchorage": 692,
+    "America/Araguaina": 693,
+    "America/Argentina/Buenos_Aires": 694,
+    "America/Argentina/Catamarca": 695,
+    "America/Argentina/Cordoba": 696,
+    "America/Argentina/Jujuy": 697,
+    "America/Argentina/La_Rioja": 698,
+    "America/Argentina/Mendoza": 699,
+    "America/Argentina/Rio_Gallegos": 700,
+    "America/Argentina/Salta": 701,
+    "America/Argentina/San_Juan": 702,
+    "America/Argentina/San_Luis": 703,
+    "America/Argentina/Tucuman": 704,
+    "America/Argentina/Ushuaia": 705,
+    "America/Asuncion": 706,
+    "America/Bahia": 707,
+    "America/Bahia_Banderas": 708,
+    "America/Barbados": 709,
+    "America/Belem": 710,
+    "America/Belize": 711,
+    "America/Boa_Vista": 712,
+    "America/Bogota": 713,
+    "America/Boise": 714,
+    "America/Cambridge_Bay": 715,
+    "America/Campo_Grande": 716,
+    "America/Cancun": 717,
+    "America/Caracas": 718,
+    "America/Cayenne": 719,
+    "America/Chicago": 720,
+    "America/Chihuahua": 721,
+    "America/Costa_Rica": 722,
+    "America/Cuiaba": 723,
+    "America/Danmarkshavn": 724,
+    "America/Dawson": 725,
+    "America/Dawson_Creek": 726,
+    "America/Denver": 727,
+    "America/Detroit": 728,
+    "America/Edmonton": 729,
+    "America/Eirunepe": 730,
+    "America/El_Salvador": 731,
+    "America/Fort_Nelson": 732,
+    "America/Fortaleza": 733,
+    "America/Glace_Bay": 734,
+    "America/Goose_Bay": 735,
+    "America/Grand_Turk": 736,
+    "America/Guatemala": 737,
+    "America/Guayaquil": 738,
+    "America/Guyana": 739,
+    "America/Halifax": 740,
+    "America/Havana": 741,
+    "America/Hermosillo": 742,
+    "America/Indiana/Indianapolis": 743,
+    "America/Indiana/Knox": 744,
+    "America/Indiana/Marengo": 745,
+    "America/Indiana/Petersburg": 746,
+    "America/Indiana/Tell_City": 747,
+    "America/Indiana/Vevay": 748,
+    "America/Indiana/Vincennes": 749,
+    "America/Indiana/Winamac": 750,
+    "America/Inuvik": 751,
+    "America/Iqaluit": 752,
+    "America/Jamaica": 753,
+    "America/Juneau": 754,
+    "America/Kentucky/Louisville": 755,
+    "America/Kentucky/Monticello": 756,
+    "America/La_Paz": 757,
+    "America/Lima": 758,
+    "America/Los_Angeles": 759,
+    "America/Maceio": 760,
+    "America/Managua": 761,
+    "America/Manaus": 762,
+    "America/Martinique": 763,
+    "America/Matamoros": 764,
+    "America/Mazatlan": 765,
+    "America/Menominee": 766,
+    "America/Merida": 767,
+    "America/Metlakatla": 768,
+    "America/Mexico_City": 769,
+    "America/Miquelon": 770,
+    "America/Moncton": 771,
+    "America/Monterrey": 772,
+    "America/Montevideo": 773,
+    "America/New_York": 774,
+    "America/Nipigon": 775,
+    "America/Nome": 776,
+    "America/Noronha": 777,
+    "America/North_Dakota/Beulah": 778,
+    "America/North_Dakota/Center": 779,
+    "America/North_Dakota/New_Salem": 780,
+    "America/Nuuk": 781,
+    "America/Ojinaga": 782,
+    "America/Panama": 783,
+    "America/Pangnirtung": 784,
+    "America/Paramaribo": 785,
+    "America/Phoenix": 786,
+    "America/Port-au-Prince": 787,
+    "America/Porto_Velho": 788,
+    "America/Puerto_Rico": 789,
+    "America/Punta_Arenas": 790,
+    "America/Rainy_River": 791,
+    "America/Rankin_Inlet": 792,
+    "America/Recife": 793,
+    "America/Regina": 794,
+    "America/Resolute": 795,
+    "America/Rio_Branco": 796,
+    "America/Santarem": 797,
+    "America/Santiago": 798,
+    "America/Santo_Domingo": 799,
+    "America/Sao_Paulo": 800,
+    "America/Scoresbysund": 801,
+    "America/Sitka": 802,
+    "America/St_Johns": 803,
+    "America/Swift_Current": 804,
+    "America/Tegucigalpa": 805,
+    "America/Thule": 806,
+    "America/Thunder_Bay": 807,
+    "America/Tijuana": 808,
+    "America/Toronto": 809,
+    "America/Vancouver": 810,
+    "America/Whitehorse": 811,
+    "America/Winnipeg": 812,
+    "America/Yakutat": 813,
+    "America/Yellowknife": 814,
+    "Antarctica/Casey": 815,
+    "Antarctica/Davis": 816,
+    "Antarctica/Macquarie": 817,
+    "Antarctica/Mawson": 818,
+    "Antarctica/Palmer": 819,
+    "Antarctica/Rothera": 820,
+    "Antarctica/Troll": 821,
+    "Antarctica/Vostok": 822,
+    "Asia/Almaty": 823,
+    "Asia/Amman": 824,
+    "Asia/Anadyr": 825,
+    "Asia/Aqtau": 826,
+    "Asia/Aqtobe": 827,
+    "Asia/Ashgabat": 828,
+    "Asia/Atyrau": 829,
+    "Asia/Baghdad": 830,
+    "Asia/Baku": 831,
+    "Asia/Bangkok": 832,
+    "Asia/Barnaul": 833,
+    "Asia/Beirut": 834,
+    "Asia/Bishkek": 835,
+    "Asia/Brunei": 836,
+    "Asia/Chita": 837,
+    "Asia/Choibalsan": 838,
+    "Asia/Colombo": 839,
+    "Asia/Damascus": 840,
+    "Asia/Dhaka": 841,
+    "Asia/Dili": 842,
+    "Asia/Dubai": 843,
+    "Asia/Dushanbe": 844,
+    "Asia/Famagusta": 845,
+    "Asia/Gaza": 846,
+    "Asia/Hebron": 847,
+    "Asia/Ho_Chi_Minh": 848,
+    "Asia/Hong_Kong": 849,
+    "Asia/Hovd": 850,
+    "Asia/Irkutsk": 851,
+    "Asia/Jakarta": 852,
+    "Asia/Jayapura": 853,
+    "Asia/Jerusalem": 854,
+    "Asia/Kabul": 855,
+    "Asia/Kamchatka": 856,
+    "Asia/Karachi": 857,
+    "Asia/Kathmandu": 858,
+    "Asia/Khandyga": 859,
+    "Asia/Kolkata": 860,
+    "Asia/Krasnoyarsk": 861,
+    "Asia/Kuala_Lumpur": 862,
+    "Asia/Kuching": 863,
+    "Asia/Macau": 864,
+    "Asia/Magadan": 865,
+    "Asia/Makassar": 866,
+    "Asia/Manila": 867,
+    "Asia/Nicosia": 868,
+    "Asia/Novokuznetsk": 869,
+    "Asia/Novosibirsk": 870,
+    "Asia/Omsk": 871,
+    "Asia/Oral": 872,
+    "Asia/Pontianak": 873,
+    "Asia/Pyongyang": 874,
+    "Asia/Qatar": 875,
+    "Asia/Qostanay": 876,
+    "Asia/Qyzylorda": 877,
+    "Asia/Riyadh": 878,
+    "Asia/Sakhalin": 879,
+    "Asia/Samarkand": 880,
+    "Asia/Seoul": 881,
+    "Asia/Shanghai": 882,
+    "Asia/Singapore": 883,
+    "Asia/Srednekolymsk": 884,
+    "Asia/Taipei": 885,
+    "Asia/Tashkent": 886,
+    "Asia/Tbilisi": 887,
+    "Asia/Tehran": 888,
+    "Asia/Thimphu": 889,
+    "Asia/Tokyo": 890,
+    "Asia/Tomsk": 891,
+    "Asia/Ulaanbaatar": 892,
+    "Asia/Urumqi": 893,
+    "Asia/Ust-Nera": 894,
+    "Asia/Vladivostok": 895,
+    "Asia/Yakutsk": 896,
+    "Asia/Yangon": 897,
+    "Asia/Yekaterinburg": 898,
+    "Asia/Yerevan": 899,
+    "Atlantic/Azores": 900,
+    "Atlantic/Bermuda": 901,
+    "Atlantic/Canary": 902,
+    "Atlantic/Cape_Verde": 903,
+    "Atlantic/Faroe": 904,
+    "Atlantic/Madeira": 905,
+    "Atlantic/Reykjavik": 906,
+    "Atlantic/South_Georgia": 907,
+    "Atlantic/Stanley": 908,
+    "Australia/Adelaide": 909,
+    "Australia/Brisbane": 910,
+    "Australia/Broken_Hill": 911,
+    "Australia/Darwin": 912,
+    "Australia/Eucla": 913,
+    "Australia/Hobart": 914,
+    "Australia/Lindeman": 915,
+    "Australia/Lord_Howe": 916,
+    "Australia/Melbourne": 917,
+    "Australia/Perth": 918,
+    "Australia/Sydney": 919,
+    "Etc/GMT": 920,
+    "Etc/UTC": 921,
+    "Europe/Amsterdam": 922,
+    "Europe/Andorra": 923,
+    "Europe/Astrakhan": 924,
+    "Europe/Athens": 925,
+    "Europe/Belgrade": 926,
+    "Europe/Berlin": 927,
+    "Europe/Brussels": 928,
+    "Europe/Bucharest": 929,
+    "Europe/Budapest": 930,
+    "Europe/Chisinau": 931,
+    "Europe/Copenhagen": 932,
+    "Europe/Dublin": 933,
+    "Europe/Gibraltar": 934,
+    "Europe/Helsinki": 935,
+    "Europe/Istanbul": 936,
+    "Europe/Kaliningrad": 937,
+    "Europe/Kiev": 938,
+    "Europe/Kirov": 939,
+    "Europe/Lisbon": 940,
+    "Europe/London": 941,
+    "Europe/Luxembourg": 942,
+    "Europe/Madrid": 943,
+    "Europe/Malta": 944,
+    "Europe/Minsk": 945,
+    "Europe/Monaco": 946,
+    "Europe/Moscow": 947,
+    "Europe/Oslo": 948,
+    "Europe/Paris": 949,
+    "Europe/Prague": 950,
+    "Europe/Riga": 951,
+    "Europe/Rome": 952,
+    "Europe/Samara": 953,
+    "Europe/Saratov": 954,
+    "Europe/Simferopol": 955,
+    "Europe/Sofia": 956,
+    "Europe/Stockholm": 957,
+    "Europe/Tallinn": 958,
+    "Europe/Tirane": 959,
+    "Europe/Ulyanovsk": 960,
+    "Europe/Uzhgorod": 961,
+    "Europe/Vienna": 962,
+    "Europe/Vilnius": 963,
+    "Europe/Volgograd": 964,
+    "Europe/Warsaw": 965,
+    "Europe/Zaporozhye": 966,
+    "Europe/Zurich": 967,
+    "Indian/Chagos": 968,
+    "Indian/Christmas": 969,
+    "Indian/Cocos": 970,
+    "Indian/Kerguelen": 971,
+    "Indian/Mahe": 972,
+    "Indian/Maldives": 973,
+    "Indian/Mauritius": 974,
+    "Indian/Reunion": 975,
+    "Pacific/Apia": 976,
+    "Pacific/Auckland": 977,
+    "Pacific/Bougainville": 978,
+    "Pacific/Chatham": 979,
+    "Pacific/Chuuk": 980,
+    "Pacific/Easter": 981,
+    "Pacific/Efate": 982,
+    "Pacific/Fakaofo": 983,
+    "Pacific/Fiji": 984,
+    "Pacific/Funafuti": 985,
+    "Pacific/Galapagos": 986,
+    "Pacific/Gambier": 987,
+    "Pacific/Guadalcanal": 988,
+    "Pacific/Guam": 989,
+    "Pacific/Honolulu": 990,
+    "Pacific/Kanton": 991,
+    "Pacific/Kiritimati": 992,
+    "Pacific/Kosrae": 993,
+    "Pacific/Kwajalein": 994,
+    "Pacific/Majuro": 995,
+    "Pacific/Marquesas": 996,
+    "Pacific/Nauru": 997,
+    "Pacific/Niue": 998,
+    "Pacific/Norfolk": 999,
+    "Pacific/Noumea": 1000,
+    "Pacific/Pago_Pago": 1001,
+    "Pacific/Palau": 1002,
+    "Pacific/Pitcairn": 1003,
+    "Pacific/Pohnpei": 1004,
+    "Pacific/Port_Moresby": 1005,
+    "Pacific/Rarotonga": 1006,
+    "Pacific/Tahiti": 1007,
+    "Pacific/Tarawa": 1008,
+    "Pacific/Tongatapu": 1009,
+    "Pacific/Wake": 1010,
+    "Pacific/Wallis": 1011,
+    "Africa/Accra": 672,
+    "Africa/Addis_Ababa": 685,
+    "Africa/Asmara": 685,
+    "Africa/Asmera": 685,
+    "Africa/Bamako": 672,
+    "Africa/Bangui": 682,
+    "Africa/Banjul": 672,
+    "Africa/Blantyre": 683,
+    "Africa/Brazzaville": 682,
+    "Africa/Bujumbura": 683,
+    "Africa/Conakry": 672,
+    "Africa/Dakar": 672,
+    "Africa/Dar_es_Salaam": 685,
+    "Africa/Djibouti": 685,
+    "Africa/Douala": 682,
+    "Africa/Freetown": 672,
+    "Africa/Gaborone": 683,
+    "Africa/Harare": 683,
+    "Africa/Kampala": 685,
+    "Africa/Kigali": 683,
+    "Africa/Kinshasa": 682,
+    "Africa/Libreville": 682,
+    "Africa/Lome": 672,
+    "Africa/Luanda": 682,
+    "Africa/Lubumbashi": 683,
+    "Africa/Lusaka": 683,
+    "Africa/Malabo": 682,
+    "Africa/Maseru": 679,
+    "Africa/Mbabane": 679,
+    "Africa/Mogadishu": 685,
+    "Africa/Niamey": 682,
+    "Africa/Nouakchott": 672,
+    "Africa/Ouagadougou": 672,
+    "Africa/Porto-Novo": 682,
+    "Africa/Timbuktu": 672,
+    "America/Anguilla": 789,
+    "America/Antigua": 789,
+    "America/Argentina/ComodRivadavia": 695,
+    "America/Aruba": 789,
+    "America/Atikokan": 783,
+    "America/Atka": 691,
+    "America/Blanc-Sablon": 789,
+    "America/Buenos_Aires": 694,
+    "America/Catamarca": 695,
+    "America/Cayman": 783,
+    "America/Coral_Harbour": 783,
+    "America/Cordoba": 696,
+    "America/Creston": 786,
+    "America/Curacao": 789,
+    "America/Dominica": 789,
+    "America/Ensenada": 808,
+    "America/Fort_Wayne": 743,
+    "America/Godthab": 781,
+    "America/Grenada": 789,
+    "America/Guadeloupe": 789,
+    "America/Indianapolis": 743,
+    "America/Jujuy": 697,
+    "America/Knox_IN": 744,
+    "America/Kralendijk": 789,
+    "America/Louisville": 755,
+    "America/Lower_Princes": 789,
+    "America/Marigot": 789,
+    "America/Mendoza": 699,
+    "America/Montreal": 809,
+    "America/Montserrat": 789,
+    "America/Nassau": 809,
+    "America/Port_of_Spain": 789,
+    "America/Porto_Acre": 796,
+    "America/Rosario": 696,
+    "America/Santa_Isabel": 808,
+    "America/Shiprock": 727,
+    "America/St_Barthelemy": 789,
+    "America/St_Kitts": 789,
+    "America/St_Lucia": 789,
+    "America/St_Thomas": 789,
+    "America/St_Vincent": 789,
+    "America/Tortola": 789,
+    "America/Virgin": 789,
+    "Antarctica/DumontDUrville": 1005,
+    "Antarctica/McMurdo": 977,
+    "Antarctica/South_Pole": 977,
+    "Antarctica/Syowa": 878,
+    "Arctic/Longyearbyen": 948,
+    "Asia/Aden": 878,
+    "Asia/Ashkhabad": 828,
+    "Asia/Bahrain": 875,
+    "Asia/Calcutta": 860,
+    "Asia/Chongqing": 882,
+    "Asia/Chungking": 882,
+    "Asia/Dacca": 841,
+    "Asia/Harbin": 882,
+    "Asia/Istanbul": 936,
+    "Asia/Kashgar": 893,
+    "Asia/Katmandu": 858,
+    "Asia/Kuwait": 878,
+    "Asia/Macao": 864,
+    "Asia/Muscat": 843,
+    "Asia/Phnom_Penh": 832,
+    "Asia/Rangoon": 897,
+    "Asia/Saigon": 848,
+    "Asia/Tel_Aviv": 854,
+    "Asia/Thimbu": 889,
+    "Asia/Ujung_Pandang": 866,
+    "Asia/Ulan_Bator": 892,
+    "Asia/Vientiane": 832,
+    "Atlantic/Faeroe": 904,
+    "Atlantic/Jan_Mayen": 948,
+    "Atlantic/St_Helena": 672,
+    "Australia/ACT": 919,
+    "Australia/Canberra": 919,
+    "Australia/Currie": 914,
+    "Australia/LHI": 916,
+    "Australia/NSW": 919,
+    "Australia/North": 912,
+    "Australia/Queensland": 910,
+    "Australia/South": 909,
+    "Australia/Tasmania": 914,
+    "Australia/Victoria": 917,
+    "Australia/West": 918,
+    "Australia/Yancowinna": 911,
+    "Brazil/Acre": 796,
+    "Brazil/DeNoronha": 777,
+    "Brazil/East": 800,
+    "Brazil/West": 762,
+    "Canada/Atlantic": 740,
+    "Canada/Central": 812,
+    "Canada/Eastern": 809,
+    "Canada/Mountain": 729,
+    "Canada/Newfoundland": 803,
+    "Canada/Pacific": 810,
+    "Canada/Saskatchewan": 794,
+    "Canada/Yukon": 811,
+    "Chile/Continental": 798,
+    "Chile/EasterIsland": 981,
+    "Cuba": 741,
+    "Egypt": 675,
+    "Eire": 933,
+    "Etc/GMT+0": 920,
+    "Etc/GMT-0": 920,
+    "Etc/GMT0": 920,
+    "Etc/Greenwich": 920,
+    "Etc/UCT": 921,
+    "Etc/Universal": 921,
+    "Etc/Zulu": 921,
+    "Europe/Belfast": 941,
+    "Europe/Bratislava": 950,
+    "Europe/Busingen": 967,
+    "Europe/Guernsey": 941,
+    "Europe/Isle_of_Man": 941,
+    "Europe/Jersey": 941,
+    "Europe/Ljubljana": 926,
+    "Europe/Mariehamn": 935,
+    "Europe/Nicosia": 868,
+    "Europe/Podgorica": 926,
+    "Europe/San_Marino": 952,
+    "Europe/Sarajevo": 926,
+    "Europe/Skopje": 926,
+    "Europe/Tiraspol": 931,
+    "Europe/Vaduz": 967,
+    "Europe/Vatican": 952,
+    "Europe/Zagreb": 926,
+    "GB": 941,
+    "GB-Eire": 941,
+    "GMT+0": 920,
+    "GMT-0": 920,
+    "GMT0": 920,
+    "Greenwich": 920,
+    "Hongkong": 849,
+    "Iceland": 906,
+    "Indian/Antananarivo": 685,
+    "Indian/Comoro": 685,
+    "Indian/Mayotte": 685,
+    "Iran": 888,
+    "Israel": 854,
+    "Jamaica": 753,
+    "Japan": 890,
+    "Kwajalein": 994,
+    "Libya": 688,
+    "Mexico/BajaNorte": 808,
+    "Mexico/BajaSur": 765,
+    "Mexico/General": 769,
+    "NZ": 977,
+    "NZ-CHAT": 979,
+    "Navajo": 727,
+    "PRC": 882,
+    "Pacific/Enderbury": 991,
+    "Pacific/Johnston": 990,
+    "Pacific/Midway": 1001,
+    "Pacific/Ponape": 1004,
+    "Pacific/Saipan": 989,
+    "Pacific/Samoa": 1001,
+    "Pacific/Truk": 980,
+    "Pacific/Yap": 980,
+    "Poland": 965,
+    "Portugal": 940,
+    "ROC": 885,
+    "ROK": 881,
+    "Singapore": 883,
+    "Turkey": 936,
+    "UCT": 921,
+    "US/Alaska": 692,
+    "US/Aleutian": 691,
+    "US/Arizona": 786,
+    "US/Central": 720,
+    "US/East-Indiana": 743,
+    "US/Eastern": 774,
+    "US/Hawaii": 990,
+    "US/Indiana-Starke": 744,
+    "US/Michigan": 728,
+    "US/Mountain": 727,
+    "US/Pacific": 759,
+    "US/Samoa": 1001,
+    "Universal": 921,
+    "W-SU": 947,
+    "Zulu": 921,
 }
 
 timezoneAbbrevInfo = {
-	"A" : {"offset" : 60, "category" : TZ_MILITARY},
-	"B" : {"offset" : 120, "category" : TZ_MILITARY},
-	"C" : {"offset" : 180, "category" : TZ_MILITARY},
-	"D" : {"offset" : 240, "category" : TZ_MILITARY},
-	"E" : {"offset" : 300, "category" : TZ_MILITARY},
-	"F" : {"offset" : 360, "category" : TZ_MILITARY},
-	"G" : {"offset" : 420, "category" : TZ_MILITARY},
-	"H" : {"offset" : 480, "category" : TZ_MILITARY},
-	"I" : {"offset" : 540, "category" : TZ_MILITARY},
-	"K" : {"offset" : 600, "category" : TZ_MILITARY},
-	"L" : {"offset" : 660, "category" : TZ_MILITARY},
-	"M" : {"offset" : 720, "category" : TZ_MILITARY},
-	"N" : {"offset" : -60, "category" : TZ_MILITARY},
-	"O" : {"offset" : -120, "category" : TZ_MILITARY},
-	"P" : {"offset" : -180, "category" : TZ_MILITARY},
-	"Q" : {"offset" : -240, "category" : TZ_MILITARY},
-	"R" : {"offset" : -300, "category" : TZ_MILITARY},
-	"S" : {"offset" : -360, "category" : TZ_MILITARY},
-	"T" : {"offset" : -420, "category" : TZ_MILITARY},
-	"U" : {"offset" : -480, "category" : TZ_MILITARY},
-	"V" : {"offset" : -540, "category" : TZ_MILITARY},
-	"W" : {"offset" : -600, "category" : TZ_MILITARY},
-	"X" : {"offset" : -660, "category" : TZ_MILITARY},
-	"Y" : {"offset" : -720, "category" : TZ_MILITARY},
-	"Z" : {"offset" : 0, "category" : TZ_MILITARY},
-	"AT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"BT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"CT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"ET" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"GT" : {"offset" : 0, "category" : 0},
-	"IT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"KT" : {"offset" : 540, "category" : 0},
-	"MT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"PT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"ST" : {"offset" : 780, "category" : 0},
-	"UT" : {"offset" : 0, "category" : TZ_UTC|TZ_RFC},
-	"WT" : {"offset" : 0, "category" : 0},
-	"ACT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"ADT" : {"offset" : 0, "category" : TZ_AMBIGUOUS|TZ_DST},
-	"AET" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"AFT" : {"offset" : 270, "category" : 0},
-	"AMT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"AoE" : {"offset" : -720, "category" : 0},
-	"ART" : {"offset" : -180, "category" : 0},
-	"AST" : {"offset" : 0, "category" : TZ_AMBIGUOUS|TZ_DST},
-	"AZT" : {"offset" : 240, "category" : 0},
-	"BDT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"BNT" : {"offset" : 480, "category" : 0},
-	"BOT" : {"offset" : -240, "category" : 0},
-	"BRT" : {"offset" : -180, "category" : 0},
-	"BST" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"BTT" : {"offset" : 360, "category" : 0},
-	"CAT" : {"offset" : 120, "category" : 0},
-	"CCT" : {"offset" : 390, "category" : 0},
-	"CDT" : {"offset" : -300, "category" : TZ_RFC|TZ_AMBIGUOUS|TZ_DST},
-	"CET" : {"offset" : 60, "category" : 0},
-	"CIT" : {"offset" : -300, "category" : 0},
-	"CKT" : {"offset" : -600, "category" : 0},
-	"CLT" : {"offset" : -180, "category" : 0},
-	"COT" : {"offset" : -300, "category" : 0},
-	"CST" : {"offset" : -360, "category" : TZ_RFC|TZ_AMBIGUOUS},
-	"CVT" : {"offset" : -60, "category" : 0},
-	"CXT" : {"offset" : 420, "category" : 0},
-	"EAT" : {"offset" : 180, "category" : 0},
-	"ECT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"EDT" : {"offset" : -240, "category" : TZ_RFC|TZ_AMBIGUOUS|TZ_DST},
-	"EET" : {"offset" : 120, "category" : 0},
-	"EGT" : {"offset" : -60, "category" : 0},
-	"EST" : {"offset" : -300, "category" : TZ_RFC|TZ_AMBIGUOUS},
-	"FET" : {"offset" : 180, "category" : 0},
-	"FJT" : {"offset" : 720, "category" : 0},
-	"FKT" : {"offset" : -240, "category" : 0},
-	"FNT" : {"offset" : -120, "category" : 0},
-	"GET" : {"offset" : 240, "category" : 0},
-	"GFT" : {"offset" : -180, "category" : 0},
-	"GMT" : {"offset" : 0, "category" : TZ_UTC|TZ_RFC},
-	"GST" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"GYT" : {"offset" : -240, "category" : 0},
-	"HAA" : {"offset" : -180, "category" : 0},
-	"HAC" : {"offset" : -300, "category" : 0},
-	"HAE" : {"offset" : -240, "category" : 0},
-	"HAP" : {"offset" : -420, "category" : 0},
-	"HAR" : {"offset" : -360, "category" : 0},
-	"HAT" : {"offset" : -90, "category" : 0},
-	"HDT" : {"offset" : -540, "category" : TZ_DST},
-	"HKT" : {"offset" : 480, "category" : 0},
-	"HLV" : {"offset" : -210, "category" : 0},
-	"HNA" : {"offset" : -240, "category" : 0},
-	"HNC" : {"offset" : -360, "category" : 0},
-	"HNE" : {"offset" : -300, "category" : 0},
-	"HNP" : {"offset" : -480, "category" : 0},
-	"HNR" : {"offset" : -420, "category" : 0},
-	"HNT" : {"offset" : -150, "category" : 0},
-	"HST" : {"offset" : -600, "category" : 0},
-	"ICT" : {"offset" : 420, "category" : 0},
-	"IDT" : {"offset" : 0, "category" : TZ_AMBIGUOUS|TZ_DST},
-	"IOT" : {"offset" : 360, "category" : 0},
-	"IST" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"JST" : {"offset" : 540, "category" : 0},
-	"KGT" : {"offset" : 360, "category" : 0},
-	"KIT" : {"offset" : 300, "category" : 0},
-	"KST" : {"offset" : 540, "category" : 0},
-	"MCK" : {"offset" : 180, "category" : 0},
-	"MDT" : {"offset" : -360, "category" : TZ_RFC|TZ_DST},
-	"MEZ" : {"offset" : 60, "category" : 0},
-	"MHT" : {"offset" : 720, "category" : 0},
-	"MMT" : {"offset" : 390, "category" : 0},
-	"MSD" : {"offset" : 240, "category" : TZ_DST},
-	"MSK" : {"offset" : 180, "category" : 0},
-	"MST" : {"offset" : -420, "category" : TZ_RFC|TZ_AMBIGUOUS},
-	"MUT" : {"offset" : 240, "category" : 0},
-	"MVT" : {"offset" : 300, "category" : 0},
-	"MYT" : {"offset" : 480, "category" : 0},
-	"NCT" : {"offset" : 660, "category" : 0},
-	"NDT" : {"offset" : -90, "category" : TZ_DST},
-	"NFT" : {"offset" : 660, "category" : 0},
-	"NPT" : {"offset" : 345, "category" : 0},
-	"NRT" : {"offset" : 720, "category" : 0},
-	"NST" : {"offset" : -150, "category" : 0},
-	"NUT" : {"offset" : -660, "category" : 0},
-	"OEZ" : {"offset" : 120, "category" : 0},
-	"PDT" : {"offset" : -420, "category" : TZ_RFC|TZ_DST},
-	"PET" : {"offset" : -300, "category" : 0},
-	"PGT" : {"offset" : 600, "category" : 0},
-	"PHT" : {"offset" : 480, "category" : 0},
-	"PKT" : {"offset" : 300, "category" : 0},
-	"PST" : {"offset" : -480, "category" : TZ_RFC|TZ_AMBIGUOUS},
-	"PWT" : {"offset" : 540, "category" : 0},
-	"PYT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"RET" : {"offset" : 240, "category" : 0},
-	"SBT" : {"offset" : 660, "category" : 0},
-	"SCT" : {"offset" : 240, "category" : 0},
-	"SGT" : {"offset" : 480, "category" : 0},
-	"SRT" : {"offset" : -180, "category" : 0},
-	"SST" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"TFT" : {"offset" : 300, "category" : 0},
-	"TJT" : {"offset" : 300, "category" : 0},
-	"TKT" : {"offset" : 780, "category" : 0},
-	"TLT" : {"offset" : 540, "category" : 0},
-	"TMT" : {"offset" : 300, "category" : 0},
-	"TOT" : {"offset" : 780, "category" : 0},
-	"TRT" : {"offset" : 180, "category" : 0},
-	"TVT" : {"offset" : 720, "category" : 0},
-	"UTC" : {"offset" : 0, "category" : TZ_UTC|TZ_RFC},
-	"UYT" : {"offset" : -180, "category" : 0},
-	"UZT" : {"offset" : 300, "category" : 0},
-	"VET" : {"offset" : -210, "category" : 0},
-	"VUT" : {"offset" : 660, "category" : 0},
-	"WAT" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"WDT" : {"offset" : 540, "category" : TZ_DST},
-	"WET" : {"offset" : 0, "category" : 0},
-	"WEZ" : {"offset" : 0, "category" : 0},
-	"WFT" : {"offset" : 720, "category" : 0},
-	"WGT" : {"offset" : -180, "category" : 0},
-	"WIB" : {"offset" : 420, "category" : 0},
-	"WIT" : {"offset" : 540, "category" : 0},
-	"WST" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"ACDT" : {"offset" : 630, "category" : TZ_DST},
-	"ACST" : {"offset" : 570, "category" : 0},
-	"ADST" : {"offset" : 0, "category" : TZ_AMBIGUOUS|TZ_DST},
-	"AEDT" : {"offset" : 660, "category" : TZ_DST},
-	"AEST" : {"offset" : 600, "category" : 0},
-	"AKDT" : {"offset" : -480, "category" : TZ_DST},
-	"AKST" : {"offset" : -540, "category" : 0},
-	"ALMT" : {"offset" : 360, "category" : 0},
-	"AMDT" : {"offset" : 300, "category" : TZ_DST},
-	"AMST" : {"offset" : 0, "category" : TZ_AMBIGUOUS|TZ_DST},
-	"ANAT" : {"offset" : 720, "category" : 0},
-	"AQTT" : {"offset" : 300, "category" : 0},
-	"AWDT" : {"offset" : 540, "category" : TZ_DST},
-	"AWST" : {"offset" : 480, "category" : 0},
-	"AZOT" : {"offset" : -60, "category" : 0},
-	"AZST" : {"offset" : 300, "category" : TZ_DST},
-	"BDST" : {"offset" : 60, "category" : TZ_DST},
-	"BRST" : {"offset" : -120, "category" : TZ_DST},
-	"CAST" : {"offset" : 480, "category" : 0},
-	"CDST" : {"offset" : 0, "category" : TZ_AMBIGUOUS|TZ_DST},
-	"CEDT" : {"offset" : 120, "category" : TZ_DST},
-	"CEST" : {"offset" : 120, "category" : TZ_DST},
-	"CHOT" : {"offset" : 480, "category" : 0},
-	"ChST" : {"offset" : 600, "category" : 0},
-	"CHUT" : {"offset" : 600, "category" : 0},
-	"CIST" : {"offset" : -300, "category" : 0},
-	"CLDT" : {"offset" : -180, "category" : TZ_DST},
-	"CLST" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"DAVT" : {"offset" : 420, "category" : 0},
-	"DDUT" : {"offset" : 600, "category" : 0},
-	"EADT" : {"offset" : -300, "category" : TZ_DST},
-	"EAST" : {"offset" : -300, "category" : 0},
-	"ECST" : {"offset" : 120, "category" : TZ_DST},
-	"EDST" : {"offset" : 0, "category" : TZ_AMBIGUOUS|TZ_DST},
-	"EEDT" : {"offset" : 180, "category" : TZ_DST},
-	"EEST" : {"offset" : 180, "category" : TZ_DST},
-	"EGST" : {"offset" : 0, "category" : TZ_DST},
-	"FJDT" : {"offset" : 780, "category" : TZ_DST},
-	"FJST" : {"offset" : 780, "category" : TZ_DST},
-	"FKDT" : {"offset" : -180, "category" : TZ_DST},
-	"FKST" : {"offset" : 0, "category" : TZ_AMBIGUOUS|TZ_DST},
-	"GALT" : {"offset" : -360, "category" : 0},
-	"GAMT" : {"offset" : -540, "category" : 0},
-	"GILT" : {"offset" : 720, "category" : 0},
-	"HADT" : {"offset" : -540, "category" : TZ_DST},
-	"HAST" : {"offset" : -600, "category" : 0},
-	"HOVT" : {"offset" : 420, "category" : 0},
-	"IRDT" : {"offset" : 270, "category" : TZ_DST},
-	"IRKT" : {"offset" : 480, "category" : 0},
-	"IRST" : {"offset" : 0, "category" : TZ_AMBIGUOUS|TZ_DST},
-	"KOST" : {"offset" : 660, "category" : 0},
-	"KRAT" : {"offset" : 420, "category" : 0},
-	"KUYT" : {"offset" : 240, "category" : 0},
-	"LHDT" : {"offset" : 660, "category" : TZ_DST},
-	"LHST" : {"offset" : 630, "category" : 0},
-	"LINT" : {"offset" : 840, "category" : 0},
-	"MAGT" : {"offset" : 600, "category" : 0},
-	"MART" : {"offset" : -510, "category" : 0},
-	"MAWT" : {"offset" : 300, "category" : 0},
-	"MDST" : {"offset" : -360, "category" : TZ_DST},
-	"MESZ" : {"offset" : 120, "category" : 0},
-	"NFDT" : {"offset" : 720, "category" : TZ_DST},
-	"NOVT" : {"offset" : 360, "category" : 0},
-	"NZDT" : {"offset" : 780, "category" : TZ_DST},
-	"NZST" : {"offset" : 720, "category" : 0},
-	"OESZ" : {"offset" : 180, "category" : 0},
-	"OMST" : {"offset" : 360, "category" : 0},
-	"ORAT" : {"offset" : 300, "category" : 0},
-	"PDST" : {"offset" : -420, "category" : TZ_DST},
-	"PETT" : {"offset" : 720, "category" : 0},
-	"PHOT" : {"offset" : 780, "category" : 0},
-	"PMDT" : {"offset" : -120, "category" : TZ_DST},
-	"PMST" : {"offset" : -180, "category" : 0},
-	"PONT" : {"offset" : 660, "category" : 0},
-	"PYST" : {"offset" : 0, "category" : TZ_AMBIGUOUS},
-	"QYZT" : {"offset" : 360, "category" : 0},
-	"ROTT" : {"offset" : -180, "category" : 0},
-	"SAKT" : {"offset" : 600, "category" : 0},
-	"SAMT" : {"offset" : 240, "category" : 0},
-	"SAST" : {"offset" : 120, "category" : 0},
-	"SRET" : {"offset" : 660, "category" : 0},
-	"SYOT" : {"offset" : 180, "category" : 0},
-	"TAHT" : {"offset" : -600, "category" : 0},
-	"TOST" : {"offset" : 840, "category" : TZ_DST},
-	"ULAT" : {"offset" : 480, "category" : 0},
-	"UYST" : {"offset" : -120, "category" : TZ_DST},
-	"VLAT" : {"offset" : 600, "category" : 0},
-	"VOST" : {"offset" : 360, "category" : 0},
-	"WAKT" : {"offset" : 720, "category" : 0},
-	"WAST" : {"offset" : 120, "category" : TZ_DST},
-	"WEDT" : {"offset" : 60, "category" : TZ_DST},
-	"WEST" : {"offset" : 60, "category" : TZ_DST},
-	"WESZ" : {"offset" : 60, "category" : 0},
-	"WGST" : {"offset" : -120, "category" : TZ_DST},
-	"WITA" : {"offset" : 480, "category" : 0},
-	"YAKT" : {"offset" : 540, "category" : 0},
-	"YAPT" : {"offset" : 600, "category" : 0},
-	"YEKT" : {"offset" : 300, "category" : 0},
-	"ACWST" : {"offset" : 525, "category" : 0},
-	"ANAST" : {"offset" : 720, "category" : TZ_DST},
-	"AZODT" : {"offset" : 0, "category" : TZ_DST},
-	"AZOST" : {"offset" : 0, "category" : TZ_AMBIGUOUS|TZ_DST},
-	"CHADT" : {"offset" : 825, "category" : TZ_DST},
-	"CHAST" : {"offset" : 765, "category" : 0},
-	"CHODT" : {"offset" : 540, "category" : TZ_DST},
-	"CHOST" : {"offset" : 540, "category" : TZ_DST},
-	"CIDST" : {"offset" : -240, "category" : TZ_DST},
-	"EASST" : {"offset" : -300, "category" : TZ_DST},
-	"EFATE" : {"offset" : 660, "category" : 0},
-	"HOVDT" : {"offset" : 480, "category" : TZ_DST},
-	"HOVST" : {"offset" : 480, "category" : TZ_DST},
-	"IRKST" : {"offset" : 540, "category" : TZ_DST},
-	"KRAST" : {"offset" : 480, "category" : TZ_DST},
-	"MAGST" : {"offset" : 720, "category" : TZ_DST},
-	"NACDT" : {"offset" : -300, "category" : TZ_DST},
-	"NACST" : {"offset" : -360, "category" : 0},
-	"NAEDT" : {"offset" : -240, "category" : TZ_DST},
-	"NAEST" : {"offset" : -300, "category" : 0},
-	"NAMDT" : {"offset" : -360, "category" : TZ_DST},
-	"NAMST" : {"offset" : -420, "category" : 0},
-	"NAPDT" : {"offset" : -420, "category" : TZ_DST},
-	"NAPST" : {"offset" : -480, "category" : 0},
-	"NOVST" : {"offset" : 420, "category" : TZ_DST},
-	"OMSST" : {"offset" : 420, "category" : TZ_DST},
-	"PETST" : {"offset" : 720, "category" : TZ_DST},
-	"SAMST" : {"offset" : 240, "category" : TZ_DST},
-	"ULAST" : {"offset" : 540, "category" : TZ_DST},
-	"VLAST" : {"offset" : 660, "category" : TZ_DST},
-	"WARST" : {"offset" : -180, "category" : TZ_DST},
-	"YAKST" : {"offset" : 600, "category" : TZ_DST},
-	"YEKST" : {"offset" : 360, "category" : TZ_DST},
-	"CHODST" : {"offset" : 540, "category" : TZ_DST},
-	"HOVDST" : {"offset" : 480, "category" : TZ_DST},
+    "A": {"offset": 60, "category": TZ_MILITARY},
+    "B": {"offset": 120, "category": TZ_MILITARY},
+    "C": {"offset": 180, "category": TZ_MILITARY},
+    "D": {"offset": 240, "category": TZ_MILITARY},
+    "E": {"offset": 300, "category": TZ_MILITARY},
+    "F": {"offset": 360, "category": TZ_MILITARY},
+    "G": {"offset": 420, "category": TZ_MILITARY},
+    "H": {"offset": 480, "category": TZ_MILITARY},
+    "I": {"offset": 540, "category": TZ_MILITARY},
+    "K": {"offset": 600, "category": TZ_MILITARY},
+    "L": {"offset": 660, "category": TZ_MILITARY},
+    "M": {"offset": 720, "category": TZ_MILITARY},
+    "N": {"offset": -60, "category": TZ_MILITARY},
+    "O": {"offset": -120, "category": TZ_MILITARY},
+    "P": {"offset": -180, "category": TZ_MILITARY},
+    "Q": {"offset": -240, "category": TZ_MILITARY},
+    "R": {"offset": -300, "category": TZ_MILITARY},
+    "S": {"offset": -360, "category": TZ_MILITARY},
+    "T": {"offset": -420, "category": TZ_MILITARY},
+    "U": {"offset": -480, "category": TZ_MILITARY},
+    "V": {"offset": -540, "category": TZ_MILITARY},
+    "W": {"offset": -600, "category": TZ_MILITARY},
+    "X": {"offset": -660, "category": TZ_MILITARY},
+    "Y": {"offset": -720, "category": TZ_MILITARY},
+    "Z": {"offset": 0, "category": TZ_MILITARY},
+    "AT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "BT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "CT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "ET": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "GT": {"offset": 0, "category": 0},
+    "IT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "KT": {"offset": 540, "category": 0},
+    "MT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "PT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "ST": {"offset": 780, "category": 0},
+    "UT": {"offset": 0, "category": TZ_UTC | TZ_RFC},
+    "WT": {"offset": 0, "category": 0},
+    "ACT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "ADT": {"offset": 0, "category": TZ_AMBIGUOUS | TZ_DST},
+    "AET": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "AFT": {"offset": 270, "category": 0},
+    "AMT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "AoE": {"offset": -720, "category": 0},
+    "ART": {"offset": -180, "category": 0},
+    "AST": {"offset": 0, "category": TZ_AMBIGUOUS | TZ_DST},
+    "AZT": {"offset": 240, "category": 0},
+    "BDT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "BNT": {"offset": 480, "category": 0},
+    "BOT": {"offset": -240, "category": 0},
+    "BRT": {"offset": -180, "category": 0},
+    "BST": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "BTT": {"offset": 360, "category": 0},
+    "CAT": {"offset": 120, "category": 0},
+    "CCT": {"offset": 390, "category": 0},
+    "CDT": {"offset": -300, "category": TZ_RFC | TZ_AMBIGUOUS | TZ_DST},
+    "CET": {"offset": 60, "category": 0},
+    "CIT": {"offset": -300, "category": 0},
+    "CKT": {"offset": -600, "category": 0},
+    "CLT": {"offset": -180, "category": 0},
+    "COT": {"offset": -300, "category": 0},
+    "CST": {"offset": -360, "category": TZ_RFC | TZ_AMBIGUOUS},
+    "CVT": {"offset": -60, "category": 0},
+    "CXT": {"offset": 420, "category": 0},
+    "EAT": {"offset": 180, "category": 0},
+    "ECT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "EDT": {"offset": -240, "category": TZ_RFC | TZ_AMBIGUOUS | TZ_DST},
+    "EET": {"offset": 120, "category": 0},
+    "EGT": {"offset": -60, "category": 0},
+    "EST": {"offset": -300, "category": TZ_RFC | TZ_AMBIGUOUS},
+    "FET": {"offset": 180, "category": 0},
+    "FJT": {"offset": 720, "category": 0},
+    "FKT": {"offset": -240, "category": 0},
+    "FNT": {"offset": -120, "category": 0},
+    "GET": {"offset": 240, "category": 0},
+    "GFT": {"offset": -180, "category": 0},
+    "GMT": {"offset": 0, "category": TZ_UTC | TZ_RFC},
+    "GST": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "GYT": {"offset": -240, "category": 0},
+    "HAA": {"offset": -180, "category": 0},
+    "HAC": {"offset": -300, "category": 0},
+    "HAE": {"offset": -240, "category": 0},
+    "HAP": {"offset": -420, "category": 0},
+    "HAR": {"offset": -360, "category": 0},
+    "HAT": {"offset": -90, "category": 0},
+    "HDT": {"offset": -540, "category": TZ_DST},
+    "HKT": {"offset": 480, "category": 0},
+    "HLV": {"offset": -210, "category": 0},
+    "HNA": {"offset": -240, "category": 0},
+    "HNC": {"offset": -360, "category": 0},
+    "HNE": {"offset": -300, "category": 0},
+    "HNP": {"offset": -480, "category": 0},
+    "HNR": {"offset": -420, "category": 0},
+    "HNT": {"offset": -150, "category": 0},
+    "HST": {"offset": -600, "category": 0},
+    "ICT": {"offset": 420, "category": 0},
+    "IDT": {"offset": 0, "category": TZ_AMBIGUOUS | TZ_DST},
+    "IOT": {"offset": 360, "category": 0},
+    "IST": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "JST": {"offset": 540, "category": 0},
+    "KGT": {"offset": 360, "category": 0},
+    "KIT": {"offset": 300, "category": 0},
+    "KST": {"offset": 540, "category": 0},
+    "MCK": {"offset": 180, "category": 0},
+    "MDT": {"offset": -360, "category": TZ_RFC | TZ_DST},
+    "MEZ": {"offset": 60, "category": 0},
+    "MHT": {"offset": 720, "category": 0},
+    "MMT": {"offset": 390, "category": 0},
+    "MSD": {"offset": 240, "category": TZ_DST},
+    "MSK": {"offset": 180, "category": 0},
+    "MST": {"offset": -420, "category": TZ_RFC | TZ_AMBIGUOUS},
+    "MUT": {"offset": 240, "category": 0},
+    "MVT": {"offset": 300, "category": 0},
+    "MYT": {"offset": 480, "category": 0},
+    "NCT": {"offset": 660, "category": 0},
+    "NDT": {"offset": -90, "category": TZ_DST},
+    "NFT": {"offset": 660, "category": 0},
+    "NPT": {"offset": 345, "category": 0},
+    "NRT": {"offset": 720, "category": 0},
+    "NST": {"offset": -150, "category": 0},
+    "NUT": {"offset": -660, "category": 0},
+    "OEZ": {"offset": 120, "category": 0},
+    "PDT": {"offset": -420, "category": TZ_RFC | TZ_DST},
+    "PET": {"offset": -300, "category": 0},
+    "PGT": {"offset": 600, "category": 0},
+    "PHT": {"offset": 480, "category": 0},
+    "PKT": {"offset": 300, "category": 0},
+    "PST": {"offset": -480, "category": TZ_RFC | TZ_AMBIGUOUS},
+    "PWT": {"offset": 540, "category": 0},
+    "PYT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "RET": {"offset": 240, "category": 0},
+    "SBT": {"offset": 660, "category": 0},
+    "SCT": {"offset": 240, "category": 0},
+    "SGT": {"offset": 480, "category": 0},
+    "SRT": {"offset": -180, "category": 0},
+    "SST": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "TFT": {"offset": 300, "category": 0},
+    "TJT": {"offset": 300, "category": 0},
+    "TKT": {"offset": 780, "category": 0},
+    "TLT": {"offset": 540, "category": 0},
+    "TMT": {"offset": 300, "category": 0},
+    "TOT": {"offset": 780, "category": 0},
+    "TRT": {"offset": 180, "category": 0},
+    "TVT": {"offset": 720, "category": 0},
+    "UTC": {"offset": 0, "category": TZ_UTC | TZ_RFC},
+    "UYT": {"offset": -180, "category": 0},
+    "UZT": {"offset": 300, "category": 0},
+    "VET": {"offset": -210, "category": 0},
+    "VUT": {"offset": 660, "category": 0},
+    "WAT": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "WDT": {"offset": 540, "category": TZ_DST},
+    "WET": {"offset": 0, "category": 0},
+    "WEZ": {"offset": 0, "category": 0},
+    "WFT": {"offset": 720, "category": 0},
+    "WGT": {"offset": -180, "category": 0},
+    "WIB": {"offset": 420, "category": 0},
+    "WIT": {"offset": 540, "category": 0},
+    "WST": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "ACDT": {"offset": 630, "category": TZ_DST},
+    "ACST": {"offset": 570, "category": 0},
+    "ADST": {"offset": 0, "category": TZ_AMBIGUOUS | TZ_DST},
+    "AEDT": {"offset": 660, "category": TZ_DST},
+    "AEST": {"offset": 600, "category": 0},
+    "AKDT": {"offset": -480, "category": TZ_DST},
+    "AKST": {"offset": -540, "category": 0},
+    "ALMT": {"offset": 360, "category": 0},
+    "AMDT": {"offset": 300, "category": TZ_DST},
+    "AMST": {"offset": 0, "category": TZ_AMBIGUOUS | TZ_DST},
+    "ANAT": {"offset": 720, "category": 0},
+    "AQTT": {"offset": 300, "category": 0},
+    "AWDT": {"offset": 540, "category": TZ_DST},
+    "AWST": {"offset": 480, "category": 0},
+    "AZOT": {"offset": -60, "category": 0},
+    "AZST": {"offset": 300, "category": TZ_DST},
+    "BDST": {"offset": 60, "category": TZ_DST},
+    "BRST": {"offset": -120, "category": TZ_DST},
+    "CAST": {"offset": 480, "category": 0},
+    "CDST": {"offset": 0, "category": TZ_AMBIGUOUS | TZ_DST},
+    "CEDT": {"offset": 120, "category": TZ_DST},
+    "CEST": {"offset": 120, "category": TZ_DST},
+    "CHOT": {"offset": 480, "category": 0},
+    "ChST": {"offset": 600, "category": 0},
+    "CHUT": {"offset": 600, "category": 0},
+    "CIST": {"offset": -300, "category": 0},
+    "CLDT": {"offset": -180, "category": TZ_DST},
+    "CLST": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "DAVT": {"offset": 420, "category": 0},
+    "DDUT": {"offset": 600, "category": 0},
+    "EADT": {"offset": -300, "category": TZ_DST},
+    "EAST": {"offset": -300, "category": 0},
+    "ECST": {"offset": 120, "category": TZ_DST},
+    "EDST": {"offset": 0, "category": TZ_AMBIGUOUS | TZ_DST},
+    "EEDT": {"offset": 180, "category": TZ_DST},
+    "EEST": {"offset": 180, "category": TZ_DST},
+    "EGST": {"offset": 0, "category": TZ_DST},
+    "FJDT": {"offset": 780, "category": TZ_DST},
+    "FJST": {"offset": 780, "category": TZ_DST},
+    "FKDT": {"offset": -180, "category": TZ_DST},
+    "FKST": {"offset": 0, "category": TZ_AMBIGUOUS | TZ_DST},
+    "GALT": {"offset": -360, "category": 0},
+    "GAMT": {"offset": -540, "category": 0},
+    "GILT": {"offset": 720, "category": 0},
+    "HADT": {"offset": -540, "category": TZ_DST},
+    "HAST": {"offset": -600, "category": 0},
+    "HOVT": {"offset": 420, "category": 0},
+    "IRDT": {"offset": 270, "category": TZ_DST},
+    "IRKT": {"offset": 480, "category": 0},
+    "IRST": {"offset": 0, "category": TZ_AMBIGUOUS | TZ_DST},
+    "KOST": {"offset": 660, "category": 0},
+    "KRAT": {"offset": 420, "category": 0},
+    "KUYT": {"offset": 240, "category": 0},
+    "LHDT": {"offset": 660, "category": TZ_DST},
+    "LHST": {"offset": 630, "category": 0},
+    "LINT": {"offset": 840, "category": 0},
+    "MAGT": {"offset": 600, "category": 0},
+    "MART": {"offset": -510, "category": 0},
+    "MAWT": {"offset": 300, "category": 0},
+    "MDST": {"offset": -360, "category": TZ_DST},
+    "MESZ": {"offset": 120, "category": 0},
+    "NFDT": {"offset": 720, "category": TZ_DST},
+    "NOVT": {"offset": 360, "category": 0},
+    "NZDT": {"offset": 780, "category": TZ_DST},
+    "NZST": {"offset": 720, "category": 0},
+    "OESZ": {"offset": 180, "category": 0},
+    "OMST": {"offset": 360, "category": 0},
+    "ORAT": {"offset": 300, "category": 0},
+    "PDST": {"offset": -420, "category": TZ_DST},
+    "PETT": {"offset": 720, "category": 0},
+    "PHOT": {"offset": 780, "category": 0},
+    "PMDT": {"offset": -120, "category": TZ_DST},
+    "PMST": {"offset": -180, "category": 0},
+    "PONT": {"offset": 660, "category": 0},
+    "PYST": {"offset": 0, "category": TZ_AMBIGUOUS},
+    "QYZT": {"offset": 360, "category": 0},
+    "ROTT": {"offset": -180, "category": 0},
+    "SAKT": {"offset": 600, "category": 0},
+    "SAMT": {"offset": 240, "category": 0},
+    "SAST": {"offset": 120, "category": 0},
+    "SRET": {"offset": 660, "category": 0},
+    "SYOT": {"offset": 180, "category": 0},
+    "TAHT": {"offset": -600, "category": 0},
+    "TOST": {"offset": 840, "category": TZ_DST},
+    "ULAT": {"offset": 480, "category": 0},
+    "UYST": {"offset": -120, "category": TZ_DST},
+    "VLAT": {"offset": 600, "category": 0},
+    "VOST": {"offset": 360, "category": 0},
+    "WAKT": {"offset": 720, "category": 0},
+    "WAST": {"offset": 120, "category": TZ_DST},
+    "WEDT": {"offset": 60, "category": TZ_DST},
+    "WEST": {"offset": 60, "category": TZ_DST},
+    "WESZ": {"offset": 60, "category": 0},
+    "WGST": {"offset": -120, "category": TZ_DST},
+    "WITA": {"offset": 480, "category": 0},
+    "YAKT": {"offset": 540, "category": 0},
+    "YAPT": {"offset": 600, "category": 0},
+    "YEKT": {"offset": 300, "category": 0},
+    "ACWST": {"offset": 525, "category": 0},
+    "ANAST": {"offset": 720, "category": TZ_DST},
+    "AZODT": {"offset": 0, "category": TZ_DST},
+    "AZOST": {"offset": 0, "category": TZ_AMBIGUOUS | TZ_DST},
+    "CHADT": {"offset": 825, "category": TZ_DST},
+    "CHAST": {"offset": 765, "category": 0},
+    "CHODT": {"offset": 540, "category": TZ_DST},
+    "CHOST": {"offset": 540, "category": TZ_DST},
+    "CIDST": {"offset": -240, "category": TZ_DST},
+    "EASST": {"offset": -300, "category": TZ_DST},
+    "EFATE": {"offset": 660, "category": 0},
+    "HOVDT": {"offset": 480, "category": TZ_DST},
+    "HOVST": {"offset": 480, "category": TZ_DST},
+    "IRKST": {"offset": 540, "category": TZ_DST},
+    "KRAST": {"offset": 480, "category": TZ_DST},
+    "MAGST": {"offset": 720, "category": TZ_DST},
+    "NACDT": {"offset": -300, "category": TZ_DST},
+    "NACST": {"offset": -360, "category": 0},
+    "NAEDT": {"offset": -240, "category": TZ_DST},
+    "NAEST": {"offset": -300, "category": 0},
+    "NAMDT": {"offset": -360, "category": TZ_DST},
+    "NAMST": {"offset": -420, "category": 0},
+    "NAPDT": {"offset": -420, "category": TZ_DST},
+    "NAPST": {"offset": -480, "category": 0},
+    "NOVST": {"offset": 420, "category": TZ_DST},
+    "OMSST": {"offset": 420, "category": TZ_DST},
+    "PETST": {"offset": 720, "category": TZ_DST},
+    "SAMST": {"offset": 240, "category": TZ_DST},
+    "ULAST": {"offset": 540, "category": TZ_DST},
+    "VLAST": {"offset": 660, "category": TZ_DST},
+    "WARST": {"offset": -180, "category": TZ_DST},
+    "YAKST": {"offset": 600, "category": TZ_DST},
+    "YEKST": {"offset": 360, "category": TZ_DST},
+    "CHODST": {"offset": 540, "category": TZ_DST},
+    "HOVDST": {"offset": 480, "category": TZ_DST},
 }
diff --git a/tarantool/msgpack_ext/types/timezones/validate_timezones.py b/tarantool/msgpack_ext/types/timezones/validate_timezones.py
deleted file mode 100644
index 943437f8..00000000
--- a/tarantool/msgpack_ext/types/timezones/validate_timezones.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""
-Script to validate that each Tarantool timezone is either a valid pytz
-timezone or an addreviated timezone with explicit offset provided.
-"""
-
-import pytz
-from timezones import timezoneToIndex, timezoneAbbrevInfo
-
-if __name__ != '__main__':
-    raise Error('Import not expected')
-
-for timezone in timezoneToIndex.keys():
-    if timezone in pytz.all_timezones:
-        continue
-
-    if not timezone in timezoneAbbrevInfo:
-        raise Exception(f'Unknown Tarantool timezone {timezone}')
diff --git a/tarantool/msgpack_ext/unpacker.py b/tarantool/msgpack_ext/unpacker.py
index 6950f485..985653d5 100644
--- a/tarantool/msgpack_ext/unpacker.py
+++ b/tarantool/msgpack_ext/unpacker.py
@@ -3,6 +3,7 @@
 
 .. _extension: https://www.tarantool.io/en/doc/latest/dev_guide/internals/msgpack_extensions/
 """
+# pylint: disable=duplicate-code
 
 import tarantool.msgpack_ext.decimal as ext_decimal
 import tarantool.msgpack_ext.uuid as ext_uuid
@@ -11,13 +12,14 @@
 import tarantool.msgpack_ext.interval as ext_interval
 
 decoders = {
-    ext_decimal.EXT_ID : ext_decimal.decode ,
-    ext_uuid.EXT_ID    : ext_uuid.decode    ,
-    ext_error.EXT_ID   : ext_error.decode   ,
+    ext_decimal.EXT_ID: ext_decimal.decode,
+    ext_uuid.EXT_ID: ext_uuid.decode,
+    ext_error.EXT_ID: ext_error.decode,
     ext_datetime.EXT_ID: ext_datetime.decode,
     ext_interval.EXT_ID: ext_interval.decode,
 }
 
+
 def ext_hook(code, data, unpacker=None):
     """
     :class:`msgpack.Unpacker` decoder.
@@ -42,4 +44,4 @@ def ext_hook(code, data, unpacker=None):
 
     if code in decoders:
         return decoders[code](data, unpacker)
-    raise NotImplementedError("Unknown msgpack extension type code %d" % (code,))
+    raise NotImplementedError(f"Unknown msgpack extension type code {code}")
diff --git a/tarantool/msgpack_ext/uuid.py b/tarantool/msgpack_ext/uuid.py
index 91b4ac94..859d096c 100644
--- a/tarantool/msgpack_ext/uuid.py
+++ b/tarantool/msgpack_ext/uuid.py
@@ -20,6 +20,7 @@
 `uuid`_ type id.
 """
 
+
 def encode(obj, _):
     """
     Encode an UUID object.
@@ -33,6 +34,7 @@ def encode(obj, _):
 
     return obj.bytes
 
+
 def decode(data, _):
     """
     Decode an UUID object.
diff --git a/tarantool/request.py b/tarantool/request.py
index 73ef9bd2..f8a7e7c9 100644
--- a/tarantool/request.py
+++ b/tarantool/request.py
@@ -1,17 +1,13 @@
-# pylint: disable=C0301,W0105,W0401,W0614
 """
 Request types definitions. For internal use only, there is no API to
 send pre-build request objects.
 """
 
-import sys
-import msgpack
 import hashlib
-
 from collections.abc import Sequence, Mapping
 
+import msgpack
 
-from tarantool.error import DatabaseError
 from tarantool.const import (
     IPROTO_REQUEST_TYPE,
     IPROTO_SYNC,
@@ -65,6 +61,7 @@
 
 from tarantool.msgpack_ext.packer import default as packer_default
 
+
 def packer_factory(conn):
     """
     Build packer to pack request.
@@ -75,7 +72,7 @@ def packer_factory(conn):
     :rtype: :class:`msgpack.Packer`
     """
 
-    packer_kwargs = dict()
+    packer_kwargs = {}
 
     # use_bin_type=True is default since msgpack-1.0.0.
     #
@@ -116,17 +113,18 @@ def packer_factory(conn):
     else:
         packer_kwargs['use_bin_type'] = True
 
-    # We need configured packer to work with error extention
+    # We need configured packer to work with error extension
     # type payload, but module do not provide access to self
     # inside extension type packers.
-    packer_no_ext = msgpack.Packer(**packer_kwargs)
-    default = lambda obj: packer_default(obj, packer_no_ext)
+    def default(obj):
+        packer_no_ext = msgpack.Packer(**packer_kwargs)
+        return packer_default(obj, packer_no_ext)
     packer_kwargs['default'] = default
 
     return msgpack.Packer(**packer_kwargs)
 
 
-class Request(object):
+class Request():
     """
     Represents a single request to the server in compliance with the
     Tarantool protocol. Responsible for data encapsulation and building
@@ -206,7 +204,6 @@ class RequestInsert(Request):
 
     request_type = REQUEST_TYPE_INSERT
 
-    # pylint: disable=W0231
     def __init__(self, conn, space_no, values):
         """
         :param conn: Request sender.
@@ -221,7 +218,7 @@ def __init__(self, conn, space_no, values):
         :raise: :exc:`~AssertionError`
         """
 
-        super(RequestInsert, self).__init__(conn)
+        super().__init__(conn)
         assert isinstance(values, (tuple, list))
 
         request_body = self._dumps({IPROTO_SPACE_ID: space_no,
@@ -229,6 +226,7 @@ def __init__(self, conn, space_no, values):
 
         self._body = request_body
 
+
 def sha1(values):
     """
     Compute hash.
@@ -250,6 +248,7 @@ def sha1(values):
                 sha.update(i.encode())
     return sha.digest()
 
+
 class RequestAuthenticate(Request):
     """
     Represents AUTHENTICATE request.
@@ -276,8 +275,9 @@ def __init__(self, conn, salt, user, password, auth_type=AUTH_TYPE_CHAP_SHA1):
         :param auth_type: Refer to :paramref:`~tarantool.Connection.auth_type`.
         :type auth_type: :obj:`str`, optional
         """
+        # pylint: disable=too-many-arguments
 
-        super(RequestAuthenticate, self).__init__(conn)
+        super().__init__(conn)
 
         if auth_type == AUTH_TYPE_CHAP_SHA1:
             hash1 = sha1((password,))
@@ -322,7 +322,6 @@ class RequestReplace(Request):
 
     request_type = REQUEST_TYPE_REPLACE
 
-    # pylint: disable=W0231
     def __init__(self, conn, space_no, values):
         """
         :param conn: Request sender.
@@ -337,7 +336,7 @@ def __init__(self, conn, space_no, values):
         :raise: :exc:`~AssertionError`
         """
 
-        super(RequestReplace, self).__init__(conn)
+        super().__init__(conn)
         assert isinstance(values, (tuple, list))
 
         request_body = self._dumps({IPROTO_SPACE_ID: space_no,
@@ -353,7 +352,6 @@ class RequestDelete(Request):
 
     request_type = REQUEST_TYPE_DELETE
 
-    # pylint: disable=W0231
     def __init__(self, conn, space_no, index_no, key):
         """
         :param conn: Request sender.
@@ -371,7 +369,7 @@ def __init__(self, conn, space_no, index_no, key):
         :raise: :exc:`~AssertionError`
         """
 
-        super(RequestDelete, self).__init__(conn)
+        super().__init__(conn)
 
         request_body = self._dumps({IPROTO_SPACE_ID: space_no,
                                     IPROTO_INDEX_ID: index_no,
@@ -387,7 +385,6 @@ class RequestSelect(Request):
 
     request_type = REQUEST_TYPE_SELECT
 
-    # pylint: disable=W0231
     def __init__(self, conn, space_no, index_no, key, offset, limit, iterator):
         """
         :param conn: Request sender.
@@ -414,8 +411,9 @@ def __init__(self, conn, space_no, index_no, key, offset, limit, iterator):
 
         :raise: :exc:`~AssertionError`
         """
+        # pylint: disable=too-many-arguments
 
-        super(RequestSelect, self).__init__(conn)
+        super().__init__(conn)
         request_body = self._dumps({IPROTO_SPACE_ID: space_no,
                                     IPROTO_INDEX_ID: index_no,
                                     IPROTO_OFFSET: offset,
@@ -433,7 +431,6 @@ class RequestUpdate(Request):
 
     request_type = REQUEST_TYPE_UPDATE
 
-    # pylint: disable=W0231
     def __init__(self, conn, space_no, index_no, key, op_list):
         """
         :param conn: Request sender.
@@ -455,8 +452,9 @@ def __init__(self, conn, space_no, index_no, key, op_list):
 
         :raise: :exc:`~AssertionError`
         """
+        # pylint: disable=too-many-arguments
 
-        super(RequestUpdate, self).__init__(conn)
+        super().__init__(conn)
 
         request_body = self._dumps({IPROTO_SPACE_ID: space_no,
                                     IPROTO_INDEX_ID: index_no,
@@ -473,7 +471,6 @@ class RequestCall(Request):
 
     request_type = REQUEST_TYPE_CALL
 
-    # pylint: disable=W0231
     def __init__(self, conn, name, args, call_16):
         """
         :param conn: Request sender.
@@ -494,7 +491,7 @@ def __init__(self, conn, name, args, call_16):
 
         if call_16:
             self.request_type = REQUEST_TYPE_CALL16
-        super(RequestCall, self).__init__(conn)
+        super().__init__(conn)
         assert isinstance(args, (list, tuple))
 
         request_body = self._dumps({IPROTO_FUNCTION_NAME: name,
@@ -510,7 +507,6 @@ class RequestEval(Request):
 
     request_type = REQUEST_TYPE_EVAL
 
-    # pylint: disable=W0231
     def __init__(self, conn, name, args):
         """
         :param conn: Request sender.
@@ -525,7 +521,7 @@ def __init__(self, conn, name, args):
         :raise: :exc:`~AssertionError`
         """
 
-        super(RequestEval, self).__init__(conn)
+        super().__init__(conn)
         assert isinstance(args, (list, tuple))
 
         request_body = self._dumps({IPROTO_EXPR: name,
@@ -547,7 +543,7 @@ def __init__(self, conn):
         :type conn: :class:`~tarantool.Connection`
         """
 
-        super(RequestPing, self).__init__(conn)
+        super().__init__(conn)
         self._body = b''
 
 
@@ -558,7 +554,6 @@ class RequestUpsert(Request):
 
     request_type = REQUEST_TYPE_UPSERT
 
-    # pylint: disable=W0231
     def __init__(self, conn, space_no, index_no, tuple_value, op_list):
         """
         :param conn: Request sender.
@@ -580,8 +575,9 @@ def __init__(self, conn, space_no, index_no, tuple_value, op_list):
 
         :raise: :exc:`~AssertionError`
         """
+        # pylint: disable=too-many-arguments
 
-        super(RequestUpsert, self).__init__(conn)
+        super().__init__(conn)
 
         request_body = self._dumps({IPROTO_SPACE_ID: space_no,
                                     IPROTO_INDEX_ID: index_no,
@@ -598,7 +594,6 @@ class RequestJoin(Request):
 
     request_type = REQUEST_TYPE_JOIN
 
-    # pylint: disable=W0231
     def __init__(self, conn, server_uuid):
         """
         :param conn: Request sender.
@@ -608,7 +603,7 @@ def __init__(self, conn, server_uuid):
         :type server_uuid: :obj:`str`
         """
 
-        super(RequestJoin, self).__init__(conn)
+        super().__init__(conn)
         request_body = self._dumps({IPROTO_SERVER_UUID: server_uuid})
         self._body = request_body
 
@@ -620,7 +615,6 @@ class RequestSubscribe(Request):
 
     request_type = REQUEST_TYPE_SUBSCRIBE
 
-    # pylint: disable=W0231
     def __init__(self, conn, cluster_uuid, server_uuid, vclock):
         """
         :param conn: Request sender.
@@ -638,7 +632,7 @@ def __init__(self, conn, cluster_uuid, server_uuid, vclock):
         :raise: :exc:`~AssertionError`
         """
 
-        super(RequestSubscribe, self).__init__(conn)
+        super().__init__(conn)
         assert isinstance(vclock, dict)
 
         request_body = self._dumps({
@@ -656,7 +650,6 @@ class RequestOK(Request):
 
     request_type = REQUEST_TYPE_OK
 
-    # pylint: disable=W0231
     def __init__(self, conn, sync):
         """
         :param conn: Request sender.
@@ -666,7 +659,7 @@ def __init__(self, conn, sync):
         :type sync: :obj:`int`
         """
 
-        super(RequestOK, self).__init__(conn)
+        super().__init__(conn)
         request_body = self._dumps({IPROTO_REQUEST_TYPE: self.request_type,
                                     IPROTO_SYNC: sync})
         self._body = request_body
@@ -693,12 +686,12 @@ def __init__(self, conn, sql, args):
         :raise: :exc:`~TypeError`
         """
 
-        super(RequestExecute, self).__init__(conn)
+        super().__init__(conn)
         if isinstance(args, Mapping):
-            args = [{":%s" % name: value} for name, value in args.items()]
+            args = [{f":{name}": value} for name, value in args.items()]
         elif not isinstance(args, Sequence):
-            raise TypeError("Parameter type '%s' is not supported. "
-                            "Must be a mapping or sequence" % type(args))
+            raise TypeError(f"Parameter type '{type(args)}' is not supported. "
+                            "Must be a mapping or sequence")
 
         request_body = self._dumps({IPROTO_SQL_TEXT: sql,
                                     IPROTO_SQL_BIND: args})
@@ -706,6 +699,7 @@ def __init__(self, conn, sql, args):
         self._body = request_body
         self.response_class = ResponseExecute
 
+
 class RequestProtocolVersion(Request):
     """
     Represents ID request: inform the server about the protocol
@@ -726,7 +720,7 @@ def __init__(self, conn, protocol_version, features):
         :type features: :obj:`list`
         """
 
-        super(RequestProtocolVersion, self).__init__(conn)
+        super().__init__(conn)
 
         request_body = self._dumps({IPROTO_VERSION: protocol_version,
                                     IPROTO_FEATURES: features})
diff --git a/tarantool/response.py b/tarantool/response.py
index ece616d4..0e062c74 100644
--- a/tarantool/response.py
+++ b/tarantool/response.py
@@ -1,4 +1,3 @@
-# pylint: disable=C0301,W0105,W0401,W0614
 """
 Request response types definitions.
 """
@@ -34,6 +33,7 @@
 
 from tarantool.msgpack_ext.unpacker import ext_hook as unpacker_ext_hook
 
+
 def unpacker_factory(conn):
     """
     Build unpacker to unpack request response.
@@ -44,7 +44,7 @@ def unpacker_factory(conn):
     :rtype: :class:`msgpack.Unpacker`
     """
 
-    unpacker_kwargs = dict()
+    unpacker_kwargs = {}
 
     # Decode MsgPack arrays into Python lists by default (not tuples).
     # Can be configured in the Connection init
@@ -68,7 +68,7 @@ def unpacker_factory(conn):
 
     # encoding option is not supported since msgpack-1.0.0,
     # but it is handled in the Connection constructor.
-    assert(msgpack.version < (1, 0, 0) or conn.encoding in (None, 'utf-8'))
+    assert msgpack.version < (1, 0, 0) or conn.encoding in (None, 'utf-8')
 
     # strict_map_key=True is default since msgpack-1.0.0.
     #
@@ -76,11 +76,12 @@ def unpacker_factory(conn):
     if msgpack.version >= (1, 0, 0):
         unpacker_kwargs['strict_map_key'] = False
 
-    # We need configured unpacker to work with error extention
+    # We need configured unpacker to work with error extension
     # type payload, but module do not provide access to self
     # inside extension type unpackers.
-    unpacker_no_ext = msgpack.Unpacker(**unpacker_kwargs)
-    ext_hook = lambda code, data: unpacker_ext_hook(code, data, unpacker_no_ext)
+    def ext_hook(code, data):
+        unpacker_no_ext = msgpack.Unpacker(**unpacker_kwargs)
+        return unpacker_ext_hook(code, data, unpacker_no_ext)
     unpacker_kwargs['ext_hook'] = ext_hook
 
     return msgpack.Unpacker(**unpacker_kwargs)
@@ -93,6 +94,7 @@ class Response(Sequence):
     received list of tuples) and parsing of binary packets received from
     the server.
     """
+    # pylint: disable=too-many-instance-attributes
 
     def __init__(self, conn, response):
         """
@@ -129,8 +131,8 @@ def __init__(self, conn, response):
             self._return_code = 0
             self._schema_version = header.get(IPROTO_SCHEMA_ID, None)
             self._data = self._body.get(IPROTO_DATA, None)
-            if (not isinstance(self._data, (list, tuple)) and
-                    self._data is not None):
+            if (not isinstance(self._data, (list, tuple))
+                    and self._data is not None):
                 self._data = [self._data]
             # # Backward-compatibility
             # if isinstance(self._data, (list, tuple)):
@@ -192,7 +194,7 @@ def index(self, *args):
             raise InterfaceError("Trying to access data when there's no data")
         return self._data.index(*args)
 
-    def count(self, item):
+    def count(self, value):
         """
         Refer to :class:`collections.abc.Sequence`.
 
@@ -201,7 +203,7 @@ def count(self, item):
 
         if self._data is None:
             raise InterfaceError("Trying to access data when there's no data")
-        return self._data.count(item)
+        return self._data.count(value)
 
     @property
     def rowcount(self):
@@ -302,7 +304,7 @@ def __str__(self):
                     'code': self.strerror[0],
                     'reason': self.return_message
                 }
-            }, sort_keys = True, indent = 4, separators=(', ', ': '))
+            }, sort_keys=True, indent=4, separators=(', ', ': '))
         output = []
         for tpl in self._data or ():
             output.extend(("- ", repr(tpl), "\n"))
diff --git a/tarantool/schema.py b/tarantool/schema.py
index 94f49048..556737b7 100644
--- a/tarantool/schema.py
+++ b/tarantool/schema.py
@@ -1,39 +1,35 @@
-# pylint: disable=R0903
 """
 Schema types definitions. For internal use only, there is no API to use
 pre-build schema objects.
 """
 
 from tarantool.error import (
-    Error,
     SchemaError,
     DatabaseError
 )
-import tarantool.const as const
-
+from tarantool.const import (
+    INDEX_SPACE_NAME,
+    INDEX_INDEX_NAME,
+    INDEX_SPACE_PRIMARY,
+    INDEX_INDEX_PRIMARY,
+    SPACE_VSPACE,
+    SPACE_VINDEX,
+    SPACE_SPACE,
+    SPACE_INDEX
+)
 
+MAX_RECURSION_DEPTH = 32
 """
 Max possible known schema depth is 4 if foreign keys are used (since
 Tarantool 2.10), but there are no restrictions in protocol.
 """
-MAX_RECURSION_DEPTH = 32
-
-
-class RecursionError(Error):
-    """
-    Report the situation when max recursion depth is reached.
-
-    This is an internal error of
-    :func:`~tarantool.schema.to_unicode_recursive` caller and it should
-    be re-raised properly by the caller.
-    """
 
 
-def to_unicode(s):
+def to_unicode(string):
     """
     Decode :obj:`bytes` to unicode :obj:`str`.
 
-    :param s: Value to convert.
+    :param string: Value to convert.
 
     :return: Decoded unicode :obj:`str`, if value is :obj:`bytes`.
         Otherwise, it returns the original value.
@@ -41,17 +37,17 @@ def to_unicode(s):
     :meta private:
     """
 
-    if isinstance(s, bytes):
-        return s.decode(encoding='utf-8')
-    return s
+    if isinstance(string, bytes):
+        return string.decode(encoding='utf-8')
+    return string
 
 
-def to_unicode_recursive(x, max_depth):
+def to_unicode_recursive(value, max_depth):
     """
     Recursively decode :obj:`bytes` to unicode :obj:`str` over
     :obj:`dict`, :obj:`list` and :obj:`tuple`.
 
-    :param x: Value to convert.
+    :param value: Value to convert.
 
     :param max_depth: Maximum depth recursion.
     :type max_depth: :obj:`int`
@@ -59,7 +55,7 @@ def to_unicode_recursive(x, max_depth):
     :return: The same structure where all :obj:`bytes` are replaced
         with unicode :obj:`str`.
 
-    :raise: :exc:`~tarantool.schema.RecursionError`
+    :raise: :exc:`~RecursionError`
 
     :meta private:
     """
@@ -67,30 +63,31 @@ def to_unicode_recursive(x, max_depth):
     if max_depth <= 0:
         raise RecursionError('Max recursion depth is reached')
 
-    if isinstance(x, dict):
-        res = dict()
-        for key, val in x.items():
+    if isinstance(value, dict):
+        res = {}
+        for key, val in value.items():
             key = to_unicode_recursive(key, max_depth - 1)
             val = to_unicode_recursive(val, max_depth - 1)
             res[key] = val
         return res
 
-    if isinstance(x, list) or isinstance(x, tuple):
+    if isinstance(value, (list, tuple)):
         res = []
-        for val in x:
-            val = to_unicode_recursive(val, max_depth - 1)
-            res.append(val)
-        if isinstance(x, tuple):
+        for item in value:
+            item = to_unicode_recursive(item, max_depth - 1)
+            res.append(item)
+        if isinstance(value, tuple):
             return tuple(res)
         return res
 
-    return to_unicode(x)
+    return to_unicode(value)
 
 
-class SchemaIndex(object):
+class SchemaIndex():
     """
     Contains schema for a space index.
     """
+    # pylint: disable=too-few-public-methods
 
     def __init__(self, index_row, space):
         """
@@ -110,9 +107,9 @@ def __init__(self, index_row, space):
         self.parts = []
         try:
             parts_raw = to_unicode_recursive(index_row[5], MAX_RECURSION_DEPTH)
-        except RecursionError as e:
-            errmsg = 'Unexpected index parts structure: ' + str(e)
-            raise SchemaError(errmsg)
+        except RecursionError as exc:
+            errmsg = 'Unexpected index parts structure: ' + str(exc)
+            raise SchemaError(errmsg) from exc
         if isinstance(parts_raw, (list, tuple)):
             for val in parts_raw:
                 if isinstance(val, dict):
@@ -140,10 +137,11 @@ def flush(self):
             del self.space.indexes[self.name]
 
 
-class SchemaSpace(object):
+class SchemaSpace():
     """
     Contains schema for a space.
     """
+    # pylint: disable=too-few-public-methods
 
     def __init__(self, space_row, schema):
         """
@@ -164,16 +162,16 @@ def __init__(self, space_row, schema):
         self.schema[self.sid] = self
         if self.name:
             self.schema[self.name] = self
-        self.format = dict()
+        self.format = {}
         try:
             format_raw = to_unicode_recursive(space_row[6], MAX_RECURSION_DEPTH)
-        except RecursionError as e:
-            errmsg = 'Unexpected space format structure: ' + str(e)
-            raise SchemaError(errmsg)
+        except RecursionError as exc:
+            errmsg = 'Unexpected space format structure: ' + str(exc)
+            raise SchemaError(errmsg) from exc
         for part_id, part in enumerate(format_raw):
             part['id'] = part_id
             self.format[part['name']] = part
-            self.format[part_id     ] = part
+            self.format[part_id] = part
 
     def flush(self):
         """
@@ -185,10 +183,11 @@ def flush(self):
             del self.schema[self.name]
 
 
-class Schema(object):
+class Schema():
     """
     Contains Tarantool server spaces schema.
     """
+    # pylint: disable=too-few-public-methods
 
     def __init__(self, con):
         """
@@ -242,10 +241,10 @@ def fetch_space(self, space):
             raise SchemaError(
                 'Some strange output from server: \n' + str(space_row)
             )
-        elif len(space_row) == 0 or not len(space_row[0]):
+        if len(space_row) == 0 or not space_row[0]:
             # We can't find space with this name or id
             temp_name = 'name' if isinstance(space, str) else 'id'
-            errmsg = "There's no space with {1} '{0}'".format(space, temp_name)
+            errmsg = f"There's no space with {temp_name} '{space}'"
             raise SchemaError(errmsg)
 
         space_row = space_row[0]
@@ -268,9 +267,9 @@ def fetch_space_from(self, space):
 
         _index = None
         if isinstance(space, str):
-            _index = const.INDEX_SPACE_NAME
+            _index = INDEX_SPACE_NAME
         else:
-            _index = const.INDEX_SPACE_PRIMARY
+            _index = INDEX_SPACE_PRIMARY
 
         if space is None:
             space = ()
@@ -278,16 +277,16 @@ def fetch_space_from(self, space):
         space_row = None
         try:
             # Try to fetch from '_vspace'
-            space_row = self.con.select(const.SPACE_VSPACE, space,
+            space_row = self.con.select(SPACE_VSPACE, space,
                                         index=_index)
-        except DatabaseError as e:
+        except DatabaseError as exc:
             # if space can't be found, then user is using old version of
             # tarantool, try again with '_space'
-            if e.args[0] != 36:
+            if exc.args[0] != 36:
                 raise
         if space_row is None:
             # Try to fetch from '_space'
-            space_row = self.con.select(const.SPACE_SPACE, space, index=_index)
+            space_row = self.con.select(SPACE_SPACE, space, index=_index)
 
         return space_row
 
@@ -354,12 +353,11 @@ def fetch_index(self, space_object, index):
             raise SchemaError(
                 'Some strange output from server: \n' + str(index_row)
             )
-        elif len(index_row) == 0 or not len(index_row[0]):
+        if len(index_row) == 0 or not index_row[0]:
             # We can't find index with this name or id
             temp_name = 'name' if isinstance(index, str) else 'id'
-            errmsg = ("There's no index with {2} '{0}'"
-                      " in space '{1}'").format(index, space_object.name,
-                                                temp_name)
+            errmsg = (f"There's no index with {temp_name} '{index}'"
+                      f" in space '{space_object.name}'")
             raise SchemaError(errmsg)
 
         index_row = index_row[0]
@@ -398,15 +396,15 @@ def fetch_index_from(self, space, index):
 
         _index = None
         if isinstance(index, str):
-            _index = const.INDEX_INDEX_NAME
+            _index = INDEX_INDEX_NAME
         else:
-            _index = const.INDEX_INDEX_PRIMARY
+            _index = INDEX_INDEX_PRIMARY
 
         _key_tuple = None
         if space is None and index is None:
             _key_tuple = ()
         elif space is not None and index is None:
-            _key_tuple = (space)
+            _key_tuple = (space, )
         elif space is not None and index is not None:
             _key_tuple = (space, index)
         else:
@@ -415,16 +413,16 @@ def fetch_index_from(self, space, index):
         index_row = None
         try:
             # Try to fetch from '_vindex'
-            index_row = self.con.select(const.SPACE_VINDEX, _key_tuple,
+            index_row = self.con.select(SPACE_VINDEX, _key_tuple,
                                         index=_index)
-        except DatabaseError as e:
+        except DatabaseError as exc:
             # if space can't be found, then user is using old version of
             # tarantool, try again with '_index'
-            if e.args[0] != 36:
+            if exc.args[0] != 36:
                 raise
         if index_row is None:
             # Try to fetch from '_index'
-            index_row = self.con.select(const.SPACE_INDEX, _key_tuple,
+            index_row = self.con.select(SPACE_INDEX, _key_tuple,
                                         index=_index)
 
         return index_row
@@ -451,12 +449,10 @@ def get_field(self, space, field):
         _space = self.get_space(space)
         try:
             return _space.format[field]
-        except:
-            tp = 'name' if isinstance(field, str) else 'id'
-            errmsg = "There's no field with {2} '{0}' in space '{1}'".format(
-                    field, _space.name, tp
-            )
-            raise SchemaError(errmsg)
+        except KeyError as exc:
+            kind = 'name' if isinstance(field, str) else 'id'
+            errmsg = f"There's no field with {kind} '{field}' in space '{_space.name}'"
+            raise SchemaError(errmsg) from exc
 
         return field
 
diff --git a/tarantool/space.py b/tarantool/space.py
index 0fa61198..11a3e3ca 100644
--- a/tarantool/space.py
+++ b/tarantool/space.py
@@ -1,11 +1,10 @@
-# pylint: disable=C0301,W0105,W0401,W0614
 """
 Space type definition. It is an object-oriented wrapper for requests to
 a Tarantool server space.
 """
 
 
-class Space(object):
+class Space():
     """
     Object-oriented wrapper for accessing a particular space.
     Encapsulates the identifier of the space and provides a more
diff --git a/tarantool/types.py b/tarantool/types.py
index 5ca86150..d849dcfa 100644
--- a/tarantool/types.py
+++ b/tarantool/types.py
@@ -5,6 +5,7 @@
 import typing
 from dataclasses import dataclass
 
+
 @dataclass
 class BoxError():
     """
@@ -13,6 +14,7 @@ class BoxError():
 
     .. _box.error: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_error/error/
     """
+    # pylint: disable=too-many-instance-attributes
 
     type: typing.Union[str, bytes]
     """
@@ -76,6 +78,7 @@ class BoxError():
 MP_ERROR_ERRCODE = 0x05
 MP_ERROR_FIELDS = 0x06
 
+
 def decode_box_error(err_map):
     """
     Decode MessagePack map received from Tarantool to `box.error`_
@@ -100,13 +103,14 @@ def decode_box_error(err_map):
             message=item[MP_ERROR_MESSAGE],
             errno=item[MP_ERROR_ERRNO],
             errcode=item[MP_ERROR_ERRCODE],
-            fields=item.get(MP_ERROR_FIELDS), # omitted if empty
+            fields=item.get(MP_ERROR_FIELDS),  # omitted if empty
             prev=prev,
         )
         prev = err
 
     return prev
 
+
 def encode_box_error(err):
     """
     Encode Python `box.error`_ representation to MessagePack map.
@@ -131,7 +135,7 @@ def encode_box_error(err):
             MP_ERROR_ERRCODE: err.errcode,
         }
 
-        if err.fields is not None: # omitted if empty
+        if err.fields is not None:  # omitted if empty
             dict_item[MP_ERROR_FIELDS] = err.fields
 
         stack.append(dict_item)
diff --git a/tarantool/utils.py b/tarantool/utils.py
index e5238707..c7d9e246 100644
--- a/tarantool/utils.py
+++ b/tarantool/utils.py
@@ -1,9 +1,14 @@
-import sys
+"""
+This module provides untility functions for the package.
+"""
+
+from base64 import decodebytes as base64_decode
+from dataclasses import dataclass
+import typing
 import uuid
 
 ENCODING_DEFAULT = "utf-8"
 
-from base64 import decodebytes as base64_decode
 
 def strxor(rhs, lhs):
     """
@@ -20,6 +25,7 @@ def strxor(rhs, lhs):
 
     return bytes([x ^ y for x, y in zip(rhs, lhs)])
 
+
 def wrap_key(*args, first=True, select=False):
     """
     Wrap request key in list, if needed.
@@ -41,7 +47,7 @@ def wrap_key(*args, first=True, select=False):
     if len(args) == 1:
         if isinstance(args[0], (list, tuple)) and first:
             return wrap_key(*args[0], first=False, select=select)
-        elif args[0] is None and select:
+        if args[0] is None and select:
             return []
 
     return list(args)
@@ -65,6 +71,34 @@ def version_id(major, minor, patch):
 
     return (((major << 8) | minor) << 8) | patch
 
+
+@dataclass
+class Greeting():
+    """
+    Connection greeting info.
+    """
+
+    version_id: typing.Optional = 0
+    """
+    :type: :obj:`tuple` or :obj:`list`
+    """
+
+    protocol: typing.Optional[str] = None
+    """
+    :type: :obj:`str`, optional
+    """
+
+    uuid: typing.Optional[str] = None
+    """
+    :type: :obj:`str`, optional
+    """
+
+    salt: typing.Optional[str] = None
+    """
+    :type: :obj:`str`, optional
+    """
+
+
 def greeting_decode(greeting_buf):
     """
     Decode Tarantool server greeting.
@@ -78,12 +112,6 @@ def greeting_decode(greeting_buf):
     :raise: :exc:`~Exception`
     """
 
-    class Greeting:
-        version_id = 0
-        protocol = None
-        uuid = None
-        salt = None
-
     # Tarantool 1.6.6
     # Tarantool 1.6.6-102-g4e9bde2
     # Tarantool 1.6.8 (Binary) 3b151c25-4c4a-4b5d-8042-0f1b3a6f61c3
@@ -92,7 +120,7 @@ class Greeting:
     try:
         (product, _, tail) = greeting_buf[0:63].decode().partition(' ')
         if product.startswith("Tarantool "):
-            raise Exception()
+            raise ValueError()
         # Parse a version string - 1.6.6-83-gc6b2129 or 1.6.7
         (version, _, tail) = tail.partition(' ')
         version = version.split('-')[0].split('.')
@@ -112,9 +140,9 @@ class Greeting:
             # Tarantool < 1.6.7 doesn't add "(Binary)" to greeting
             result.protocol = "Binary"
         elif len(tail.strip()) != 0:
-            raise Exception("x")  # Unsupported greeting
+            raise ValueError("x")  # Unsupported greeting
         result.salt = base64_decode(greeting_buf[64:])[:20]
         return result
-    except Exception as e:
-        print('exx', e)
-        raise ValueError("Invalid greeting: " + str(greeting_buf))
+    except ValueError as exc:
+        print('exx', exc)
+        raise ValueError("Invalid greeting: " + str(greeting_buf)) from exc


Test patch:
diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml
index 90ae0e49..c49f8b92 100644
--- a/.github/workflows/testing.yml
+++ b/.github/workflows/testing.yml
@@ -37,7 +37,7 @@ jobs:
           - ''
 
         # Adding too many elements to three-dimentional matrix results in
-        # too many test cases. It causes GitHub webpages to fail with 
+        # too many test cases. It causes GitHub webpages to fail with
         # "This page is taking too long to load." error. Thus we use
         # pairwise testing.
         include:
diff --git a/requirements-test.txt b/requirements-test.txt
index ae4091d2..94d16351 100644
--- a/requirements-test.txt
+++ b/requirements-test.txt
@@ -1,3 +1,6 @@
 git+https://github.com/baztian/dbapi-compliance.git@ea7cb1b4#egg=dbapi-compliance
 pyyaml==6.0
 importlib-metadata >= 1.0 ; python_version < '3.8'
+pylint
+flake8
+codespell
diff --git a/test/setup_command.py b/test/setup_command.py
index da0cb6c4..9df5f8cd 100755
--- a/test/setup_command.py
+++ b/test/setup_command.py
@@ -1,30 +1,47 @@
 #!/usr/bin/env python
+"""
+This module describes class implementing `python setup.py test`.
+"""
 
-import os
-import sys
 import unittest
+
 import setuptools
-from distutils.errors import DistutilsError
 
-from glob import glob
+try:
+    from setuptools.errors import BaseError
+except (ModuleNotFoundError, ImportError):
+    # pylint: disable=deprecated-module
+    from distutils.errors import DistutilsError as BaseError
+
+
+class Test(setuptools.Command):
+    """
+    Class implementing `python setup.py test`.
+    """
+    # pylint: disable=bad-option-value,no-self-use
 
-class test(setuptools.Command):
     user_options = []
     description = 'Run tests'
 
     def initialize_options(self):
-        pass
+        """
+        Do nothing. setuptools requires to override this abstract
+        method.
+        """
 
     def finalize_options(self):
-        pass
+        """
+        Do nothing. setuptools requires to override this abstract
+        method.
+        """
 
     def run(self):
-        '''
+        """
         Find all tests in test/tarantool/ and run them
-        '''
+        """
 
         tests = unittest.defaultTestLoader.discover('test', pattern='suites')
         test_runner = unittest.TextTestRunner(verbosity=2)
         result = test_runner.run(tests)
         if not result.wasSuccessful():
-            raise DistutilsError('There are failed tests')
+            raise BaseError('There are failed tests')
diff --git a/test/suites/__init__.py b/test/suites/__init__.py
index c8fa35d7..d56b2889 100644
--- a/test/suites/__init__.py
+++ b/test/suites/__init__.py
@@ -1,47 +1,57 @@
+"""
+Module tests entrypoint.
+"""
+
 import os
 import unittest
 
-__tmp = os.getcwd()
-os.chdir(os.path.abspath(os.path.dirname(__file__)))
+from .test_schema import TestSuiteSchemaUnicodeConnection
+from .test_schema import TestSuiteSchemaBinaryConnection
+from .test_dml import TestSuiteRequest
+from .test_protocol import TestSuiteProtocol
+from .test_reconnect import TestSuiteReconnect
+from .test_mesh import TestSuiteMesh
+from .test_pool import TestSuitePool
+from .test_execute import TestSuiteExecute
+from .test_dbapi import TestSuiteDBAPI
+from .test_encoding import TestSuiteEncoding
+from .test_ssl import TestSuiteSsl
+from .test_decimal import TestSuiteDecimal
+from .test_uuid import TestSuiteUUID
+from .test_datetime import TestSuiteDatetime
+from .test_interval import TestSuiteInterval
+from .test_package import TestSuitePackage
+from .test_error_ext import TestSuiteErrorExt
+from .test_push import TestSuitePush
+from .test_connection import TestSuiteConnection
+from .test_crud import TestSuiteCrud
+
+test_cases = (TestSuiteSchemaUnicodeConnection,
+              TestSuiteSchemaBinaryConnection,
+              TestSuiteRequest, TestSuiteProtocol, TestSuiteReconnect,
+              TestSuiteMesh, TestSuiteExecute, TestSuiteDBAPI,
+              TestSuiteEncoding, TestSuitePool, TestSuiteSsl,
+              TestSuiteDecimal, TestSuiteUUID, TestSuiteDatetime,
+              TestSuiteInterval, TestSuitePackage, TestSuiteErrorExt,
+              TestSuitePush, TestSuiteConnection, TestSuiteCrud,)
 
-from .test_schema import TestSuite_Schema_UnicodeConnection
-from .test_schema import TestSuite_Schema_BinaryConnection
-from .test_dml import TestSuite_Request
-from .test_protocol import TestSuite_Protocol
-from .test_reconnect import TestSuite_Reconnect
-from .test_mesh import TestSuite_Mesh
-from .test_pool import TestSuite_Pool
-from .test_execute import TestSuite_Execute
-from .test_dbapi import TestSuite_DBAPI
-from .test_encoding import TestSuite_Encoding
-from .test_ssl import TestSuite_Ssl
-from .test_decimal import TestSuite_Decimal
-from .test_uuid import TestSuite_UUID
-from .test_datetime import TestSuite_Datetime
-from .test_interval import TestSuite_Interval
-from .test_package import TestSuite_Package
-from .test_error_ext import TestSuite_ErrorExt
-from .test_push import TestSuite_Push
-from .test_connection import TestSuite_Connection
-from .test_crud import TestSuite_Crud
-
-test_cases = (TestSuite_Schema_UnicodeConnection,
-              TestSuite_Schema_BinaryConnection,
-              TestSuite_Request, TestSuite_Protocol, TestSuite_Reconnect,
-              TestSuite_Mesh, TestSuite_Execute, TestSuite_DBAPI,
-              TestSuite_Encoding, TestSuite_Pool, TestSuite_Ssl,
-              TestSuite_Decimal, TestSuite_UUID, TestSuite_Datetime,
-              TestSuite_Interval, TestSuite_ErrorExt, TestSuite_Push,
-              TestSuite_Connection, TestSuite_Crud,)
 
 def load_tests(loader, tests, pattern):
+    """
+    Add suites to test run.
+    """
+    # pylint: disable=unused-argument
+
     suite = unittest.TestSuite()
     for testc in test_cases:
         suite.addTests(loader.loadTestsFromTestCase(testc))
     return suite
 
 
+__tmp = os.getcwd()
+os.chdir(os.path.abspath(os.path.dirname(__file__)))
+
 os.chdir(__tmp)
 
 # Workaround to disable unittest output truncating
-__import__('sys').modules['unittest.util']._MAX_LENGTH = 99999
+__import__('sys').modules['unittest.util']._MAX_LENGTH = 99999  # pylint: disable=protected-access
diff --git a/test/suites/lib/remote_tarantool_server.py b/test/suites/lib/remote_tarantool_server.py
index 5d6afd77..7d4118ba 100644
--- a/test/suites/lib/remote_tarantool_server.py
+++ b/test/suites/lib/remote_tarantool_server.py
@@ -1,3 +1,8 @@
+"""
+This module provides helpers to work with remote Tarantool server
+(used on Windows).
+"""
+
 import sys
 import os
 import random
@@ -15,10 +20,17 @@
 
 
 def get_random_string():
+    """
+    :type: :obj:`str`
+    """
     return ''.join(random.choice(string.ascii_lowercase) for _ in range(16))
 
 
-class RemoteTarantoolServer(object):
+class RemoteTarantoolServer():
+    """
+    Class to work with remote Tarantool server.
+    """
+
     def __init__(self):
         self.host = os.environ['REMOTE_TARANTOOL_HOST']
 
@@ -26,7 +38,7 @@ def __init__(self):
         self.args['primary'] = BINARY_PORT
         self.args['admin'] = os.environ['REMOTE_TARANTOOL_CONSOLE_PORT']
 
-        assert(self.args['primary'] != self.args['admin'])
+        assert self.args['primary'] != self.args['admin']
 
         # a name to using for a lock
         self.whoami = get_random_string()
@@ -39,54 +51,78 @@ def __init__(self):
         self.admin.execute('box.cfg{listen = box.NULL}')
 
     def acquire_lock(self):
+        """
+        Acquire lock on the remote server so no concurrent tests would run.
+        """
+
         deadline = time.time() + AWAIT_TIME
         while True:
-            res = self.admin.execute('return acquire_lock("%s")' % self.whoami)
+            res = self.admin.execute(f'return acquire_lock("{ self.whoami}")')
             ok = res[0]
             err = res[1] if not ok else None
             if ok:
                 break
             if time.time() > deadline:
-                raise RuntimeError('can not acquire "%s" lock: %s' % (
-                    self.whoami, str(err)))
-            print('waiting to acquire "%s" lock' % self.whoami,
+                raise RuntimeError(f'can not acquire "{self.whoami}" lock: {str(err)}')
+            print(f'waiting to acquire "{self.whoami}" lock',
                   file=sys.stderr)
             time.sleep(1)
         self.lock_is_acquired = True
 
     def touch_lock(self):
-        assert(self.lock_is_acquired)
-        res = self.admin.execute('return touch_lock("%s")' % self.whoami)
+        """
+        Refresh locked state on the remote server so no concurrent
+        tests would run.
+        """
+
+        assert self.lock_is_acquired
+        res = self.admin.execute(f'return touch_lock("{self.whoami}")')
         ok = res[0]
         err = res[1] if not ok else None
         if not ok:
-            raise RuntimeError('can not update "%s" lock: %s' % (
-                self.whoami, str(err)))
+            raise RuntimeError(f'can not update "{self.whoami}" lock: {str(err)}')
 
     def release_lock(self):
-        res = self.admin.execute('return release_lock("%s")' % self.whoami)
+        """
+        Release loack so another test suite can run on the remote
+        server.
+        """
+
+        res = self.admin.execute(f'return release_lock("{self.whoami}")')
         ok = res[0]
         err = res[1] if not ok else None
         if not ok:
-            raise RuntimeError('can not release "%s" lock: %s' % (
-                self.whoami, str(err)))
+            raise RuntimeError(f'can not release "{self.whoami}" lock: {str(err)}')
         self.lock_is_acquired = False
 
     def start(self):
+        """
+        Initialize the work with the remote server.
+        """
+
         if not self.lock_is_acquired:
             self.acquire_lock()
-        self.admin.execute('box.cfg{listen = "0.0.0.0:%s"}' %
-                           self.args['primary'])
+        self.admin.execute(f'box.cfg{{listen = "0.0.0.0:{self.args["primary"]}"}}')
 
     def stop(self):
+        """
+        Finish the work with the remote server.
+        """
+
         self.admin.execute('box.cfg{listen = box.NULL}')
         self.release_lock()
 
     def is_started(self):
+        """
+        Check if we still work with the remote server.
+        """
+
         return self.lock_is_acquired
 
     def clean(self):
-        pass
+        """
+        Do nothing.
+        """
 
     def __del__(self):
         self.admin.disconnect()
diff --git a/test/suites/lib/skip.py b/test/suites/lib/skip.py
index c37fba0d..694d8d57 100644
--- a/test/suites/lib/skip.py
+++ b/test/suites/lib/skip.py
@@ -1,10 +1,16 @@
+"""
+This module provides helpers to skip specific tests.
+"""
+
 import functools
-import pkg_resources
-import re
 import sys
 
+import pkg_resources
+
+
 def fetch_tarantool_version(self):
-    """Helper to fetch current Tarantool version.
+    """
+    Helper to fetch current Tarantool version.
     """
     if not hasattr(self, 'tnt_version') or self.tnt_version is None:
         srv = None
@@ -19,11 +25,13 @@ def fetch_tarantool_version(self):
 
         try:
             self.tnt_version = srv.admin.tnt_version
-        except:
+        except AttributeError:
             self.__class__.tnt_version = srv.admin.tnt_version
 
-def skip_or_run_test_tarantool_impl(self, REQUIRED_TNT_VERSION, msg):
-    """Helper to skip or run tests depending on the Tarantool
+
+def skip_or_run_test_tarantool_impl(self, required_tt_version, msg):
+    """
+    Helper to skip or run tests depending on the Tarantool
     version.
 
     Also, it can be used with the 'setUp' method for skipping
@@ -31,14 +39,15 @@ def skip_or_run_test_tarantool_impl(self, REQUIRED_TNT_VERSION, msg):
     """
     fetch_tarantool_version(self)
 
-    support_version = pkg_resources.parse_version(REQUIRED_TNT_VERSION)
+    support_version = pkg_resources.parse_version(required_tt_version)
 
     if self.tnt_version < support_version:
-        self.skipTest('Tarantool %s %s' % (self.tnt_version, msg))
+        self.skipTest(f'Tarantool {self.tnt_version} {msg}')
 
 
-def skip_or_run_test_tarantool(func, REQUIRED_TNT_VERSION, msg):
-    """Decorator to skip or run tests depending on the tarantool
+def skip_or_run_test_tarantool(func, required_tt_version, msg):
+    """
+    Decorator to skip or run tests depending on the tarantool
     version.
 
     Also, it can be used with the 'setUp' method for skipping
@@ -50,15 +59,17 @@ def wrapper(self, *args, **kwargs):
         if func.__name__ == 'setUp':
             func(self, *args, **kwargs)
 
-        skip_or_run_test_tarantool_impl(self, REQUIRED_TNT_VERSION, msg)
+        skip_or_run_test_tarantool_impl(self, required_tt_version, msg)
 
         if func.__name__ != 'setUp':
             func(self, *args, **kwargs)
 
     return wrapper
 
-def skip_or_run_test_tarantool_call(self, REQUIRED_TNT_VERSION, msg):
-    """Function to skip or run tests depending on the tarantool
+
+def skip_or_run_test_tarantool_call(self, required_tt_version, msg):
+    """
+    Function to skip or run tests depending on the tarantool
     version. Useful in cases when in is inconvenient to work
     with decorators.
 
@@ -66,12 +77,13 @@ def skip_or_run_test_tarantool_call(self, REQUIRED_TNT_VERSION, msg):
     the whole test suite.
     """
 
-    skip_or_run_test_tarantool_impl(self, REQUIRED_TNT_VERSION, msg)
+    skip_or_run_test_tarantool_impl(self, required_tt_version, msg)
 
 
-def skip_or_run_test_pcall_require(func, REQUIRED_TNT_MODULE, msg):
-    """Decorator to skip or run tests depending on tarantool
-    module requre success or fail.
+def skip_or_run_test_pcall_require(func, required_tt_module, msg):
+    """
+    Decorator to skip or run tests depending on tarantool
+    module require success or fail.
 
     Also, it can be used with the 'setUp' method for skipping
     the whole test suite.
@@ -84,17 +96,17 @@ def wrapper(self, *args, **kwargs):
 
         srv = None
 
-        if hasattr(self, 'servers'):
+        if hasattr(self, 'servers') and self.servers:
             srv = self.servers[0]
 
-        if hasattr(self, 'srv'):
+        if hasattr(self, 'srv') and self.srv:
             srv = self.srv
 
         assert srv is not None
 
-        resp = srv.admin("pcall(require, '%s')" % REQUIRED_TNT_MODULE)
+        resp = srv.admin(f"pcall(require, '{required_tt_module}')")
         if not resp[0]:
-            self.skipTest('Tarantool %s' % (msg, ))
+            self.skipTest(f'Tarantool {msg}')
 
         if func.__name__ != 'setUp':
             func(self, *args, **kwargs)
@@ -102,8 +114,9 @@ def wrapper(self, *args, **kwargs):
     return wrapper
 
 
-def skip_or_run_test_python(func, REQUIRED_PYTHON_VERSION, msg):
-    """Decorator to skip or run tests depending on the Python version.
+def skip_or_run_test_python(func, required_python_version, msg):
+    """
+    Decorator to skip or run tests depending on the Python version.
 
     Also, it can be used with the 'setUp' method for skipping
     the whole test suite.
@@ -115,11 +128,11 @@ def wrapper(self, *args, **kwargs):
             func(self, *args, **kwargs)
 
         ver = sys.version_info
-        python_version_str = '%d.%d' % (ver.major, ver.minor)
+        python_version_str = f'{ver.major}.{ver.minor}'
         python_version = pkg_resources.parse_version(python_version_str)
-        support_version = pkg_resources.parse_version(REQUIRED_PYTHON_VERSION)
+        support_version = pkg_resources.parse_version(required_python_version)
         if python_version < support_version:
-            self.skipTest('Python %s connector %s' % (python_version, msg))
+            self.skipTest(f'Python {python_version} connector {msg}')
 
         if func.__name__ != 'setUp':
             func(self, *args, **kwargs)
@@ -128,7 +141,8 @@ def wrapper(self, *args, **kwargs):
 
 
 def skip_or_run_sql_test(func):
-    """Decorator to skip or run SQL-related tests depending on the
+    """
+    Decorator to skip or run SQL-related tests depending on the
     tarantool version.
 
     Tarantool supports SQL-related stuff only since 2.0.0 version.
@@ -140,7 +154,8 @@ def skip_or_run_sql_test(func):
 
 
 def skip_or_run_varbinary_test(func):
-    """Decorator to skip or run VARBINARY-related tests depending on
+    """
+    Decorator to skip or run VARBINARY-related tests depending on
     the tarantool version.
 
     Tarantool supports VARBINARY type only since 2.2.1 version.
@@ -152,7 +167,8 @@ def skip_or_run_varbinary_test(func):
 
 
 def skip_or_run_decimal_test(func):
-    """Decorator to skip or run decimal-related tests depending on
+    """
+    Decorator to skip or run decimal-related tests depending on
     the tarantool version.
 
     Tarantool supports decimal type only since 2.2.1 version.
@@ -160,10 +176,12 @@ def skip_or_run_decimal_test(func):
     """
 
     return skip_or_run_test_pcall_require(func, 'decimal',
-                                      'does not support decimal type')
+                                          'does not support decimal type')
+
 
-def skip_or_run_UUID_test(func):
-    """Decorator to skip or run UUID-related tests depending on
+def skip_or_run_uuid_test(func):
+    """
+    Decorator to skip or run UUID-related tests depending on
     the tarantool version.
 
     Tarantool supports UUID type only since 2.4.1 version.
@@ -173,8 +191,10 @@ def skip_or_run_UUID_test(func):
     return skip_or_run_test_tarantool(func, '2.4.1',
                                       'does not support UUID type')
 
+
 def skip_or_run_datetime_test(func):
-    """Decorator to skip or run datetime-related tests depending on
+    """
+    Decorator to skip or run datetime-related tests depending on
     the tarantool version.
 
     Tarantool supports datetime type only since 2.10.0 version.
@@ -182,10 +202,12 @@ def skip_or_run_datetime_test(func):
     """
 
     return skip_or_run_test_pcall_require(func, 'datetime',
-                                      'does not support datetime type')
+                                          'does not support datetime type')
+
 
 def skip_or_run_error_extra_info_test(func):
-    """Decorator to skip or run tests related to extra error info
+    """
+    Decorator to skip or run tests related to extra error info
     provided over iproto depending on the tarantool version.
 
     Tarantool provides extra error info only since 2.4.1 version.
@@ -195,8 +217,10 @@ def skip_or_run_error_extra_info_test(func):
     return skip_or_run_test_tarantool(func, '2.4.1',
                                       'does not provide extra error info')
 
+
 def skip_or_run_error_ext_type_test(func):
-    """Decorator to skip or run tests related to error extension
+    """
+    Decorator to skip or run tests related to error extension
     type depending on the tarantool version.
 
     Tarantool supports error extension type only since 2.4.1 version,
@@ -208,8 +232,10 @@ def skip_or_run_error_ext_type_test(func):
     return skip_or_run_test_tarantool(func, '2.10.0',
                                       'does not support error extension type')
 
+
 def skip_or_run_ssl_password_test_call(self):
-    """Function to skip or run tests related to SSL password
+    """
+    Function to skip or run tests related to SSL password
     and SSL password files support. Supported only in Tarantool EE.
     Do not check Enterprise prefix since TNT_SSL_TEST already assumes
     it.
@@ -222,8 +248,10 @@ def skip_or_run_ssl_password_test_call(self):
     return skip_or_run_test_tarantool_call(self, '2.11.0',
                                            'does not support SSL passwords')
 
+
 def skip_or_run_auth_type_test_call(self):
-    """Function to skip or run tests related to configuring
+    """
+    Function to skip or run tests related to configuring
     authentication method.
 
     Tarantool supports auth_type only in current master since
@@ -237,8 +265,10 @@ def skip_or_run_auth_type_test_call(self):
     return skip_or_run_test_tarantool_call(self, '2.11.0',
                                            'does not support auth type')
 
+
 def skip_or_run_constraints_test(func):
-    """Decorator to skip or run tests related to spaces with
+    """
+    Decorator to skip or run tests related to spaces with
     schema constraints.
 
     Tarantool supports schema constraints only since 2.10.0 version.
diff --git a/test/suites/lib/tarantool_admin.py b/test/suites/lib/tarantool_admin.py
index 33a6d61f..de75a0e2 100644
--- a/test/suites/lib/tarantool_admin.py
+++ b/test/suites/lib/tarantool_admin.py
@@ -1,10 +1,19 @@
+"""
+This module provides helpers to setup running Tarantool server.
+"""
+
 import socket
-import yaml
 import re
+
 import pkg_resources
+import yaml
+
 
+class TarantoolAdmin():
+    """
+    Class to setup running Tarantool server.
+    """
 
-class TarantoolAdmin(object):
     def __init__(self, host, port):
         self.host = host
         self.port = port
@@ -13,18 +22,30 @@ def __init__(self, host, port):
         self._tnt_version = None
 
     def connect(self):
+        """
+        Connect to running Tarantool server.
+        """
+
         self.socket = socket.create_connection((self.host, self.port))
         self.socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
         self.is_connected = True
         self.socket.recv(256)  # skip greeting
 
     def disconnect(self):
+        """
+        Disconnect from the Tarantool server.
+        """
+
         if self.is_connected:
             self.socket.close()
             self.socket = None
             self.is_connected = False
 
     def reconnect(self):
+        """
+        Reconnect to the running Tarantool server.
+        """
+
         self.disconnect()
         self.connect()
 
@@ -32,15 +53,19 @@ def __enter__(self):
         self.connect()
         return self
 
-    def __exit__(self, type, value, tb):
+    def __exit__(self, exception_type, exception_value, exception_traceback):
         self.disconnect()
 
     def __call__(self, command):
         return self.execute(command)
 
     def execute(self, command):
+        """
+        Evaluate some Lua code on the Tarantool server.
+        """
+
         if not command:
-            return
+            return None
 
         if not self.is_connected:
             self.connect()
@@ -68,6 +93,10 @@ def execute(self, command):
 
     @property
     def tnt_version(self):
+        """
+        Connected Tarantool server version.
+        """
+
         if self._tnt_version is not None:
             return self._tnt_version
 
diff --git a/test/suites/lib/tarantool_server.py b/test/suites/lib/tarantool_server.py
index ceecb5a7..241e0c92 100644
--- a/test/suites/lib/tarantool_server.py
+++ b/test/suites/lib/tarantool_server.py
@@ -1,3 +1,7 @@
+"""
+This module provides helpers start up a Tarantool server.
+"""
+
 import os
 import os.path
 import errno
@@ -10,14 +14,19 @@
 import shutil
 import subprocess
 
-from .tarantool_admin import TarantoolAdmin
-
 from tarantool.const import (
     SSL_TRANSPORT
 )
 
+from .tarantool_admin import TarantoolAdmin
+from .remote_tarantool_server import RemoteTarantoolServer
+
 
 def check_port(port, rais=True):
+    """
+    Check if port is free.
+    """
+
     try:
         sock = socket.create_connection(("0.0.0.0", port))
     except socket.error:
@@ -25,11 +34,15 @@ def check_port(port, rais=True):
     sock.close()
 
     if rais:
-        raise RuntimeError("The server is already running on port {0}".format(port))
+        raise RuntimeError(f"The server is already running on port {port}")
     return False
 
 
 def find_port(port=None):
+    """
+    Pick some free socket.
+    """
+
     if port is None:
         port = random.randrange(3300, 9999)
     while port < 9999:
@@ -39,44 +52,70 @@ def find_port(port=None):
     return find_port(3300)
 
 
-class RunnerException(object):
-    pass
-
+class TarantoolServer():
+    """
+    Class to start up a new Tarantool server.
+    """
+    # pylint: disable=too-many-instance-attributes,too-many-arguments,duplicate-code
 
-class TarantoolServer(object):
     default_tarantool = {
-            "bin":     "tarantool",
-            "logfile": "tarantool.log",
-            "init":    "init.lua"}
+        "bin": "tarantool",
+        "logfile": "tarantool.log",
+        "init": "init.lua"}
 
     default_cfg = {
-            "custom_proc_title": "\"tarantool-python testing\"",
-            "memtx_memory":      0.5 * 1024**3,  # 0.5 GiB
-            "pid_file":          "\"box.pid\""}
+        "custom_proc_title": "\"tarantool-python testing\"",
+        "memtx_memory": 0.5 * 1024**3,  # 0.5 GiB
+        "pid_file": "\"box.pid\""}
 
     @property
     def logfile_path(self):
+        """
+        Path to server logs.
+        """
+
         return os.path.join(self.vardir, self.default_tarantool['logfile'])
 
     @property
     def cfgfile_path(self):
+        """
+        Path to server configuration.
+        """
+
         return os.path.join(self.vardir, self.default_tarantool['config'])
 
     @property
     def script_path(self):
+        """
+        Path to server init.lua script.
+        """
+
         return os.path.join(self.vardir, self.default_tarantool['init'])
 
     @property
     def script_dst(self):
+        """
+        Path to server init.lua folder.
+        """
+
         return os.path.join(self.vardir, os.path.basename(self.script))
 
     @property
     def script(self):
-        if not hasattr(self, '_script'): self._script = None
+        """
+        Get server init.lua script.
+        """
+
+        if not hasattr(self, '_script'):
+            self._script = None
         return self._script
 
     @script.setter
     def script(self, val):
+        """
+        Set server init.lua script.
+        """
+
         if val is None:
             if hasattr(self, '_script'):
                 delattr(self, '_script')
@@ -85,39 +124,61 @@ def script(self, val):
 
     @property
     def binary(self):
-        if not hasattr(self, '_binary'):
+        """
+        Get Tarantool binary used to start the server.
+        """
+
+        if self._binary is None:
             self._binary = self.find_exe()
         return self._binary
 
     @property
     def _admin(self):
+        """
+        Get admin connection used to set up the server.
+        """
+
         if not hasattr(self, 'admin'):
             self.admin = None
         return self.admin
 
     @_admin.setter
     def _admin(self, port):
+        """
+        Set admin connection used to set up the server.
+        """
+
         try:
             int(port)
-        except ValueError:
-            raise ValueError("Bad port number: '%s'" % port)
+        except ValueError as exc:
+            raise ValueError(f"Bad port number: '{port}'") from exc
         if hasattr(self, 'admin'):
             del self.admin
         self.admin = TarantoolAdmin('0.0.0.0', port)
 
     @property
     def log_des(self):
-        if not hasattr(self, '_log_des'):
-            self._log_des = open(self.logfile_path, 'a')
+        """
+        Get server log file descriptor.
+        """
+        # pylint: disable=consider-using-with
+
+        if self._log_des is None:
+            self._log_des = open(self.logfile_path, 'a', encoding='utf-8')
         return self._log_des
 
     @log_des.deleter
     def log_des(self):
-        if not hasattr(self, '_log_des'):
+        """
+        Set server log file descriptor.
+        """
+
+        if self._log_des is None:
             return
         if not self._log_des.closed:
             self._log_des.close()
-        delattr(self, '_log_des')
+
+        self._log_des = None
 
     def __new__(cls,
                 transport=None,
@@ -129,8 +190,9 @@ def __new__(cls,
                 ssl_password_file=None,
                 create_unix_socket=False,
                 auth_type=None):
+        # pylint: disable=unused-argument
+
         if os.name == 'nt':
-            from .remote_tarantool_server import RemoteTarantoolServer
             return RemoteTarantoolServer()
         return super(TarantoolServer, cls).__new__(cls)
 
@@ -144,6 +206,8 @@ def __init__(self,
                  ssl_password_file=None,
                  create_unix_socket=False,
                  auth_type=None):
+        # pylint: disable=consider-using-with
+
         os.popen('ulimit -c unlimited').close()
 
         if create_unix_socket:
@@ -171,8 +235,14 @@ def __init__(self,
         self.ssl_password = ssl_password
         self.ssl_password_file = ssl_password_file
         self.auth_type = auth_type
+        self._binary = None
+        self._log_des = None
 
     def find_exe(self):
+        """
+        Find Tarantool executable.
+        """
+
         if 'TARANTOOL_BOX_PATH' in os.environ:
             os.environ["PATH"] = os.environ["TARANTOOL_BOX_PATH"] + os.pathsep + os.environ["PATH"]
 
@@ -183,26 +253,34 @@ def find_exe(self):
         raise RuntimeError("Can't find server executable in " + os.environ["PATH"])
 
     def generate_listen(self, port, port_only):
+        """
+        Generate Tarantool server box.cfg listen.
+        """
+
         if not port_only and self.transport == SSL_TRANSPORT:
             listen = self.host + ":" + str(port) + "?transport=ssl&"
             if self.ssl_key_file:
-                listen += "ssl_key_file={}&".format(self.ssl_key_file)
+                listen += f"ssl_key_file={self.ssl_key_file}&"
             if self.ssl_cert_file:
-                listen += "ssl_cert_file={}&".format(self.ssl_cert_file)
+                listen += f"ssl_cert_file={self.ssl_cert_file}&"
             if self.ssl_ca_file:
-                listen += "ssl_ca_file={}&".format(self.ssl_ca_file)
+                listen += f"ssl_ca_file={self.ssl_ca_file}&"
             if self.ssl_ciphers:
-                listen += "ssl_ciphers={}&".format(self.ssl_ciphers)
+                listen += f"ssl_ciphers={self.ssl_ciphers}&"
             if self.ssl_password:
-                listen += "ssl_password={}&".format(self.ssl_password)
+                listen += f"ssl_password={self.ssl_password}&"
             if self.ssl_password_file:
-                listen += "ssl_password_file={}&".format(self.ssl_password_file)
+                listen += f"ssl_password_file={self.ssl_password_file}&"
             listen = listen[:-1]
         else:
             listen = str(port)
         return listen
 
     def generate_configuration(self):
+        """
+        Generate Tarantool box.cfg values.
+        """
+
         primary_listen = self.generate_listen(self.args['primary'], False)
         admin_listen = self.generate_listen(self.args['admin'], True)
         os.putenv("LISTEN", primary_listen)
@@ -213,10 +291,15 @@ def generate_configuration(self):
             os.putenv("AUTH_TYPE", "")
 
     def prepare_args(self):
+        """
+        Prepare Tarantool server init.lua script.
+        """
+
         return shlex.split(self.binary if not self.script else self.script_dst)
 
     def wait_until_started(self):
-        """ Wait until server is started.
+        """
+        Wait until server is started.
 
         Server consists of two parts:
         1) wait until server is listening on sockets
@@ -231,48 +314,64 @@ def wait_until_started(self):
                     if ans in ('running', 'hot_standby', 'orphan') or ans.startswith('replica'):
                         temp.disconnect()
                         return True
-                    elif ans in ('loading',):
+                    if ans in ('loading',):
                         continue
-                    else:
-                        raise Exception("Strange output for `box.info.status`: %s" % (ans))
-            except socket.error as e:
-                if e.errno == errno.ECONNREFUSED:
+
+                    raise ValueError(f"Strange output for `box.info.status`: {ans}")
+            except socket.error as exc:
+                if exc.errno == errno.ECONNREFUSED:
                     time.sleep(0.1)
                     continue
                 raise
 
     def start(self):
-        # Main steps for running Tarantool\Box
-        # * Find binary file          --DONE(find_exe -> binary)
-        # * Create vardir             --DONE(__init__)
-        # * Generate cfgfile          --DONE(generate_configuration)
-        # * (MAYBE) Copy init.lua     --INSIDE
-        # * Concatenate arguments and
-        #   start Tarantool\Box       --DONE(prepare_args)
-        # * Wait unitl Tarantool\Box
-        #   started                   --DONE(wait_until_started)
+        """
+        Main steps for running Tarantool\\Box
+        * Find binary file          --DONE(find_exe -> binary)
+        * Create vardir             --DONE(__init__)
+        * Generate cfgfile          --DONE(generate_configuration)
+        * (MAYBE) Copy init.lua     --INSIDE
+        * Concatenate arguments and
+          start Tarantool\\Box       --DONE(prepare_args)
+        * Wait until Tarantool\\Box
+          started                   --DONE(wait_until_started)
+        """
+        # pylint: disable=consider-using-with
+
         self.generate_configuration()
         if self.script:
             shutil.copy(self.script, self.script_dst)
             os.chmod(self.script_dst, 0o777)
         args = self.prepare_args()
         self.process = subprocess.Popen(args,
-                cwd=self.vardir,
-                stdout=self.log_des,
-                stderr=self.log_des)
+                                        cwd=self.vardir,
+                                        stdout=self.log_des,
+                                        stderr=self.log_des)
         self.wait_until_started()
 
     def stop(self):
+        """
+        Stop Tarantool server.
+        """
+
         self.admin.disconnect()
         if self.process.poll() is None:
             self.process.terminate()
             self.process.wait()
 
     def restart(self):
+        """
+        Restart Tarantool server.
+        """
+
         self.stop()
         self.start()
 
     def clean(self):
+        """
+        Clean Tarantool resources.
+        """
+
         if os.path.isdir(self.vardir):
             shutil.rmtree(self.vardir)
 
@@ -289,9 +388,14 @@ def __del__(self):
         self.clean()
 
     def touch_lock(self):
-        # A stub method to be compatible with
-        # RemoteTarantoolServer.
-        pass
+        """
+        A stub method to be compatible with
+        RemoteTarantoolServer.
+        """
 
     def is_started(self):
+        """
+        Is Tarantool server has need started.
+        """
+
         return self.process is not None
diff --git a/test/suites/test_connection.py b/test/suites/test_connection.py
index 4132d35e..52234608 100644
--- a/test/suites/test_connection.py
+++ b/test/suites/test_connection.py
@@ -1,3 +1,8 @@
+"""
+This module tests basic connection behavior.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,duplicate-code
+
 import sys
 import unittest
 
@@ -10,17 +15,18 @@
 from .lib.skip import skip_or_run_decimal_test, skip_or_run_varbinary_test
 from .lib.tarantool_server import TarantoolServer
 
-class TestSuite_Connection(unittest.TestCase):
+
+class TestSuiteConnection(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' CONNECTION '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
 
-        self.adm = self.srv.admin
-        self.adm(r"""
+        cls.adm = cls.srv.admin
+        cls.adm(r"""
             box.schema.user.create('test', {password = 'test', if_not_exists = true})
             box.schema.user.grant('test', 'read,write,execute', 'universe')
 
@@ -49,6 +55,7 @@ def setUpClass(self):
                 parts = {2, 'varbinary'},
                 unique = true})
         """)
+        cls.con = None
 
     def setUp(self):
         # prevent a remote tarantool from clean our session
@@ -61,7 +68,7 @@ def my_ext_type_encoder(obj):
             if isinstance(obj, decimal.Decimal):
                 obj = obj + 1
                 return msgpack.ExtType(ext_decimal.EXT_ID, ext_decimal.encode(obj, None))
-            raise TypeError("Unknown type: %r" % (obj,))
+            raise TypeError(f"Unknown type: {repr(obj)}")
 
         def my_packer_factory(_):
             return msgpack.Packer(default=my_ext_type_encoder)
@@ -92,14 +99,13 @@ def test_custom_unpacker(self):
         def my_ext_type_decoder(code, data):
             if code == ext_decimal.EXT_ID:
                 return ext_decimal.decode(data, None) - 1
-            raise NotImplementedError("Unknown msgpack extension type code %d" % (code,))
+            raise NotImplementedError(f"Unknown msgpack extension type code {code}")
 
         def my_unpacker_factory(_):
             if msgpack.version >= (1, 0, 0):
                 return msgpack.Unpacker(ext_hook=my_ext_type_decoder, strict_map_key=False)
             return msgpack.Unpacker(ext_hook=my_ext_type_decoder)
 
-
         self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'],
                                         user='test', password='test',
                                         unpacker_factory=my_unpacker_factory)
@@ -127,13 +133,13 @@ def my_unpacker_factory(_):
         data = bytes(bytearray.fromhex(data_hex))
         space = 'space_varbin'
 
-        self.con.execute("""
-            INSERT INTO "%s" VALUES (%d, x'%s');
-        """ % (space, data_id, data_hex))
+        self.con.execute(f"""
+            INSERT INTO "{space}" VALUES ({data_id}, x'{data_hex}');
+        """)
 
-        resp = self.con.execute("""
-            SELECT * FROM "%s" WHERE "varbin" == x'%s';
-        """ % (space, data_hex))
+        resp = self.con.execute(f"""
+            SELECT * FROM "{space}" WHERE "varbin" == x'{data_hex}';
+        """)
         self.assertSequenceEqual(resp, [[data_id, data]])
 
     def test_custom_unpacker_supersedes_use_list(self):
@@ -150,12 +156,11 @@ def my_unpacker_factory(_):
         resp = self.con.eval("return {1, 2, 3}")
         self.assertIsInstance(resp[0], tuple)
 
-    @classmethod
     def tearDown(self):
-        if hasattr(self, 'con'):
+        if self.con:
             self.con.close()
 
     @classmethod
-    def tearDownClass(self):
-        self.srv.stop()
-        self.srv.clean()
+    def tearDownClass(cls):
+        cls.srv.stop()
+        cls.srv.clean()
diff --git a/test/suites/test_crud.py b/test/suites/test_crud.py
index 4af62d90..d1d7e186 100644
--- a/test/suites/test_crud.py
+++ b/test/suites/test_crud.py
@@ -1,11 +1,18 @@
+"""
+This module tests integration with tarantool/crud.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,protected-access
+
 import re
 import sys
 import time
 import unittest
+
 import tarantool
-from .lib.tarantool_server import TarantoolServer
 from tarantool.error import DatabaseError
 
+from .lib.tarantool_server import TarantoolServer
+
 
 def create_server():
     srv = TarantoolServer()
@@ -16,36 +23,36 @@ def create_server():
 
 
 @unittest.skipIf(sys.platform.startswith("win"),
-                 "Crud tests on windows platform are not supported: " +
+                 "Crud tests on windows platform are not supported: "
                  "complexity of the vshard replicaset configuration")
-class TestSuite_Crud(unittest.TestCase):
+class TestSuiteCrud(unittest.TestCase):
 
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' CRUD '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
         # Create server and extract helpful fields for tests.
-        self.srv = create_server()
-        self.host = self.srv.host
-        self.port = self.srv.args['primary']
+        cls.srv = create_server()
+        cls.host = cls.srv.host
+        cls.port = cls.srv.args['primary']
 
     def setUp(self):
         time.sleep(1)
         # Open connections to instance.
-        self.conn = tarantool.Connection(host=self.host, port=self.port, 
-                                         user='guest', password='', fetch_schema=False)
-        self.conn_mesh = tarantool.MeshConnection(host=self.host, port=self.port, 
+        self.conn = tarantool.Connection(host=self.host, port=self.port,
                                          user='guest', password='', fetch_schema=False)
-        self.conn_pool = tarantool.ConnectionPool([{'host':self.host, 'port':self.port}], 
-                                                     user='guest', password='', 
-                                                     fetch_schema=False)
+        self.conn_mesh = tarantool.MeshConnection(host=self.host, port=self.port,
+                                                  user='guest', password='', fetch_schema=False)
+        self.conn_pool = tarantool.ConnectionPool([{'host': self.host, 'port': self.port}],
+                                                  user='guest', password='',
+                                                  fetch_schema=False)
         # Time for vshard group configuration.
         time.sleep(1)
-        if self.conn.eval('return ROCKS_IMPORT_FAIL').data[0] == True:
-            raise unittest.SkipTest('The crud/vshard modules are not detected, ' +
-                                    'installation via rocks install is required ' +
-                                    'for CRUD testing purposes. You can use ' +
-                                    '<tarantoolctl rocks install crud> or ' +
+        if self.conn.eval('return ROCKS_IMPORT_FAIL').data[0] is True:
+            raise unittest.SkipTest('The crud/vshard modules are not detected, '
+                                    'installation via rocks install is required '
+                                    'for CRUD testing purposes. You can use '
+                                    '<tarantoolctl rocks install crud> or '
                                     '<tt rocks install crud> to install modules')
 
     crud_test_cases = {
@@ -63,9 +70,7 @@ def setUp(self):
                     'args': ['tester', [1, 100, 'Bob'], {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r'Duplicate key exists',
-                        ],
+                    'str': [r'Duplicate key exists'],
                 },
             },
         },
@@ -80,12 +85,11 @@ def setUp(self):
             },
             'error': {
                 'input': {
-                    'args': ['tester', {'id': 2, 'bucket_id': 100, 'name': 'Logan'}, {'timeout': 10}],
+                    'args': ['tester', {'id': 2, 'bucket_id': 100, 'name': 'Logan'},
+                             {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r'Duplicate key exists',
-                        ],
+                    'str': [r'Duplicate key exists'],
                 },
             },
         },
@@ -93,7 +97,7 @@ def setUp(self):
             'success': {
                 'input': {
                     'args': [
-                        'tester', 
+                        'tester',
                         [
                             [3, 100, 'Jacob'],
                             [4, 100, 'Wyatt'],
@@ -105,17 +109,17 @@ def setUp(self):
                 },
                 'output': {
                     'rows': [
-                                [3, 100, 'Jacob'],
-                                [4, 100, 'Wyatt'],
-                                [5, 100, 'David'],
-                                [6, 100, 'Leo'],
-                            ],
+                        [3, 100, 'Jacob'],
+                        [4, 100, 'Wyatt'],
+                        [5, 100, 'David'],
+                        [6, 100, 'Leo'],
+                    ],
                 },
             },
             'error': {
                 'input': {
                     'args': [
-                        'tester', 
+                        'tester',
                         [
                             [3, 100, 'Julian'],
                             [4, 100, 'Hudson'],
@@ -126,9 +130,7 @@ def setUp(self):
                     ],
                 },
                 'output': {
-                    'str': [
-                            r'Duplicate key exists',
-                        ],
+                    'str': [r'Duplicate key exists'],
                     'res_rows': [[7, 100, 'Grayson'], [8, 100, 'Ezra']]
                 },
             },
@@ -137,7 +139,7 @@ def setUp(self):
             'success': {
                 'input': {
                     'args': [
-                        'tester', 
+                        'tester',
                         [
                             {'id': 9, 'bucket_id': 100, 'name': 'Sharar'},
                             {'id': 10, 'bucket_id': 100, 'name': 'Thaddeus'},
@@ -149,17 +151,17 @@ def setUp(self):
                 },
                 'output': {
                     'rows': [
-                                [9, 100, 'Sharar'],
-                                [10, 100, 'Thaddeus'],
-                                [11, 100, 'Tobit'],
-                                [12, 100, 'Zeb'],
-                            ],
+                        [9, 100, 'Sharar'],
+                        [10, 100, 'Thaddeus'],
+                        [11, 100, 'Tobit'],
+                        [12, 100, 'Zeb'],
+                    ],
                 },
             },
             'error': {
                 'input': {
                     'args': [
-                        'tester', 
+                        'tester',
                         [
                             {'id': 9, 'bucket_id': 100, 'name': 'Silvanus'},
                             {'id': 10, 'bucket_id': 100, 'name': 'Timeus'},
@@ -170,9 +172,7 @@ def setUp(self):
                     ],
                 },
                 'output': {
-                    'str': [
-                            r'Duplicate key exists',
-                        ],
+                    'str': [r'Duplicate key exists'],
                     'res_rows': [[13, 100, 'Uzzi'], [14, 100, 'Zimiri']]
                 },
             },
@@ -191,9 +191,7 @@ def setUp(self):
                     'args': ['no-such-space-name', [1, 100, 'Bob'], {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r'GetError: Space "no-such-space-name" doesn\'t exist', 
-                        ],
+                    'str': [r'GetError: Space "no-such-space-name" doesn\'t exist'],
                 },
             },
         },
@@ -211,9 +209,7 @@ def setUp(self):
                     'args': ['tester', 1, [['+', 'age', 1]], {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r"UpdateError", 
-                        ],
+                    'str': [r"UpdateError"],
                 },
             },
         },
@@ -231,9 +227,7 @@ def setUp(self):
                     'args': ['no-such-space-name', 1, {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r'DeleteError: Space "no-such-space-name" doesn\'t exist', 
-                        ],
+                    'str': [r'DeleteError: Space "no-such-space-name" doesn\'t exist'],
                 },
             },
         },
@@ -251,16 +245,17 @@ def setUp(self):
                     'args': ['tester', [1, 100, 0], {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r'expected string',
-                        ],
+                    'str': [r'expected string'],
                 },
             },
         },
         'crud_replace_object': {
             'success': {
                 'input': {
-                    'args': ['tester', {'id': 2, 'bucket_id': 100, 'name': 'Eliza'}, {'timeout': 10}],
+                    'args': [
+                        'tester', {'id': 2, 'bucket_id': 100, 'name': 'Eliza'},
+                        {'timeout': 10}
+                    ],
                 },
                 'output': {
                     'rows': [[2, 100, 'Eliza']],
@@ -271,9 +266,7 @@ def setUp(self):
                     'args': ['tester', {'id': 2, 'bucket_id': 100, 'name': 0}, {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r'expected string',
-                        ],
+                    'str': [r'expected string'],
                 },
             },
         },
@@ -281,7 +274,7 @@ def setUp(self):
             'success': {
                 'input': {
                     'args': [
-                        'tester', 
+                        'tester',
                         [
                             [2, 100, 'Cephus'],
                             [3, 100, 'Esau'],
@@ -293,17 +286,17 @@ def setUp(self):
                 },
                 'output': {
                     'rows': [
-                                [2, 100, 'Cephus'],
-                                [3, 100, 'Esau'],
-                                [4, 100, 'Haman'],
-                                [5, 100, 'Gershon'],
-                            ],
+                        [2, 100, 'Cephus'],
+                        [3, 100, 'Esau'],
+                        [4, 100, 'Haman'],
+                        [5, 100, 'Gershon'],
+                    ],
                 },
             },
             'error': {
                 'input': {
                     'args': [
-                        'tester', 
+                        'tester',
                         [
                             [3, 100, 'Ephron'],
                             [4, 100, 'Ethan'],
@@ -314,9 +307,7 @@ def setUp(self):
                     ],
                 },
                 'output': {
-                    'str': [
-                            r'expected string',
-                        ],
+                    'str': [r'expected string'],
                     'res_rows': [[3, 100, 'Ephron'], [4, 100, 'Ethan']]
                 },
             },
@@ -325,7 +316,7 @@ def setUp(self):
             'success': {
                 'input': {
                     'args': [
-                        'tester', 
+                        'tester',
                         [
                             {'id': 2, 'bucket_id': 100, 'name': 'Cephus'},
                             {'id': 3, 'bucket_id': 100, 'name': 'Esau'},
@@ -337,17 +328,17 @@ def setUp(self):
                 },
                 'output': {
                     'rows': [
-                                [2, 100, 'Cephus'],
-                                [3, 100, 'Esau'],
-                                [4, 100, 'Haman'],
-                                [5, 100, 'Gershon'],
-                            ],
+                        [2, 100, 'Cephus'],
+                        [3, 100, 'Esau'],
+                        [4, 100, 'Haman'],
+                        [5, 100, 'Gershon'],
+                    ],
                 },
             },
             'error': {
                 'input': {
                     'args': [
-                        'tester', 
+                        'tester',
                         [
                             {'id': 3, 'bucket_id': 100, 'name': 'Ephron'},
                             {'id': 4, 'bucket_id': 100, 'name': 'Ethan'},
@@ -358,9 +349,7 @@ def setUp(self):
                     ],
                 },
                 'output': {
-                    'str': [
-                            r'expected string',
-                        ],
+                    'str': [r'expected string'],
                     'res_rows': [[3, 100, 'Ephron'], [4, 100, 'Ethan']]
                 },
             },
@@ -368,7 +357,8 @@ def setUp(self):
         'crud_upsert': {
             'success': {
                 'input': {
-                    'args': ['tester', [2, 100, 'Cephus'], [['+', 'bucket_id', 1]], {'timeout': 10}],
+                    'args': ['tester', [2, 100, 'Cephus'], [['+', 'bucket_id', 1]],
+                             {'timeout': 10}],
                 },
                 'output': {
                     'rows': [],
@@ -379,17 +369,15 @@ def setUp(self):
                     'args': ['tester', [2, 100, 'Cephus'], [['+', 'age', 1]], {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r"UpsertError", 
-                        ],
+                    'str': [r"UpsertError"],
                 },
             },
         },
         'crud_upsert_object': {
             'success': {
                 'input': {
-                    'args': ['tester', {'id': 2, 'bucket_id': 100, 'name': 'Cephus'}, 
-                        [['+', 'bucket_id', 1]], {'timeout': 10}],
+                    'args': ['tester', {'id': 2, 'bucket_id': 100, 'name': 'Cephus'},
+                             [['+', 'bucket_id', 1]], {'timeout': 10}],
                 },
                 'output': {
                     'rows': [],
@@ -397,13 +385,11 @@ def setUp(self):
             },
             'error': {
                 'input': {
-                    'args': ['tester', {'id': 2, 'bucket_id': 100, 'name': 'Cephus'}, 
-                        [['+', 'age', 1]], {'timeout': 10}],
+                    'args': ['tester', {'id': 2, 'bucket_id': 100, 'name': 'Cephus'},
+                             [['+', 'age', 1]], {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r"UpsertError",
-                        ],
+                    'str': [r"UpsertError"],
                 },
             },
         },
@@ -426,7 +412,7 @@ def setUp(self):
             'error': {
                 'input': {
                     'args': [
-                        'tester', 
+                        'tester',
                         [
                             [[3, 100, 'Ephron'], [['+', 'bucket_id', 1]]],
                             [[4, 100, 'Ethan'], [['+', 'bucket_id', 1]]],
@@ -437,9 +423,7 @@ def setUp(self):
                     ],
                 },
                 'output': {
-                    'str': [
-                            r'expected string',
-                        ],
+                    'str': [r'expected string'],
                 },
             },
         },
@@ -449,10 +433,22 @@ def setUp(self):
                     'args': [
                         'tester',
                         [
-                            [{'id': 2, 'bucket_id': 100, 'name': 'Cephus'}, [['+', 'bucket_id', 1]]],
-                            [{'id': 3, 'bucket_id': 100, 'name': 'Esau'}, [['+', 'bucket_id', 1]]],
-                            [{'id': 4, 'bucket_id': 100, 'name': 'Haman'}, [['+', 'bucket_id', 1]]],
-                            [{'id': 5, 'bucket_id': 100, 'name': 'Gershon'}, [['+', 'bucket_id', 1]]],
+                            [
+                                {'id': 2, 'bucket_id': 100, 'name': 'Cephus'},
+                                [['+', 'bucket_id', 1]]
+                            ],
+                            [
+                                {'id': 3, 'bucket_id': 100, 'name': 'Esau'},
+                                [['+', 'bucket_id', 1]]
+                            ],
+                            [
+                                {'id': 4, 'bucket_id': 100, 'name': 'Haman'},
+                                [['+', 'bucket_id', 1]]
+                            ],
+                            [
+                                {'id': 5, 'bucket_id': 100, 'name': 'Gershon'},
+                                [['+', 'bucket_id', 1]]
+                            ],
                         ],
                         {'timeout': 10},
                     ],
@@ -462,20 +458,30 @@ def setUp(self):
             'error': {
                 'input': {
                     'args': [
-                        'tester', 
+                        'tester',
                         [
-                            [{'id': 3, 'bucket_id': 100, 'name': 'Ephron'}, [['+', 'bucket_id', 1]]],
-                            [{'id': 4, 'bucket_id': 100, 'name': 'Ethan'}, [['+', 'bucket_id', 1]]],
-                            [{'id': 7, 'bucket_id': 100, 'name': 0}, [['+', 'bucket_id', 1]]],
-                            [{'id': 8, 'bucket_id': 100, 'name': 0}, [['+', 'bucket_id', 1]]],
+                            [
+                                {'id': 3, 'bucket_id': 100, 'name': 'Ephron'},
+                                [['+', 'bucket_id', 1]]
+                            ],
+                            [
+                                {'id': 4, 'bucket_id': 100, 'name': 'Ethan'},
+                                [['+', 'bucket_id', 1]]
+                            ],
+                            [
+                                {'id': 7, 'bucket_id': 100, 'name': 0},
+                                [['+', 'bucket_id', 1]]
+                            ],
+                            [
+                                {'id': 8, 'bucket_id': 100, 'name': 0},
+                                [['+', 'bucket_id', 1]]
+                            ],
                         ],
                         {'timeout': 10},
                     ],
                 },
                 'output': {
-                    'str': [
-                            r'expected string',
-                        ],
+                    'str': [r'expected string'],
                 },
             },
         },
@@ -493,9 +499,7 @@ def setUp(self):
                     'args': ['no-such-space-name'],
                 },
                 'output': {
-                    'str': [
-                            r'SelectError: Space "no-such-space-name" doesn\'t exist', 
-                        ],
+                    'str': [r'SelectError: Space "no-such-space-name" doesn\'t exist'],
                 },
             },
         },
@@ -513,9 +517,7 @@ def setUp(self):
                     'args': ['tester', 'no-idx'],
                 },
                 'output': {
-                    'str': [
-                            r'BorderError: Index "no-idx" of space "tester" doesn\'t exist', 
-                        ],
+                    'str': [r'BorderError: Index "no-idx" of space "tester" doesn\'t exist'],
                 },
             },
         },
@@ -533,9 +535,7 @@ def setUp(self):
                     'args': ['tester', 'no-idx', {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r'BorderError: Index "no-idx" of space "tester" doesn\'t exist', 
-                        ],
+                    'str': [r'BorderError: Index "no-idx" of space "tester" doesn\'t exist'],
                 },
             },
         },
@@ -553,9 +553,7 @@ def setUp(self):
                     'args': ['no-such-space-name', {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r'LenError: Space "no-such-space-name" doesn\'t exist', 
-                        ],
+                    'str': [r'LenError: Space "no-such-space-name" doesn\'t exist'],
                 },
             },
         },
@@ -573,9 +571,7 @@ def setUp(self):
                     'args': ['no-such-space-name', [['==', 'bucket_id', 100]], {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r'CountError: Space "no-such-space-name" doesn\'t exist', 
-                        ],
+                    'str': [r'CountError: Space "no-such-space-name" doesn\'t exist'],
                 },
             },
         },
@@ -584,34 +580,34 @@ def setUp(self):
                 'input': {
                     'args': [
                         [
-                            [1, 100, 'Mike'], 
-                            [2, 100, 'Mike'], 
-                            [3, 100, 'Mike'], 
-                            [4, 100, 'Mike'], 
-                            [5, 200, 'Bill'], 
+                            [1, 100, 'Mike'],
+                            [2, 100, 'Mike'],
+                            [3, 100, 'Mike'],
+                            [4, 100, 'Mike'],
+                            [5, 200, 'Bill'],
                             [6, 300, 'Rob'],
                         ],
                         [
-                            {'name': 'id', 'type': 'unsigned'}, 
-                            {'name': 'bucket_id', 'type': 'unsigned'}, 
+                            {'name': 'id', 'type': 'unsigned'},
+                            {'name': 'bucket_id', 'type': 'unsigned'},
                             {'name': 'name', 'type': 'string'}
                         ],
                     ],
                 },
                 'output': {
                     'scalar': [
-                        {'bucket_id': 100, 'name': 'Mike', 'id': 1}, 
-                        {'bucket_id': 100, 'name': 'Mike', 'id': 2}, 
-                        {'bucket_id': 100, 'name': 'Mike', 'id': 3}, 
-                        {'bucket_id': 100, 'name': 'Mike', 'id': 4}, 
-                        {'bucket_id': 200, 'name': 'Bill', 'id': 5}, 
+                        {'bucket_id': 100, 'name': 'Mike', 'id': 1},
+                        {'bucket_id': 100, 'name': 'Mike', 'id': 2},
+                        {'bucket_id': 100, 'name': 'Mike', 'id': 3},
+                        {'bucket_id': 100, 'name': 'Mike', 'id': 4},
+                        {'bucket_id': 200, 'name': 'Bill', 'id': 5},
                         {'bucket_id': 300, 'name': 'Rob', 'id': 6},
                     ],
                 },
             },
             'error': {
                 'input': {
-                    'args': [[],[]],
+                    'args': [[], []],
                 },
                 'output': {
                     'str': [],
@@ -632,9 +628,7 @@ def setUp(self):
                     'args': ['no-such-space-name', {'timeout': 10}],
                 },
                 'output': {
-                    'str': [
-                            r'"no-such-space-name" doesn\'t exist', 
-                        ],
+                    'str': [r'"no-such-space-name" doesn\'t exist'],
                 },
             },
         },
@@ -645,13 +639,13 @@ def setUp(self):
                 },
                 'output': {
                     'operations': [
-                            'insert', 'replace',
-                            'upsert', 'len',
-                            'delete', 'get',
-                            'select', 'borders',
-                            'update', 'count',
-                            'truncate',
-                        ],
+                        'insert', 'replace',
+                        'upsert', 'len',
+                        'delete', 'get',
+                        'select', 'borders',
+                        'update', 'count',
+                        'truncate',
+                    ],
                 },
             },
             'error': {
@@ -676,17 +670,17 @@ def _correct_operation_with_crud(self, testing_function, case, mode=None):
                 *case['success']['input']['args'],
             )
         if 'rows' in case['success']['output']:
-            # Case for crud responce as tarantool.crud.CrudResult obj.
+            # Case for crud response as tarantool.crud.CrudResult obj.
             self.assertEqual(resp.rows, case['success']['output']['rows'])
         if 'scalar' in case['success']['output']:
-            # Case for scalar value as crud responce, not tarantool.crud.CrudResult obj.
+            # Case for scalar value as crud response, not tarantool.crud.CrudResult obj.
             self.assertEqual(resp, case['success']['output']['scalar'])
         if 'operations' in case['success']['output']:
             # Case for statistics testing.
             for operation in case['success']['output']['operations']:
-                self.assertEqual(operation in resp.__dict__, True, 
-                    'Problem with finding a field with a statistic about operation ' 
-                        + operation)
+                self.assertEqual(
+                    operation in resp.__dict__, True,
+                    'Problem with finding a field with a statistic about operation ' + operation)
 
     def _exception_operation_with_crud(self, testing_function, case, mode=None):
         try:
@@ -699,47 +693,44 @@ def _exception_operation_with_crud(self, testing_function, case, mode=None):
                 _ = testing_function(
                     *case['error']['input']['args'],
                 )
-        except DatabaseError as e:
+        except DatabaseError as exc:
             for regexp_case in case['error']['output']['str']:
-                if hasattr(e, 'extra_info_error'):
+                if hasattr(exc, 'extra_info_error'):
                     # Case for non-batch operations.
-                    self.assertNotEqual(re.search(regexp_case, e.extra_info_error.str), None)
-                if hasattr(e, 'errors_list'):
+                    self.assertNotEqual(re.search(regexp_case, exc.extra_info_error.str), None)
+                if hasattr(exc, 'errors_list'):
                     # Case for *_many() operations.
                     err_sum = str()
-                    for err in e.errors_list:
+                    for err in exc.errors_list:
                         err_sum = err_sum + err.str
                     self.assertNotEqual(re.search(regexp_case, err_sum), None)
-            if hasattr(e, 'success_list'):
+            if hasattr(exc, 'success_list'):
                 # Case for *_many() operations.
                 if 'res_rows' in case['error']['output']:
-                    self.assertEqual(e.success_list.rows, case['error']['output']['res_rows'])
+                    self.assertEqual(exc.success_list.rows, case['error']['output']['res_rows'])
 
     def test_crud_module_via_connection(self):
-        for case_name in self.crud_test_cases.keys():
-            with self.subTest(name=case_name):
-                case = self.crud_test_cases[case_name]
-                testing_function = getattr(self.conn, case_name)
+        for name, case in self.crud_test_cases.items():
+            with self.subTest(name=name):
+                testing_function = getattr(self.conn, name)
                 # Correct try testing.
                 self._correct_operation_with_crud(testing_function, case)
                 # Exception try testing.
                 self._exception_operation_with_crud(testing_function, case)
 
     def test_crud_module_via_mesh_connection(self):
-        for case_name in self.crud_test_cases.keys():
-            with self.subTest(name=case_name):
-                case = self.crud_test_cases[case_name]
-                testing_function = getattr(self.conn_mesh, case_name)
+        for name, case in self.crud_test_cases.items():
+            with self.subTest(name=name):
+                testing_function = getattr(self.conn_mesh, name)
                 # Correct try testing.
                 self._correct_operation_with_crud(testing_function, case)
                 # Exception try testing.
                 self._exception_operation_with_crud(testing_function, case)
 
     def test_crud_module_via_pool_connection(self):
-        for case_name in self.crud_test_cases.keys():
-            with self.subTest(name=case_name):
-                case = self.crud_test_cases[case_name]
-                testing_function = getattr(self.conn_pool, case_name)
+        for name, case in self.crud_test_cases.items():
+            with self.subTest(name=name):
+                testing_function = getattr(self.conn_pool, name)
                 # Correct try testing.
                 self._correct_operation_with_crud(testing_function, case, mode=tarantool.Mode.RW)
                 # Exception try testing.
@@ -752,7 +743,7 @@ def tearDown(self):
         self.conn_pool.close()
 
     @classmethod
-    def tearDownClass(self):
+    def tearDownClass(cls):
         # Stop instance.
-        self.srv.stop()
-        self.srv.clean()
+        cls.srv.stop()
+        cls.srv.clean()
diff --git a/test/suites/test_datetime.py b/test/suites/test_datetime.py
index fb2d2855..f02cf523 100644
--- a/test/suites/test_datetime.py
+++ b/test/suites/test_datetime.py
@@ -1,29 +1,34 @@
+"""
+This module tests work with datetime type.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,too-many-public-methods,too-many-function-args,duplicate-code
+
 import sys
 import re
 import unittest
+
 import msgpack
-import warnings
-import tarantool
-import pandas
 
+import tarantool
+from tarantool.error import MsgpackError
 from tarantool.msgpack_ext.packer import default as packer_default
 from tarantool.msgpack_ext.unpacker import ext_hook as unpacker_ext_hook
 
 from .lib.tarantool_server import TarantoolServer
 from .lib.skip import skip_or_run_datetime_test
-from tarantool.error import MsgpackError, MsgpackWarning
 
-class TestSuite_Datetime(unittest.TestCase):
+
+class TestSuiteDatetime(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' DATETIME EXT TYPE '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
 
-        self.adm = self.srv.admin
-        self.adm(r"""
+        cls.adm = cls.srv.admin
+        cls.adm(r"""
             _, datetime = pcall(require, 'datetime')
 
             box.schema.space.create('test')
@@ -54,8 +59,8 @@ def setUpClass(self):
             rawset(_G, 'sub', sub)
         """)
 
-        self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'],
-                                        user='test', password='test')
+        cls.con = tarantool.Connection(cls.srv.host, cls.srv.args['primary'],
+                                       user='test', password='test')
 
     def setUp(self):
         # prevent a remote tarantool from clean our session
@@ -64,41 +69,39 @@ def setUp(self):
 
         self.adm("box.space['test']:truncate()")
 
-
-    def test_Datetime_class_API(self):
-        dt = tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
-                                nsec=308543321, tzoffset=180)
-
-        self.assertEqual(dt.year, 2022)
-        self.assertEqual(dt.month, 8)
-        self.assertEqual(dt.day, 31)
-        self.assertEqual(dt.hour, 18)
-        self.assertEqual(dt.minute, 7)
-        self.assertEqual(dt.sec, 54)
-        self.assertEqual(dt.nsec, 308543321)
+    def test_datetime_class_api(self):
+        datetime = tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
+                                      nsec=308543321, tzoffset=180)
+
+        self.assertEqual(datetime.year, 2022)
+        self.assertEqual(datetime.month, 8)
+        self.assertEqual(datetime.day, 31)
+        self.assertEqual(datetime.hour, 18)
+        self.assertEqual(datetime.minute, 7)
+        self.assertEqual(datetime.sec, 54)
+        self.assertEqual(datetime.nsec, 308543321)
         # Both Tarantool and pandas prone to precision loss for timestamp() floats
-        self.assertEqual(dt.timestamp, 1661958474.308543)
-        self.assertEqual(dt.tzoffset, 180)
-        self.assertEqual(dt.tz, '')
-        self.assertEqual(dt.value, 1661958474308543321)
-
-    def test_Datetime_class_API_wth_tz(self):
-        dt = tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
-                                nsec=308543321, tzoffset=123, tz='Europe/Moscow')
-
-        self.assertEqual(dt.year, 2022)
-        self.assertEqual(dt.month, 8)
-        self.assertEqual(dt.day, 31)
-        self.assertEqual(dt.hour, 18)
-        self.assertEqual(dt.minute, 7)
-        self.assertEqual(dt.sec, 54)
-        self.assertEqual(dt.nsec, 308543321)
+        self.assertEqual(datetime.timestamp, 1661958474.308543)
+        self.assertEqual(datetime.tzoffset, 180)
+        self.assertEqual(datetime.tz, '')
+        self.assertEqual(datetime.value, 1661958474308543321)
+
+    def test_datetime_class_api_wth_tz(self):
+        datetime = tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
+                                      nsec=308543321, tzoffset=123, tz='Europe/Moscow')
+
+        self.assertEqual(datetime.year, 2022)
+        self.assertEqual(datetime.month, 8)
+        self.assertEqual(datetime.day, 31)
+        self.assertEqual(datetime.hour, 18)
+        self.assertEqual(datetime.minute, 7)
+        self.assertEqual(datetime.sec, 54)
+        self.assertEqual(datetime.nsec, 308543321)
         # Both Tarantool and pandas prone to precision loss for timestamp() floats
-        self.assertEqual(dt.timestamp, 1661958474.308543)
-        self.assertEqual(dt.tzoffset, 180)
-        self.assertEqual(dt.tz, 'Europe/Moscow')
-        self.assertEqual(dt.value, 1661958474308543321)
-
+        self.assertEqual(datetime.timestamp, 1661958474.308543)
+        self.assertEqual(datetime.tzoffset, 180)
+        self.assertEqual(datetime.tz, 'Europe/Moscow')
+        self.assertEqual(datetime.value, 1661958474308543321)
 
     datetime_class_invalid_init_cases = {
         'positional_year': {
@@ -139,15 +142,15 @@ def test_Datetime_class_API_wth_tz(self):
         },
     }
 
-    def test_Datetime_class_invalid_init(self):
-        for name in self.datetime_class_invalid_init_cases.keys():
+    def test_datetime_class_invalid_init(self):
+        # pylint: disable=cell-var-from-loop
+
+        for name, case in self.datetime_class_invalid_init_cases.items():
             with self.subTest(msg=name):
-                case = self.datetime_class_invalid_init_cases[name]
                 self.assertRaisesRegex(
                     case['type'], re.escape(case['msg']),
                     lambda: tarantool.Datetime(*case['args'], **case['kwargs']))
 
-
     integration_cases = {
         'date': {
             'python': tarantool.Datetime(year=2022, month=8, day=31),
@@ -178,14 +181,14 @@ def test_Datetime_class_invalid_init(self):
             'python': tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
                                          nsec=308543000),
             'msgpack': (b'\x7a\xa3\x0f\x63\x00\x00\x00\x00\x18\xfe\x63\x12\x00\x00\x00\x00'),
-            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, " +
+            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, "
                          r"nsec=308543000})",
         },
         'datetime_with_nanoseconds': {
             'python': tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
                                          nsec=308543321),
             'msgpack': (b'\x7a\xa3\x0f\x63\x00\x00\x00\x00\x59\xff\x63\x12\x00\x00\x00\x00'),
-            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, " +
+            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, "
                          r"nsec=308543321})",
         },
         'date_before_1970_with_nanoseconds': {
@@ -207,14 +210,14 @@ def test_Datetime_class_invalid_init(self):
             'python': tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
                                          nsec=308543321, tzoffset=180),
             'msgpack': (b'\x4a\x79\x0f\x63\x00\x00\x00\x00\x59\xff\x63\x12\xb4\x00\x00\x00'),
-            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, " +
+            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, "
                          r"nsec=308543321, tzoffset=180})",
         },
         'datetime_with_negative_offset': {
             'python': tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
                                          nsec=308543321, tzoffset=-60),
             'msgpack': (b'\x8a\xb1\x0f\x63\x00\x00\x00\x00\x59\xff\x63\x12\xc4\xff\x00\x00'),
-            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, " +
+            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, "
                          r"nsec=308543321, tzoffset=-60})",
         },
         'timestamp_with_positive_offset': {
@@ -241,7 +244,7 @@ def test_Datetime_class_invalid_init(self):
             'python': tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
                                          nsec=308543321, tz='Europe/Moscow'),
             'msgpack': (b'\x4a\x79\x0f\x63\x00\x00\x00\x00\x59\xff\x63\x12\xb4\x00\xb3\x03'),
-            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, " +
+            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, "
                          r"nsec=308543321, tz='Europe/Moscow'})",
         },
         'datetime_with_tz_winter_time': {
@@ -253,69 +256,62 @@ def test_Datetime_class_invalid_init(self):
             'python': tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
                                          nsec=308543321, tz='Europe/Moscow', tzoffset=123),
             'msgpack': (b'\x4a\x79\x0f\x63\x00\x00\x00\x00\x59\xff\x63\x12\xb4\x00\xb3\x03'),
-            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, " +
+            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, "
                          r"nsec=308543321, tz='Europe/Moscow', tzoffset=123})",
         },
         'datetime_with_abbrev_tz': {
             'python': tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
                                          nsec=308543321, tz='MSK'),
             'msgpack': (b'\x4a\x79\x0f\x63\x00\x00\x00\x00\x59\xff\x63\x12\xb4\x00\xee\x00'),
-            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, " +
+            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, "
                          r"nsec=308543321, tz='MSK'})",
         },
         'datetime_with_abbrev_tz_and_zero_offset': {
             'python': tarantool.Datetime(year=2022, month=8, day=31, hour=18, minute=7, sec=54,
                                          nsec=308543321, tz='AZODT'),
             'msgpack': (b'\x7a\xa3\x0f\x63\x00\x00\x00\x00\x59\xff\x63\x12\x00\x00\x12\x02'),
-            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, " +
+            'tarantool': r"datetime.new({year=2022, month=8, day=31, hour=18, min=7, sec=54, "
                          r"nsec=308543321, tz='AZODT'})",
         },
         'timestamp_since_utc_epoch': {
             'python': tarantool.Datetime(timestamp=1661958474, nsec=308543321,
                                          tz='Europe/Moscow', timestamp_since_utc_epoch=True),
             'msgpack': (b'\x4a\x79\x0f\x63\x00\x00\x00\x00\x59\xff\x63\x12\xb4\x00\xb3\x03'),
-            'tarantool': r"datetime.new({timestamp=1661969274, nsec=308543321, tz='Europe/Moscow'})",
+            'tarantool': r"datetime.new({timestamp=1661969274, nsec=308543321, "
+                         r"tz='Europe/Moscow'})",
         },
     }
 
     def test_msgpack_decode(self):
-        for name in self.integration_cases.keys():
+        for name, case in self.integration_cases.items():
             with self.subTest(msg=name):
-                case = self.integration_cases[name]
-
                 self.assertEqual(unpacker_ext_hook(4, case['msgpack']),
                                  case['python'])
 
     @skip_or_run_datetime_test
     def test_tarantool_decode(self):
-        for name in self.integration_cases.keys():
+        for name, case in self.integration_cases.items():
             with self.subTest(msg=name):
-                case = self.integration_cases[name]
-
                 self.adm(f"box.space['test']:replace{{'{name}', {case['tarantool']}, 'field'}}")
 
                 self.assertSequenceEqual(self.con.select('test', name),
                                          [[name, case['python'], 'field']])
 
     def test_msgpack_encode(self):
-        for name in self.integration_cases.keys():
+        for name, case in self.integration_cases.items():
             with self.subTest(msg=name):
-                case = self.integration_cases[name]
-
                 self.assertEqual(packer_default(case['python']),
                                  msgpack.ExtType(code=4, data=case['msgpack']))
 
     @skip_or_run_datetime_test
     def test_tarantool_encode(self):
-        for name in self.integration_cases.keys():
+        for name, case in self.integration_cases.items():
             with self.subTest(msg=name):
-                case = self.integration_cases[name]
-
                 self.con.insert('test', [name, case['python'], 'field'])
 
                 lua_eval = f"""
                     local dt = {case['tarantool']}
-                    
+
                     local tuple = box.space['test']:get('{name}')
                     assert(tuple ~= nil)
 
@@ -341,7 +337,6 @@ def test_msgpack_decode_ambiguous_tzindex(self):
             ValueError, 'Failed to create datetime with ambiguous timezone "AET"',
             lambda: unpacker_ext_hook(4, case))
 
-
     datetime_subtraction_cases = {
         'date': {
             'arg_1': tarantool.Datetime(year=2008, month=2, day=3),
@@ -370,22 +365,17 @@ def test_msgpack_decode_ambiguous_tzindex(self):
     }
 
     def test_python_datetime_subtraction(self):
-        for name in self.datetime_subtraction_cases.keys():
+        for name, case in self.datetime_subtraction_cases.items():
             with self.subTest(msg=name):
-                case = self.datetime_subtraction_cases[name]
-
                 self.assertEqual(case['arg_1'] - case['arg_2'], case['res'])
 
     @skip_or_run_datetime_test
     def test_tarantool_datetime_subtraction(self):
-        for name in self.datetime_subtraction_cases.keys():
+        for name, case in self.datetime_subtraction_cases.items():
             with self.subTest(msg=name):
-                case = self.datetime_subtraction_cases[name]
-
                 self.assertSequenceEqual(self.con.call('sub', case['arg_1'], case['arg_2']),
                                          [case['res']])
 
-
     datetime_subtraction_different_timezones_case = {
         'arg_1': tarantool.Datetime(year=2001, month=2, day=3, tz='UTC'),
         'arg_2': tarantool.Datetime(year=2001, month=2, day=3, tz='MSK'),
@@ -403,8 +393,7 @@ def test_tarantool_datetime_subtraction_different_timezones(self):
         case = self.datetime_subtraction_different_timezones_case
 
         self.assertSequenceEqual(self.con.call('sub', case['arg_1'], case['arg_2']),
-                                         [case['res']])
-
+                                 [case['res']])
 
     interval_arithmetic_cases = {
         'year': {
@@ -441,9 +430,9 @@ def test_tarantool_datetime_subtraction_different_timezones(self):
             'arg_1': tarantool.Datetime(year=2008, month=2, day=3, hour=3, minute=36, sec=43),
             'arg_2': tarantool.Interval(nsec=10000023),
             'res_add': tarantool.Datetime(year=2008, month=2, day=3, hour=3, minute=36, sec=43,
-                                      nsec=10000023),
+                                          nsec=10000023),
             'res_sub': tarantool.Datetime(year=2008, month=2, day=3, hour=3, minute=36, sec=42,
-                                      nsec=989999977),
+                                          nsec=989999977),
         },
         'zero': {
             'arg_1': tarantool.Datetime(year=2008, month=2, day=3, hour=3, minute=36, sec=43),
@@ -489,39 +478,30 @@ def test_tarantool_datetime_subtraction_different_timezones(self):
         },
     }
 
-    def test_python_datetime_addition(self):
-        for name in self.interval_arithmetic_cases.keys():
+    def test_python_interval_addition(self):
+        for name, case in self.interval_arithmetic_cases.items():
             with self.subTest(msg=name):
-                case = self.interval_arithmetic_cases[name]
-
                 self.assertEqual(case['arg_1'] + case['arg_2'], case['res_add'])
 
-    def test_python_datetime_subtraction(self):
-        for name in self.interval_arithmetic_cases.keys():
+    def test_python_interval_subtraction(self):
+        for name, case in self.interval_arithmetic_cases.items():
             with self.subTest(msg=name):
-                case = self.interval_arithmetic_cases[name]
-
                 self.assertEqual(case['arg_1'] - case['arg_2'], case['res_sub'])
 
     @skip_or_run_datetime_test
-    def test_tarantool_datetime_addition(self):
-        for name in self.interval_arithmetic_cases.keys():
+    def test_tarantool_interval_addition(self):
+        for name, case in self.interval_arithmetic_cases.items():
             with self.subTest(msg=name):
-                case = self.interval_arithmetic_cases[name]
-
                 self.assertSequenceEqual(self.con.call('add', case['arg_1'], case['arg_2']),
                                          [case['res_add']])
 
     @skip_or_run_datetime_test
-    def test_tarantool_datetime_subtraction(self):
-        for name in self.interval_arithmetic_cases.keys():
+    def test_tarantool_interval_subtraction(self):
+        for name, case in self.interval_arithmetic_cases.items():
             with self.subTest(msg=name):
-                case = self.interval_arithmetic_cases[name]
-
                 self.assertSequenceEqual(self.con.call('sub', case['arg_1'], case['arg_2']),
                                          [case['res_sub']])
 
-
     datetime_addition_winter_time_switch_case = {
         'arg_1': tarantool.Datetime(year=2008, month=1, day=1, hour=12, tz='Europe/Moscow'),
         'arg_2': tarantool.Interval(month=6),
@@ -541,7 +521,6 @@ def test_tarantool_datetime_addition_winter_time_switch(self):
         self.assertSequenceEqual(self.con.call('add', case['arg_1'], case['arg_2']),
                                  [case['res']])
 
-
     @skip_or_run_datetime_test
     def test_primary_key(self):
         data = [tarantool.Datetime(year=1970, month=1, day=1), 'content']
@@ -550,7 +529,7 @@ def test_primary_key(self):
         self.assertSequenceEqual(self.con.select('test_pk', data[0]), [data])
 
     @classmethod
-    def tearDownClass(self):
-        self.con.close()
-        self.srv.stop()
-        self.srv.clean()
+    def tearDownClass(cls):
+        cls.con.close()
+        cls.srv.stop()
+        cls.srv.clean()
diff --git a/test/suites/test_dbapi.py b/test/suites/test_dbapi.py
index 0df06337..65799960 100644
--- a/test/suites/test_dbapi.py
+++ b/test/suites/test_dbapi.py
@@ -1,3 +1,8 @@
+"""
+This module tests compatibility with DBAPI standards.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,protected-access,fixme
+
 import sys
 import unittest
 
@@ -9,27 +14,28 @@
 from .lib.skip import skip_or_run_sql_test
 
 
-class TestSuite_DBAPI(dbapi20.DatabaseAPI20Test):
+class TestSuiteDBAPI(dbapi20.DatabaseAPI20Test):
     table_prefix = 'dbapi20test_'  # If you need to specify a prefix for tables
 
-    ddl0 = 'create table %s (id INTEGER PRIMARY KEY AUTOINCREMENT, ' \
+    ddl0 = f'create table {table_prefix} (id INTEGER PRIMARY KEY AUTOINCREMENT, ' \
            'name varchar(20))'
-    ddl1 = 'create table %sbooze (name varchar(20) primary key)' % table_prefix
-    ddl2 = 'create table %sbarflys (name varchar(20) primary key, ' \
-           'drink varchar(30))' % table_prefix
+    ddl1 = f'create table {table_prefix}booze (name varchar(20) primary key)'
+    ddl2 = f'create table {table_prefix}barflys (name varchar(20) primary key, ' \
+           'drink varchar(30))'
 
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' DBAPI '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
-        self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'])
-        self.driver = dbapi
-        self.connect_kw_args = dict(
-            host=self.srv.host,
-            port=self.srv.args['primary'])
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
+        cls.con = tarantool.Connection(cls.srv.host, cls.srv.args['primary'])
+        cls.driver = dbapi
+        cls.connect_kw_args = {
+            "host": cls.srv.host,
+            "port": cls.srv.args['primary']
+        }
 
     @skip_or_run_sql_test
     def setUp(self):
@@ -43,37 +49,47 @@ def setUp(self):
                        "execute', 'universe')")
 
     @classmethod
-    def tearDownClass(self):
-        self.con.close()
-        self.srv.stop()
-        self.srv.clean()
+    def tearDownClass(cls):
+        cls.con.close()
+        cls.srv.stop()
+        cls.srv.clean()
+
+    def help_nextset_setUp(self, cur):
+        # pylint: disable=unused-argument
+        pass
+
+    def help_nextset_tearDown(self, cur):
+        # pylint: disable=unused-argument
+        pass
 
     def test_rowcount(self):
         con = self._connect()
         try:
             cur = con.cursor()
             self.executeDDL1(cur)
-            dbapi20._failUnless(self,cur.rowcount in (-1, 1),
+            dbapi20._failUnless(
+                self, cur.rowcount in (-1, 1),
                 'cursor.rowcount should be -1 or 1 after executing no-result '
                 'statements' + str(cur.rowcount)
-                )
-            cur.execute("%s into %sbooze values ('Victoria Bitter')" % (
-                self.insert, self.table_prefix
-                ))
-            dbapi20._failUnless(self,cur.rowcount == 1,
+            )
+            cur.execute(f"{self.insert} into {self.table_prefix}booze values ('Victoria Bitter')")
+            dbapi20._failUnless(
+                self, cur.rowcount == 1,
                 'cursor.rowcount should == number or rows inserted, or '
                 'set to -1 after executing an insert statement'
-                )
-            cur.execute("select name from %sbooze" % self.table_prefix)
-            dbapi20._failUnless(self,cur.rowcount == -1,
+            )
+            cur.execute(f"select name from {self.table_prefix}booze")
+            dbapi20._failUnless(
+                self, cur.rowcount == -1,
                 'cursor.rowcount should == number of rows returned, or '
                 'set to -1 after executing a select statement'
-                )
+            )
             self.executeDDL2(cur)
-            dbapi20._failUnless(self,cur.rowcount in (-1, 1),
+            dbapi20._failUnless(
+                self, cur.rowcount in (-1, 1),
                 'cursor.rowcount should be -1 or 1 after executing no-result '
                 'statements'
-                )
+            )
         finally:
             con.close()
 
@@ -127,43 +143,3 @@ def test_setoutputsize(self):  # Do nothing
     @unittest.skip('Not implemented')
     def test_description(self):
         pass
-
-    def test_ExceptionsAsConnectionAttributes(self):
-        # Workaround for https://github.com/baztian/dbapi-compliance/issues/5
-
-        # OPTIONAL EXTENSION 
-        # Test for the optional DB API 2.0 extension, where the exceptions 
-        # are exposed as attributes on the Connection object 
-        # I figure this optional extension will be implemented by any 
-        # driver author who is using this test suite, so it is enabled 
-        # by default. 
-        drv = self.driver
-        con = self._connect()
-        try:
-            dbapi20._failUnless(self,con.Warning is drv.Warning)
-            dbapi20._failUnless(self,con.Error is drv.Error)
-            dbapi20._failUnless(self,con.InterfaceError is drv.InterfaceError)
-            dbapi20._failUnless(self,con.DatabaseError is drv.DatabaseError)
-            dbapi20._failUnless(self,con.OperationalError is drv.OperationalError)
-            dbapi20._failUnless(self,con.IntegrityError is drv.IntegrityError)
-            dbapi20._failUnless(self,con.InternalError is drv.InternalError)
-            dbapi20._failUnless(self,con.ProgrammingError is drv.ProgrammingError)
-            dbapi20. _failUnless(self,con.NotSupportedError is drv.NotSupportedError)
-        finally:
-            con.close()
-
-
-    def test_rollback(self):
-        # Workaround for https://github.com/baztian/dbapi-compliance/issues/5
-
-        con = self._connect()
-        try:
-            # If rollback is defined, it should either work or throw
-            # the documented exception
-            if hasattr(con,'rollback'):
-                try:
-                    con.rollback()
-                except self.driver.NotSupportedError:
-                    pass
-        finally:
-            con.close()
diff --git a/test/suites/test_decimal.py b/test/suites/test_decimal.py
index 8029d7b9..c817ad08 100644
--- a/test/suites/test_decimal.py
+++ b/test/suites/test_decimal.py
@@ -1,28 +1,34 @@
+"""
+This module tests work with decimal type.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,duplicate-code
+
 import sys
 import unittest
 import decimal
+
 import msgpack
-import warnings
-import tarantool
 
+import tarantool
+from tarantool.error import MsgpackError, MsgpackWarning
 from tarantool.msgpack_ext.packer import default as packer_default
 from tarantool.msgpack_ext.unpacker import ext_hook as unpacker_ext_hook
 
 from .lib.tarantool_server import TarantoolServer
 from .lib.skip import skip_or_run_decimal_test
-from tarantool.error import MsgpackError, MsgpackWarning
 
-class TestSuite_Decimal(unittest.TestCase):
+
+class TestSuiteDecimal(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' DECIMAL EXT TYPE '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
 
-        self.adm = self.srv.admin
-        self.adm(r"""
+        cls.adm = cls.srv.admin
+        cls.adm(r"""
             _, decimal = pcall(require, 'decimal')
 
             box.schema.space.create('test')
@@ -43,8 +49,8 @@ def setUpClass(self):
             box.schema.user.grant('test', 'read,write,execute', 'universe')
         """)
 
-        self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'],
-                                        user='test', password='test')
+        cls.con = tarantool.Connection(cls.srv.host, cls.srv.args['primary'],
+                                       user='test', password='test')
 
     def setUp(self):
         # prevent a remote tarantool from clean our session
@@ -53,7 +59,6 @@ def setUp(self):
 
         self.adm("box.space['test']:truncate()")
 
-
     valid_cases = {
         'simple_decimal_1': {
             'python': decimal.Decimal('0.7'),
@@ -157,13 +162,13 @@ def setUp(self):
         },
         'decimal_limits_1': {
             'python': decimal.Decimal('11111111111111111111111111111111111111'),
-            'msgpack': (b'\x00\x01\x11\x11\x11\x11\x11\x11\x11\x11\x11' +
+            'msgpack': (b'\x00\x01\x11\x11\x11\x11\x11\x11\x11\x11\x11'
                         b'\x11\x11\x11\x11\x11\x11\x11\x11\x11\x1c'),
             'tarantool': "decimal.new('11111111111111111111111111111111111111')",
         },
         'decimal_limits_2': {
             'python': decimal.Decimal('-11111111111111111111111111111111111111'),
-            'msgpack': (b'\x00\x01\x11\x11\x11\x11\x11\x11\x11\x11\x11' +
+            'msgpack': (b'\x00\x01\x11\x11\x11\x11\x11\x11\x11\x11\x11'
                         b'\x11\x11\x11\x11\x11\x11\x11\x11\x11\x1d'),
             'tarantool': "decimal.new('-11111111111111111111111111111111111111')",
         },
@@ -199,44 +204,40 @@ def setUp(self):
         },
         'decimal_limits_9': {
             'python': decimal.Decimal('99999999999999999999999999999999999999'),
-            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99' +
+            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99'
                         b'\x99\x99\x99\x99\x99\x99\x99\x99\x99\x9c'),
             'tarantool': "decimal.new('99999999999999999999999999999999999999')",
         },
         'decimal_limits_10': {
             'python': decimal.Decimal('-99999999999999999999999999999999999999'),
-            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99' +
+            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99'
                         b'\x99\x99\x99\x99\x99\x99\x99\x99\x99\x9d'),
             'tarantool': "decimal.new('-99999999999999999999999999999999999999')",
         },
         'decimal_limits_11': {
             'python': decimal.Decimal('1234567891234567890.0987654321987654321'),
-            'msgpack': (b'\x13\x01\x23\x45\x67\x89\x12\x34\x56\x78\x90' +
+            'msgpack': (b'\x13\x01\x23\x45\x67\x89\x12\x34\x56\x78\x90'
                         b'\x09\x87\x65\x43\x21\x98\x76\x54\x32\x1c'),
             'tarantool': "decimal.new('1234567891234567890.0987654321987654321')",
         },
         'decimal_limits_12': {
             'python': decimal.Decimal('-1234567891234567890.0987654321987654321'),
-            'msgpack': (b'\x13\x01\x23\x45\x67\x89\x12\x34\x56\x78\x90' +
+            'msgpack': (b'\x13\x01\x23\x45\x67\x89\x12\x34\x56\x78\x90'
                         b'\x09\x87\x65\x43\x21\x98\x76\x54\x32\x1d'),
             'tarantool': "decimal.new('-1234567891234567890.0987654321987654321')",
         },
     }
 
     def test_msgpack_decode(self):
-        for name in self.valid_cases.keys():
+        for name, case in self.valid_cases.items():
             with self.subTest(msg=name):
-                case = self.valid_cases[name]
-
                 self.assertEqual(unpacker_ext_hook(1, case['msgpack']),
                                  case['python'])
 
     @skip_or_run_decimal_test
     def test_tarantool_decode(self):
-        for name in self.valid_cases.keys():
+        for name, case in self.valid_cases.items():
             with self.subTest(msg=name):
-                case = self.valid_cases[name]
-
                 self.adm(f"box.space['test']:replace{{'{name}', {case['tarantool']}}}")
 
                 self.assertSequenceEqual(
@@ -244,19 +245,15 @@ def test_tarantool_decode(self):
                     [[name, case['python']]])
 
     def test_msgpack_encode(self):
-        for name in self.valid_cases.keys():
+        for name, case in self.valid_cases.items():
             with self.subTest(msg=name):
-                case = self.valid_cases[name]
-
                 self.assertEqual(packer_default(case['python']),
                                  msgpack.ExtType(code=1, data=case['msgpack']))
 
     @skip_or_run_decimal_test
     def test_tarantool_encode(self):
-        for name in self.valid_cases.keys():
+        for name, case in self.valid_cases.items():
             with self.subTest(msg=name):
-                case = self.valid_cases[name]
-
                 self.con.insert('test', [name, case['python']])
 
                 lua_eval = f"""
@@ -274,7 +271,6 @@ def test_tarantool_encode(self):
 
                 self.assertSequenceEqual(self.con.eval(lua_eval), [True])
 
-
     error_cases = {
         'decimal_limit_break_head_1': {
             'python': decimal.Decimal('999999999999999999999999999999999999999'),
@@ -303,10 +299,10 @@ def test_tarantool_encode(self):
     }
 
     def test_msgpack_encode_error(self):
-        for name in self.error_cases.keys():
-            with self.subTest(msg=name):
-                case = self.error_cases[name]
+        # pylint: disable=cell-var-from-loop
 
+        for name, case in self.error_cases.items():
+            with self.subTest(msg=name):
                 msg = 'Decimal cannot be encoded: Tarantool decimal ' + \
                       'supports a maximum of 38 digits.'
                 self.assertRaisesRegex(
@@ -315,17 +311,16 @@ def test_msgpack_encode_error(self):
 
     @skip_or_run_decimal_test
     def test_tarantool_encode_error(self):
-        for name in self.error_cases.keys():
-            with self.subTest(msg=name):
-                case = self.error_cases[name]
+        # pylint: disable=cell-var-from-loop
 
+        for name, case in self.error_cases.items():
+            with self.subTest(msg=name):
                 msg = 'Decimal cannot be encoded: Tarantool decimal ' + \
                       'supports a maximum of 38 digits.'
                 self.assertRaisesRegex(
                     MsgpackError, msg,
                     lambda: self.con.insert('test', [name, case['python']]))
 
-
     precision_loss_cases = {
         'decimal_limit_break_tail_1': {
             'python': decimal.Decimal('1.00000000000000000000000000000000000001'),
@@ -359,53 +354,54 @@ def test_tarantool_encode_error(self):
         },
         'decimal_limit_break_tail_7': {
             'python': decimal.Decimal('99999999999999999999999999999999999999.1'),
-            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99' +
+            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99'
                         b'\x99\x99\x99\x99\x99\x99\x99\x99\x99\x9c'),
             'tarantool': "decimal.new('99999999999999999999999999999999999999')",
         },
         'decimal_limit_break_tail_8': {
             'python': decimal.Decimal('-99999999999999999999999999999999999999.1'),
-            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99' +
+            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99'
                         b'\x99\x99\x99\x99\x99\x99\x99\x99\x99\x9d'),
             'tarantool': "decimal.new('-99999999999999999999999999999999999999')",
         },
         'decimal_limit_break_tail_9': {
-            'python': decimal.Decimal('99999999999999999999999999999999999999.1111111111111111111111111'),
-            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99' +
+            'python': decimal.Decimal('99999999999999999999999999999999999999.11111111111111'
+                                      '11111111111'),
+            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99'
                         b'\x99\x99\x99\x99\x99\x99\x99\x99\x99\x9c'),
             'tarantool': "decimal.new('99999999999999999999999999999999999999')",
         },
         'decimal_limit_break_tail_10': {
-            'python': decimal.Decimal('-99999999999999999999999999999999999999.1111111111111111111111111'),
-            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99' +
+            'python': decimal.Decimal('-99999999999999999999999999999999999999.11111111111111'
+                                      '11111111111'),
+            'msgpack': (b'\x00\x09\x99\x99\x99\x99\x99\x99\x99\x99\x99'
                         b'\x99\x99\x99\x99\x99\x99\x99\x99\x99\x9d'),
             'tarantool': "decimal.new('-99999999999999999999999999999999999999')",
         },
     }
 
     def test_msgpack_encode_with_precision_loss(self):
-        for name in self.precision_loss_cases.keys():
-            with self.subTest(msg=name):
-                case = self.precision_loss_cases[name]
+        # pylint: disable=cell-var-from-loop
 
+        for name, case in self.precision_loss_cases.items():
+            with self.subTest(msg=name):
                 msg = 'Decimal encoded with loss of precision: ' + \
                       'Tarantool decimal supports a maximum of 38 digits.'
 
                 self.assertWarnsRegex(
                     MsgpackWarning, msg,
                     lambda: self.assertEqual(
-                                packer_default(case['python']),
-                                msgpack.ExtType(code=1, data=case['msgpack'])
-                            )
+                        packer_default(case['python']),
+                        msgpack.ExtType(code=1, data=case['msgpack'])
                     )
-                
+                )
 
     @skip_or_run_decimal_test
     def test_tarantool_encode_with_precision_loss(self):
-        for name in self.precision_loss_cases.keys():
-            with self.subTest(msg=name):
-                case = self.precision_loss_cases[name]
+        # pylint: disable=cell-var-from-loop
 
+        for name, case in self.precision_loss_cases.items():
+            with self.subTest(msg=name):
                 msg = 'Decimal encoded with loss of precision: ' + \
                       'Tarantool decimal supports a maximum of 38 digits.'
 
@@ -428,7 +424,6 @@ def test_tarantool_encode_with_precision_loss(self):
 
                 self.assertSequenceEqual(self.con.eval(lua_eval), [True])
 
-
     @skip_or_run_decimal_test
     def test_primary_key(self):
         data = [decimal.Decimal('0'), 'content']
@@ -436,9 +431,8 @@ def test_primary_key(self):
         self.assertSequenceEqual(self.con.insert('test_pk', data), [data])
         self.assertSequenceEqual(self.con.select('test_pk', data[0]), [data])
 
-
     @classmethod
-    def tearDownClass(self):
-        self.con.close()
-        self.srv.stop()
-        self.srv.clean()
+    def tearDownClass(cls):
+        cls.con.close()
+        cls.srv.stop()
+        cls.srv.clean()
diff --git a/test/suites/test_dml.py b/test/suites/test_dml.py
index 2dbff1b5..0263d451 100644
--- a/test/suites/test_dml.py
+++ b/test/suites/test_dml.py
@@ -1,3 +1,8 @@
+"""
+This module tests basic data operations.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,protected-access,fixme,too-many-public-methods,duplicate-code
+
 import sys
 import unittest
 import tarantool
@@ -6,46 +11,47 @@
 from .lib.tarantool_server import TarantoolServer
 from .lib.skip import skip_or_run_error_extra_info_test
 
-class TestSuite_Request(unittest.TestCase):
+
+class TestSuiteRequest(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' DML '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
-        self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'])
-        self.adm = self.srv.admin
-        self.space_created = self.adm("box.schema.create_space('space_1')")
-        self.adm("""
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
+        cls.con = tarantool.Connection(cls.srv.host, cls.srv.args['primary'])
+        cls.adm = cls.srv.admin
+        cls.space_created = cls.adm("box.schema.create_space('space_1')")
+        cls.adm("""
         box.space['space_1']:create_index('primary', {
             type = 'tree',
             parts = {1, 'num'},
             unique = true})
         """.replace('\n', ' '))
-        self.adm("""
+        cls.adm("""
         box.space['space_1']:create_index('secondary', {
             type = 'tree',
             parts = {2, 'num', 3, 'str'},
             unique = false})
         """.replace('\n', ' '))
-        self.space_created = self.adm("box.schema.create_space('space_2')")
-        self.adm("""
+        cls.space_created = cls.adm("box.schema.create_space('space_2')")
+        cls.adm("""
         box.space['space_2']:create_index('primary', {
             type = 'hash',
             parts = {1, 'num'},
             unique = true})
         """.replace('\n', ' '))
-        self.adm("json = require('json')")
-        self.adm("fiber = require('fiber')")
-        self.adm("uuid = require('uuid')")
+        cls.adm("json = require('json')")
+        cls.adm("fiber = require('fiber')")
+        cls.adm("uuid = require('uuid')")
 
         if not sys.platform.startswith("win"):
-            self.sock_srv = TarantoolServer(create_unix_socket=True)
-            self.sock_srv.script = 'test/suites/box.lua'
-            self.sock_srv.start()
+            cls.sock_srv = TarantoolServer(create_unix_socket=True)
+            cls.sock_srv.script = 'test/suites/box.lua'
+            cls.sock_srv.start()
         else:
-            self.sock_srv = None
+            cls.sock_srv = None
 
     def setUp(self):
         # prevent a remote tarantool from clean our session
@@ -72,9 +78,10 @@ def test_00_02_fill_space(self):
                 # prevent a remote tarantool from clean our session
                 self.srv.touch_lock()
             self.assertEqual(
-                    self.con.insert('space_1', [i, i%5, 'tuple_'+str(i)])[0],
-                    [i, i%5, 'tuple_'+str(i)]
+                self.con.insert('space_1', [i, i % 5, 'tuple_' + str(i)])[0],
+                [i, i % 5, 'tuple_' + str(i)]
             )
+
     def test_00_03_answer_repr(self):
         repr_str = """- [1, 1, 'tuple_1']"""
         self.assertEqual(repr(self.con.select('space_1', 1)), repr_str)
@@ -83,47 +90,52 @@ def test_02_select(self):
         # Check that select with different keys are Ok. (With and without index names)
         self.assertSequenceEqual(self.con.select('space_1', 20), [[20, 0, 'tuple_20']])
         self.assertSequenceEqual(self.con.select('space_1', [21]), [[21, 1, 'tuple_21']])
-        self.assertSequenceEqual(self.con.select('space_1', [22], index='primary'), [[22, 2, 'tuple_22']])
-        self.assertSequenceEqual(self.con.select('space_1', [23], index='primary'), [[23, 3, 'tuple_23']])
+        self.assertSequenceEqual(self.con.select('space_1', [22], index='primary'),
+                                 [[22, 2, 'tuple_22']])
+        self.assertSequenceEqual(self.con.select('space_1', [23], index='primary'),
+                                 [[23, 3, 'tuple_23']])
         # Check that Offset and Limit args are working fine.
-        self.assertSequenceEqual(self.con.select('space_1', [20], index='primary', limit=1), [[20, 0, 'tuple_20']])
+        self.assertSequenceEqual(self.con.select('space_1', [20], index='primary', limit=1),
+                                 [[20, 0, 'tuple_20']])
         # With other indexes too
         self.assertSequenceEqual(
-                sorted(
-                    self.con.select('space_1', [0], index='secondary', offset=3, limit=0),
-                    key = lambda x: x[0]),
-                []
-            )
+            sorted(
+                self.con.select('space_1', [0], index='secondary', offset=3, limit=0),
+                key=lambda x: x[0]),
+            []
+        )
         self.assertSequenceEqual(
-                sorted(
-                    self.con.select('space_1', [0], index='secondary', offset=3, limit=1),
-                    key = lambda x: x[0]),
-                [[110, 0, 'tuple_110']]
-            )
+            sorted(
+                self.con.select('space_1', [0], index='secondary', offset=3, limit=1),
+                key=lambda x: x[0]),
+            [[110, 0, 'tuple_110']]
+        )
         self.assertSequenceEqual(
-                sorted(
-                    self.con.select('space_1', [0], index='secondary', offset=3, limit=2),
-                    key = lambda x: x[0]),
-                [[110, 0, 'tuple_110'],\
-                [115, 0, 'tuple_115']]
-            )
+            sorted(
+                self.con.select('space_1', [0], index='secondary', offset=3, limit=2),
+                key=lambda x: x[0]),
+            [[110, 0, 'tuple_110'], [115, 0, 'tuple_115']]
+        )
 
         select_req = self.con.select('space_1', [0], index='secondary')
         self.assertEqual(len(select_req), 99)
         for i in select_req:
-            self.assertTrue(not (i[0] % 5))
+            self.assertTrue(not i[0] % 5)
             self.assertTrue(not i[1])
             self.assertTrue(i[2] == 'tuple_' + str(i[0]))
 
         # Check limit again.
-        self.assertEqual(len(self.con.select('space_1', [0, 'tuple_20'], index='secondary', limit=0)), 0)
+        self.assertEqual(
+            len(self.con.select('space_1', [0, 'tuple_20'], index='secondary', limit=0)),
+            0)
         self.assertEqual(len(self.con.select('space_1', [0], index='secondary', limit=0)), 0)
         self.assertEqual(len(self.con.select('space_1', [0], index='secondary', limit=100)), 99)
         self.assertEqual(len(self.con.select('space_1', [0], index='secondary', limit=50)), 50)
 
         # TODO: Check iterator_types
         self.assertSequenceEqual(
-            self.con.select('space_1', [0, 'tuple_20'], index='secondary', limit=2, iterator=tarantool.const.ITERATOR_GT),
+            self.con.select('space_1', [0, 'tuple_20'], index='secondary', limit=2,
+                            iterator=tarantool.const.ITERATOR_GT),
             [[200, 0, 'tuple_200'], [205, 0, 'tuple_205']]
         )
 
@@ -133,18 +145,18 @@ def test_03_delete(self):
         self.assertSequenceEqual(self.con.delete('space_1', [20]), [])
         self.assertSequenceEqual(self.con.select('space_1', [20], index='primary'), [])
         # Check that <index_id> field has no meaning, yet.
-        with self.assertRaisesRegex(tarantool.DatabaseError,
-                '(19, .*)'):
-                self.con.delete('space_1', [1, 'tuple_21'])
-        self.assertSequenceEqual(self.con.select('space_1', [21], index='primary'), [[21, 1, 'tuple_21']])
+        with self.assertRaisesRegex(tarantool.DatabaseError, '(19, .*)'):
+            self.con.delete('space_1', [1, 'tuple_21'])
+        self.assertSequenceEqual(self.con.select('space_1', [21], index='primary'),
+                                 [[21, 1, 'tuple_21']])
 
     def test_04_replace(self):
         # Check replace that is Ok.
-        self.assertSequenceEqual(self.con.replace('space_1', [2, 2, 'tuple_3']), [[2, 2, 'tuple_3']])
+        self.assertSequenceEqual(self.con.replace('space_1', [2, 2, 'tuple_3']),
+                                 [[2, 2, 'tuple_3']])
         self.assertSequenceEqual(self.con.select('space_1', 2), [[2, 2, 'tuple_3']])
         # Check replace that isn't Ok.
-        with self.assertRaisesRegex(tarantool.DatabaseError,
-                '(39, .*)'):
+        with self.assertRaisesRegex(tarantool.DatabaseError, '(39, .*)'):
             self.assertSequenceEqual(self.con.replace('space_1', [2, 2]), [[2, 2, 'tuple_2']])
 
     def test_05_ping(self):
@@ -159,25 +171,28 @@ def test_05_ping(self):
 
     def test_06_update(self):
         self.assertSequenceEqual(self.con.update('space_1', (2,), [('+', 1, 3)]),
-                [[2, 5, 'tuple_3']])
+                                 [[2, 5, 'tuple_3']])
         self.assertSequenceEqual(self.con.update('space_1', (2,), [('-', 1, 3)]),
-                [[2, 2, 'tuple_3']])
+                                 [[2, 2, 'tuple_3']])
         self.assertSequenceEqual(self.con.update('space_1', (2,), [(':', 2, 3, 2, 'lalal')]),
-                [[2, 2, 'tuplalal_3']])
+                                 [[2, 2, 'tuplalal_3']])
         self.assertSequenceEqual(self.con.update('space_1', (2,), [('!', 2, '1')]),
-                [[2, 2, '1', 'tuplalal_3']])
+                                 [[2, 2, '1', 'tuplalal_3']])
         self.assertSequenceEqual(self.con.update('space_1', (2,), [('!', 2, 'oingo, boingo')]),
-                [[2, 2, 'oingo, boingo', '1', 'tuplalal_3']])
+                                 [[2, 2, 'oingo, boingo', '1', 'tuplalal_3']])
         self.assertSequenceEqual(self.con.update('space_1', (2,), [('#', 2, 2)]),
-                [[2, 2, 'tuplalal_3']])
+                                 [[2, 2, 'tuplalal_3']])
 
     def test_07_call_16(self):
-        con = tarantool.Connection(self.srv.host, self.srv.args['primary'], call_16 = True)
+        con = tarantool.Connection(self.srv.host, self.srv.args['primary'], call_16=True)
         try:
             con.authenticate('test', 'test')
-            self.assertSequenceEqual(con.call('json.decode', '[123, 234, 345]'), [[123, 234, 345]])
-            self.assertSequenceEqual(con.call('json.decode', ['[123, 234, 345]']), [[123, 234, 345]])
-            self.assertSequenceEqual(con.call('json.decode', ('[123, 234, 345]',)), [[123, 234, 345]])
+            self.assertSequenceEqual(con.call('json.decode', '[123, 234, 345]'),
+                                     [[123, 234, 345]])
+            self.assertSequenceEqual(con.call('json.decode', ['[123, 234, 345]']),
+                                     [[123, 234, 345]])
+            self.assertSequenceEqual(con.call('json.decode', ('[123, 234, 345]',)),
+                                     [[123, 234, 345]])
             with self.assertRaisesRegex(tarantool.DatabaseError, '(32, .*)'):
                 con.call('json.decode')
             with self.assertRaisesRegex(tarantool.DatabaseError, '(32, .*)'):
@@ -195,7 +210,8 @@ def test_07_call_16(self):
             self.assertEqual(len(ans[0]), 1)
             self.assertIsInstance(ans[0][0], str)
 
-            self.assertSequenceEqual(con.call('box.tuple.new', [1, 2, 3, 'fld_1']), [[1, 2, 3, 'fld_1']])
+            self.assertSequenceEqual(con.call('box.tuple.new', [1, 2, 3, 'fld_1']),
+                                     [[1, 2, 3, 'fld_1']])
             self.assertSequenceEqual(con.call('box.tuple.new', 'fld_1'), [['fld_1']])
         finally:
             con.close()
@@ -220,36 +236,42 @@ def test_07_call_17(self):
         self.assertEqual(len(ans), 1)
         self.assertIsInstance(ans[0], str)
 
-        self.assertSequenceEqual(con.call('box.tuple.new', [1, 2, 3, 'fld_1']), [[1, 2, 3, 'fld_1']])
+        self.assertSequenceEqual(con.call('box.tuple.new', [1, 2, 3, 'fld_1']),
+                                 [[1, 2, 3, 'fld_1']])
         self.assertSequenceEqual(con.call('box.tuple.new', 'fld_1'), [['fld_1']])
 
         con.close()
 
     def test_08_eval(self):
         self.assertSequenceEqual(self.con.eval('return json.decode(...)',
-                                       '[123, 234, 345]'), [[123, 234, 345]])
+                                 '[123, 234, 345]'), [[123, 234, 345]])
         self.assertSequenceEqual(self.con.eval('return json.decode(...)',
-                                       ['[123, 234, 345]']), [[123, 234, 345]])
+                                 ['[123, 234, 345]']), [[123, 234, 345]])
         self.assertSequenceEqual(self.con.eval('return json.decode(...)',
-                                       ('[123, 234, 345]',)), [[123, 234, 345]])
+                                 ('[123, 234, 345]',)), [[123, 234, 345]])
         self.assertSequenceEqual(self.con.eval('return json.decode("[123, 234, 345]")'),
-                                       [[123, 234, 345]])
-        self.assertSequenceEqual(self.con.eval('return json.decode("[123, 234, 345]"), '+
-                                       'json.decode("[123, 234, 345]")'),
-                                       [[123, 234, 345], [123, 234, 345]])
+                                 [[123, 234, 345]])
+        self.assertSequenceEqual(
+            self.con.eval('return json.decode("[123, 234, 345]"), json.decode("[123, 234, 345]")'),
+            [[123, 234, 345], [123, 234, 345]])
         self.assertSequenceEqual(self.con.eval('json.decode("[123, 234, 345]")'), [])
 
     def test_09_upsert(self):
-        self.assertSequenceEqual(self.con.select('space_1', [22], index='primary'), [[22, 2, 'tuple_22']])
-        self.assertSequenceEqual(self.con.select('space_1', [23], index='primary'), [[23, 3, 'tuple_23']])
-        self.assertSequenceEqual(self.con.select('space_1', [499], index='primary'), [[499, 4, 'tuple_499']])
+        self.assertSequenceEqual(self.con.select('space_1', [22], index='primary'),
+                                 [[22, 2, 'tuple_22']])
+        self.assertSequenceEqual(self.con.select('space_1', [23], index='primary'),
+                                 [[23, 3, 'tuple_23']])
+        self.assertSequenceEqual(self.con.select('space_1', [499], index='primary'),
+                                 [[499, 4, 'tuple_499']])
         self.assertSequenceEqual(self.con.select('space_1', [500], index='primary'), [])
+        self.assertSequenceEqual(
+            self.con.upsert('space_1', [500, 123, 'hello, world'], [(':', 2, 2, 3, "---")]), [])
+        self.assertSequenceEqual(self.con.select('space_1', [500], index='primary'),
+                                 [[500, 123, 'hello, world']])
         self.assertSequenceEqual(self.con.upsert('space_1', [500, 123, 'hello, world'],
-                                         [(':', 2, 2, 3, "---")]), [])
-        self.assertSequenceEqual(self.con.select('space_1', [500], index='primary'), [[500, 123, 'hello, world']])
-        self.assertSequenceEqual(self.con.upsert('space_1', [500, 123, 'hello, world'],
-                                         [(':', 2, 2, 3, "---")]), [])
-        self.assertSequenceEqual(self.con.select('space_1', [500], index='primary'), [[500, 123, 'he---, world']])
+                                 [(':', 2, 2, 3, "---")]), [])
+        self.assertSequenceEqual(self.con.select('space_1', [500], index='primary'),
+                                 [[500, 123, 'he---, world']])
 
     def test_10_space(self):
         space = self.con.space('space_1')
@@ -266,15 +288,15 @@ def test_10_space(self):
             [22, 10, 'lol']
         ])
         self.assertSequenceEqual(space.select([501], index='primary'), [])
-        self.assertSequenceEqual(space.upsert([501, 123, 'hello, world'],
-                                         [(':', 2, 2, 3, "---")]), [])
+        self.assertSequenceEqual(
+            space.upsert([501, 123, 'hello, world'], [(':', 2, 2, 3, "---")]), [])
         self.assertSequenceEqual(space.select([501], index='primary'), [[501, 123, 'hello, world']])
-        self.assertSequenceEqual(space.upsert([501, 123, 'hello, world'],
-                                         [(':', 2, 2, 3, "---")]), [])
+        self.assertSequenceEqual(
+            space.upsert([501, 123, 'hello, world'], [(':', 2, 2, 3, "---")]), [])
         self.assertSequenceEqual(space.update([400], [('!', 2, 'oingo, boingo')]),
-                [[400, 0, 'oingo, boingo', 'tuple_400']])
+                                 [[400, 0, 'oingo, boingo', 'tuple_400']])
         self.assertSequenceEqual(space.update([400], [('#', 2, 1)]),
-                [[400, 0, 'tuple_400']])
+                                 [[400, 0, 'tuple_400']])
         self.assertSequenceEqual(space.delete([900]), [[900, 10, 'foo']])
 
     def test_11_select_all_hash(self):
@@ -290,20 +312,20 @@ def test_11_select_all_hash(self):
 
     def test_12_update_fields(self):
         self.srv.admin(
-        """
-        do
-            local sp = box.schema.create_space('sp', {
-                format = {
-                    { name = 'fir', type = 'unsigned' },
-                    { name = 'sec', type = 'string'   },
-                    { name = 'thi', type = 'unsigned' },
-                }
-            })
-            sp:create_index('pr', {
-                parts = {1, 'unsigned'}
-            })
-        end
-        """)
+            """
+            do
+                local sp = box.schema.create_space('sp', {
+                    format = {
+                        { name = 'fir', type = 'unsigned' },
+                        { name = 'sec', type = 'string'   },
+                        { name = 'thi', type = 'unsigned' },
+                    }
+                })
+                sp:create_index('pr', {
+                    parts = {1, 'unsigned'}
+                })
+            end
+            """)
         self.con.insert('sp', [2, 'help', 4])
         self.assertSequenceEqual(
             self.con.update('sp', (2,), [('+', 'thi', 3)]),
@@ -383,8 +405,8 @@ def test_16_extra_error_info_fields(self):
             self.assertTrue(isinstance(exc.extra_info.file, str))
             self.assertTrue(exc.extra_info.line > 0)
             self.assertEqual(
-                    exc.extra_info.message,
-                    "Create access to function 'forbidden_function' is denied for user 'test'")
+                exc.extra_info.message,
+                "Create access to function 'forbidden_function' is denied for user 'test'")
             self.assertEqual(exc.extra_info.errno, 0)
             self.assertEqual(exc.extra_info.errcode, 42)
             self.assertEqual(
@@ -399,11 +421,11 @@ def test_16_extra_error_info_fields(self):
             self.fail('Expected error')
 
     @classmethod
-    def tearDownClass(self):
-        self.con.close()
-        self.srv.stop()
-        self.srv.clean()
-
-        if self.sock_srv is not None:
-            self.sock_srv.stop()
-            self.sock_srv.clean()
+    def tearDownClass(cls):
+        cls.con.close()
+        cls.srv.stop()
+        cls.srv.clean()
+
+        if cls.sock_srv is not None:
+            cls.sock_srv.stop()
+            cls.sock_srv.clean()
diff --git a/test/suites/test_encoding.py b/test/suites/test_encoding.py
index 45bc6053..14a08f54 100644
--- a/test/suites/test_encoding.py
+++ b/test/suites/test_encoding.py
@@ -1,3 +1,8 @@
+"""
+This module tests various type encoding cases.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring
+
 import sys
 import unittest
 
@@ -7,36 +12,39 @@
 from .lib.skip import skip_or_run_varbinary_test, skip_or_run_error_extra_info_test
 from .lib.tarantool_server import TarantoolServer
 
-class TestSuite_Encoding(unittest.TestCase):
+
+class TestSuiteEncoding(unittest.TestCase):
+    # pylint: disable=invalid-name
+
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' ENCODING '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
 
-        self.srv.admin("""
+        cls.srv.admin("""
             box.schema.user.create('test', { password = 'test' })
             box.schema.user.grant('test', 'execute,read,write', 'universe')
         """)
 
-        args = [self.srv.host, self.srv.args['primary']]
-        kwargs = { 'user': 'test', 'password': 'test' }
-        self.con_encoding_utf8 = tarantool.Connection(*args, encoding='utf-8', **kwargs)
-        self.con_encoding_none = tarantool.Connection(*args, encoding=None, **kwargs)
-        self.conns = [self.con_encoding_utf8, self.con_encoding_none]
+        args = [cls.srv.host, cls.srv.args['primary']]
+        kwargs = {'user': 'test', 'password': 'test'}
+        cls.con_encoding_utf8 = tarantool.Connection(*args, encoding='utf-8', **kwargs)
+        cls.con_encoding_none = tarantool.Connection(*args, encoding=None, **kwargs)
+        cls.conns = [cls.con_encoding_utf8, cls.con_encoding_none]
 
-        self.srv.admin("box.schema.create_space('space_str')")
-        self.srv.admin("""
+        cls.srv.admin("box.schema.create_space('space_str')")
+        cls.srv.admin("""
             box.space['space_str']:create_index('primary', {
                 type = 'tree',
                 parts = {1, 'str'},
                 unique = true})
         """.replace('\n', ' '))
 
-        self.srv.admin("box.schema.create_space('space_varbin')")
-        self.srv.admin(r"""
+        cls.srv.admin("box.schema.create_space('space_varbin')")
+        cls.srv.admin(r"""
             box.space['space_varbin']:format({
                 {
                     'id',
@@ -50,13 +58,13 @@ def setUpClass(self):
                 }
             })
         """.replace('\n', ' '))
-        self.srv.admin("""
+        cls.srv.admin("""
             box.space['space_varbin']:create_index('id', {
                 type = 'tree',
                 parts = {1, 'number'},
                 unique = true})
         """.replace('\n', ' '))
-        self.srv.admin("""
+        cls.srv.admin("""
             box.space['space_varbin']:create_index('varbin', {
                 type = 'tree',
                 parts = {2, 'varbinary'},
@@ -66,8 +74,8 @@ def setUpClass(self):
     def assertNotRaises(self, func, *args, **kwargs):
         try:
             func(*args, **kwargs)
-        except Exception as e:
-            self.fail('Function raised Exception: %s' % repr(e))
+        except Exception as exc:  # pylint: disable=bad-option-value,broad-exception-caught,broad-except
+            self.fail(f'Function raised Exception: {repr(exc)}')
 
     def setUp(self):
         # prevent a remote tarantool from clean our session
@@ -92,9 +100,9 @@ def test_01_02_string_decode_for_encoding_utf8_behavior(self):
         data = 'test_01_02'
         space = 'space_str'
 
-        self.srv.admin("box.space['%s']:insert{'%s'}" % (space, data))
+        self.srv.admin(f"box.space['{space}']:insert{{'{data}'}}")
 
-        resp = self.con_encoding_utf8.eval("return box.space['%s']:get('%s')" % (space, data))
+        resp = self.con_encoding_utf8.eval(f"return box.space['{space}']:get('{data}')")
         self.assertSequenceEqual(resp, [[data]])
 
     @skip_or_run_varbinary_test
@@ -105,7 +113,7 @@ def test_01_03_bytes_encode_for_encoding_utf8_behavior(self):
 
         self.assertNotRaises(self.con_encoding_utf8.insert, space, [data_id, data])
 
-        resp = self.con_encoding_utf8.select(space, [ data ], index='varbin')
+        resp = self.con_encoding_utf8.select(space, [data], index='varbin')
         self.assertSequenceEqual(resp, [[data_id, data]])
 
     @skip_or_run_varbinary_test
@@ -115,13 +123,13 @@ def test_01_04_varbinary_decode_for_encoding_utf8_behavior(self):
         data = bytes(bytearray.fromhex(data_hex))
         space = 'space_varbin'
 
-        self.con_encoding_utf8.execute("""
-            INSERT INTO "%s" VALUES (%d, x'%s');
-        """ % (space, data_id, data_hex))
+        self.con_encoding_utf8.execute(f"""
+            INSERT INTO "{space}" VALUES ({data_id}, x'{data_hex}');
+        """)
 
-        resp = self.con_encoding_utf8.execute("""
-            SELECT * FROM "%s" WHERE "varbin" == x'%s';
-        """ % (space, data_hex))
+        resp = self.con_encoding_utf8.execute(f"""
+            SELECT * FROM "{space}" WHERE "varbin" == x'{data_hex}';
+        """)
         self.assertSequenceEqual(resp, [[data_id, data]])
 
     # encoding = None
@@ -144,9 +152,9 @@ def test_02_02_string_decode_for_encoding_none_behavior(self):
         data_decoded = b'test_02_02'
         space = 'space_str'
 
-        self.srv.admin("box.space['%s']:insert{'%s'}" % (space, data))
+        self.srv.admin(f"box.space['{space}']:insert{{'{data}'}}")
 
-        resp = self.con_encoding_none.eval("return box.space['%s']:get('%s')" % (space, data))
+        resp = self.con_encoding_none.eval(f"return box.space['{space}']:get('{data}')")
         self.assertSequenceEqual(resp, [[data_decoded]])
 
     def test_02_03_bytes_encode_for_encoding_none_behavior(self):
@@ -165,13 +173,13 @@ def test_02_04_varbinary_decode_for_encoding_none_behavior(self):
         data = bytes(bytearray.fromhex(data_hex))
         space = 'space_varbin'
 
-        self.con_encoding_none.execute("""
-            INSERT INTO "%s" VALUES (%d, x'%s');
-        """ % (space, data_id, data_hex))
+        self.con_encoding_none.execute(f"""
+            INSERT INTO "{space}" VALUES ({data_id}, x'{data_hex}');
+        """)
 
-        resp = self.con_encoding_none.execute("""
-            SELECT * FROM "%s" WHERE "varbin" == x'%s';
-        """ % (space, data_hex))
+        resp = self.con_encoding_none.execute(f"""
+            SELECT * FROM "{space}" WHERE "varbin" == x'{data_hex}';
+        """)
         self.assertSequenceEqual(resp, [[data_id, data]])
 
     @skip_or_run_error_extra_info_test
@@ -195,8 +203,8 @@ def test_02_05_error_extra_info_decode_for_encoding_none_behavior(self):
             self.fail('Expected error')
 
     @classmethod
-    def tearDownClass(self):
-        for con in self.conns:
+    def tearDownClass(cls):
+        for con in cls.conns:
             con.close()
-        self.srv.stop()
-        self.srv.clean()
+        cls.srv.stop()
+        cls.srv.clean()
diff --git a/test/suites/test_error_ext.py b/test/suites/test_error_ext.py
index 89f5c35f..8d1a63cf 100644
--- a/test/suites/test_error_ext.py
+++ b/test/suites/test_error_ext.py
@@ -1,28 +1,33 @@
+"""
+This module tests work with extended error type.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,protected-access,line-too-long,duplicate-code
+
 import sys
 import unittest
-import uuid
-import msgpack
-import warnings
-import tarantool
 import pkg_resources
 
+import msgpack
+
+import tarantool
 from tarantool.msgpack_ext.packer import default as packer_default
 from tarantool.msgpack_ext.unpacker import ext_hook as unpacker_ext_hook
 
 from .lib.tarantool_server import TarantoolServer
 from .lib.skip import skip_or_run_error_ext_type_test
 
-class TestSuite_ErrorExt(unittest.TestCase):
+
+class TestSuiteErrorExt(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' ERROR EXT TYPE '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
 
-        self.adm = self.srv.admin
-        self.adm(r"""
+        cls.adm = cls.srv.admin
+        cls.adm(r"""
             box.schema.space.create('test')
             box.space['test']:create_index('primary', {
                 type = 'tree',
@@ -35,23 +40,23 @@ def setUpClass(self):
             box.schema.user.create('no_grants', {if_not_exists = true})
         """)
 
-        self.conn_encoding_utf8 = tarantool.Connection(
-            self.srv.host, self.srv.args['primary'],
+        cls.conn_encoding_utf8 = tarantool.Connection(
+            cls.srv.host, cls.srv.args['primary'],
             user='test', password='test',
             encoding='utf-8')
-        self.conn_encoding_none = tarantool.Connection(
-            self.srv.host, self.srv.args['primary'],
+        cls.conn_encoding_none = tarantool.Connection(
+            cls.srv.host, cls.srv.args['primary'],
             user='test', password='test',
             encoding=None)
 
-        if self.adm.tnt_version >= pkg_resources.parse_version('2.10.0'):
-            self.conn_encoding_utf8.eval(r"""
+        if cls.adm.tnt_version >= pkg_resources.parse_version('2.10.0'):
+            cls.conn_encoding_utf8.eval(r"""
                 local err = box.error.new(box.error.UNKNOWN)
                 rawset(_G, 'simple_error', err)
             """)
 
             # https://github.com/tarantool/tarantool/blob/125c13c81abb302708771ba04d59382d44a4a512/test/box-tap/extended_error.test.lua
-            self.conn_encoding_utf8.eval(r"""
+            cls.conn_encoding_utf8.eval(r"""
                 local user = box.session.user()
                 box.schema.func.create('forbidden_function', {body = 'function() end'})
                 box.session.su('no_grants')
@@ -61,7 +66,7 @@ def setUpClass(self):
             """)
 
             # https://github.com/tarantool/tarantool/blob/125c13c81abb302708771ba04d59382d44a4a512/test/box-tap/extended_error.test.lua
-            self.conn_encoding_utf8.eval(r"""
+            cls.conn_encoding_utf8.eval(r"""
                 local e1 = box.error.new(box.error.UNKNOWN)
                 local e2 = box.error.new(box.error.UNKNOWN)
                 e2:set_prev(e1)
@@ -75,10 +80,9 @@ def setUp(self):
 
         self.adm("box.space['test']:truncate()")
 
-
     # msgpack data for different encodings are actually the same,
     # but sometimes python msgpack module use different string
-    # types (str8 and str16) for the same strings depending on use_bin_type: 
+    # types (str8 and str16) for the same strings depending on use_bin_type:
     #
     # >>> msgpack.Packer(use_bin_type=True).pack('[string "                     local err = box.error.ne..."]')
     # b'\xd9;[string "                     local err = box.error.ne..."]'
@@ -97,9 +101,9 @@ def setUp(self):
                 errno=0,
                 errcode=0,
             ),
-            'msgpack': (b'\x81\x00\x91\x86\x00\xab\x43\x6c\x69\x65\x6e\x74' +
-                        b'\x45\x72\x72\x6f\x72\x01\xa4\x65\x76\x61\x6c\x02' +
-                        b'\x01\x03\xad\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x65' +
+            'msgpack': (b'\x81\x00\x91\x86\x00\xab\x43\x6c\x69\x65\x6e\x74'
+                        b'\x45\x72\x72\x6f\x72\x01\xa4\x65\x76\x61\x6c\x02'
+                        b'\x01\x03\xad\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x65'
                         b'\x72\x72\x6f\x72\x04\x00\x05\x00'),
             'tarantool': "simple_error",
         },
@@ -114,9 +118,9 @@ def setUp(self):
                 errno=0,
                 errcode=0,
             ),
-            'msgpack': (b'\x81\x00\x91\x86\x00\xab\x43\x6c\x69\x65\x6e\x74' +
-                        b'\x45\x72\x72\x6f\x72\x01\xa4\x65\x76\x61\x6c\x02' +
-                        b'\x01\x03\xad\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x65' +
+            'msgpack': (b'\x81\x00\x91\x86\x00\xab\x43\x6c\x69\x65\x6e\x74'
+                        b'\x45\x72\x72\x6f\x72\x01\xa4\x65\x76\x61\x6c\x02'
+                        b'\x01\x03\xad\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x65'
                         b'\x72\x72\x6f\x72\x04\x00\x05\x00'),
             'tarantool': "simple_error",
         },
@@ -127,7 +131,8 @@ def setUp(self):
                 type='AccessDeniedError',
                 file='/__w/sdk/sdk/tarantool-2.10/tarantool/src/box/func.c',
                 line=535,
-                message="Execute access to function 'forbidden_function' is denied for user 'no_grants'",
+                message=("Execute access to function 'forbidden_function' is denied "
+                         "for user 'no_grants'"),
                 errno=0,
                 errcode=42,
                 fields={
@@ -136,26 +141,26 @@ def setUp(self):
                     'access_type': 'Execute',
                 },
             ),
-            'msgpack': (b'\x81\x00\x91\x87\x00\xb1\x41\x63\x63\x65\x73\x73' +
-                        b'\x44\x65\x6e\x69\x65\x64\x45\x72\x72\x6f\x72\x01' +
-                        b'\xd9\x34\x2f\x5f\x5f\x77\x2f\x73\x64\x6b\x2f\x73' +
-                        b'\x64\x6b\x2f\x74\x61\x72\x61\x6e\x74\x6f\x6f\x6c' +
-                        b'\x2d\x32\x2e\x31\x30\x2f\x74\x61\x72\x61\x6e\x74' +
-                        b'\x6f\x6f\x6c\x2f\x73\x72\x63\x2f\x62\x6f\x78\x2f' +
-                        b'\x66\x75\x6e\x63\x2e\x63\x02\xcd\x02\x17\x03\xd9' +
-                        b'\x4e\x45\x78\x65\x63\x75\x74\x65\x20\x61\x63\x63' +
-                        b'\x65\x73\x73\x20\x74\x6f\x20\x66\x75\x6e\x63\x74' +
-                        b'\x69\x6f\x6e\x20\x27\x66\x6f\x72\x62\x69\x64\x64' +
-                        b'\x65\x6e\x5f\x66\x75\x6e\x63\x74\x69\x6f\x6e\x27' +
-                        b'\x20\x69\x73\x20\x64\x65\x6e\x69\x65\x64\x20\x66' +
-                        b'\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x6e\x6f\x5f' +
-                        b'\x67\x72\x61\x6e\x74\x73\x27\x04\x00\x05\x2a\x06' +
-                        b'\x83\xab\x6f\x62\x6a\x65\x63\x74\x5f\x74\x79\x70' +
-                        b'\x65\xa8\x66\x75\x6e\x63\x74\x69\x6f\x6e\xab\x6f' +
-                        b'\x62\x6a\x65\x63\x74\x5f\x6e\x61\x6d\x65\xb2\x66' +
-                        b'\x6f\x72\x62\x69\x64\x64\x65\x6e\x5f\x66\x75\x6e' +
-                        b'\x63\x74\x69\x6f\x6e\xab\x61\x63\x63\x65\x73\x73' +
-                        b'\x5f\x74\x79\x70\x65\xa7\x45\x78\x65\x63\x75\x74' +
+            'msgpack': (b'\x81\x00\x91\x87\x00\xb1\x41\x63\x63\x65\x73\x73'
+                        b'\x44\x65\x6e\x69\x65\x64\x45\x72\x72\x6f\x72\x01'
+                        b'\xd9\x34\x2f\x5f\x5f\x77\x2f\x73\x64\x6b\x2f\x73'
+                        b'\x64\x6b\x2f\x74\x61\x72\x61\x6e\x74\x6f\x6f\x6c'
+                        b'\x2d\x32\x2e\x31\x30\x2f\x74\x61\x72\x61\x6e\x74'
+                        b'\x6f\x6f\x6c\x2f\x73\x72\x63\x2f\x62\x6f\x78\x2f'
+                        b'\x66\x75\x6e\x63\x2e\x63\x02\xcd\x02\x17\x03\xd9'
+                        b'\x4e\x45\x78\x65\x63\x75\x74\x65\x20\x61\x63\x63'
+                        b'\x65\x73\x73\x20\x74\x6f\x20\x66\x75\x6e\x63\x74'
+                        b'\x69\x6f\x6e\x20\x27\x66\x6f\x72\x62\x69\x64\x64'
+                        b'\x65\x6e\x5f\x66\x75\x6e\x63\x74\x69\x6f\x6e\x27'
+                        b'\x20\x69\x73\x20\x64\x65\x6e\x69\x65\x64\x20\x66'
+                        b'\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x6e\x6f\x5f'
+                        b'\x67\x72\x61\x6e\x74\x73\x27\x04\x00\x05\x2a\x06'
+                        b'\x83\xab\x6f\x62\x6a\x65\x63\x74\x5f\x74\x79\x70'
+                        b'\x65\xa8\x66\x75\x6e\x63\x74\x69\x6f\x6e\xab\x6f'
+                        b'\x62\x6a\x65\x63\x74\x5f\x6e\x61\x6d\x65\xb2\x66'
+                        b'\x6f\x72\x62\x69\x64\x64\x65\x6e\x5f\x66\x75\x6e'
+                        b'\x63\x74\x69\x6f\x6e\xab\x61\x63\x63\x65\x73\x73'
+                        b'\x5f\x74\x79\x70\x65\xa7\x45\x78\x65\x63\x75\x74'
                         b'\x65'),
             'tarantool': "access_denied_error",
             'ignore_file_info': True,
@@ -167,7 +172,8 @@ def setUp(self):
                 type=b'AccessDeniedError',
                 file=b'/__w/sdk/sdk/tarantool-2.10/tarantool/src/box/func.c',
                 line=535,
-                message=b"Execute access to function 'forbidden_function' is denied for user 'no_grants'",
+                message=(b"Execute access to function 'forbidden_function' is denied "
+                         b"for user 'no_grants'"),
                 errno=0,
                 errcode=42,
                 fields={
@@ -176,26 +182,26 @@ def setUp(self):
                     b'access_type': b'Execute',
                 },
             ),
-            'msgpack': (b'\x81\x00\x91\x87\x00\xb1\x41\x63\x63\x65\x73\x73' +
-                        b'\x44\x65\x6e\x69\x65\x64\x45\x72\x72\x6f\x72\x01' +
-                        b'\xda\x00\x34\x2f\x5f\x5f\x77\x2f\x73\x64\x6b\x2f' +
-                        b'\x73\x64\x6b\x2f\x74\x61\x72\x61\x6e\x74\x6f\x6f' +
-                        b'\x6c\x2d\x32\x2e\x31\x30\x2f\x74\x61\x72\x61\x6e' +
-                        b'\x74\x6f\x6f\x6c\x2f\x73\x72\x63\x2f\x62\x6f\x78' +
-                        b'\x2f\x66\x75\x6e\x63\x2e\x63\x02\xcd\x02\x17\x03' +
-                        b'\xda\x00\x4e\x45\x78\x65\x63\x75\x74\x65\x20\x61' +
-                        b'\x63\x63\x65\x73\x73\x20\x74\x6f\x20\x66\x75\x6e' +
-                        b'\x63\x74\x69\x6f\x6e\x20\x27\x66\x6f\x72\x62\x69' +
-                        b'\x64\x64\x65\x6e\x5f\x66\x75\x6e\x63\x74\x69\x6f' +
-                        b'\x6e\x27\x20\x69\x73\x20\x64\x65\x6e\x69\x65\x64' +
-                        b'\x20\x66\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x6e' +
-                        b'\x6f\x5f\x67\x72\x61\x6e\x74\x73\x27\x04\x00\x05' +
-                        b'\x2a\x06\x83\xab\x6f\x62\x6a\x65\x63\x74\x5f\x74' +
-                        b'\x79\x70\x65\xa8\x66\x75\x6e\x63\x74\x69\x6f\x6e' +
-                        b'\xab\x6f\x62\x6a\x65\x63\x74\x5f\x6e\x61\x6d\x65' +
-                        b'\xb2\x66\x6f\x72\x62\x69\x64\x64\x65\x6e\x5f\x66' +
-                        b'\x75\x6e\x63\x74\x69\x6f\x6e\xab\x61\x63\x63\x65' +
-                        b'\x73\x73\x5f\x74\x79\x70\x65\xa7\x45\x78\x65\x63' +
+            'msgpack': (b'\x81\x00\x91\x87\x00\xb1\x41\x63\x63\x65\x73\x73'
+                        b'\x44\x65\x6e\x69\x65\x64\x45\x72\x72\x6f\x72\x01'
+                        b'\xda\x00\x34\x2f\x5f\x5f\x77\x2f\x73\x64\x6b\x2f'
+                        b'\x73\x64\x6b\x2f\x74\x61\x72\x61\x6e\x74\x6f\x6f'
+                        b'\x6c\x2d\x32\x2e\x31\x30\x2f\x74\x61\x72\x61\x6e'
+                        b'\x74\x6f\x6f\x6c\x2f\x73\x72\x63\x2f\x62\x6f\x78'
+                        b'\x2f\x66\x75\x6e\x63\x2e\x63\x02\xcd\x02\x17\x03'
+                        b'\xda\x00\x4e\x45\x78\x65\x63\x75\x74\x65\x20\x61'
+                        b'\x63\x63\x65\x73\x73\x20\x74\x6f\x20\x66\x75\x6e'
+                        b'\x63\x74\x69\x6f\x6e\x20\x27\x66\x6f\x72\x62\x69'
+                        b'\x64\x64\x65\x6e\x5f\x66\x75\x6e\x63\x74\x69\x6f'
+                        b'\x6e\x27\x20\x69\x73\x20\x64\x65\x6e\x69\x65\x64'
+                        b'\x20\x66\x6f\x72\x20\x75\x73\x65\x72\x20\x27\x6e'
+                        b'\x6f\x5f\x67\x72\x61\x6e\x74\x73\x27\x04\x00\x05'
+                        b'\x2a\x06\x83\xab\x6f\x62\x6a\x65\x63\x74\x5f\x74'
+                        b'\x79\x70\x65\xa8\x66\x75\x6e\x63\x74\x69\x6f\x6e'
+                        b'\xab\x6f\x62\x6a\x65\x63\x74\x5f\x6e\x61\x6d\x65'
+                        b'\xb2\x66\x6f\x72\x62\x69\x64\x64\x65\x6e\x5f\x66'
+                        b'\x75\x6e\x63\x74\x69\x6f\x6e\xab\x61\x63\x63\x65'
+                        b'\x73\x73\x5f\x74\x79\x70\x65\xa7\x45\x78\x65\x63'
                         b'\x75\x74\x65'),
             'tarantool': "access_denied_error",
             'ignore_file_info': True,
@@ -219,12 +225,12 @@ def setUp(self):
                     errcode=0,
                 ),
             ),
-            'msgpack': (b'\x81\x00\x92\x86\x00\xab\x43\x6c\x69\x65\x6e\x74' +
-                        b'\x45\x72\x72\x6f\x72\x01\xa4\x65\x76\x61\x6c\x02' +
-                        b'\x03\x03\xad\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x65' +
-                        b'\x72\x72\x6f\x72\x04\x00\x05\x00\x86\x00\xab\x43' +
-                        b'\x6c\x69\x65\x6e\x74\x45\x72\x72\x6f\x72\x01\xa4' +
-                        b'\x65\x76\x61\x6c\x02\x02\x03\xad\x55\x6e\x6b\x6e' +
+            'msgpack': (b'\x81\x00\x92\x86\x00\xab\x43\x6c\x69\x65\x6e\x74'
+                        b'\x45\x72\x72\x6f\x72\x01\xa4\x65\x76\x61\x6c\x02'
+                        b'\x03\x03\xad\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x65'
+                        b'\x72\x72\x6f\x72\x04\x00\x05\x00\x86\x00\xab\x43'
+                        b'\x6c\x69\x65\x6e\x74\x45\x72\x72\x6f\x72\x01\xa4'
+                        b'\x65\x76\x61\x6c\x02\x02\x03\xad\x55\x6e\x6b\x6e'
                         b'\x6f\x77\x6e\x20\x65\x72\x72\x6f\x72\x04\x00\x05\x00'),
             'tarantool': "chained_error",
             'ignore_file_info': False,
@@ -248,23 +254,21 @@ def setUp(self):
                     errcode=0,
                 ),
             ),
-            'msgpack': (b'\x81\x00\x92\x86\x00\xab\x43\x6c\x69\x65\x6e\x74' +
-                        b'\x45\x72\x72\x6f\x72\x01\xa4\x65\x76\x61\x6c\x02' +
-                        b'\x03\x03\xad\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x65' +
-                        b'\x72\x72\x6f\x72\x04\x00\x05\x00\x86\x00\xab\x43' +
-                        b'\x6c\x69\x65\x6e\x74\x45\x72\x72\x6f\x72\x01\xa4' +
-                        b'\x65\x76\x61\x6c\x02\x02\x03\xad\x55\x6e\x6b\x6e' +
+            'msgpack': (b'\x81\x00\x92\x86\x00\xab\x43\x6c\x69\x65\x6e\x74'
+                        b'\x45\x72\x72\x6f\x72\x01\xa4\x65\x76\x61\x6c\x02'
+                        b'\x03\x03\xad\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x65'
+                        b'\x72\x72\x6f\x72\x04\x00\x05\x00\x86\x00\xab\x43'
+                        b'\x6c\x69\x65\x6e\x74\x45\x72\x72\x6f\x72\x01\xa4'
+                        b'\x65\x76\x61\x6c\x02\x02\x03\xad\x55\x6e\x6b\x6e'
                         b'\x6f\x77\x6e\x20\x65\x72\x72\x6f\x72\x04\x00\x05\x00'),
             'tarantool': "chained_error",
             'ignore_file_info': False,
         }
     }
 
-
     def test_msgpack_decode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
                 conn = getattr(self, case['conn'])
 
                 self.assertEqual(
@@ -277,9 +281,8 @@ def test_msgpack_decode(self):
 
     @skip_or_run_error_ext_type_test
     def test_tarantool_decode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
                 conn = getattr(self, case['conn'])
 
                 self.adm(f"""
@@ -321,11 +324,9 @@ def test_tarantool_decode(self):
 
                 self.assertEqual(err, expected_err)
 
-
     def test_msgpack_encode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
                 conn = getattr(self, case['conn'])
 
                 self.assertEqual(packer_default(case['python'], conn._packer_factory()),
@@ -333,9 +334,8 @@ def test_msgpack_encode(self):
 
     @skip_or_run_error_ext_type_test
     def test_tarantool_encode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
                 conn = getattr(self, case['conn'])
 
                 conn.insert(
@@ -388,10 +388,9 @@ def test_tarantool_encode(self):
 
                 self.assertSequenceEqual(conn.eval(lua_eval), [True])
 
-
     @classmethod
-    def tearDownClass(self):
-        self.conn_encoding_utf8.close()
-        self.conn_encoding_none.close()
-        self.srv.stop()
-        self.srv.clean()
+    def tearDownClass(cls):
+        cls.conn_encoding_utf8.close()
+        cls.conn_encoding_none.close()
+        cls.srv.stop()
+        cls.srv.clean()
diff --git a/test/suites/test_execute.py b/test/suites/test_execute.py
index f90b2fc3..66fe0982 100644
--- a/test/suites/test_execute.py
+++ b/test/suites/test_execute.py
@@ -1,3 +1,8 @@
+"""
+This module tests API for running SQL on a server.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,duplicate-code
+
 import sys
 import unittest
 
@@ -6,7 +11,7 @@
 from .lib.skip import skip_or_run_sql_test
 
 
-class TestSuite_Execute(unittest.TestCase):
+class TestSuiteExecute(unittest.TestCase):
     ddl = 'create table %s (id INTEGER PRIMARY KEY AUTOINCREMENT, ' \
           'name varchar(20))'
 
@@ -19,13 +24,13 @@ class TestSuite_Execute(unittest.TestCase):
     ]
 
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' EXECUTE '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
-        self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'])
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
+        cls.con = tarantool.Connection(cls.srv.host, cls.srv.args['primary'])
 
     @skip_or_run_sql_test
     def setUp(self):
@@ -39,13 +44,13 @@ def setUp(self):
                        "execute', 'universe')")
 
     @classmethod
-    def tearDownClass(self):
-        self.con.close()
-        self.srv.stop()
-        self.srv.clean()
+    def tearDownClass(cls):
+        cls.con.close()
+        cls.srv.stop()
+        cls.srv.clean()
 
     def _populate_data(self, table_name):
-        query = "insert into %s values (:id, :name)" % table_name
+        query = f"insert into {table_name} values (:id, :name)"
         for param in self.dml_params:
             self.con.execute(query, param)
 
@@ -59,7 +64,7 @@ def test_dml_response(self):
         self.assertEqual(response.affected_row_count, 1)
         self.assertEqual(response.data, None)
 
-        query = "insert into %s values (:id, :name)" % table_name
+        query = f"insert into {table_name} values (:id, :name)"
 
         for num, param in enumerate(self.dml_params, start=1):
             response = self.con.execute(query, param)
@@ -67,7 +72,7 @@ def test_dml_response(self):
             self.assertEqual(response.affected_row_count, 1)
             self.assertEqual(response.data, None)
 
-        query = "delete from %s where id in (4, 5)" % table_name
+        query = f"delete from {table_name} where id in (4, 5)"
         response = self.con.execute(query)
         self.assertEqual(response.autoincrement_ids, None)
         self.assertEqual(response.affected_row_count, 2)
@@ -78,7 +83,7 @@ def test_dql_response(self):
         self._create_table(table_name)
         self._populate_data(table_name)
 
-        select_query = "select name from %s where id in (1, 3, 5)" % table_name
+        select_query = f"select name from {table_name} where id in (1, 3, 5)"
         response = self.con.execute(select_query)
         self.assertEqual(response.autoincrement_ids, None)
         self.assertEqual(response.affected_row_count, None)
diff --git a/test/suites/test_interval.py b/test/suites/test_interval.py
index 2252ebe8..77f2cf52 100644
--- a/test/suites/test_interval.py
+++ b/test/suites/test_interval.py
@@ -1,30 +1,34 @@
+"""
+This module tests work with datetime interval type.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,protected-access,too-many-function-args,duplicate-code
+
 import re
 import sys
 import unittest
+
 import msgpack
-import warnings
-import tarantool
-import pandas
-import pytz
 
+import tarantool
+from tarantool.error import MsgpackError
 from tarantool.msgpack_ext.packer import default as packer_default
 from tarantool.msgpack_ext.unpacker import ext_hook as unpacker_ext_hook
 
 from .lib.tarantool_server import TarantoolServer
 from .lib.skip import skip_or_run_datetime_test
-from tarantool.error import MsgpackError
 
-class TestSuite_Interval(unittest.TestCase):
+
+class TestSuiteInterval(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' INTERVAL EXT TYPE '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
 
-        self.adm = self.srv.admin
-        self.adm(r"""
+        cls.adm = cls.srv.admin
+        cls.adm(r"""
             _, datetime = pcall(require, 'datetime')
 
             box.schema.space.create('test')
@@ -47,8 +51,8 @@ def setUpClass(self):
             rawset(_G, 'sub', sub)
         """)
 
-        self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'],
-                                        user='test', password='test')
+        cls.con = tarantool.Connection(cls.srv.host, cls.srv.args['primary'],
+                                       user='test', password='test')
 
     def setUp(self):
         # prevent a remote tarantool from clean our session
@@ -57,7 +61,7 @@ def setUp(self):
 
         self.adm("box.space['test']:truncate()")
 
-    def test_Interval_positional_init(self):
+    def test_interval_positional_init(self):
         self.assertRaisesRegex(
             TypeError, re.escape('__init__() takes 1 positional argument but 2 were given'),
             lambda: tarantool.Interval(1))
@@ -96,7 +100,8 @@ def test_Interval_positional_init(self):
         'datetime': {
             'python': tarantool.Interval(year=1, month=2, day=3, hour=1, minute=2, sec=3000),
             'msgpack': (b'\x07\x00\x01\x01\x02\x03\x03\x04\x01\x05\x02\x06\xcd\x0b\xb8\x08\x01'),
-            'tarantool': r"datetime.interval.new({year=1, month=2, day=3, hour=1, min=2, sec=3000})",
+            'tarantool': r"datetime.interval.new({year=1, month=2, day=3, hour=1, "
+                         r"min=2, sec=3000})",
         },
         'nanoseconds': {
             'python': tarantool.Interval(nsec=10000000),
@@ -106,36 +111,36 @@ def test_Interval_positional_init(self):
         'datetime_with_nanoseconds': {
             'python': tarantool.Interval(year=1, month=2, day=3, hour=1, minute=2,
                                          sec=3000, nsec=10000000),
-            'msgpack': (b'\x08\x00\x01\x01\x02\x03\x03\x04\x01\x05\x02\x06\xcd\x0b\xb8\x07\xce' +
+            'msgpack': (b'\x08\x00\x01\x01\x02\x03\x03\x04\x01\x05\x02\x06\xcd\x0b\xb8\x07\xce'
                         b'\x00\x98\x96\x80\x08\x01'),
-            'tarantool': r"datetime.interval.new({year=1, month=2, day=3, hour=1, " +
+            'tarantool': r"datetime.interval.new({year=1, month=2, day=3, hour=1, "
                          r"min=2, sec=3000, nsec=10000000})",
         },
         'datetime_none_adjust': {
             'python': tarantool.Interval(year=1, month=2, day=3, hour=1, minute=2,
                                          sec=3000, nsec=10000000,
                                          adjust=tarantool.IntervalAdjust.NONE),
-            'msgpack': (b'\x08\x00\x01\x01\x02\x03\x03\x04\x01\x05\x02\x06\xcd\x0b\xb8\x07\xce' +
+            'msgpack': (b'\x08\x00\x01\x01\x02\x03\x03\x04\x01\x05\x02\x06\xcd\x0b\xb8\x07\xce'
                         b'\x00\x98\x96\x80\x08\x01'),
-            'tarantool': r"datetime.interval.new({year=1, month=2, day=3, hour=1, " +
+            'tarantool': r"datetime.interval.new({year=1, month=2, day=3, hour=1, "
                          r"min=2, sec=3000, nsec=10000000, adjust='none'})",
         },
         'datetime_excess_adjust': {
             'python': tarantool.Interval(year=1, month=2, day=3, hour=1, minute=2,
                                          sec=3000, nsec=10000000,
                                          adjust=tarantool.IntervalAdjust.EXCESS),
-            'msgpack': (b'\x07\x00\x01\x01\x02\x03\x03\x04\x01\x05\x02\x06\xcd\x0b\xb8\x07\xce' +
+            'msgpack': (b'\x07\x00\x01\x01\x02\x03\x03\x04\x01\x05\x02\x06\xcd\x0b\xb8\x07\xce'
                         b'\x00\x98\x96\x80'),
-            'tarantool': r"datetime.interval.new({year=1, month=2, day=3, hour=1, " +
+            'tarantool': r"datetime.interval.new({year=1, month=2, day=3, hour=1, "
                          r"min=2, sec=3000, nsec=10000000, adjust='excess'})",
         },
         'datetime_last_adjust': {
             'python': tarantool.Interval(year=1, month=2, day=3, hour=1, minute=2,
                                          sec=3000, nsec=10000000,
                                          adjust=tarantool.IntervalAdjust.LAST),
-            'msgpack': (b'\x08\x00\x01\x01\x02\x03\x03\x04\x01\x05\x02\x06\xcd\x0b\xb8\x07\xce' +
+            'msgpack': (b'\x08\x00\x01\x01\x02\x03\x03\x04\x01\x05\x02\x06\xcd\x0b\xb8\x07\xce'
                         b'\x00\x98\x96\x80\x08\x02'),
-            'tarantool': r"datetime.interval.new({year=1, month=2, day=3, hour=1, " +
+            'tarantool': r"datetime.interval.new({year=1, month=2, day=3, hour=1, "
                          r"min=2, sec=3000, nsec=10000000, adjust='last'})",
         },
         'all_zeroes': {
@@ -146,47 +151,40 @@ def test_Interval_positional_init(self):
     }
 
     def test_msgpack_decode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
-
-                self.assertEqual(unpacker_ext_hook(
-                                    6,
-                                    case['msgpack'],
-                                    self.con._unpacker_factory(),
-                                 ),
-                                 case['python'])
+                self.assertEqual(
+                    unpacker_ext_hook(
+                        6,
+                        case['msgpack'],
+                        self.con._unpacker_factory(),
+                    ),
+                    case['python'])
 
     @skip_or_run_datetime_test
     def test_tarantool_decode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
-
                 self.adm(f"box.space['test']:replace{{'{name}', {case['tarantool']}, 'field'}}")
 
                 self.assertSequenceEqual(self.con.select('test', name),
                                          [[name, case['python'], 'field']])
 
     def test_msgpack_encode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
-
                 self.assertEqual(packer_default(case['python']),
                                  msgpack.ExtType(code=6, data=case['msgpack']))
 
     @skip_or_run_datetime_test
     def test_tarantool_encode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
-
                 self.con.insert('test', [name, case['python'], 'field'])
 
                 lua_eval = f"""
                     local interval = {case['tarantool']}
-                    
+
                     local tuple = box.space['test']:get('{name}')
                     assert(tuple ~= nil)
 
@@ -200,7 +198,6 @@ def test_tarantool_encode(self):
 
                 self.assertSequenceEqual(self.adm(lua_eval), [True])
 
-
     def test_unknown_field_decode(self):
         case = b'\x01\x09\xce\x00\x98\x96\x80'
         self.assertRaisesRegex(
@@ -213,7 +210,6 @@ def test_unknown_adjust_decode(self):
             MsgpackError, '3 is not a valid Adjust',
             lambda: unpacker_ext_hook(6, case, self.con._unpacker_factory()))
 
-
     arithmetic_cases = {
         'year': {
             'arg_1': tarantool.Interval(year=2),
@@ -241,9 +237,9 @@ def test_unknown_adjust_decode(self):
         },
         'datetime_with_nsec': {
             'arg_1': tarantool.Interval(year=1, month=2, day=3, hour=1, minute=2,
-                                           sec=3000, nsec=10000000),
+                                        sec=3000, nsec=10000000),
             'arg_2': tarantool.Interval(year=2, month=1, day=31, hour=-3, minute=0,
-                                           sec=1000, nsec=9876543),
+                                        sec=1000, nsec=9876543),
             'res_add': tarantool.Interval(year=3, month=3, day=34, hour=-2, minute=2,
                                           sec=4000, nsec=19876543),
             'res_sub': tarantool.Interval(year=-1, month=1, day=-28, hour=4, minute=2,
@@ -272,40 +268,31 @@ def test_unknown_adjust_decode(self):
     }
 
     def test_python_interval_addition(self):
-        for name in self.arithmetic_cases.keys():
+        for name, case in self.arithmetic_cases.items():
             with self.subTest(msg=name):
-                case = self.arithmetic_cases[name]
-
                 self.assertEqual(case['arg_1'] + case['arg_2'], case['res_add'])
 
     def test_python_interval_subtraction(self):
-        for name in self.arithmetic_cases.keys():
+        for name, case in self.arithmetic_cases.items():
             with self.subTest(msg=name):
-                case = self.arithmetic_cases[name]
-
                 self.assertEqual(case['arg_1'] - case['arg_2'], case['res_sub'])
 
     @skip_or_run_datetime_test
     def test_tarantool_interval_addition(self):
-        for name in self.arithmetic_cases.keys():
+        for name, case in self.arithmetic_cases.items():
             with self.subTest(msg=name):
-                case = self.arithmetic_cases[name]
-
                 self.assertSequenceEqual(self.con.call('add', case['arg_1'], case['arg_2']),
                                          [case['res_add']])
 
     @skip_or_run_datetime_test
     def test_tarantool_interval_subtraction(self):
-        for name in self.arithmetic_cases.keys():
+        for name, case in self.arithmetic_cases.items():
             with self.subTest(msg=name):
-                case = self.arithmetic_cases[name]
-
                 self.assertSequenceEqual(self.con.call('sub', case['arg_1'], case['arg_2']),
                                          [case['res_sub']])
 
-
     @classmethod
-    def tearDownClass(self):
-        self.con.close()
-        self.srv.stop()
-        self.srv.clean()
+    def tearDownClass(cls):
+        cls.con.close()
+        cls.srv.stop()
+        cls.srv.clean()
diff --git a/test/suites/test_mesh.py b/test/suites/test_mesh.py
index ae621bf5..b82ccc0e 100644
--- a/test/suites/test_mesh.py
+++ b/test/suites/test_mesh.py
@@ -1,3 +1,9 @@
+"""
+This module tests work with a cluster of Tarantool servers through
+MeshConnection.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring
+
 import sys
 import unittest
 import warnings
@@ -16,40 +22,42 @@ def create_server(_id):
     srv = TarantoolServer()
     srv.script = 'test/suites/box.lua'
     srv.start()
-    srv.admin("box.schema.user.create('test', {password = 'test', " +
+    srv.admin("box.schema.user.create('test', {password = 'test', "
               "if_not_exists = true})")
     srv.admin("box.schema.user.grant('test', 'execute', 'universe')")
 
     # Create srv_id function (for testing purposes).
-    srv.admin("function srv_id() return %s end" % _id)
+    srv.admin(f"function srv_id() return {_id} end")
     return srv
 
 
 @unittest.skipIf(sys.platform.startswith("win"),
                  'Mesh tests on windows platform are not supported')
-class TestSuite_Mesh(unittest.TestCase):
+class TestSuiteMesh(unittest.TestCase):
+    # pylint: disable=too-many-instance-attributes
+
     def define_cluster_function(self, func_name, servers):
         addresses = [(srv.host, srv.args['primary']) for srv in servers]
-        addresses_lua = ",".join("'%s:%d'" % address for address in addresses)
-        func_body = """
-            function %s()
-                return {%s}
+        addresses_lua = ",".join(f"'{address[0]}:{address[1]}'" for address in addresses)
+        func_body = f"""
+            function {func_name}()
+                return {{{addresses_lua}}}
             end
-        """ % (func_name, addresses_lua)
+        """
         for srv in self.servers:
             srv.admin(func_body)
 
     def define_custom_cluster_function(self, func_name, retval):
-        func_body = """
-            function %s()
-                return %s
+        func_body = f"""
+            function {func_name}()
+                return {retval}
             end
-        """ % (func_name, retval)
+        """
         for srv in self.servers:
             srv.admin(func_body)
 
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' MESH '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
 
@@ -158,11 +166,11 @@ def test_02_discovery_bad_address(self):
 
                 # Verify that a cluster discovery (that is triggered
                 # by ping) give one or two warnings.
-                with warnings.catch_warnings(record=True) as ws:
+                with warnings.catch_warnings(record=True) as warns:
                     con.ping()
-                    self.assertTrue(len(ws) in (1, 2))
-                    for w in ws:
-                        self.assertIs(w.category, ClusterDiscoveryWarning)
+                    self.assertTrue(len(warns) in (1, 2))
+                    for warn in warns:
+                        self.assertIs(warn.category, ClusterDiscoveryWarning)
 
                 # Verify that incorrect or empty result was discarded.
                 self.assertEqual(len(con.strategy.addrs), 1)
@@ -173,7 +181,7 @@ def test_02_discovery_bad_address(self):
 
     def test_03_discovery_bad_good_addresses(self):
         func_name = 'bad_and_good_addresses'
-        retval = "{'localhost:', '%s:%d'}" % (self.host_2, self.port_2)
+        retval = f"{{'localhost:', '{self.host_2}:{self.port_2}'}}"
         self.define_custom_cluster_function(func_name, retval)
         con = tarantool.MeshConnection(self.host_1, self.port_1,
                                        user='test', password='test')
@@ -182,10 +190,10 @@ def test_03_discovery_bad_good_addresses(self):
 
             # Verify that a cluster discovery (that is triggered
             # by ping) give one warning.
-            with warnings.catch_warnings(record=True) as ws:
+            with warnings.catch_warnings(record=True) as warns:
                 con.ping()
-                self.assertEqual(len(ws), 1)
-                self.assertIs(ws[0].category, ClusterDiscoveryWarning)
+                self.assertEqual(len(warns), 1)
+                self.assertIs(warns[0].category, ClusterDiscoveryWarning)
 
             # Verify that only second address was accepted.
             self.assertEqual(len(con.strategy.addrs), 1)
diff --git a/test/suites/test_package.py b/test/suites/test_package.py
index a136c958..8d13858a 100644
--- a/test/suites/test_package.py
+++ b/test/suites/test_package.py
@@ -1,30 +1,34 @@
+"""
+This module tests package features.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring
+
 import os
 import sys
 import unittest
 
+import tarantool
+
 if sys.version_info >= (3, 8):
     from importlib import metadata
 else:
     import importlib_metadata as metadata
 
-import tarantool
-
 
 def is_test_pure_install():
     env = os.getenv("TEST_PURE_INSTALL")
     if env:
         env = env.upper()
-        return env == "1" or env == "TRUE"
+        return env in ("1", "TRUE")
     return False
 
 
-class TestSuite_Package(unittest.TestCase):
+class TestSuitePackage(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' PACKAGE '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
 
-
     def test_version(self):
         if is_test_pure_install():
             self.assertEqual(tarantool.__version__, metadata.version('tarantool'))
diff --git a/test/suites/test_pool.py b/test/suites/test_pool.py
index f5e27f16..7134f220 100644
--- a/test/suites/test_pool.py
+++ b/test/suites/test_pool.py
@@ -1,3 +1,9 @@
+"""
+This module tests work with a cluster of Tarantool servers through
+ConnectionPool.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,too-many-public-methods,too-many-locals,duplicate-code,bad-option-value,no-self-use
+
 import sys
 import time
 import unittest
@@ -7,7 +13,6 @@
 from tarantool.error import (
     ClusterConnectWarning,
     DatabaseError,
-    NetworkError,
     NetworkWarning,
     PoolTolopogyError,
     PoolTolopogyWarning,
@@ -21,31 +26,31 @@ def create_server(_id):
     srv = TarantoolServer()
     srv.script = 'test/suites/box.lua'
     srv.start()
-    srv.admin("box.schema.user.create('test', {password = 'test', " +
+    srv.admin("box.schema.user.create('test', {password = 'test', "
               "if_not_exists = true})")
     srv.admin("box.schema.user.grant('test', 'execute', 'universe')")
     srv.admin("box.schema.space.create('test')")
     srv.admin(r"box.space.test:format({"
-             +r" { name = 'pk', type = 'string' }," +
-              r" { name = 'id', type = 'number', is_nullable = true }" +
+              r" { name = 'pk', type = 'string' },"
+              r" { name = 'id', type = 'number', is_nullable = true }"
               r"})")
-    srv.admin(r"box.space.test:create_index('pk'," +
-              r"{ unique = true," +
+    srv.admin(r"box.space.test:create_index('pk',"
+              r"{ unique = true,"
               r"  parts = {{field = 1, type = 'string'}}})")
-    srv.admin(r"box.space.test:create_index('id'," +
-              r"{ unique = true," +
+    srv.admin(r"box.space.test:create_index('id',"
+              r"{ unique = true,"
               r"  parts = {{field = 2, type = 'number', is_nullable=true}}})")
     srv.admin("box.schema.user.grant('test', 'read,write', 'space', 'test')")
     srv.admin("json = require('json')")
 
     # Create srv_id function (for testing purposes).
-    srv.admin("function srv_id() return %s end" % _id)
+    srv.admin(f"function srv_id() return {_id} end")
     return srv
 
 
 @unittest.skipIf(sys.platform.startswith("win"),
                  'Pool tests on windows platform are not supported')
-class TestSuite_Pool(unittest.TestCase):
+class TestSuitePool(unittest.TestCase):
     def set_ro(self, srv, read_only):
         if read_only:
             req = r'box.cfg{read_only = true}'
@@ -57,21 +62,21 @@ def set_ro(self, srv, read_only):
     def set_cluster_ro(self, read_only_list):
         assert len(self.servers) == len(read_only_list)
 
-        for i in range(len(self.servers)):
-            self.set_ro(self.servers[i], read_only_list[i])
+        for i, server in enumerate(self.servers):
+            self.set_ro(server, read_only_list[i])
 
     def retry(self, func, count=5, timeout=0.5):
         for i in range(count):
             try:
                 func()
-            except Exception as e:
+            except Exception as exc:  # pylint: disable=bad-option-value,broad-exception-caught,broad-except
                 if i + 1 == count:
-                    raise e
+                    raise exc
 
             time.sleep(timeout)
 
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' POOL '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
 
@@ -79,6 +84,7 @@ def setUp(self):
         # Create five servers and extract helpful fields for tests.
         self.servers = []
         self.addrs = []
+        self.pool = None
         self.servers_count = 5
         for i in range(self.servers_count):
             srv = create_server(i)
@@ -108,8 +114,9 @@ def test_00_basic(self):
 
     def test_01_roundrobin(self):
         self.set_cluster_ro([False, False, True, False, True])
-        RW_ports = set([str(self.addrs[0]['port']), str(self.addrs[1]['port']), str(self.addrs[3]['port'])])
-        RO_ports = set([str(self.addrs[2]['port']), str(self.addrs[4]['port'])])
+        rw_ports = set([str(self.addrs[0]['port']), str(self.addrs[1]['port']),
+                        str(self.addrs[3]['port'])])
+        ro_ports = set([str(self.addrs[2]['port']), str(self.addrs[4]['port'])])
         all_ports = set()
         for addr in self.addrs:
             all_ports.add(str(addr['port']))
@@ -126,79 +133,79 @@ def get_port(self, mode):
             return resp.data[0]
 
         # Expect ANY iterate through all instances.
-        ANY_ports_result = set()
-        for i in range(len(self.servers)):
-            ANY_ports_result.add(get_port(self, tarantool.Mode.ANY))
+        any_ports_result = set()
+        for _ in range(len(self.servers)):
+            any_ports_result.add(get_port(self, tarantool.Mode.ANY))
 
-        self.assertSetEqual(ANY_ports_result, all_ports)
+        self.assertSetEqual(any_ports_result, all_ports)
 
         # Expect RW iterate through all RW instances.
-        RW_ports_result = set()
-        for i in range(len(self.servers)):
-            RW_ports_result.add(get_port(self, tarantool.Mode.RW))
+        rw_ports_result = set()
+        for _ in range(len(self.servers)):
+            rw_ports_result.add(get_port(self, tarantool.Mode.RW))
 
-        self.assertSetEqual(RW_ports_result, RW_ports)
+        self.assertSetEqual(rw_ports_result, rw_ports)
 
         # Expect RO iterate through all RO instances.
-        RO_ports_result = set()
-        for i in range(len(self.servers)):
-            RO_ports_result.add(get_port(self, tarantool.Mode.RO))
+        ro_ports_result = set()
+        for _ in range(len(self.servers)):
+            ro_ports_result.add(get_port(self, tarantool.Mode.RO))
 
-        self.assertSetEqual(RO_ports_result, RO_ports)
+        self.assertSetEqual(ro_ports_result, ro_ports)
 
         # Expect PREFER_RW iterate through all RW instances if there is at least one.
-        PREFER_RW_ports_result = set()
-        for i in range(len(self.servers)):
-            PREFER_RW_ports_result.add(get_port(self, tarantool.Mode.PREFER_RW))
+        prefer_rw_ports_result = set()
+        for _ in range(len(self.servers)):
+            prefer_rw_ports_result.add(get_port(self, tarantool.Mode.PREFER_RW))
 
-        self.assertSetEqual(PREFER_RW_ports_result, RW_ports)
+        self.assertSetEqual(prefer_rw_ports_result, rw_ports)
 
         # Expect PREFER_RO iterate through all RO instances if there is at least one.
-        PREFER_RO_ports_result = set()
-        for i in range(len(self.servers)):
-            PREFER_RO_ports_result.add(get_port(self, tarantool.Mode.PREFER_RO))
+        prefer_ro_ports_result = set()
+        for _ in range(len(self.servers)):
+            prefer_ro_ports_result.add(get_port(self, tarantool.Mode.PREFER_RO))
 
-        self.assertSetEqual(PREFER_RO_ports_result, RO_ports)
+        self.assertSetEqual(prefer_ro_ports_result, ro_ports)
 
         # Setup cluster with no RW.
         self.set_cluster_ro([True, True, True, True, True])
 
         # Expect RW to fail if there are no RW.
-        def expect_RW_to_fail_if_there_are_no_RW():
+        def expect_rw_to_fail_if_there_are_no_rw():
             with self.assertRaises(PoolTolopogyError):
                 self.pool.eval('return box.cfg.listen', mode=tarantool.Mode.RW)
 
-        self.retry(func=expect_RW_to_fail_if_there_are_no_RW)
+        self.retry(func=expect_rw_to_fail_if_there_are_no_rw)
 
         # Expect PREFER_RW iterate through all instances if there are no RW.
-        def expect_PREFER_RW_iterate_through_all_instances_if_there_are_no_RW():
-            PREFER_RW_ports_result_all_ro = set()
-            for i in range(len(self.servers)):
-                PREFER_RW_ports_result_all_ro.add(get_port(self, tarantool.Mode.PREFER_RW))
+        def expect_prefer_rw_iterate_through_all_instances_if_there_are_no_rw():
+            prefer_rw_ports_result_all_ro = set()
+            for _ in range(len(self.servers)):
+                prefer_rw_ports_result_all_ro.add(get_port(self, tarantool.Mode.PREFER_RW))
+
+            self.assertSetEqual(prefer_rw_ports_result_all_ro, all_ports)
 
-            self.assertSetEqual(PREFER_RW_ports_result_all_ro, all_ports)
-    
-        self.retry(func=expect_PREFER_RW_iterate_through_all_instances_if_there_are_no_RW)
+        self.retry(func=expect_prefer_rw_iterate_through_all_instances_if_there_are_no_rw)
 
         # Setup cluster with no RO.
         self.set_cluster_ro([False, False, False, False, False])
 
         # Expect RO to fail if there are no RO.
-        def expect_RO_to_fail_if_there_are_no_RO():
+        def expect_ro_to_fail_if_there_are_no_ro():
             with self.assertRaises(PoolTolopogyError):
                 self.pool.eval('return box.cfg.listen', mode=tarantool.Mode.RO)
 
-        self.retry(func=expect_RO_to_fail_if_there_are_no_RO)
+        self.retry(func=expect_ro_to_fail_if_there_are_no_ro)
 
         # Expect PREFER_RO iterate through all instances if there are no RO.
-        def expect_PREFER_RO_iterate_through_all_instances_if_there_are_no_RO():
-            PREFER_RO_ports_result_all_rw = set()
-            for i in range(len(self.servers)):
-                PREFER_RO_ports_result_all_rw.add(get_port(self, tarantool.Mode.PREFER_RO))
+        def expect_prefer_ro_iterate_through_all_instances_if_there_are_no_ro():
+            prefer_ro_ports_result_all_rw = set()
+            for _ in range(len(self.servers)):
+                prefer_ro_ports_result_all_rw.add(get_port(self, tarantool.Mode.PREFER_RO))
 
-            self.assertSetEqual(PREFER_RO_ports_result_all_rw, all_ports)
+            self.assertSetEqual(prefer_ro_ports_result_all_rw, all_ports)
 
-        self.retry(func=expect_PREFER_RO_iterate_through_all_instances_if_there_are_no_RO)
+        self.retry(func=expect_prefer_ro_iterate_through_all_instances_if_there_are_no_ro)
 
     def test_02_exception_raise(self):
         self.set_cluster_ro([False, False, True, False, True])
@@ -222,8 +229,7 @@ def test_03_insert(self):
             self.pool.insert('test', ['test_03_insert_1', 1]),
             [['test_03_insert_1', 1]])
         self.assertSequenceEqual(
-            self.pool.insert('test', ['test_03_insert_2', 2],
-                mode=tarantool.Mode.RW),
+            self.pool.insert('test', ['test_03_insert_2', 2], mode=tarantool.Mode.RW),
             [['test_03_insert_2', 2]])
 
         conn_2 = tarantool.connect(
@@ -294,8 +300,9 @@ def test_05_upsert(self):
                 [['test_05_upsert', 3]])
 
             self.assertSequenceEqual(
-                self.pool.upsert('test', ['test_05_upsert', 3],
-                    [('+', 1, 1)], mode=tarantool.Mode.RW), [])
+                self.pool.upsert('test', ['test_05_upsert', 3], [('+', 1, 1)],
+                                 mode=tarantool.Mode.RW),
+                [])
             self.assertSequenceEqual(
                 conn_1.select('test', 'test_05_upsert'),
                 [['test_05_upsert', 4]])
@@ -327,8 +334,8 @@ def test_06_update(self):
                 [['test_06_update_1', 4]])
 
             self.assertSequenceEqual(
-                self.pool.update('test', ('test_06_update_2',),
-                    [('=', 1, 10)], mode=tarantool.Mode.RW),
+                self.pool.update('test', ('test_06_update_2',), [('=', 1, 10)],
+                                 mode=tarantool.Mode.RW),
                 [['test_06_update_2', 10]])
             self.assertSequenceEqual(
                 conn_4.select('test', 'test_06_update_2'),
@@ -354,7 +361,7 @@ def test_07_replace(self):
 
             self.assertSequenceEqual(
                 self.pool.replace('test', ['test_07_replace', 4],
-                    mode=tarantool.Mode.RW),
+                                  mode=tarantool.Mode.RW),
                 [['test_07_replace', 4]])
             self.assertSequenceEqual(
                 conn_4.select('test', 'test_07_replace'),
@@ -394,22 +401,17 @@ def test_08_select(self):
             self.pool.select('test', 'test_08_select'),
             [['test_08_select', 3]])
         self.assertSequenceEqual(
-            self.pool.select('test', ['test_08_select'],
-                mode=tarantool.Mode.ANY),
+            self.pool.select('test', ['test_08_select'], mode=tarantool.Mode.ANY),
             [['test_08_select', 3]])
         self.assertSequenceEqual(
-            self.pool.select('test', 3, index='id',
-                mode=tarantool.Mode.RO),
+            self.pool.select('test', 3, index='id', mode=tarantool.Mode.RO),
             [['test_08_select', 3]])
         self.assertSequenceEqual(
-            self.pool.select('test', [3], index='id',
-                mode=tarantool.Mode.PREFER_RW),
+            self.pool.select('test', [3], index='id', mode=tarantool.Mode.PREFER_RW),
             [['test_08_select', 3]])
 
     def test_09_ping(self):
-        self.pool = tarantool.ConnectionPool(addrs=self.addrs,
-            user='test',
-            password='test')
+        self.pool = tarantool.ConnectionPool(addrs=self.addrs, user='test', password='test')
 
         with self.assertRaisesRegex(ValueError, "Please, specify 'mode' keyword argument"):
             self.pool.ping()
@@ -473,7 +475,7 @@ def test_12_execute(self):
 
         resp = self.pool.execute(
             'insert into "test" values (:pk, :id)',
-            { 'pk': 'test_12_execute_2', 'id': 2},
+            {'pk': 'test_12_execute_2', 'id': 2},
             mode=tarantool.Mode.RW)
         self.assertEqual(resp.affected_row_count, 1)
         self.assertEqual(resp.data, None)
@@ -509,12 +511,12 @@ def test_13_failover(self):
         self.servers[0].stop()
         self.set_ro(self.servers[1], False)
 
-        def expect_RW_request_execute_on_new_master():
+        def expect_rw_request_execute_on_new_master():
             self.assertSequenceEqual(
                 self.pool.eval('return box.cfg.listen', mode=tarantool.Mode.RW),
-                [ str(self.addrs[1]['port']) ])
+                [str(self.addrs[1]['port'])])
 
-        self.retry(func=expect_RW_request_execute_on_new_master)
+        self.retry(func=expect_rw_request_execute_on_new_master)
 
     def test_14_cluster_with_instances_dead_in_runtime_is_ok(self):
         warnings.simplefilter('ignore', category=ClusterConnectWarning)
@@ -544,10 +546,10 @@ def test_15_cluster_with_dead_instances_on_start_is_ok(self):
 
         self.servers[0].start()
 
-        def ping_RW():
+        def ping_rw():
             self.pool.ping(mode=tarantool.Mode.RW)
 
-        self.retry(func=ping_RW)
+        self.retry(func=ping_rw)
 
     def test_16_is_closed(self):
         self.set_cluster_ro([False, False, True, False, True])
@@ -564,7 +566,7 @@ def test_16_is_closed(self):
         self.assertEqual(self.pool.is_closed(), True)
 
     def tearDown(self):
-        if hasattr(self, 'pool'):
+        if self.pool:
             self.pool.close()
 
         for srv in self.servers:
diff --git a/test/suites/test_protocol.py b/test/suites/test_protocol.py
index 6a548e4f..6f3025f6 100644
--- a/test/suites/test_protocol.py
+++ b/test/suites/test_protocol.py
@@ -1,30 +1,36 @@
+"""
+This module tests connection authentication.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,protected-access,duplicate-code
+
 import sys
-import pkg_resources
 import unittest
 import uuid
 
-import tarantool
-from tarantool.utils import greeting_decode, version_id
-
-from .lib.tarantool_server import TarantoolServer
+import pkg_resources
 
+import tarantool
 from tarantool.const import (
     IPROTO_FEATURE_STREAMS,
     IPROTO_FEATURE_TRANSACTIONS,
     IPROTO_FEATURE_ERROR_EXTENSION,
     IPROTO_FEATURE_WATCHERS,
 )
+from tarantool.utils import greeting_decode, version_id
+
+from .lib.tarantool_server import TarantoolServer
+
 
-class TestSuite_Protocol(unittest.TestCase):
+class TestSuiteProtocol(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' PROTOCOL '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
-        self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'])
-        self.adm = self.srv.admin
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
+        cls.con = tarantool.Connection(cls.srv.host, cls.srv.args['primary'])
+        cls.adm = cls.srv.admin
 
     def setUp(self):
         # prevent a remote tarantool from clean our session
@@ -33,7 +39,7 @@ def setUp(self):
 
     def test_00_greeting_1_6(self):
         buf = "Tarantool 1.6.6                                                \n" + \
-              "AtQnb9SAIaKazZZy9lJKvK3urtbjCEJndhRVbslSPGc=                   \n";
+              "AtQnb9SAIaKazZZy9lJKvK3urtbjCEJndhRVbslSPGc=                   \n"
         greeting = greeting_decode(buf.encode())
         self.assertEqual(greeting.version_id, version_id(1, 6, 6))
         self.assertEqual(greeting.protocol, "Binary")
@@ -42,7 +48,7 @@ def test_00_greeting_1_6(self):
 
     def test_01_greeting_1_6_with_tag(self):
         buf = "Tarantool 1.6.6-232-gcf47324                                   \n" + \
-              "AtQnb9SAIaKazZZy9lJKvK3urtbjCEJndhRVbslSPGc=                   \n";
+              "AtQnb9SAIaKazZZy9lJKvK3urtbjCEJndhRVbslSPGc=                   \n"
         greeting = greeting_decode(buf.encode())
         self.assertEqual(greeting.version_id, version_id(1, 6, 6))
         self.assertEqual(greeting.protocol, "Binary")
@@ -51,7 +57,7 @@ def test_01_greeting_1_6_with_tag(self):
 
     def test_02_greeting_1_6_console(self):
         buf = "Tarantool 1.6.6-132-g82f5424 (Lua console)                     \n" + \
-              "type 'help' for interactive help                               \n";
+              "type 'help' for interactive help                               \n"
         greeting = greeting_decode(buf.encode())
         self.assertEqual(greeting.version_id, version_id(1, 6, 6))
         self.assertEqual(greeting.protocol, "Lua console")
@@ -60,7 +66,7 @@ def test_02_greeting_1_6_console(self):
 
     def test_03_greeting_1_6_7(self):
         buf = "Tarantool 1.6.7 (Binary) 52dc2837-8001-48fe-bdce-c493c04599ce  \n" + \
-              "Z+2F+VRlyK1nKT82xQtxqEggMtkTK5RtPYf27JryRas=                   \n";
+              "Z+2F+VRlyK1nKT82xQtxqEggMtkTK5RtPYf27JryRas=                   \n"
         greeting = greeting_decode(buf.encode())
         self.assertEqual(greeting.version_id, version_id(1, 6, 7))
         self.assertEqual(greeting.protocol, "Binary")
@@ -87,8 +93,7 @@ def test_04_protocol(self):
         self.assertEqual(self.con._features[IPROTO_FEATURE_WATCHERS], False)
 
     @classmethod
-    def tearDownClass(self):
-        self.con.close()
-        self.srv.stop()
-        self.srv.clean()
-
+    def tearDownClass(cls):
+        cls.con.close()
+        cls.srv.stop()
+        cls.srv.clean()
diff --git a/test/suites/test_push.py b/test/suites/test_push.py
index 618a56f5..bd14455b 100644
--- a/test/suites/test_push.py
+++ b/test/suites/test_push.py
@@ -1,3 +1,8 @@
+"""
+This module tests work with IPROTO pushed messages.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,duplicate-code
+
 import sys
 import unittest
 import tarantool
@@ -8,7 +13,7 @@ def create_server():
     srv = TarantoolServer()
     srv.script = 'test/suites/box.lua'
     srv.start()
-    srv.admin("box.schema.user.create('test', {password = 'test', " +
+    srv.admin("box.schema.user.create('test', {password = 'test', "
               "if_not_exists = true})")
     srv.admin("box.schema.user.grant('test', 'read,write,execute', 'universe')")
 
@@ -69,29 +74,29 @@ def create_server():
 
 
 # Callback for on_push arg (for testing purposes).
-def push_callback(data, on_push_ctx=[]):
+def push_callback(data, on_push_ctx):
     data[0][1] = data[0][1] + 1
     on_push_ctx.append(data)
 
 
-class TestSuite_Push(unittest.TestCase):
+class TestSuitePush(unittest.TestCase):
 
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' PUSH '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
         # Create server and extract helpful fields for tests.
-        self.srv = create_server()
-        self.host = self.srv.host
-        self.port = self.srv.args['primary']
+        cls.srv = create_server()
+        cls.host = cls.srv.host
+        cls.port = cls.srv.args['primary']
 
     def setUp(self):
         # Open connection, connection pool and mesh connection to instance.
-        self.conn = tarantool.Connection(host=self.host, port=self.port, 
+        self.conn = tarantool.Connection(host=self.host, port=self.port,
                                          user='test', password='test')
-        self.conn_pool = tarantool.ConnectionPool([{'host':self.host, 'port':self.port}], 
-                                                     user='test', password='test')
-        self.mesh_conn = tarantool.MeshConnection(host=self.host, port=self.port, 
+        self.conn_pool = tarantool.ConnectionPool([{'host': self.host, 'port': self.port}],
+                                                  user='test', password='test')
+        self.mesh_conn = tarantool.MeshConnection(host=self.host, port=self.port,
                                                   user='test', password='test')
 
     push_test_cases = {
@@ -199,11 +204,10 @@ def setUp(self):
     }
 
     def test_00_00_push_via_connection(self):
-        for case_name in self.push_test_cases.keys():
-            with self.subTest(name=case_name):
+        for name, case in self.push_test_cases.items():
+            with self.subTest(name=name):
                 callback_res = []
-                case = self.push_test_cases[case_name]
-                testing_function = getattr(self.conn, case_name)
+                testing_function = getattr(self.conn, name)
                 case['input']['kwargs']['on_push_ctx'] = callback_res
                 resp = testing_function(
                     *case['input']['args'],
@@ -214,11 +218,10 @@ def test_00_00_push_via_connection(self):
                     self.assertEqual(resp.data[0], case['output']['resp'])
 
     def test_00_01_push_via_mesh_connection(self):
-        for case_name in self.push_test_cases.keys():
-            with self.subTest(name=case_name):
+        for name, case in self.push_test_cases.items():
+            with self.subTest(name=name):
                 callback_res = []
-                case = self.push_test_cases[case_name]
-                testing_function = getattr(self.mesh_conn, case_name)
+                testing_function = getattr(self.mesh_conn, name)
                 case['input']['kwargs']['on_push_ctx'] = callback_res
                 resp = testing_function(
                     *case['input']['args'],
@@ -229,11 +232,10 @@ def test_00_01_push_via_mesh_connection(self):
                     self.assertEqual(resp.data[0], case['output']['resp'])
 
     def test_00_02_push_via_connection_pool(self):
-        for case_name in self.push_test_cases.keys():
-            with self.subTest(name=case_name):
+        for name, case in self.push_test_cases.items():
+            with self.subTest(name=name):
                 callback_res = []
-                case = self.push_test_cases[case_name]
-                testing_function = getattr(self.conn_pool, case_name)
+                testing_function = getattr(self.conn_pool, name)
                 case['input']['kwargs']['on_push_ctx'] = callback_res
                 resp = testing_function(
                     *case['input']['args'],
@@ -251,7 +253,7 @@ def tearDown(self):
         self.mesh_conn.close()
 
     @classmethod
-    def tearDownClass(self):
+    def tearDownClass(cls):
         # Stop instance.
-        self.srv.stop()
-        self.srv.clean()
+        cls.srv.stop()
+        cls.srv.clean()
diff --git a/test/suites/test_reconnect.py b/test/suites/test_reconnect.py
index fc41cb57..f7811fab 100644
--- a/test/suites/test_reconnect.py
+++ b/test/suites/test_reconnect.py
@@ -1,3 +1,8 @@
+"""
+This module tests basic reconnect behavior.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring
+
 import sys
 import unittest
 import warnings
@@ -5,13 +10,13 @@
 from .lib.tarantool_server import TarantoolServer
 
 
-class TestSuite_Reconnect(unittest.TestCase):
+class TestSuiteReconnect(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' RECONNECT '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
 
     def setUp(self):
         # prevent a remote tarantool from clean our session
@@ -80,5 +85,5 @@ def test_03_connect_after_close(self):
         self.srv.stop()
 
     @classmethod
-    def tearDownClass(self):
-        self.srv.clean()
+    def tearDownClass(cls):
+        cls.srv.clean()
diff --git a/test/suites/test_schema.py b/test/suites/test_schema.py
index 55460018..91c3e217 100644
--- a/test/suites/test_schema.py
+++ b/test/suites/test_schema.py
@@ -1,11 +1,17 @@
+"""
+This module tests space and index schema fetch.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,fixme,too-many-public-methods,too-many-branches,too-many-statements
+
 import sys
 import unittest
-import tarantool
 import pkg_resources
 
+import tarantool
+from tarantool.error import NotSupportedError
+
 from .lib.tarantool_server import TarantoolServer
 from .lib.skip import skip_or_run_constraints_test
-from tarantool.error import NotSupportedError
 
 
 # FIXME: I'm quite sure that there is a simpler way to count
@@ -20,9 +26,11 @@ def _bind(self, obj, method_name):
         self._obj = obj
         self._method_name = method_name
         self._saved_method = getattr(obj, method_name)
+
         def wrapper(_, *args, **kwargs):
             self._call_count += 1
             return self._saved_method(*args, **kwargs)
+
         bound_wrapper = wrapper.__get__(obj.__class__, obj)
         setattr(obj, method_name, bound_wrapper)
 
@@ -34,24 +42,24 @@ def call_count(self):
         return self._call_count
 
 
-class TestSuite_Schema_Abstract(unittest.TestCase):
+class TestSuiteSchemaAbstract(unittest.TestCase):
     # Define 'encoding' field in a concrete class.
+    encoding = None
 
     @classmethod
-    def setUpClass(self):
-        params = 'connection.encoding: {}'.format(repr(self.encoding))
-        print(' SCHEMA ({}) '.format(params).center(70, '='), file=sys.stderr)
+    def setUpClass(cls):
+        params = f'connection.encoding: {repr(cls.encoding)}'
+        print(f' SCHEMA ({params}) '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
-        self.srv.admin("box.schema.user.create('test', {password = 'test', " +
-              "if_not_exists = true})")
-        self.srv.admin("box.schema.user.grant('test', 'read,write,execute', 'universe')")
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
+        cls.srv.admin("box.schema.user.create('test', {password = 'test', if_not_exists = true})")
+        cls.srv.admin("box.schema.user.grant('test', 'read,write,execute', 'universe')")
 
         # Create server_function and tester space (for fetch_schema opt testing purposes).
-        self.srv.admin("function server_function() return 2+2 end")
-        self.srv.admin("""
+        cls.srv.admin("function server_function() return 2+2 end")
+        cls.srv.admin("""
         box.schema.create_space(
             'tester', {
             format = {
@@ -60,7 +68,7 @@ def setUpClass(self):
             }
         })
         """)
-        self.srv.admin("""
+        cls.srv.admin("""
         box.space.tester:create_index(
             'primary_index', {
             parts = {
@@ -68,36 +76,34 @@ def setUpClass(self):
             }
         })
         """)
-        self.srv.admin("box.space.tester:insert({1, null})")
+        cls.srv.admin("box.space.tester:insert({1, null})")
 
-        self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'],
-                                        encoding=self.encoding, user='test', password='test')
-        self.con_schema_disable = tarantool.Connection(self.srv.host, self.srv.args['primary'],
-                                                       encoding=self.encoding, fetch_schema=False,
-                                                       user='test', password='test')
+        cls.con = tarantool.Connection(cls.srv.host, cls.srv.args['primary'],
+                                       encoding=cls.encoding, user='test', password='test')
+        cls.con_schema_disable = tarantool.Connection(cls.srv.host, cls.srv.args['primary'],
+                                                      encoding=cls.encoding, fetch_schema=False,
+                                                      user='test', password='test')
         if not sys.platform.startswith("win"):
             # Schema fetch disable tests via mesh and pool connection
             # are not supported on windows platform.
-            self.mesh_con_schema_disable = tarantool.MeshConnection(host=self.srv.host, 
-                                                                    port=self.srv.args['primary'],
-                                                                    fetch_schema=False, 
-                                                                    user='test', password='test')
-            self.pool_con_schema_disable = tarantool.ConnectionPool([{'host':self.srv.host, 
-                                                                    'port':self.srv.args['primary']}], 
-                                                                    user='test', password='test',
-                                                                    fetch_schema=False)
-        self.sch = self.con.schema
-
-        # The relevant test cases mainly target Python 2, where
-        # a user may want to pass a string literal as a space or
-        # an index name and don't bother whether all symbols in it
-        # are ASCII.
-        self.unicode_space_name_literal = '∞'
-        self.unicode_index_name_literal = '→'
-
-        self.unicode_space_name_u = u'∞'
-        self.unicode_index_name_u = u'→'
-        self.unicode_space_id, self.unicode_index_id = self.srv.admin("""
+            cls.mesh_con_schema_disable = tarantool.MeshConnection(
+                host=cls.srv.host,
+                port=cls.srv.args['primary'],
+                fetch_schema=False,
+                user='test', password='test')
+            cls.pool_con_schema_disable = tarantool.ConnectionPool(
+                [{
+                    'host': cls.srv.host,
+                    'port': cls.srv.args['primary']
+                }],
+                user='test', password='test',
+                fetch_schema=False)
+        cls.sch = cls.con.schema
+
+        cls.unicode_space_name_literal = '∞'
+        cls.unicode_index_name_literal = '→'
+
+        cls.unicode_space_id, cls.unicode_index_id = cls.srv.admin("""
             do
                 local space = box.schema.create_space('\\xe2\\x88\\x9e')
                 local index = space:create_index('\\xe2\\x86\\x92')
@@ -105,8 +111,8 @@ def setUpClass(self):
             end
         """)
 
-        if self.srv.admin.tnt_version >= pkg_resources.parse_version('2.10.0'):
-            self.srv.admin("""
+        if cls.srv.admin.tnt_version >= pkg_resources.parse_version('2.10.0'):
+            cls.srv.admin("""
             box.schema.create_space(
                 'constr_tester_1', {
                 format = {
@@ -122,7 +128,7 @@ def setUpClass(self):
                 'constr_tester_2', {
                 format = {
                     { name = 'id', type = 'unsigned' },
-                    { name = 'table1_id', type = 'unsigned', 
+                    { name = 'table1_id', type = 'unsigned',
                       foreign_key = { fk_video = { space = 'constr_tester_1', field = 'id' } },
                     },
                     { name = 'payload', type = 'number' },
@@ -158,41 +164,33 @@ def fetch_count(self):
 
     def verify_unicode_space(self, space):
         self.assertEqual(space.sid, self.unicode_space_id)
-        self.assertEqual(space.name, self.unicode_space_name_u)
+        self.assertEqual(space.name, self.unicode_space_name_literal)
         self.assertEqual(space.arity, 1)
 
     def verify_unicode_index(self, index):
-        self.assertEqual(index.space.name, self.unicode_space_name_u)
+        self.assertEqual(index.space.name, self.unicode_space_name_literal)
         self.assertEqual(index.iid, self.unicode_index_id)
-        self.assertEqual(index.name, self.unicode_index_name_u)
+        self.assertEqual(index.name, self.unicode_index_name_literal)
         self.assertEqual(len(index.parts), 1)
 
     def test_01_space_bad(self):
-        with self.assertRaisesRegex(tarantool.SchemaError,
-                'There\'s no space.*'):
+        with self.assertRaisesRegex(tarantool.SchemaError, 'There\'s no space.*'):
             self.sch.get_space(0)
-        with self.assertRaisesRegex(tarantool.SchemaError,
-                'There\'s no space.*'):
+        with self.assertRaisesRegex(tarantool.SchemaError, 'There\'s no space.*'):
             self.sch.get_space(0)
-        with self.assertRaisesRegex(tarantool.SchemaError,
-                'There\'s no space.*'):
+        with self.assertRaisesRegex(tarantool.SchemaError, 'There\'s no space.*'):
             self.sch.get_space('bad_name')
 
     def test_02_index_bad(self):
-        with self.assertRaisesRegex(tarantool.SchemaError,
-                'There\'s no space.*'):
+        with self.assertRaisesRegex(tarantool.SchemaError, 'There\'s no space.*'):
             self.sch.get_index(0, 'primary')
-        with self.assertRaisesRegex(tarantool.SchemaError,
-                'There\'s no space.*'):
+        with self.assertRaisesRegex(tarantool.SchemaError, 'There\'s no space.*'):
             self.sch.get_index('bad_space', 'primary')
-        with self.assertRaisesRegex(tarantool.SchemaError,
-                'There\'s no index.*'):
+        with self.assertRaisesRegex(tarantool.SchemaError, 'There\'s no index.*'):
             self.sch.get_index(280, 'bad_index')
-        with self.assertRaisesRegex(tarantool.SchemaError,
-                'There\'s no index.*'):
+        with self.assertRaisesRegex(tarantool.SchemaError, 'There\'s no index.*'):
             self.sch.get_index(280, 'bad_index')
-        with self.assertRaisesRegex(tarantool.SchemaError,
-                'There\'s no index.*'):
+        with self.assertRaisesRegex(tarantool.SchemaError, 'There\'s no index.*'):
             self.sch.get_index(280, 3)
 
     def test_03_01_space_name__(self):
@@ -393,8 +391,8 @@ def test_06_index_cached(self):
             (self.unicode_space_id, self.unicode_index_name_literal),
             (self.unicode_space_id, self.unicode_index_id),
         )
-        for s, i in cases:
-            index = self.sch.get_index(s, i)
+        for space, index_id in cases:
+            index = self.sch.get_index(space, index_id)
             self.verify_unicode_index(index)
 
         # Verify that no schema fetches occurs.
@@ -412,14 +410,14 @@ def test_07_schema_version_update(self):
                 'input': ['tester', (1, None)],
                 'output': [[1, None]],
             },
-             'delete': {
+            'delete': {
                 'input': ['tester', 1],
                 'output': [[1, None]],
             },
             'insert': {
                 'input': ['tester', (1, None)],
                 'output': [[1, None]],
-            }, 
+            },
             'upsert': {
                 'input': ['tester', (1, None), []],
                 'output': [],
@@ -427,7 +425,7 @@ def test_07_schema_version_update(self):
             'update': {
                 'input': ['tester', 1, []],
                 'output': [[1, None]],
-            }, 
+            },
             'select': {
                 'input': ['tester', 1],
                 'output': [[1, None]],
@@ -454,118 +452,120 @@ def test_07_schema_version_update(self):
     }
 
     def _run_test_schema_fetch_disable(self, con, mode=None):
-            # Enable SQL test case for tarantool 2.* and higher.
-            if int(self.srv.admin.tnt_version.__str__()[0]) > 1:
-                self.testing_methods['available']['execute'] = {
-                    'input': ['SELECT * FROM "tester"'],
-                    'output': [[1, None]],
-                }
+        # Enable SQL test case for tarantool 2.* and higher.
+        if int(str(self.srv.admin.tnt_version)[0]) > 1:
+            self.testing_methods['available']['execute'] = {
+                'input': ['SELECT * FROM "tester"'],
+                'output': [[1, None]],
+            }
 
-            # Testing the schemaless connection with methods
-            # that should NOT be available.
-            if mode is not None:
-                for addr in con.pool.keys():
-                    self.assertEqual(con.pool[addr].conn.schema_version, 0)
-                    self.assertEqual(con.pool[addr].conn.schema, None)
-            else:
-                self.assertEqual(con.schema_version, 0)
-                self.assertEqual(con.schema, None)
-            for method_case in self.testing_methods['unavailable'].keys():
-                with self.subTest(name=method_case):
-                    if isinstance(con, tarantool.ConnectionPool) and method_case == 'space':
-                        continue
-                    testing_function = getattr(con, method_case)
-                    try:
-                        if mode is not None:
-                            _ = testing_function(
-                                *self.testing_methods['unavailable'][method_case]['input'], 
-                                mode=mode)
-                        else:
-                            _ = testing_function(
-                                *self.testing_methods['unavailable'][method_case]['input'])
-                    except NotSupportedError as e:
-                        self.assertEqual(e.message, 'This method is not available in ' + 
-                                                    'connection opened with fetch_schema=False')
-            # Testing the schemaless connection with methods
-            # that should be available.
-            for method_case in self.testing_methods['available'].keys():
-                with self.subTest(name=method_case):
-                    testing_function = getattr(con, method_case)
-                    if mode is not None:
-                        resp = testing_function(
-                            *self.testing_methods['available'][method_case]['input'], 
-                            mode=mode)
-                    else:
-                        resp = testing_function(
-                            *self.testing_methods['available'][method_case]['input'])
-                    if method_case == 'ping':
-                        self.assertEqual(isinstance(resp, float), True)
-                    else:
-                        self.assertEqual(
-                            resp.data,
-                            self.testing_methods['available'][method_case]['output'])
-
-            # Turning the same connection into schemaful.
-            if mode is not None:
-                for addr in con.pool.keys():
-                    con.pool[addr].conn.update_schema(con.pool[addr].conn.schema_version)
-            else:
-                con.update_schema(con.schema_version)
-
-            # Testing the schemaful connection with methods
-            # that should NOW be available.
-            for method_case in self.testing_methods['unavailable'].keys():
-                with self.subTest(name=method_case):
-                    if isinstance(con, tarantool.ConnectionPool) and method_case == 'space':
-                        continue
-                    testing_function = getattr(con, method_case)
+        # Testing the schemaless connection with methods
+        # that should NOT be available.
+        if mode is not None:
+            for addr in con.pool.keys():
+                self.assertEqual(con.pool[addr].conn.schema_version, 0)
+                self.assertEqual(con.pool[addr].conn.schema, None)
+        else:
+            self.assertEqual(con.schema_version, 0)
+            self.assertEqual(con.schema, None)
+        for method_case in self.testing_methods['unavailable']:
+            with self.subTest(name=method_case):
+                if isinstance(con, tarantool.ConnectionPool) and method_case == 'space':
+                    continue
+                testing_function = getattr(con, method_case)
+                try:
                     if mode is not None:
-                        resp = testing_function(
-                            *self.testing_methods['unavailable'][method_case]['input'], 
+                        _ = testing_function(
+                            *self.testing_methods['unavailable'][method_case]['input'],
                             mode=mode)
                     else:
-                        resp = testing_function(
+                        _ = testing_function(
                             *self.testing_methods['unavailable'][method_case]['input'])
-                    if method_case == 'space':
-                        self.assertEqual(isinstance(resp, tarantool.space.Space), True)
-                    else:
-                        self.assertEqual(
-                            resp.data, 
-                            self.testing_methods['unavailable'][method_case]['output'])
-            # Testing the schemaful connection with methods
-            # that should have remained available.
-            for method_case in self.testing_methods['available'].keys():
-                with self.subTest(name=method_case):
-                    testing_function = getattr(con, method_case)
-                    if mode is not None:
-                        resp = testing_function(
-                            *self.testing_methods['available'][method_case]['input'], 
-                            mode=mode)
-                    else:
-                        resp = testing_function(
-                            *self.testing_methods['available'][method_case]['input'])
-                    if method_case == 'ping':
-                        self.assertEqual(isinstance(resp, float), True)
-                    else:
-                        self.assertEqual(
-                            resp.data, 
-                            self.testing_methods['available'][method_case]['output'])
-            if mode is not None:
-                self.assertNotEqual(con.pool[addr].conn.schema_version, 1)
-                self.assertNotEqual(con.pool[addr].conn.schema, None)
-            else:      
-                self.assertNotEqual(con.schema_version, 1)
-                self.assertNotEqual(con.schema, None)
+                except NotSupportedError as exc:
+                    self.assertEqual(exc.message, 'This method is not available in '
+                                                  'connection opened with fetch_schema=False')
+        # Testing the schemaless connection with methods
+        # that should be available.
+        for method_case in self.testing_methods['available']:
+            with self.subTest(name=method_case):
+                testing_function = getattr(con, method_case)
+                if mode is not None:
+                    resp = testing_function(
+                        *self.testing_methods['available'][method_case]['input'],
+                        mode=mode)
+                else:
+                    resp = testing_function(
+                        *self.testing_methods['available'][method_case]['input'])
+                if method_case == 'ping':
+                    self.assertEqual(isinstance(resp, float), True)
+                else:
+                    self.assertEqual(
+                        resp.data,
+                        self.testing_methods['available'][method_case]['output'])
+
+        # Turning the same connection into schemaful.
+        if mode is not None:
+            for addr in con.pool.keys():
+                con.pool[addr].conn.update_schema(con.pool[addr].conn.schema_version)
+        else:
+            con.update_schema(con.schema_version)
+
+        # Testing the schemaful connection with methods
+        # that should NOW be available.
+        for method_case in self.testing_methods['unavailable']:
+            with self.subTest(name=method_case):
+                if isinstance(con, tarantool.ConnectionPool) and method_case == 'space':
+                    continue
+                testing_function = getattr(con, method_case)
+                if mode is not None:
+                    resp = testing_function(
+                        *self.testing_methods['unavailable'][method_case]['input'],
+                        mode=mode)
+                else:
+                    resp = testing_function(
+                        *self.testing_methods['unavailable'][method_case]['input'])
+                if method_case == 'space':
+                    self.assertEqual(isinstance(resp, tarantool.space.Space), True)
+                else:
+                    self.assertEqual(
+                        resp.data,
+                        self.testing_methods['unavailable'][method_case]['output'])
+        # Testing the schemaful connection with methods
+        # that should have remained available.
+        for method_case in self.testing_methods['available']:
+            with self.subTest(name=method_case):
+                testing_function = getattr(con, method_case)
+                if mode is not None:
+                    resp = testing_function(
+                        *self.testing_methods['available'][method_case]['input'],
+                        mode=mode)
+                else:
+                    resp = testing_function(
+                        *self.testing_methods['available'][method_case]['input'])
+                if method_case == 'ping':
+                    self.assertEqual(isinstance(resp, float), True)
+                else:
+                    self.assertEqual(
+                        resp.data,
+                        self.testing_methods['available'][method_case]['output'])
+        if mode is not None:
+            self.assertNotEqual(con.pool[addr].conn.schema_version, 1)
+            self.assertNotEqual(con.pool[addr].conn.schema, None)
+        else:
+            self.assertNotEqual(con.schema_version, 1)
+            self.assertNotEqual(con.schema, None)
 
     def test_08_schema_fetch_disable_via_connection(self):
         self._run_test_schema_fetch_disable(self.con_schema_disable)
 
-    @unittest.skipIf(sys.platform.startswith("win"),
+    @unittest.skipIf(
+        sys.platform.startswith("win"),
         'Schema fetch disable tests via mesh connection on windows platform are not supported')
     def test_08_schema_fetch_disable_via_mesh_connection(self):
         self._run_test_schema_fetch_disable(self.mesh_con_schema_disable)
 
-    @unittest.skipIf(sys.platform.startswith("win"),
+    @unittest.skipIf(
+        sys.platform.startswith("win"),
         'Schema fetch disable tests via connection pool on windows platform are not supported')
     def test_08_schema_fetch_disable_via_connection_pool(self):
         self._run_test_schema_fetch_disable(self.pool_con_schema_disable,
@@ -585,32 +585,32 @@ def test_10_foreign_key_valid_replace(self):
     def test_11_foreign_key_invalid_replace(self):
         with self.assertRaisesRegex(tarantool.DatabaseError,
                                     'foreign tuple was not found'):
-                self.con.replace('constr_tester_2', [2, 999, 623])
+            self.con.replace('constr_tester_2', [2, 999, 623])
 
     @classmethod
-    def tearDownClass(self):
+    def tearDownClass(cls):
         # We need to drop spaces with foreign keys with predetermined order,
         # otherwise remote server clean() will fail to clean up resources.
-        if self.srv.admin.tnt_version >= pkg_resources.parse_version('2.10.0'):
-            self.srv.admin("""
+        if cls.srv.admin.tnt_version >= pkg_resources.parse_version('2.10.0'):
+            cls.srv.admin("""
             box.space.constr_tester_2:drop()
             box.space.constr_tester_1:drop()
             """)
 
-        self.con.close()
-        self.con_schema_disable.close()
+        cls.con.close()
+        cls.con_schema_disable.close()
         if not sys.platform.startswith("win"):
             # Schema fetch disable tests via mesh and pool connection
             # are not supported on windows platform.
-            self.mesh_con_schema_disable.close()
-            self.pool_con_schema_disable.close()
-        self.srv.stop()
-        self.srv.clean()
+            cls.mesh_con_schema_disable.close()
+            cls.pool_con_schema_disable.close()
+        cls.srv.stop()
+        cls.srv.clean()
 
 
-class TestSuite_Schema_UnicodeConnection(TestSuite_Schema_Abstract):
+class TestSuiteSchemaUnicodeConnection(TestSuiteSchemaAbstract):
     encoding = 'utf-8'
 
 
-class TestSuite_Schema_BinaryConnection(TestSuite_Schema_Abstract):
+class TestSuiteSchemaBinaryConnection(TestSuiteSchemaAbstract):
     encoding = None
diff --git a/test/suites/test_ssl.py b/test/suites/test_ssl.py
index 36e172de..9452e83b 100644
--- a/test/suites/test_ssl.py
+++ b/test/suites/test_ssl.py
@@ -1,3 +1,8 @@
+"""
+This module tests connection through SSL.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,too-many-branches,too-many-locals,bad-option-value,no-self-use
+
 import os
 import sys
 import unittest
@@ -24,11 +29,13 @@ def is_test_ssl():
     env = os.getenv("TEST_TNT_SSL")
     if env:
         env = env.upper()
-        return env == "1" or env == "TRUE"
+        return env in ("1", "TRUE")
     return False
 
 
 class SslTestCase:
+    # pylint: disable=too-few-public-methods,too-many-instance-attributes,too-many-arguments
+
     def __init__(self,
                  name="",
                  ok=False,
@@ -69,37 +76,38 @@ def __init__(self,
         self.client_password_file = client_password_file
         self.client_auth_type = client_auth_type
 
+
 @unittest.skipIf(not is_test_ssl(), "TEST_TNT_SSL is not set.")
-class TestSuite_Ssl(unittest.TestCase):
+class TestSuiteSsl(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' SSL '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
 
         test_suites_dir = os.path.dirname(__file__)
         test_data_dir = os.path.join(test_suites_dir, "..", "data")
-        self.cert_file = os.path.join(test_data_dir, "localhost.crt")
-        self.invalidhost_cert_file = os.path.join(test_data_dir,
-                                                  "invalidhost.crt")
-        self.key_file = os.path.join(test_data_dir, "localhost.key")
-        self.key_enc_file = os.path.join(test_data_dir, "localhost.enc.key")
-        self.ca_file = os.path.join(test_data_dir, "ca.crt")
-        self.empty_file = os.path.join(test_data_dir, "empty")
-        self.password = "mysslpassword"
-        self.invalid_password = "notmysslpassword"
-        self.password_file = os.path.join(test_data_dir, "passwords")
-        self.invalid_password_file = os.path.join(test_data_dir, "invalidpasswords")
-        self.invalid_file = "any_invalid_path"
+        cls.cert_file = os.path.join(test_data_dir, "localhost.crt")
+        cls.invalidhost_cert_file = os.path.join(test_data_dir,
+                                                 "invalidhost.crt")
+        cls.key_file = os.path.join(test_data_dir, "localhost.key")
+        cls.key_enc_file = os.path.join(test_data_dir, "localhost.enc.key")
+        cls.ca_file = os.path.join(test_data_dir, "ca.crt")
+        cls.empty_file = os.path.join(test_data_dir, "empty")
+        cls.password = "mysslpassword"
+        cls.invalid_password = "notmysslpassword"
+        cls.password_file = os.path.join(test_data_dir, "passwords")
+        cls.invalid_password_file = os.path.join(test_data_dir, "invalidpasswords")
+        cls.invalid_file = "any_invalid_path"
 
         # Extract the version for skips.
-        self.tnt_version = None
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
-        fetch_tarantool_version(self)
-        self.srv.stop()
-        self.srv.clean()
-        self.srv = None
+        cls.tnt_version = None
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
+        fetch_tarantool_version(cls)
+        cls.srv.stop()
+        cls.srv.clean()
+        cls.srv = None
 
     def stop_srv(self, srv):
         if srv:
@@ -450,13 +458,13 @@ def test_single(self):
         for t in testcases:
             with self.subTest(msg=t.name):
                 if t.server_password is not None \
-                or t.server_password_file is not None \
-                or t.client_password is not None \
-                or t.server_password_file is not None:
+                        or t.server_password_file is not None \
+                        or t.client_password is not None \
+                        or t.server_password_file is not None:
                     skip_or_run_ssl_password_test_call(self)
 
                 if t.server_auth_type is not None \
-                or t.client_auth_type is not None:
+                        or t.client_auth_type is not None:
                     skip_or_run_auth_type_test_call(self)
 
                 srv = TarantoolServer(
@@ -567,18 +575,18 @@ def test_pool(self):
             cnt = 5
             with self.subTest(msg=t.name):
                 if t.server_password is not None \
-                or t.server_password_file is not None \
-                or t.client_password is not None \
-                or t.server_password_file is not None:
+                        or t.server_password_file is not None \
+                        or t.client_password is not None \
+                        or t.server_password_file is not None:
                     skip_or_run_ssl_password_test_call(self)
 
                 if t.server_auth_type is not None \
-                or t.client_auth_type is not None:
+                        or t.client_auth_type is not None:
                     skip_or_run_auth_type_test_call(self)
 
                 addrs = []
                 servers = []
-                for i in range(cnt):
+                for _ in range(cnt):
                     srv = TarantoolServer(
                         transport=t.server_transport,
                         ssl_key_file=t.server_key_file,
@@ -692,13 +700,13 @@ def test_mesh(self):
             cnt = 5
             with self.subTest(msg=t.name):
                 if t.server_password is not None \
-                or t.server_password_file is not None \
-                or t.client_password is not None \
-                or t.server_password_file is not None:
+                        or t.server_password_file is not None \
+                        or t.client_password is not None \
+                        or t.server_password_file is not None:
                     skip_or_run_ssl_password_test_call(self)
 
                 if t.server_auth_type is not None \
-                or t.client_auth_type is not None:
+                        or t.client_auth_type is not None:
                     skip_or_run_auth_type_test_call(self)
 
                 addrs = []
@@ -721,7 +729,7 @@ def test_mesh(self):
                     srv.admin("""
                     box.schema.user.grant('test', 'execute,read,write', 'universe')
                     """.replace('\n', ' '))
-                    srv.admin("function srv_id() return %s end" % i)
+                    srv.admin(f"function srv_id() return {i} end")
                     servers.append(srv)
                     addr = {
                         'host': srv.host,
diff --git a/test/suites/test_uuid.py b/test/suites/test_uuid.py
index f81f1117..0a9ef06b 100644
--- a/test/suites/test_uuid.py
+++ b/test/suites/test_uuid.py
@@ -1,28 +1,33 @@
+"""
+This module tests work with UUID type.
+"""
+# pylint: disable=missing-class-docstring,missing-function-docstring,duplicate-code
+
 import sys
 import unittest
 import uuid
+
 import msgpack
-import warnings
-import tarantool
 
+import tarantool
 from tarantool.msgpack_ext.packer import default as packer_default
 from tarantool.msgpack_ext.unpacker import ext_hook as unpacker_ext_hook
 
 from .lib.tarantool_server import TarantoolServer
-from .lib.skip import skip_or_run_UUID_test
-from tarantool.error import MsgpackError, MsgpackWarning
+from .lib.skip import skip_or_run_uuid_test
+
 
-class TestSuite_UUID(unittest.TestCase):
+class TestSuiteUUID(unittest.TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         print(' UUID EXT TYPE '.center(70, '='), file=sys.stderr)
         print('-' * 70, file=sys.stderr)
-        self.srv = TarantoolServer()
-        self.srv.script = 'test/suites/box.lua'
-        self.srv.start()
+        cls.srv = TarantoolServer()
+        cls.srv.script = 'test/suites/box.lua'
+        cls.srv.start()
 
-        self.adm = self.srv.admin
-        self.adm(r"""
+        cls.adm = cls.srv.admin
+        cls.adm(r"""
             _, uuid = pcall(require, 'uuid')
 
             box.schema.space.create('test')
@@ -43,8 +48,8 @@ def setUpClass(self):
             box.schema.user.grant('test', 'read,write,execute', 'universe')
         """)
 
-        self.con = tarantool.Connection(self.srv.host, self.srv.args['primary'],
-                                        user='test', password='test')
+        cls.con = tarantool.Connection(cls.srv.host, cls.srv.args['primary'],
+                                       user='test', password='test')
 
     def setUp(self):
         # prevent a remote tarantool from clean our session
@@ -53,7 +58,6 @@ def setUp(self):
 
         self.adm("box.space['test']:truncate()")
 
-
     cases = {
         'uuid_1': {
             'python': uuid.UUID('ae28d4f6-076c-49dd-8227-7f9fae9592d0'),
@@ -83,38 +87,30 @@ def setUp(self):
     }
 
     def test_msgpack_decode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
-
                 self.assertEqual(unpacker_ext_hook(2, case['msgpack']),
                                  case['python'])
 
-    @skip_or_run_UUID_test
+    @skip_or_run_uuid_test
     def test_tarantool_decode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
-
                 self.adm(f"box.space['test']:replace{{'{name}', {case['tarantool']}}}")
 
                 self.assertSequenceEqual(self.con.select('test', name),
                                          [[name, case['python']]])
 
     def test_msgpack_encode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
-
                 self.assertEqual(packer_default(case['python']),
                                  msgpack.ExtType(code=2, data=case['msgpack']))
 
-    @skip_or_run_UUID_test
+    @skip_or_run_uuid_test
     def test_tarantool_encode(self):
-        for name in self.cases.keys():
+        for name, case in self.cases.items():
             with self.subTest(msg=name):
-                case = self.cases[name]
-
                 self.con.insert('test', [name, case['python']])
 
                 lua_eval = f"""
@@ -132,17 +128,15 @@ def test_tarantool_encode(self):
 
                 self.assertSequenceEqual(self.con.eval(lua_eval), [True])
 
-
-    @skip_or_run_UUID_test
+    @skip_or_run_uuid_test
     def test_primary_key(self):
         data = [uuid.UUID('ae28d4f6-076c-49dd-8227-7f9fae9592d0'), 'content']
 
         self.assertSequenceEqual(self.con.insert('test_pk', data), [data])
         self.assertSequenceEqual(self.con.select('test_pk', data[0]), [data])
 
-
     @classmethod
-    def tearDownClass(self):
-        self.con.close()
-        self.srv.stop()
-        self.srv.clean()
+    def tearDownClass(cls):
+        cls.con.close()
+        cls.srv.stop()
+        cls.srv.clean()