diff --git a/.editorconfig b/.editorconfig
index be4e91561989dc2ea74c2fdf456e2761bb4cd394..3d9a076af8f5a06a155a88ad07e2efc102a972e8 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -16,15 +16,6 @@ insert_final_newline = true
 trim_trailing_whitespace = true
 charset = utf-8
 
-# Python files
-[*.py]
-indent_size = 4
-# isort plugin configuration
-known_first_party = invenio_previewer
-known_third_party = invenio_files_rest, invenio_records_ui
-multi_line_output = 2
-default_section = THIRDPARTY
-
 # RST files (used by sphinx)
 [*.rst]
 indent_size = 4
diff --git a/docs/conf.py b/docs/conf.py
index 68a75b798179a382c8180038bc16dbd8725070c6..bb6db2f67b128140c25d2c6af2ebcf25d0662dfb 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -8,47 +8,47 @@
 
 from __future__ import print_function
 
-from invenio_previewer import __version__
-
 import sphinx.environment
 
+from invenio_previewer import __version__
+
 # -- General configuration ------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# needs_sphinx = '1.0'
 
 # Do not warn on external images.
-suppress_warnings = ['image.nonlocal_uri']
+suppress_warnings = ["image.nonlocal_uri"]
 
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 extensions = [
-    'sphinx.ext.autodoc',
-    'sphinx.ext.coverage',
-    'sphinx.ext.doctest',
-    'sphinx.ext.intersphinx',
-    'sphinx.ext.viewcode',
+    "sphinx.ext.autodoc",
+    "sphinx.ext.coverage",
+    "sphinx.ext.doctest",
+    "sphinx.ext.intersphinx",
+    "sphinx.ext.viewcode",
 ]
 
 # Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
 
 # The suffix(es) of source filenames.
 # You can specify multiple suffix as a list of string:
 # source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
+source_suffix = ".rst"
 
 # The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
 
 # The master toctree document.
-master_doc = 'index'
+master_doc = "index"
 
 # General information about the project.
-project = u'Invenio-Previewer'
-copyright = u'2016-2019, CERN'
-author = u'CERN'
+project = "Invenio-Previewer"
+copyright = "2016-2019, CERN"
+author = "CERN"
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -68,9 +68,9 @@ language = None
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
-#today = ''
+# today = ''
 # Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
+# today_fmt = '%B %d, %Y'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
@@ -78,46 +78,46 @@ exclude_patterns = []
 
 # The reST default role (used for this markup: `text`) to use for all
 # documents.
-#default_role = None
+# default_role = None
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
 
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
-#show_authors = False
+# show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
 
 # A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
 
 # If true, keep warnings as "system message" paragraphs in the built documents.
-#keep_warnings = False
+# keep_warnings = False
 
 # If true, `todo` and `todoList` produce output, else they produce nothing.
 todo_include_todos = False
 
 
 # -- Options for HTML output ----------------------------------------------
