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' \ - ' "name": "invenio",\n' \ - ' "num": 42,\n' \ - ' "flt": 3.14159,\n' \ - ' "lst": [\n' \ - ' 1,\n' \ - ' 2,\n' \ - ' 3\n' \ - ' ],\n' \ - ' "obj": {\n' \ - ' "field": "<script>alert(1)' \ - '</script>",\n' \ - ' "num": 4\n' \ - ' }\n' \ - '}' + rendered_json = ( + "{\n" + " "name": "invenio",\n" + " "num": 42,\n" + " "flt": 3.14159,\n" + " "lst": [\n" + " 1,\n" + " 2,\n" + " 3\n" + " ],\n" + " "obj": {\n" + " "field": "<script>alert(1)" + "</script>",\n" + " "num": 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 '<el a="some">' in res.get_data(as_text=True) - assert '<c>1</c>' in res.get_data(as_text=True) - assert '<c>2</c>' in res.get_data(as_text=True) - assert '</el>' in res.get_data(as_text=True) + assert "<el a="some">" in res.get_data(as_text=True) + assert "<c>1</c>" in res.get_data(as_text=True) + assert "<c>2</c>" in res.get_data(as_text=True) + assert "</el>" 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"