-html_theme = 'alabaster'
+html_theme = "alabaster"
 
 html_theme_options = {
-    'description': 'Invenio module for previewing files.',
-    'github_user': 'inveniosoftware',
-    'github_repo': 'invenio-previewer',
-    'github_button': False,
-    'github_banner': True,
-    'show_powered_by': False,
-    'extra_nav_links': {
-        'invenio-previewer@GitHub': 'https://github.com/inveniosoftware/invenio-previewer',
-        'invenio-previewer@PyPI': 'https://pypi.python.org/pypi/invenio-previewer/',
-    }
+    "description": "Invenio module for previewing files.",
+    "github_user": "inveniosoftware",
+    "github_repo": "invenio-previewer",
+    "github_button": False,
+    "github_banner": True,
+    "show_powered_by": False,
+    "extra_nav_links": {
+        "invenio-previewer@GitHub": "https://github.com/inveniosoftware/invenio-previewer",
+        "invenio-previewer@PyPI": "https://pypi.python.org/pypi/invenio-previewer/",
+    },
 }
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
@@ -126,146 +126,148 @@ html_theme_options = {
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
-#html_theme_options = {}
+# html_theme_options = {}
 
 # Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
-#html_title = None
+# html_title = None
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
 
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
-#html_logo = None
+# html_logo = None
 
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
-#html_favicon = None
+# html_favicon = None
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-#html_static_path = ['_static']
+# html_static_path = ['_static']
 
 # Add any extra paths that contain custom files (such as robots.txt or
 # .htaccess) here, relative to this directory. These files are copied
 # directly to the root of the documentation.
-#html_extra_path = []
+# html_extra_path = []
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
 html_sidebars = {
-    '**': [
-        'about.html',
-        'navigation.html',
-        'relations.html',
-        'searchbox.html',
-        'donate.html',
+    "**": [
+        "about.html",
+        "navigation.html",
+        "relations.html",
+        "searchbox.html",
+        "donate.html",
     ]
 }
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
 
 # If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
 
 # If false, no index is generated.
-#html_use_index = True
+# html_use_index = True
 
 # If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
 
 # If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+# html_show_sourcelink = True
 
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+# html_show_sphinx = True
 
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
 
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
 
 # Language to be used for generating the HTML full-text search index.
 # Sphinx supports the following languages:
 #   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
 #   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
-#html_search_language = 'en'
+# html_search_language = 'en'
 
 # A dictionary with options for the search language support, empty by default.
 # Now only 'ja' uses this config value
-#html_search_options = {'type': 'default'}
+# html_search_options = {'type': 'default'}
 
 # The name of a javascript file (relative to the configuration directory) that
 # implements a search results scorer. If empty, the default will be used.
-#html_search_scorer = 'scorer.js'
+# html_search_scorer = 'scorer.js'
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'invenio-previewer_namedoc'
+htmlhelp_basename = "invenio-previewer_namedoc"
 
 # -- Options for LaTeX output ---------------------------------------------
 
 latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-
-# Latex figure (float) alignment
-#'figure_align': 'htbp',
+    # The paper size ('letterpaper' or 'a4paper').
+    #'papersize': 'letterpaper',
+    # The font size ('10pt', '11pt' or '12pt').
+    #'pointsize': '10pt',
+    # Additional stuff for the LaTeX preamble.
+    #'preamble': '',
+    # Latex figure (float) alignment
+    #'figure_align': 'htbp',
 }
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-  (master_doc, 'invenio-previewer.tex', u'invenio-previewer Documentation',
-   u'CERN', 'manual'),
+    (
+        master_doc,
+        "invenio-previewer.tex",
+        "invenio-previewer Documentation",
+        "CERN",
+        "manual",
+    ),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
-#latex_logo = None
+# latex_logo = None
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
 
 # If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
 
 # If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
 
 # Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
 
 # If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
 
 
 # -- Options for manual page output ---------------------------------------
@@ -273,12 +275,11 @@ latex_documents = [
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    (master_doc, 'invenio-previewer', u'invenio-previewer Documentation',
-     [author], 1)
+    (master_doc, "invenio-previewer", "invenio-previewer Documentation", [author], 1)
 ]
 
 # If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
 
 
 # -- Options for Texinfo output -------------------------------------------
@@ -287,31 +288,38 @@ man_pages = [
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-  (master_doc, 'invenio-previewer', u'Invenio-Previewer Documentation',
-   author, 'invenio-previewer', 'Invenio module for previewing files.',
-   'Miscellaneous'),
+    (
+        master_doc,
+        "invenio-previewer",
+        "Invenio-Previewer Documentation",
+        author,
+        "invenio-previewer",
+        "Invenio module for previewing files.",
+        "Miscellaneous",
+    ),
 ]
 
 # Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
 
 # If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
 
 # If true, do not generate a @detailmenu in the "Top" node's menu.
-#texinfo_no_detailmenu = False
+# texinfo_no_detailmenu = False
 
 
 # Example configuration for intersphinx: refer to the Python standard library.
 intersphinx_mapping = {
-    'https://docs.python.org/': None,
-    'invenio_records_ui': (
-        'https://invenio-records-ui.readthedocs.io/en/latest/', None
-    )
+    "https://docs.python.org/": None,
+    "invenio_records_ui": (
+        "https://invenio-records-ui.readthedocs.io/en/latest/",
+        None,
+    ),
 }
 
 # Autodoc configuraton.
-autoclass_content = 'both'
+autoclass_content = "both"
diff --git a/invenio_previewer/__init__.py b/invenio_previewer/__init__.py
index 9487c047743dbe76392756f4da301362a3257e43..73a76e3ff5d5da671266971728df0e586245b4e2 100644
--- a/invenio_previewer/__init__.py
+++ b/invenio_previewer/__init__.py
@@ -322,4 +322,4 @@ from .proxies import current_previewer
 
 __version__ = "1.3.9"
 
-__all__ = ('__version__', 'current_previewer', 'InvenioPreviewer')
+__all__ = ("__version__", "current_previewer", "InvenioPreviewer")
diff --git a/invenio_previewer/_compat.py b/invenio_previewer/_compat.py
index 7b47e704d3aadd67dc930461fd8ff2bcfd97b5a6..eae0289dcc2566de6fab3f981fc428426090024b 100644
--- a/invenio_previewer/_compat.py
+++ b/invenio_previewer/_compat.py
@@ -19,4 +19,4 @@ if PY2:
     string_types = (str, unicode)
 else:
     text_type = str
-    string_types = (str, )
+    string_types = (str,)
diff --git a/invenio_previewer/api.py b/invenio_previewer/api.py
index 5fa0b6e1640307175a1935491c382843cd1faf72..576f6357059e22c4cd11edc5d50f4daa17dec9cc 100644
--- a/invenio_previewer/api.py
+++ b/invenio_previewer/api.py
@@ -30,7 +30,7 @@ class PreviewFile(object):
     @property
     def size(self):
         """Get file size."""
-        return self.file['size']
+        return self.file["size"]
 
     @property
     def filename(self):
@@ -52,9 +52,10 @@ class PreviewFile(object):
             view ``invenio_records_ui.<pid_type>_files``.
         """
         return url_for(
-            '.{0}_files'.format(self.pid.pid_type),
+            ".{0}_files".format(self.pid.pid_type),
             pid_value=self.pid.pid_value,
-            filename=self.file.key)
+            filename=self.file.key,
+        )
 
     def is_local(self):
         """Check if file is local."""
diff --git a/invenio_previewer/config.py b/invenio_previewer/config.py
index b962a913fbf51f10259a6aa032502ef780296fa9..db545af47b34cd56c7c5d7e10ef2389b7ea3b988 100644
--- a/invenio_previewer/config.py
+++ b/invenio_previewer/config.py
@@ -33,24 +33,24 @@ PREVIEWER_ZIP_MAX_FILES = 1000
 """Max number of files showed in the ZIP previewer."""
 
 PREVIEWER_PREFERENCE = [
-    'csv_dthreejs',
-    'simple_image',
-    'json_prismjs',
-    'xml_prismjs',
-    'mistune',
-    'pdfjs',
-    'ipynb',
-    'zip',
+    "csv_dthreejs",
+    "simple_image",
+    "json_prismjs",
+    "xml_prismjs",
+    "mistune",
+    "pdfjs",
+    "ipynb",
+    "zip",
 ]
 """Decides which previewers are available and their priority."""
 
-PREVIEWER_ABSTRACT_TEMPLATE = 'invenio_previewer/abstract_previewer.html'
+PREVIEWER_ABSTRACT_TEMPLATE = "invenio_previewer/abstract_previewer.html"
 """Parent template used by the available previewers."""
 
-PREVIEWER_BASE_CSS_BUNDLES = ['previewer_theme.css']
+PREVIEWER_BASE_CSS_BUNDLES = ["previewer_theme.css"]
 """Basic bundle which includes Font-Awesome/Bootstrap."""
 
-PREVIEWER_BASE_JS_BUNDLES = ['previewer_theme.js']
+PREVIEWER_BASE_JS_BUNDLES = ["previewer_theme.js"]
 """Basic bundle which includes Bootstrap/jQuery."""
 
 PREVIEWER_RECORD_FILE_FACOTRY = None
diff --git a/invenio_previewer/ext.py b/invenio_previewer/ext.py
index a10eaaeeecda2bcb0df92126898b6d9a3cc74847..69a91c068aac552c1242156a476701055a41cc2a 100644
--- a/invenio_previewer/ext.py
+++ b/invenio_previewer/ext.py
@@ -57,36 +57,38 @@ class _InvenioPreviewerState(object):
     def record_file_factory(self):
         """Load default record file factory."""
         try:
-            get_distribution('invenio-records-files')
+            get_distribution("invenio-records-files")
             from invenio_records_files.utils import record_file_factory
+
             default = record_file_factory
         except DistributionNotFound:
+
             def default(pid, record, filename):
                 return None
 
         return load_or_import_from_config(
-            'PREVIEWER_RECORD_FILE_FACOTRY',
+            "PREVIEWER_RECORD_FILE_FACOTRY",
             app=self.app,
             default=default,
         )
 
     @property
     def css_bundles(self):
-        return self.app.config['PREVIEWER_BASE_CSS_BUNDLES']
+        return self.app.config["PREVIEWER_BASE_CSS_BUNDLES"]
 
     @property
     def js_bundles(self):
-        return self.app.config['PREVIEWER_BASE_JS_BUNDLES']
+        return self.app.config["PREVIEWER_BASE_JS_BUNDLES"]
 
     def register_previewer(self, name, previewer):
         """Register a previewer in the system."""
         if name in self.previewers:
-            assert name not in self.previewers, \
-                "Previewer with same name already registered"
+            assert (
+                name not in self.previewers
+            ), "Previewer with same name already registered"
         self.previewers[name] = previewer
-        if hasattr(previewer, 'previewable_extensions'):
-            self._previewable_extensions |= set(
-                previewer.previewable_extensions)
+        if hasattr(previewer, "previewable_extensions"):
+            self._previewable_extensions |= set(previewer.previewable_extensions)
 
     def load_entry_point_group(self, entry_point_group):
         """Load previewers from an entry point group."""
@@ -99,8 +101,7 @@ class _InvenioPreviewerState(object):
             self.load_entry_point_group(self.entry_point_group)
             self.entry_point_group = None
 
-        previewers = previewers or \
-            self.app.config.get('PREVIEWER_PREFERENCE', [])
+        previewers = previewers or self.app.config.get("PREVIEWER_PREFERENCE", [])
 
         for item in previewers:
             if item in self.previewers:
@@ -115,23 +116,20 @@ class InvenioPreviewer(object):
         if app:
             self._state = self.init_app(app, **kwargs)
 
-    def init_app(self, app, entry_point_group='invenio_previewer.previewers'):
+    def init_app(self, app, entry_point_group="invenio_previewer.previewers"):
         """Flask application initialization."""
         self.init_config(app)
         app.register_blueprint(blueprint)
-        state = _InvenioPreviewerState(
-            app,
-            entry_point_group=entry_point_group)
-        app.extensions['invenio-previewer'] = state
+        state = _InvenioPreviewerState(app, entry_point_group=entry_point_group)
+        app.extensions["invenio-previewer"] = state
         return state
 
     def init_config(self, app):
         """Initialize configuration."""
-        app.config.setdefault(
-            'PREVIEWER_BASE_TEMPLATE', 'invenio_previewer/base.html')
+        app.config.setdefault("PREVIEWER_BASE_TEMPLATE", "invenio_previewer/base.html")
 
         for k in dir(config):
-            if k.startswith('PREVIEWER_'):
+            if k.startswith("PREVIEWER_"):
                 app.config.setdefault(k, getattr(config, k))
 
     def __getattr__(self, name):
diff --git a/invenio_previewer/extensions/csv_dthreejs.py b/invenio_previewer/extensions/csv_dthreejs.py
index 80349d5b7de34359029f6aa39e2969c1cb2cfcf5..8658650b86ce7eaff7e174a0dfffdaf19ccec849 100644
--- a/invenio_previewer/extensions/csv_dthreejs.py
+++ b/invenio_previewer/extensions/csv_dthreejs.py
@@ -17,7 +17,7 @@ from flask import current_app, render_template
 from ..proxies import current_previewer
 from ..utils import detect_encoding
 
-previewable_extensions = ['csv', 'dsv']
+previewable_extensions = ["csv", "dsv"]
 
 
 def validate_csv(file):
@@ -25,33 +25,32 @@ def validate_csv(file):
     try:
         # Detect encoding and dialect
         with file.open() as fp:
-            encoding = detect_encoding(fp, default='utf-8')
+            encoding = detect_encoding(fp, default="utf-8")
             sample = fp.read(
-                current_app.config.get('PREVIEWER_CSV_VALIDATION_BYTES', 1024))
+                current_app.config.get("PREVIEWER_CSV_VALIDATION_BYTES", 1024)
+            )
             allowed_delimiters = current_app.config.get(
-                'PREVIEWER_CSV_SNIFFER_ALLOWED_DELIMITERS', None)
-            delimiter = csv.Sniffer().sniff(
-                sample=sample.decode(encoding),
-                delimiters=allowed_delimiters).delimiter
+                "PREVIEWER_CSV_SNIFFER_ALLOWED_DELIMITERS", None
+            )
+            delimiter = (
+                csv.Sniffer()
+                .sniff(sample=sample.decode(encoding), delimiters=allowed_delimiters)
+                .delimiter
+            )
             is_valid = True
     except Exception as e:
-        current_app.logger.debug(
-            'File {0} is not valid CSV: {1}'.format(file.uri, e))
-        encoding = ''
-        delimiter = ''
+        current_app.logger.debug("File {0} is not valid CSV: {1}".format(file.uri, e))
+        encoding = ""
+        delimiter = ""
         is_valid = False
 
-    return {
-        'delimiter': delimiter,
-        'encoding': encoding,
-        'is_valid': is_valid
-    }
+    return {"delimiter": delimiter, "encoding": encoding, "is_valid": is_valid}
 
 
 def can_preview(file):
     """Determine if the given file can be previewed."""
-    if file.is_local() and file.has_extensions('.csv', '.dsv'):
-        return validate_csv(file)['is_valid']
+    if file.is_local() and file.has_extensions(".csv", ".dsv"):
+        return validate_csv(file)["is_valid"]
     return False
 
 
@@ -59,10 +58,10 @@ def preview(file):
     """Render the appropriate template with embed flag."""
     file_info = validate_csv(file)
     return render_template(
-        'invenio_previewer/csv_bar.html',
+        "invenio_previewer/csv_bar.html",
         file=file,
-        delimiter=file_info['delimiter'],
-        encoding=file_info['encoding'],
-        js_bundles=current_previewer.js_bundles + ['d3_csv.js'],
+        delimiter=file_info["delimiter"],
+        encoding=file_info["encoding"],
+        js_bundles=current_previewer.js_bundles + ["d3_csv.js"],
         css_bundles=current_previewer.css_bundles,
     )
diff --git a/invenio_previewer/extensions/ipynb.py b/invenio_previewer/extensions/ipynb.py
index 61a74b51e93df3985946952a306b9e9a6c72ed8f..5401a8d17d05a0fb87f81a489ef5e2896b606be1 100644
--- a/invenio_previewer/extensions/ipynb.py
+++ b/invenio_previewer/extensions/ipynb.py
@@ -17,7 +17,7 @@ from nbconvert import HTMLExporter
 
 from ..proxies import current_previewer
 
-previewable_extensions = ['ipynb']
+previewable_extensions = ["ipynb"]
 
 
 def render(file):
diff --git a/invenio_previewer/extensions/json_prismjs.py b/invenio_previewer/extensions/json_prismjs.py
index 105fa3d5a919f10a65d974086994bfbb71db48d5..42c36e87502491547a9227b1e04115f4d20b4330 100644
--- a/invenio_previewer/extensions/json_prismjs.py
+++ b/invenio_previewer/extensions/json_prismjs.py
@@ -18,28 +18,29 @@ from flask import current_app, render_template
 from ..proxies import current_previewer
 from ..utils import detect_encoding
 
-previewable_extensions = ['json']
+previewable_extensions = ["json"]
 
 
 def render(file):
     """Pretty print the JSON file for rendering."""
     with file.open() as fp:
-        encoding = detect_encoding(fp, default='utf-8')
+        encoding = detect_encoding(fp, default="utf-8")
         file_content = fp.read().decode(encoding)
         json_data = json.loads(file_content, object_pairs_hook=OrderedDict)
-        return json.dumps(json_data, indent=4, separators=(',', ': '))
+        return json.dumps(json_data, indent=4, separators=(",", ": "))
 
 
 def validate_json(file):
     """Validate a JSON file."""
     max_file_size = current_app.config.get(
-        'PREVIEWER_MAX_FILE_SIZE_BYTES', 1 * 1024 * 1024)
+        "PREVIEWER_MAX_FILE_SIZE_BYTES", 1 * 1024 * 1024
+    )
     if file.size > max_file_size:
         return False
 
     with file.open() as fp:
         try:
-            json.loads(fp.read().decode('utf-8'))
+            json.loads(fp.read().decode("utf-8"))
             return True
         except Exception:
             return False
@@ -47,17 +48,15 @@ def validate_json(file):
 
 def can_preview(file):
     """Determine if the given file can be previewed."""
-    return (file.is_local() and
-            file.has_extensions('.json') and
-            validate_json(file))
+    return file.is_local() and file.has_extensions(".json") and validate_json(file)
 
 
 def preview(file):
     """Render the appropriate template with embed flag."""
     return render_template(
-        'invenio_previewer/json_prismjs.html',
+        "invenio_previewer/json_prismjs.html",
         file=file,
         content=render(file),
-        js_bundles=current_previewer.js_bundles + ['prism_js.js'],
-        css_bundles=['prism_css.css']
+        js_bundles=current_previewer.js_bundles + ["prism_js.js"],
+        css_bundles=["prism_css.css"],
     )
diff --git a/invenio_previewer/extensions/pdfjs.py b/invenio_previewer/extensions/pdfjs.py
index 49bed2925ef1d3724099d15e7df26114255a50d3..80f6f36252b4f093fb05554d95f6424719fc2452 100644
--- a/invenio_previewer/extensions/pdfjs.py
+++ b/invenio_previewer/extensions/pdfjs.py
@@ -14,23 +14,20 @@ from flask import render_template
 
 from ..proxies import current_previewer
 
-previewable_extensions = ['pdf', 'pdfa']
+previewable_extensions = ["pdf", "pdfa"]
 
 
 def can_preview(file):
     """Check if file can be previewed."""
-    return file.has_extensions('.pdf', '.pdfa')
+    return file.has_extensions(".pdf", ".pdfa")
 
 
 def preview(file):
     """Preview file."""
     return render_template(
-        'invenio_previewer/pdfjs.html',
+        "invenio_previewer/pdfjs.html",
         file=file,
         html_tags='dir="ltr" mozdisallowselectionprint moznomarginboxes',
-        css_bundles=['pdfjs_css.css'],
-        js_bundles=current_previewer.js_bundles + [
-            'pdfjs_js.js',
-            'fullscreen_js.js'
-        ]
+        css_bundles=["pdfjs_css.css"],
+        js_bundles=current_previewer.js_bundles + ["pdfjs_js.js", "fullscreen_js.js"],
     )
diff --git a/invenio_previewer/extensions/xml_prismjs.py b/invenio_previewer/extensions/xml_prismjs.py
index a5b0d8b0328e89120848ac6e6c0861c7370507f1..51e6f5ce98aa38764f62dc2c59ff8ab86fcc62ee 100644
--- a/invenio_previewer/extensions/xml_prismjs.py
+++ b/invenio_previewer/extensions/xml_prismjs.py
@@ -17,28 +17,29 @@ from flask import current_app, render_template
 from ..proxies import current_previewer
 from ..utils import detect_encoding
 
-previewable_extensions = ['xml']
+previewable_extensions = ["xml"]
 
 
 def render(file):
     """Pretty print the XML file for rendering."""
     with file.open() as fp:
-        encoding = detect_encoding(fp, default='utf-8')
+        encoding = detect_encoding(fp, default="utf-8")
         file_content = fp.read().decode(encoding)
         parsed_xml = xml.dom.minidom.parseString(file_content)
-        return parsed_xml.toprettyxml(indent='  ', newl='')
+        return parsed_xml.toprettyxml(indent="  ", newl="")
 
 
 def validate_xml(file):
     """Validate an XML file."""
     max_file_size = current_app.config.get(
-        'PREVIEWER_MAX_FILE_SIZE_BYTES', 1 * 1024 * 1024)
+        "PREVIEWER_MAX_FILE_SIZE_BYTES", 1 * 1024 * 1024
+    )
     if file.size > max_file_size:
         return False
 
     with file.open() as fp:
         try:
-            content = fp.read().decode('utf-8')
+            content = fp.read().decode("utf-8")
             xml.dom.minidom.parseString(content)
             return True
         except Exception:
@@ -47,17 +48,15 @@ def validate_xml(file):
 
 def can_preview(file):
     """Determine if the given file can be previewed."""
-    return (file.is_local() and
-            file.has_extensions('.xml') and
-            validate_xml(file))
+    return file.is_local() and file.has_extensions(".xml") and validate_xml(file)
 
 
 def preview(file):
     """Render appropiate template with embed flag."""
     return render_template(
-        'invenio_previewer/xml_prismjs.html',
+        "invenio_previewer/xml_prismjs.html",
         file=file,
         content=render(file),
-        js_bundles=current_previewer.js_bundles + ['prism_js.js'],
-        css_bundles=['prism_css.css']
+        js_bundles=current_previewer.js_bundles + ["prism_js.js"],
+        css_bundles=["prism_css.css"],
     )
diff --git a/invenio_previewer/extensions/zip.py b/invenio_previewer/extensions/zip.py
index b841fe8ac4c1189e8475be37c39e5c6ecfb43d77..a4d0821445039996864f28f7f3a884c5190c086e 100644
--- a/invenio_previewer/extensions/zip.py
+++ b/invenio_previewer/extensions/zip.py
@@ -20,80 +20,80 @@ from six import binary_type
 from .._compat import text_type
 from ..proxies import current_previewer
 
-previewable_extensions = ['zip']
+previewable_extensions = ["zip"]
 
 
 def make_tree(file):
     """Create tree structure from ZIP archive."""
-    max_files_count = current_app.config.get('PREVIEWER_ZIP_MAX_FILES', 1000)
-    tree = {'type': 'folder', 'id': -1, 'children': {}}
+    max_files_count = current_app.config.get("PREVIEWER_ZIP_MAX_FILES", 1000)
+    tree = {"type": "folder", "id": -1, "children": {}}
 
     try:
         with file.open() as fp:
             zf = zipfile.ZipFile(fp)
             # Detect filenames encoding.
-            sample = ' '.join(zf.namelist()[:max_files_count])
+            sample = " ".join(zf.namelist()[:max_files_count])
             if not isinstance(sample, binary_type):
-                sample = sample.encode('utf-16be')
-            encoding = chardet.detect(sample).get('encoding', 'utf-8')
+                sample = sample.encode("utf-16be")
+            encoding = chardet.detect(sample).get("encoding", "utf-8")
             for i, info in enumerate(zf.infolist()):
                 if i > max_files_count:
-                    raise BufferError('Too many files inside the ZIP file.')
+                    raise BufferError("Too many files inside the ZIP file.")
                 comps = info.filename.split(os.sep)
                 node = tree
                 for c in comps:
                     if not isinstance(c, text_type):
                         c = c.decode(encoding)
-                    if c not in node['children']:
-                        if c == '':
-                            node['type'] = 'folder'
+                    if c not in node["children"]:
+                        if c == "":
+                            node["type"] = "folder"
                             continue
-                        node['children'][c] = {
-                            'name': c,
-                            'type': 'item',
-                            'id': 'item{0}'.format(i),
-                            'children': {}
+                        node["children"][c] = {
+                            "name": c,
+                            "type": "item",
+                            "id": "item{0}".format(i),
+                            "children": {},
                         }
-                    node = node['children'][c]
-                node['size'] = info.file_size
+                    node = node["children"][c]
+                node["size"] = info.file_size
     except BufferError:
         return tree, True, None
-    except (zipfile.LargeZipFile):
-        return tree, False, 'Zipfile is too large to be previewed.'
+    except zipfile.LargeZipFile:
+        return tree, False, "Zipfile is too large to be previewed."
     except Exception as e:
         current_app.logger.warning(str(e), exc_info=True)
-        return tree, False, 'Zipfile is not previewable.'
+        return tree, False, "Zipfile is not previewable."
 
     return tree, False, None
 
 
 def children_to_list(node):
     """Organize children structure."""
-    if node['type'] == 'item' and len(node['children']) == 0:
-        del node['children']
+    if node["type"] == "item" and len(node["children"]) == 0:
+        del node["children"]
     else:
-        node['type'] = 'folder'
-        node['children'] = list(node['children'].values())
-        node['children'].sort(key=lambda x: x['name'])
-        node['children'] = map(children_to_list, node['children'])
+        node["type"] = "folder"
+        node["children"] = list(node["children"].values())
+        node["children"].sort(key=lambda x: x["name"])
+        node["children"] = map(children_to_list, node["children"])
     return node
 
 
 def can_preview(file):
     """Return True if filetype can be previewed."""
-    return file.is_local() and file.has_extensions('.zip')
+    return file.is_local() and file.has_extensions(".zip")
 
 
 def preview(file):
     """Return the appropriate template and pass the file and an embed flag."""
     tree, limit_reached, error = make_tree(file)
-    list = children_to_list(tree)['children']
+    list = children_to_list(tree)["children"]
     return render_template(
         "invenio_previewer/zip.html",
         file=file,
         tree=list,
         limit_reached=limit_reached,
         error=error,
-        js_bundles=current_previewer.js_bundles + ['fullscreen_js.js'],
+        js_bundles=current_previewer.js_bundles + ["fullscreen_js.js"],
         css_bundles=current_previewer.css_bundles + ["zip_css.css"],
     )
diff --git a/invenio_previewer/proxies.py b/invenio_previewer/proxies.py
index 9987f518afe7c2bf18aa99e1ad36c47ad512334a..6fefae3dae3671cb4b3b8a9cd2b9c3a8271c9916 100644
--- a/invenio_previewer/proxies.py
+++ b/invenio_previewer/proxies.py
@@ -13,6 +13,5 @@ from __future__ import absolute_import, print_function
 from flask import current_app
 from werkzeug.local import LocalProxy
 
-current_previewer = LocalProxy(
-    lambda: current_app.extensions['invenio-previewer'])
+current_previewer = LocalProxy(lambda: current_app.extensions["invenio-previewer"])
 """Proxy object to the current previewer extension."""
diff --git a/invenio_previewer/views.py b/invenio_previewer/views.py
index e65afcf112173baa002ba4f1edbec19c64715143..e9483cb7fa4f54ad0e9709ace8d1723c95c8a638 100644
--- a/invenio_previewer/views.py
+++ b/invenio_previewer/views.py
@@ -17,10 +17,10 @@ from .extensions import default
 from .proxies import current_previewer
 
 blueprint = Blueprint(
-    'invenio_previewer',
+    "invenio_previewer",
     __name__,
-    template_folder='templates',
-    static_folder='static',
+    template_folder="templates",
+    static_folder="static",
 )
 """Blueprint used to register template and static folders."""
 
@@ -43,33 +43,39 @@ def preview(pid, record, template=None, **kwargs):
     """
     # Get file from record
     fileobj = current_previewer.record_file_factory(
-        pid, record, request.view_args.get(
-            'filename', request.args.get('filename', type=str))
+        pid,
+        record,
+        request.view_args.get("filename", request.args.get("filename", type=str)),
     )
     if not fileobj:
         abort(404)
 
     # Try to see if specific previewer is set
-    file_previewer = fileobj.get('previewer')
+    file_previewer = fileobj.get("previewer")
 
     # Find a suitable previewer
     fileobj = PreviewFile(pid, record, fileobj)
     for plugin in current_previewer.iter_previewers(
-            previewers=[file_previewer] if file_previewer else None):
+        previewers=[file_previewer] if file_previewer else None
+    ):
         if plugin.can_preview(fileobj):
             try:
                 return plugin.preview(fileobj)
             except Exception:
                 current_app.logger.warning(
-                    ('Preview failed for {key}, in {pid_type}:{pid_value}'
-                     .format(key=fileobj.file.key,
-                             pid_type=fileobj.pid.pid_type,
-                             pid_value=fileobj.pid.pid_value)),
-                    exc_info=True)
+                    (
+                        "Preview failed for {key}, in {pid_type}:{pid_value}".format(
+                            key=fileobj.file.key,
+                            pid_type=fileobj.pid.pid_type,
+                            pid_value=fileobj.pid.pid_value,
+                        )
+                    ),
+                    exc_info=True,
+                )
     return default.preview(fileobj)
 
 
-@blueprint.app_template_test('previewable')
+@blueprint.app_template_test("previewable")
 def is_previewable(extension):
     """Test if a file can be previewed checking its extension."""
     return extension in current_previewer.previewable_extensions
diff --git a/invenio_previewer/webpack.py b/invenio_previewer/webpack.py
index 66005518179e606ccf97fe01b33b7c75cf88235e..d6dbedfa0c26921d46556764342e871f5b9fbcd9 100644
--- a/invenio_previewer/webpack.py
+++ b/invenio_previewer/webpack.py
@@ -31,36 +31,35 @@ from invenio_assets.webpack import WebpackThemeBundle
 
 previewer = WebpackThemeBundle(
     __name__,
-    'assets',
-    default='semantic-ui',
+    "assets",
+    default="semantic-ui",
     themes={
-        'bootstrap3': dict(
+        "bootstrap3": dict(
             entry={
-                'd3_csv': './js/invenio_previewer/csv_previewer/init.js',
-                'previewer_theme': './js/invenio_previewer/previewer_theme.js',
-                'fullscreen_js': './js/invenio_previewer/fullscreen.js',
-                'prism_js': './js/invenio_previewer/prismjs.js',
-                'prism_css': './scss/invenio_previewer/prismjs.scss',
-                'pdfjs_js': './js/invenio_previewer/pdfjs.js',
-                'pdfjs_css': './scss/invenio_previewer/pdfjs.scss',
-                'open_pdf': './js/invenio_previewer/open_pdf.js',
-                'simple_image_css':
-                    './scss/invenio_previewer/simple_image.scss',
+                "d3_csv": "./js/invenio_previewer/csv_previewer/init.js",
+                "previewer_theme": "./js/invenio_previewer/previewer_theme.js",
+                "fullscreen_js": "./js/invenio_previewer/fullscreen.js",
+                "prism_js": "./js/invenio_previewer/prismjs.js",
+                "prism_css": "./scss/invenio_previewer/prismjs.scss",
+                "pdfjs_js": "./js/invenio_previewer/pdfjs.js",
+                "pdfjs_css": "./scss/invenio_previewer/pdfjs.scss",
+                "open_pdf": "./js/invenio_previewer/open_pdf.js",
+                "simple_image_css": "./scss/invenio_previewer/simple_image.scss",
             },
             dependencies={
-                'bootstrap-sass': '~3.3.5',
-                'd3': '^3.5.17',
-                'flightjs': '~1.5.1',
-                'font-awesome': '~4.5.0',
-                'jquery': '^3.3.1',
-                'pdfjs-dist': '^1.4.192',
-                'prismjs': '^1.15.0',
+                "bootstrap-sass": "~3.3.5",
+                "d3": "^3.5.17",
+                "flightjs": "~1.5.1",
+                "font-awesome": "~4.5.0",
+                "jquery": "^3.3.1",
+                "pdfjs-dist": "^1.4.192",
+                "prismjs": "^1.15.0",
             },
             aliases={
-                '@scss/invenio_previewer': 'scss/invenio_previewer',
-            }
+                "@scss/invenio_previewer": "scss/invenio_previewer",
+            },
         ),
-        'semantic-ui': dict(
+        "semantic-ui": dict(
             entry={
                 'd3_csv': './js/invenio_previewer/csv_previewer/init.js',
                 'previewer_theme': './js/invenio_previewer/previewer_theme.js',
@@ -78,14 +77,14 @@ previewer = WebpackThemeBundle(
                 'txt_css': './scss/invenio_previewer/txt.scss',
             },
             dependencies={
-                'd3': '^3.5.17',
-                'flightjs': '~1.5.1',
-                'font-awesome': '~4.5.0',
-                'jquery': '^3.3.1',
-                'pdfjs-dist': '^1.4.192',
-                'prismjs': '^1.15.0',
-            }
+                "d3": "^3.5.17",
+                "flightjs": "~1.5.1",
+                "font-awesome": "~4.5.0",
+                "jquery": "^3.3.1",
+                "pdfjs-dist": "^1.4.192",
+                "prismjs": "^1.15.0",
+            },
         ),
-    }
+    },
 )
 """Bundle of webpack assets."""
diff --git a/pytest.ini b/pytest.ini
deleted file mode 100644
index 1e86c32efa598b49a848b7accbed71d95c757991..0000000000000000000000000000000000000000
--- a/pytest.ini
+++ /dev/null
@@ -1,12 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file is part of Invenio.
-# Copyright (C) 2016-2020 CERN.
-# Copyright (C) 2020 Northwestern University.
-#
-# Invenio is free software; you can redistribute it and/or modify it
-# under the terms of the MIT License; see LICENSE file for more details.
-
-[pytest]
-addopts = --isort --pydocstyle --pycodestyle --cov=invenio_previewer --cov-report=term-missing
-testpaths = tests invenio_previewer
diff --git a/setup.cfg b/setup.cfg
index 7a2d773587f34540fd0ec9b09931a5e33c127dfb..816a2a68330658089c9ff1a7faf374d20c2da9da 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -43,6 +43,7 @@ install_requires =
 
 [options.extras_require]
 tests =
+    pytest-black>=0.3.0,<0.3.10
     invenio-config>=1.0.3
     invenio-theme>=1.3.20
     invenio-db[versioning]>=1.0.14
@@ -99,9 +100,13 @@ output-dir = invenio_previewer/translations/
 [pydocstyle]
 add_ignore = D401
 
-[pycodestyle]
-exclude = docs/conf.py
-
 [update_catalog]
 input-file = invenio_previewer/translations/messages.pot
 output-dir = invenio_previewer/translations/
+
+[isort]
+profile=black
+
+[tool:pytest]
+addopts = --black --isort --pydocstyle --cov=invenio_previewer --cov-report=term-missing
+testpaths = tests invenio_previewer
diff --git a/tests/conftest.py b/tests/conftest.py
index c812cbc9718521ef7141b75d395bc9d8057fd39e..1bcf57d04bc0092725ff1f21d9a33a5eb6fc7624 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -39,41 +39,40 @@ from sqlalchemy_utils.functions import create_database, database_exists
 from invenio_previewer import InvenioPreviewer
 
 
-@pytest.yield_fixture(scope='session', autouse=True)
+@pytest.yield_fixture(scope="session", autouse=True)
 def app():
     """Flask application fixture with database initialization."""
     instance_path = tempfile.mkdtemp()
 
-    app_ = Flask(
-        'testapp', static_folder=instance_path, instance_path=instance_path)
+    app_ = Flask("testapp", static_folder=instance_path, instance_path=instance_path)
     app_.config.update(
         TESTING=True,
         SQLALCHEMY_DATABASE_URI=os.environ.get(
-            'SQLALCHEMY_DATABASE_URI',
-            'sqlite:///:memory:'),
+            "SQLALCHEMY_DATABASE_URI", "sqlite:///:memory:"
+        ),
         SQLALCHEMY_TRACK_MODIFICATIONS=True,
         RECORDS_UI_DEFAULT_PERMISSION_FACTORY=None,
         RECORDS_UI_ENDPOINTS=dict(
             recid=dict(
-                pid_type='recid',
-                route='/records/<pid_value>',
-                template='invenio_records_ui/detail.html',
+                pid_type="recid",
+                route="/records/<pid_value>",
+                template="invenio_records_ui/detail.html",
             ),
             recid_previewer=dict(
-                pid_type='recid',
-                route='/records/<pid_value>/preview',
-                view_imp='invenio_previewer.views:preview',
-                record_class='invenio_records_files.api:Record',
+                pid_type="recid",
+                route="/records/<pid_value>/preview",
+                view_imp="invenio_previewer.views:preview",
+                record_class="invenio_records_files.api:Record",
             ),
             recid_files=dict(
-                pid_type='recid',
-                route='/record/<pid_value>/files/<filename>',
-                view_imp='invenio_records_files.utils.file_download_ui',
-                record_class='invenio_records_files.api:Record',
+                pid_type="recid",
+                route="/record/<pid_value>/files/<filename>",
+                view_imp="invenio_records_files.utils.file_download_ui",
+                record_class="invenio_records_files.api:Record",
             ),
         ),
-        SERVER_NAME='localhost',
-        APP_THEME=['semantic-ui']
+        SERVER_NAME="localhost",
+        APP_THEME=["semantic-ui"],
     )
     Babel(app_)
     InvenioAssets(app_)
@@ -103,15 +102,14 @@ def db(app):
     db_.drop_all()
 
 
-@pytest.yield_fixture(scope='session')
+@pytest.yield_fixture(scope="session")
 def webassets(app):
     """Flask application fixture with assets."""
     initial_dir = os.getcwd()
     os.chdir(app.instance_path)
     # force theme.config alias pinting to less/invenio_theme/theme.config
     theme_bundle = current_webpack.project.bundles[0]
-    theme_bundle.aliases['../../theme.config'] = \
-        'less/invenio_theme/theme.config'
+    theme_bundle.aliases["../../theme.config"] = "less/invenio_theme/theme.config"
     current_webpack.project.buildall()
     yield app
     os.chdir(initial_dir)
@@ -122,11 +120,7 @@ def location(db):
     """File system location."""
     tmppath = tempfile.mkdtemp()
 
-    loc = Location(
-        name='testloc',
-        uri=tmppath,
-        default=True
-    )
+    loc = Location(name="testloc", uri=tmppath, default=True)
     db.session.add(loc)
     db.session.commit()
 
@@ -139,12 +133,14 @@ def location(db):
 def record(db, location):
     """Record fixture."""
     rec_uuid = uuid.uuid4()
-    provider = RecordIdProvider.create(
-        object_type='rec', object_uuid=rec_uuid)
-    record = Record.create({
-        'control_number': provider.pid.pid_value,
-        'title': 'TestDefault',
-    }, id_=rec_uuid)
+    provider = RecordIdProvider.create(object_type="rec", object_uuid=rec_uuid)
+    record = Record.create(
+        {
+            "control_number": provider.pid.pid_value,
+            "title": "TestDefault",
+        },
+        id_=rec_uuid,
+    )
     db.session.commit()
     return record
 
@@ -152,17 +148,20 @@ def record(db, location):
 @pytest.fixture()
 def record_with_file(db, record, location):
     """Record with a test file."""
-    testfile = ObjectVersion.create(record.bucket, 'testfile',
-                                    stream=BytesIO(b'atest'))
-    record.update(dict(
-        _files=[dict(
-            bucket=str(testfile.bucket_id),
-            key=testfile.key,
-            size=testfile.file.size,
-            checksum=str(testfile.file.checksum),
-            version_id=str(testfile.version_id),
-        ), ]
-    ))
+    testfile = ObjectVersion.create(record.bucket, "testfile", stream=BytesIO(b"atest"))
+    record.update(
+        dict(
+            _files=[
+                dict(
+                    bucket=str(testfile.bucket_id),
+                    key=testfile.key,
+                    size=testfile.file.size,
+                    checksum=str(testfile.file.checksum),
+                    version_id=str(testfile.version_id),
+                ),
+            ]
+        )
+    )
     record.commit()
     db.session.commit()
     return record, testfile
@@ -173,9 +172,9 @@ def zip_fp(db):
     """ZIP file stream."""
     fp = BytesIO()
 
-    zipf = ZipFile(fp, 'w')
-    zipf.writestr('Example.txt', 'This is an example'.encode('utf-8'))
-    zipf.writestr(u'Lé UTF8 test.txt', 'This is an example'.encode('utf-8'))
+    zipf = ZipFile(fp, "w")
+    zipf.writestr("Example.txt", "This is an example".encode("utf-8"))
+    zipf.writestr("Lé UTF8 test.txt", "This is an example".encode("utf-8"))
     zipf.close()
 
     fp.seek(0)
diff --git a/tests/test_invenio_previewer.py b/tests/test_invenio_previewer.py
index 0fa5af75f524f393afd7e2d9b612f0d317ea600a..2ed8348ed8d1cb91525b96c1586843ab2d110eda 100644
--- a/tests/test_invenio_previewer.py
+++ b/tests/test_invenio_previewer.py
@@ -30,14 +30,14 @@ class MockEntryPoint(EntryPoint):
 def _mock_entry_points(group=None):
     """Mocking funtion of entrypoints."""
     data = {
-        'invenio_previewer.previewers': [
+        "invenio_previewer.previewers": [
             MockEntryPoint(
-                'default',
-                'invenio_previewer.extensions.default',
+                "default",
+                "invenio_previewer.extensions.default",
             ),
             MockEntryPoint(
-                'zip',
-                'invenio_previewer.extensions.zip',
+                "zip",
+                "invenio_previewer.extensions.zip",
             ),
         ],
     }
@@ -50,20 +50,21 @@ def _mock_entry_points(group=None):
 def test_version():
     """Test version import."""
     from invenio_previewer import __version__
+
     assert __version__
 
 
 def test_init():
     """Test extension initialization."""
-    app = Flask('testapp')
+    app = Flask("testapp")
     InvenioPreviewer(app)
-    assert 'invenio-previewer' in app.extensions
+    assert "invenio-previewer" in app.extensions
 
 
-@patch('pkg_resources.iter_entry_points', _mock_entry_points)
+@patch("pkg_resources.iter_entry_points", _mock_entry_points)
 def test_entrypoint_previewer():
     """Test the entry points."""
-    app = Flask('testapp')
+    app = Flask("testapp")
     ext = InvenioPreviewer(app)
-    ext.load_entry_point_group('invenio_previewer.previewers')
+    ext.load_entry_point_group("invenio_previewer.previewers")
     assert len(ext.previewers) == 2
diff --git a/tests/test_macros.py b/tests/test_macros.py
index c265b2d873acad97ffaa4fc87676352828724f80..f16b3d78b004d020b7bc1182d770c8a94b7c6790 100644
--- a/tests/test_macros.py
+++ b/tests/test_macros.py
@@ -22,168 +22,172 @@ from six import BytesIO, b
 def create_file(record, filename, stream):
     """Create a file and add in record."""
     obj = ObjectVersion.create(record.bucket, filename, stream=stream)
-    record.update(dict(
-        _files=[dict(
-            bucket=str(record.bucket.id),
-            key=filename,
-            size=obj.file.size,
-            checksum=str(obj.file.checksum),
-            version_id=str(obj.version_id),
-        ), ]
-    ))
+    record.update(
+        dict(
+            _files=[
+                dict(
+                    bucket=str(record.bucket.id),
+                    key=filename,
+                    size=obj.file.size,
+                    checksum=str(obj.file.checksum),
+                    version_id=str(obj.version_id),
+                ),
+            ]
+        )
+    )
     record.commit()
     db.session.commit()
 
 
 def preview_url(pid_val, filename):
     """Preview URL."""
-    return url_for('invenio_records_ui.recid_previewer',
-                   pid_value=pid_val, filename=filename)
+    return url_for(
+        "invenio_records_ui.recid_previewer", pid_value=pid_val, filename=filename
+    )
 
 
 def test_default_extension(app, webassets, record):
     """Test view by default."""
-    create_file(record, 'testfile', BytesIO(b'empty'))
+    create_file(record, "testfile", BytesIO(b"empty"))
 
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'testfile'))
-        assert 'we are unfortunately not' in res.get_data(as_text=True)
+        res = client.get(preview_url(record["control_number"], "testfile"))
+        assert "we are unfortunately not" in res.get_data(as_text=True)
 
 
 def test_markdown_extension(app, webassets, record):
     """Test view with md files."""
-    create_file(
-        record, 'markdown.md', BytesIO(b'### Testing markdown ###'))
+    create_file(record, "markdown.md", BytesIO(b"### Testing markdown ###"))
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'markdown.md'))
-        assert '<h3>Testing markdown' in res.get_data(as_text=True)
-        with patch('mistune.markdown', side_effect=Exception):
-            res = client.get(preview_url(record['control_number'],
-                                         'markdown.md'))
-            assert 'we are unfortunately not' in res.get_data(as_text=True)
+        res = client.get(preview_url(record["control_number"], "markdown.md"))
+        assert "<h3>Testing markdown" in res.get_data(as_text=True)
+        with patch("mistune.markdown", side_effect=Exception):
+            res = client.get(preview_url(record["control_number"], "markdown.md"))
+            assert "we are unfortunately not" in res.get_data(as_text=True)
 
 
 def test_pdf_extension(app, webassets, record):
     """Test view with pdf files."""
-    create_file(
-        record, 'test.pdf', BytesIO(b'Content not used'))
+    create_file(record, "test.pdf", BytesIO(b"Content not used"))
 
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'test.pdf'))
-        assert 'PDFView.open(\'' in res.get_data(as_text=True)
+        res = client.get(preview_url(record["control_number"], "test.pdf"))
+        assert "PDFView.open('" in res.get_data(as_text=True)
 
 
 def test_csv_dthreejs_extension(app, webassets, record):
     """Test view with csv files."""
-    create_file(record, 'test.csv', BytesIO(b'A,B\n1,2'))
+    create_file(record, "test.csv", BytesIO(b"A,B\n1,2"))
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'test.csv'))
+        res = client.get(preview_url(record["control_number"], "test.csv"))
         assert 'data-csv-source="' in res.get_data(as_text=True)
         assert 'data-csv-delimiter=","' in res.get_data(as_text=True)
 
-        with patch('csv.Sniffer', side_effect=Exception):
-            res = client.get(preview_url(record['control_number'], 'test.csv'))
-            assert 'we are unfortunately not' in res.get_data(as_text=True)
+        with patch("csv.Sniffer", side_effect=Exception):
+            res = client.get(preview_url(record["control_number"], "test.csv"))
+            assert "we are unfortunately not" in res.get_data(as_text=True)
 
 
 def test_csv_dthreejs_delimiter(app, webassets, record):
     """Test view with csv files."""
-    create_file(record, 'test.csv', BytesIO(b'A#B\n1#2'))
+    create_file(record, "test.csv", BytesIO(b"A#B\n1#2"))
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'test.csv'))
+        res = client.get(preview_url(record["control_number"], "test.csv"))
         assert 'data-csv-source="' in res.get_data(as_text=True)
         assert 'data-csv-delimiter="#"' in res.get_data(as_text=True)
 
 
 def test_zip_extension(app, webassets, record, zip_fp):
     """Test view with a zip file."""
-    create_file(
-        record, 'test.zip', zip_fp)
+    create_file(record, "test.zip", zip_fp)
 
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'test.zip'))
-        assert 'Example.txt' in res.get_data(as_text=True)
-        assert u'Lé UTF8 test.txt' in res.get_data(as_text=True)
+        res = client.get(preview_url(record["control_number"], "test.zip"))
+        assert "Example.txt" in res.get_data(as_text=True)
+        assert "Lé UTF8 test.txt" in res.get_data(as_text=True)
 
-        with patch('zipfile.ZipFile', side_effect=zipfile.LargeZipFile):
-            res = client.get(preview_url(record['control_number'], 'test.zip'))
-            assert 'Zipfile is too large' in res.get_data(as_text=True)
+        with patch("zipfile.ZipFile", side_effect=zipfile.LargeZipFile):
+            res = client.get(preview_url(record["control_number"], "test.zip"))
+            assert "Zipfile is too large" in res.get_data(as_text=True)
 
-        with patch('zipfile.ZipFile', side_effect=Exception):
-            res = client.get(preview_url(record['control_number'], 'test.zip'))
-            assert 'Zipfile is not previewable' in res.get_data(as_text=True)
+        with patch("zipfile.ZipFile", side_effect=Exception):
+            res = client.get(preview_url(record["control_number"], "test.zip"))
+            assert "Zipfile is not previewable" in res.get_data(as_text=True)
 
 
 def test_json_extension(app, webassets, record):
     """Test view with JSON files."""
-    json_data = '{"name":"invenio","num":42,'\
-                '"flt":3.14159,"lst":[1,2,3],'\
-                '"obj":{"field":"<script>alert(1)</script>","num":4}}'
-    create_file(record, 'test.json', BytesIO(b(json_data)))
+    json_data = (
+        '{"name":"invenio","num":42,'
+        '"flt":3.14159,"lst":[1,2,3],'
+        '"obj":{"field":"<script>alert(1)</script>","num":4}}'
+    )
+    create_file(record, "test.json", BytesIO(b(json_data)))
 
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'test.json'))
+        res = client.get(preview_url(record["control_number"], "test.json"))
         assert 'class="language-javascript"' in res.get_data(as_text=True)
 
-        rendered_json = \
-            '{\n' \
-            '    &#34;name&#34;: &#34;invenio&#34;,\n' \
-            '    &#34;num&#34;: 42,\n' \
-            '    &#34;flt&#34;: 3.14159,\n' \
-            '    &#34;lst&#34;: [\n' \
-            '        1,\n' \
-            '        2,\n' \
-            '        3\n' \
-            '    ],\n' \
-            '    &#34;obj&#34;: {\n' \
-            '        &#34;field&#34;: &#34;&lt;script&gt;alert(1)' \
-            '&lt;/script&gt;&#34;,\n' \
-            '        &#34;num&#34;: 4\n' \
-            '    }\n' \
-            '}'
+        rendered_json = (
+            "{\n"
+            "    &#34;name&#34;: &#34;invenio&#34;,\n"
+            "    &#34;num&#34;: 42,\n"
+            "    &#34;flt&#34;: 3.14159,\n"
+            "    &#34;lst&#34;: [\n"
+            "        1,\n"
+            "        2,\n"
+            "        3\n"
+            "    ],\n"
+            "    &#34;obj&#34;: {\n"
+            "        &#34;field&#34;: &#34;&lt;script&gt;alert(1)"
+            "&lt;/script&gt;&#34;,\n"
+            "        &#34;num&#34;: 4\n"
+            "    }\n"
+            "}"
+        )
         assert rendered_json in res.get_data(as_text=True)
 
-        with patch('json.dumps', side_effect=Exception):
-            res = client.get(preview_url(record['control_number'],
-                                         'test.json'))
-            assert 'we are unfortunately not' in res.get_data(as_text=True)
+        with patch("json.dumps", side_effect=Exception):
+            res = client.get(preview_url(record["control_number"], "test.json"))
+            assert "we are unfortunately not" in res.get_data(as_text=True)
 
 
 def test_max_file_size(app, webassets, record):
     """Test file size limitation."""
-    max_file_size = app.config.get(
-        'PREVIEWER_MAX_FILE_SIZE_BYTES', 1 * 1024 * 1024)
-    too_large_string = '1' * (max_file_size + 1)
-    create_file(record, 'test.json', BytesIO(b(too_large_string)))
+    max_file_size = app.config.get("PREVIEWER_MAX_FILE_SIZE_BYTES", 1 * 1024 * 1024)
+    too_large_string = "1" * (max_file_size + 1)
+    create_file(record, "test.json", BytesIO(b(too_large_string)))
 
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'test.json'))
-        assert 'we are unfortunately not' in res.get_data(as_text=True)
+        res = client.get(preview_url(record["control_number"], "test.json"))
+        assert "we are unfortunately not" in res.get_data(as_text=True)
 
 
 def test_xml_extension(app, webassets, record):
     """Test view with XML files."""
     xml_data = b'<el a="some"><script>alert(1)</script><c>1</c><c>2</c></el>'
-    create_file(
-        record, 'test.xml', BytesIO(xml_data))
+    create_file(record, "test.xml", BytesIO(xml_data))
 
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'test.xml'))
+        res = client.get(preview_url(record["control_number"], "test.xml"))
         assert 'class="language-markup"' in res.get_data(as_text=True)
-        assert '&lt;el a=&#34;some&#34;&gt;' in res.get_data(as_text=True)
-        assert '&lt;c&gt;1&lt;/c&gt;' in res.get_data(as_text=True)
-        assert '&lt;c&gt;2&lt;/c&gt;' in res.get_data(as_text=True)
-        assert '&lt;/el&gt;' in res.get_data(as_text=True)
+        assert "&lt;el a=&#34;some&#34;&gt;" in res.get_data(as_text=True)
+        assert "&lt;c&gt;1&lt;/c&gt;" in res.get_data(as_text=True)
+        assert "&lt;c&gt;2&lt;/c&gt;" in res.get_data(as_text=True)
+        assert "&lt;/el&gt;" in res.get_data(as_text=True)
 
-        with patch('xml.dom.minidom.Node.toprettyxml', side_effect=Exception):
-            res = client.get(preview_url(record['control_number'], 'test.xml'))
-            assert 'we are unfortunately not' in res.get_data(as_text=True)
+        with patch("xml.dom.minidom.Node.toprettyxml", side_effect=Exception):
+            res = client.get(preview_url(record["control_number"], "test.xml"))
+            assert "we are unfortunately not" in res.get_data(as_text=True)
 
 
 def test_ipynb_extension(app, webassets, record):
     """Test view with IPython notebooks files."""
     create_file(
-        record, 'test.ipynb', BytesIO(b'''
+        record,
+        "test.ipynb",
+        BytesIO(
+            b"""
 {
   "cells": [
     {
@@ -215,19 +219,21 @@ def test_ipynb_extension(app, webassets, record):
    },
   "nbformat":4,
   "nbformat_minor":0
-}'''))
+}"""
+        ),
+    )
 
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'test.ipynb'))
-        assert 'This is an example notebook.' in res.get_data(as_text=True)
+        res = client.get(preview_url(record["control_number"], "test.ipynb"))
+        assert "This is an example notebook." in res.get_data(as_text=True)
 
 
 def test_simple_image_extension(app, webassets, record):
     """Test view with simple image files (PNG)."""
-    create_file(record, 'test.png', BytesIO(b'Content not used'))
+    create_file(record, "test.png", BytesIO(b"Content not used"))
 
     with app.test_client() as client:
-        res = client.get(preview_url(record['control_number'], 'test.png'))
+        res = client.get(preview_url(record["control_number"], "test.png"))
         assert '<img src="' in res.get_data(as_text=True)
         assert 'class="previewer-simple-image"' in res.get_data(as_text=True)
 
@@ -255,25 +261,27 @@ def test_view_macro_file_list(app):
     with app.test_request_context():
         files = [
             {
-                'key': 'test1.txt',
-                'size': 10,
-                'date': '2016-07-12',
+                "key": "test1.txt",
+                "size": 10,
+                "date": "2016-07-12",
             },
             {
-                'key': 'test2.txt',
-                'size': 12000000,
-                'date': '2016-07-12',
+                "key": "test2.txt",
+                "size": 12000000,
+                "date": "2016-07-12",
             },
         ]
 
-        pid = {
-            'pid_value': 1
-        }
+        pid = {"pid_value": 1}
 
-        result = render_template_string("""
+        result = render_template_string(
+            """
             {%- from "invenio_previewer/macros.html" import file_list %}
             {{ file_list(files, pid) }}
-            """, files=files, pid=pid)
+            """,
+            files=files,
+            pid=pid,
+        )
 
         print(result)
 
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 8a2c184248315cbcd87d7b7288f013b65dd4a130..e5096ebc5e43a5b12931ca15a42e016e0b63bd98 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -21,37 +21,38 @@ from invenio_previewer.utils import detect_encoding
 def test_default_file_reader(app, record_with_file):
     """Test view by default."""
     record, testfile = record_with_file
-    file_ = current_previewer.record_file_factory(
-        None, record, testfile.key)
+    file_ = current_previewer.record_file_factory(None, record, testfile.key)
     assert file_.version_id == testfile.version_id
 
 
-@pytest.mark.parametrize('string, confidence, encoding, detect', [
-    (u'Γκρήκ Στρίνγκ'.encode('utf-8'), 0.99000, 'UTF-8', 'UTF-8'),
-    (u'dhǾk: kjd köd, ddȪj@dd.k'.encode('utf-8'), 0.87625, 'UTF-8', None),
-    (u'क्या हाल तुम या कर रहे हो?'.encode('utf-8'), 0.99000, 'UTF-8', 'UTF-8'),
-    (u'石原氏 移転は「既定路線」'.encode('euc-jp'), 0.46666, 'EUC-JP', None),
-    (u'Hi bye sigh die'.encode('utf-8'), 1.00000, 'UTF-8', 'UTF-8'),
-    (u'Monkey donkey cow crow'.encode('euc-jp'), 0.00000, 'ASCII', None),
-    (u'Monkey donkey cow crow'.encode('euc-jp'), 0.90000, 'EUC-JP', None),
-    (u'Monkey donkey cow crow'.encode('euc-jp'), 0.90001, 'EUC-JP', 'EUC-JP'),
-    (u'Monkey donkey cow crow'.encode('euc-jp'), 0.50000, 'UTF-8', None),
-])
+@pytest.mark.parametrize(
+    "string, confidence, encoding, detect",
+    [
+        ("Γκρήκ Στρίνγκ".encode("utf-8"), 0.99000, "UTF-8", "UTF-8"),
+        ("dhǾk: kjd köd, ddȪj@dd.k".encode("utf-8"), 0.87625, "UTF-8", None),
+        ("क्या हाल तुम या कर रहे हो?".encode("utf-8"), 0.99000, "UTF-8", "UTF-8"),
+        ("石原氏 移転は「既定路線」".encode("euc-jp"), 0.46666, "EUC-JP", None),
+        ("Hi bye sigh die".encode("utf-8"), 1.00000, "UTF-8", "UTF-8"),
+        ("Monkey donkey cow crow".encode("euc-jp"), 0.00000, "ASCII", None),
+        ("Monkey donkey cow crow".encode("euc-jp"), 0.90000, "EUC-JP", None),
+        ("Monkey donkey cow crow".encode("euc-jp"), 0.90001, "EUC-JP", "EUC-JP"),
+        ("Monkey donkey cow crow".encode("euc-jp"), 0.50000, "UTF-8", None),
+    ],
+)
 def test_detect_encoding(app, string, confidence, encoding, detect):
     """Test encoding detection."""
 
     f = BytesIO(string)
     initial_position = f.tell()
 
-    with patch('cchardet.detect') as mock_detect:
-        mock_detect.return_value = {'encoding': encoding,
-                                    'confidence': confidence}
+    with patch("cchardet.detect") as mock_detect:
+        mock_detect.return_value = {"encoding": encoding, "confidence": confidence}
         assert detect_encoding(f) is detect
         assert f.tell() == initial_position
 
 
 def test_detect_encoding_exception(app):
-    f = BytesIO(u'Γκρήκ Στρίνγκ'.encode('utf-8'))
+    f = BytesIO("Γκρήκ Στρίνγκ".encode("utf-8"))
 
-    with patch('cchardet.detect', Exception):
+    with patch("cchardet.detect", Exception):
         assert detect_encoding(f) is None
diff --git a/tests/test_views.py b/tests/test_views.py
index b8851f94f0ae9fafbdff3230843baeb1f89b0e24..6cae350479e3e4fe8bbd09fd0256a017e1292a30 100644
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -18,25 +18,27 @@ def test_view_macro_file_list(app):
     with app.test_request_context():
         files = [
             {
-                'key': 'test1.txt',
-                'size': 10,
-                'date': '2016-07-12',
+                "key": "test1.txt",
+                "size": 10,
+                "date": "2016-07-12",
             },
             {
-                'key': 'test2.txt',
-                'size': 12000000,
-                'date': '2016-07-12',
+                "key": "test2.txt",
+                "size": 12000000,
+                "date": "2016-07-12",
             },
         ]
 
-        pid = {
-            'pid_value': 1
-        }
+        pid = {"pid_value": 1}
 
-        result = render_template_string("""
+        result = render_template_string(
+            """
             {%- from "invenio_previewer/macros.html" import file_list %}
             {{ file_list(files, pid) }}
-            """, files=files, pid=pid)
+            """,
+            files=files,
+            pid=pid,
+        )
 
         assert 'href="/record/1/files/test1.txt?download=1"' in result
         assert '<td class="nowrap">10 Bytes</td>' in result
@@ -46,18 +48,18 @@ def test_view_macro_file_list(app):
 
 def test_previwable_test(app):
     """Test template test."""
-    file = {
-        'type': 'md'
-    }
-    template = "{% if file.type is previewable %}Previwable" \
-               "{% else %}Not previwable{% endif %}"
+    file = {"type": "md"}
+    template = (
+        "{% if file.type is previewable %}Previwable"
+        "{% else %}Not previwable{% endif %}"
+    )
     assert render_template_string(template, file=file) == "Previwable"
 
-    file['type'] = 'no'
+    file["type"] = "no"
     assert render_template_string(template, file=file) == "Not previwable"
 
-    file['type'] = 'pdf'
+    file["type"] = "pdf"
     assert render_template_string(template, file=file) == "Previwable"
 
-    file['type'] = ''
+    file["type"] = ""
     assert render_template_string(template, file=file) == "Not previwable"