From 0c6ad845e6f461e880b423bd8f79156754658f8a Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Sat, 9 Oct 2021 09:43:40 +0300 Subject: Move markdown_routes to api/markdown All new API definitions should be migrated to "wqflask/ api" --- .../tests/unit/wqflask/api/test_markdown_routes.py | 54 ++++++ wqflask/tests/unit/wqflask/test_markdown_routes.py | 54 ------ wqflask/wqflask/__init__.py | 16 +- wqflask/wqflask/api/correlation.py | 6 - wqflask/wqflask/api/markdown.py | 186 +++++++++++++++++++++ wqflask/wqflask/markdown_routes.py | 186 --------------------- 6 files changed, 248 insertions(+), 254 deletions(-) create mode 100644 wqflask/tests/unit/wqflask/api/test_markdown_routes.py delete mode 100644 wqflask/tests/unit/wqflask/test_markdown_routes.py create mode 100644 wqflask/wqflask/api/markdown.py delete mode 100644 wqflask/wqflask/markdown_routes.py diff --git a/wqflask/tests/unit/wqflask/api/test_markdown_routes.py b/wqflask/tests/unit/wqflask/api/test_markdown_routes.py new file mode 100644 index 00000000..1c513ac5 --- /dev/null +++ b/wqflask/tests/unit/wqflask/api/test_markdown_routes.py @@ -0,0 +1,54 @@ +"""Test functions for wqflask/api/markdown.py""" + +import unittest +from unittest import mock + +from dataclasses import dataclass +from wqflask.api.markdown import render_markdown + + +@dataclass +class MockRequests404: + status_code: int = 404 + + +@dataclass +class MockRequests200: + status_code: int = 200 + content: str = b""" +# Glossary +This is some content + +## Sub-heading +This is another sub-heading""" + + +class TestMarkdownRoutesFunctions(unittest.TestCase): + """Test cases for functions in markdown""" + + @mock.patch('wqflask.api.markdown.requests.get') + def test_render_markdown_when_fetching_locally(self, requests_mock): + requests_mock.return_value = MockRequests404() + markdown_content = render_markdown("general/glossary/glossary.md") + requests_mock.assert_called_with( + "https://raw.githubusercontent.com" + "/genenetwork/gn-docs/" + "master/general/" + "glossary/glossary.md") + self.assertRegexpMatches(markdown_content, + "Content for general/glossary/glossary.md not available.") + + @mock.patch('wqflask.api.markdown.requests.get') + def test_render_markdown_when_fetching_remotely(self, requests_mock): + requests_mock.return_value = MockRequests200() + markdown_content = render_markdown("general/glossary/glossary.md") + requests_mock.assert_called_with( + "https://raw.githubusercontent.com" + "/genenetwork/gn-docs/" + "master/general/" + "glossary/glossary.md") + self.assertEqual("""

Glossary

+

This is some content

+

Sub-heading

+

This is another sub-heading

""", + markdown_content) diff --git a/wqflask/tests/unit/wqflask/test_markdown_routes.py b/wqflask/tests/unit/wqflask/test_markdown_routes.py deleted file mode 100644 index 90e0f17c..00000000 --- a/wqflask/tests/unit/wqflask/test_markdown_routes.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Test functions in markdown utils""" - -import unittest -from unittest import mock - -from dataclasses import dataclass -from wqflask.markdown_routes import render_markdown - - -@dataclass -class MockRequests404: - status_code: int = 404 - - -@dataclass -class MockRequests200: - status_code: int = 200 - content: str = b""" -# Glossary -This is some content - -## Sub-heading -This is another sub-heading""" - - -class TestMarkdownRoutesFunctions(unittest.TestCase): - """Test cases for functions in markdown_routes""" - - @mock.patch('wqflask.markdown_routes.requests.get') - def test_render_markdown_when_fetching_locally(self, requests_mock): - requests_mock.return_value = MockRequests404() - markdown_content = render_markdown("general/glossary/glossary.md") - requests_mock.assert_called_with( - "https://raw.githubusercontent.com" - "/genenetwork/gn-docs/" - "master/general/" - "glossary/glossary.md") - self.assertRegexpMatches(markdown_content, - "Content for general/glossary/glossary.md not available.") - - @mock.patch('wqflask.markdown_routes.requests.get') - def test_render_markdown_when_fetching_remotely(self, requests_mock): - requests_mock.return_value = MockRequests200() - markdown_content = render_markdown("general/glossary/glossary.md") - requests_mock.assert_called_with( - "https://raw.githubusercontent.com" - "/genenetwork/gn-docs/" - "master/general/" - "glossary/glossary.md") - self.assertEqual("""

Glossary

-

This is some content

-

Sub-heading

-

This is another sub-heading

""", - markdown_content) diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py index 8b2055cd..5758b13e 100644 --- a/wqflask/wqflask/__init__.py +++ b/wqflask/wqflask/__init__.py @@ -8,14 +8,14 @@ from flask import Flask from typing import Tuple from urllib.parse import urlparse from utility import formatting -from wqflask.markdown_routes import glossary_blueprint -from wqflask.markdown_routes import references_blueprint -from wqflask.markdown_routes import links_blueprint -from wqflask.markdown_routes import policies_blueprint -from wqflask.markdown_routes import environments_blueprint -from wqflask.markdown_routes import facilities_blueprint -from wqflask.markdown_routes import blogs_blueprint -from wqflask.markdown_routes import news_blueprint +from wqflask.api.markdown import glossary_blueprint +from wqflask.api.markdown import references_blueprint +from wqflask.api.markdown import links_blueprint +from wqflask.api.markdown import policies_blueprint +from wqflask.api.markdown import environments_blueprint +from wqflask.api.markdown import facilities_blueprint +from wqflask.api.markdown import blogs_blueprint +from wqflask.api.markdown import news_blueprint app = Flask(__name__) diff --git a/wqflask/wqflask/api/correlation.py b/wqflask/wqflask/api/correlation.py index a135ecc8..9b875c99 100644 --- a/wqflask/wqflask/api/correlation.py +++ b/wqflask/wqflask/api/correlation.py @@ -9,7 +9,6 @@ from utility.db_tools import escape from wqflask.correlation import correlation_functions - def do_correlation(start_vars): assert('db' in start_vars) assert('target_db' in start_vars) @@ -26,7 +25,6 @@ def do_correlation(start_vars): corr_results = calculate_results( this_trait, this_dataset, target_dataset, corr_params) - #corr_results = collections.OrderedDict(sorted(corr_results.items(), key=lambda t: -abs(t[1][0]))) final_results = [] for _trait_counter, trait in enumerate(list(corr_results.keys())[:corr_params['return_count']]): @@ -54,11 +52,7 @@ def do_correlation(start_vars): "#_strains": num_overlap, "p_value": sample_p } - final_results.append(result_dict) - - # json_corr_results = generate_corr_json(final_corr_results, this_trait, this_dataset, target_dataset, for_api = True) - return final_results diff --git a/wqflask/wqflask/api/markdown.py b/wqflask/wqflask/api/markdown.py new file mode 100644 index 00000000..580b9ac0 --- /dev/null +++ b/wqflask/wqflask/api/markdown.py @@ -0,0 +1,186 @@ +"""Markdown routes + +Render pages from github, or if they are unavailable, look for it else where +""" + +import requests +import markdown +import os +import sys + +from bs4 import BeautifulSoup # type: ignore + +from flask import send_from_directory +from flask import Blueprint +from flask import render_template + +from typing import Dict +from typing import List + +glossary_blueprint = Blueprint('glossary_blueprint', __name__) +references_blueprint = Blueprint("references_blueprint", __name__) +environments_blueprint = Blueprint("environments_blueprint", __name__) +links_blueprint = Blueprint("links_blueprint", __name__) +policies_blueprint = Blueprint("policies_blueprint", __name__) +facilities_blueprint = Blueprint("facilities_blueprint", __name__) +news_blueprint = Blueprint("news_blueprint", __name__) + +blogs_blueprint = Blueprint("blogs_blueprint", __name__) + + +def render_markdown(file_name, is_remote_file=True): + """Try to fetch the file name from Github and if that fails, try to +look for it inside the file system """ + github_url = ("https://raw.githubusercontent.com/" + "genenetwork/gn-docs/master/") + + if not is_remote_file: + text = "" + with open(file_name, "r", encoding="utf-8") as input_file: + text = input_file.read() + return markdown.markdown(text, + extensions=['tables']) + + md_content = requests.get(f"{github_url}{file_name}") + + if md_content.status_code == 200: + return markdown.markdown(md_content.content.decode("utf-8"), + extensions=['tables']) + + return (f"\nContent for {file_name} not available. " + "Please check " + "(here to see where content exists)" + "[https://github.com/genenetwork/gn-docs]. " + "Please reach out to the gn2 team to have a look at this") + + +def get_file_from_python_search_path(pathname_suffix): + cands = [os.path.join(d, pathname_suffix) for d in sys.path] + try: + return list(filter(os.path.exists, cands))[0] + except IndexError: + return None + + +def get_blogs(user: str = "genenetwork", + repo_name: str = "gn-docs") -> dict: + + blogs: Dict[int, List] = {} + github_url = f"https://api.github.com/repos/{user}/{repo_name}/git/trees/master?recursive=1" + + repo_tree = requests.get(github_url).json()["tree"] + + for data in repo_tree: + path_name = data["path"] + if path_name.startswith("blog") and path_name.endswith(".md"): + split_path = path_name.split("/")[1:] + try: + year, title, file_name = split_path + except Exception as e: + year, file_name = split_path + title = "" + + subtitle = os.path.splitext(file_name)[0] + + blog = { + "title": title, + "subtitle": subtitle, + "full_path": path_name + } + + if year in blogs: + blogs[int(year)].append(blog) + else: + blogs[int(year)] = [blog] + + return dict(sorted(blogs.items(), key=lambda x: x[0], reverse=True)) + + +@glossary_blueprint.route('/') +def glossary(): + return render_template( + "glossary.html", + rendered_markdown=render_markdown("general/glossary/glossary.md")), 200 + + +@references_blueprint.route('/') +def references(): + return render_template( + "references.html", + rendered_markdown=render_markdown("general/references/references.md")), 200 + + +@news_blueprint.route('/') +def news(): + return render_template( + "news.html", + rendered_markdown=render_markdown("general/news/news.md")), 200 + + +@environments_blueprint.route("/") +def environments(): + + md_file = get_file_from_python_search_path("wqflask/DEPENDENCIES.md") + svg_file = get_file_from_python_search_path( + "wqflask/dependency-graph.html") + svg_data = None + if svg_file: + with open(svg_file, 'r') as f: + svg_data = "".join( + BeautifulSoup(f.read(), + 'lxml').body.script.contents) + + if md_file is not None: + return ( + render_template("environment.html", + svg_data=svg_data, + rendered_markdown=render_markdown( + md_file, + is_remote_file=False)), + 200 + ) + # Fallback: Fetch file from server + return (render_template( + "environment.html", + svg_data=None, + rendered_markdown=render_markdown( + "general/environments/environments.md")), + 200) + + +@environments_blueprint.route('/svg-dependency-graph') +def svg_graph(): + directory, file_name, _ = get_file_from_python_search_path( + "wqflask/dependency-graph.svg").partition("dependency-graph.svg") + return send_from_directory(directory, file_name) + + +@links_blueprint.route("/") +def links(): + return render_template( + "links.html", + rendered_markdown=render_markdown("general/links/links.md")), 200 + + +@policies_blueprint.route("/") +def policies(): + return render_template( + "policies.html", + rendered_markdown=render_markdown("general/policies/policies.md")), 200 + + +@facilities_blueprint.route("/") +def facilities(): + return render_template("facilities.html", rendered_markdown=render_markdown("general/help/facilities.md")), 200 + + +@blogs_blueprint.route("/") +def display_blog(blog_path): + return render_template("blogs.html", rendered_markdown=render_markdown(blog_path)) + + +@blogs_blueprint.route("/") +def blogs_list(): + blogs = get_blogs() + + return render_template("blogs_list.html", blogs=blogs) diff --git a/wqflask/wqflask/markdown_routes.py b/wqflask/wqflask/markdown_routes.py deleted file mode 100644 index 580b9ac0..00000000 --- a/wqflask/wqflask/markdown_routes.py +++ /dev/null @@ -1,186 +0,0 @@ -"""Markdown routes - -Render pages from github, or if they are unavailable, look for it else where -""" - -import requests -import markdown -import os -import sys - -from bs4 import BeautifulSoup # type: ignore - -from flask import send_from_directory -from flask import Blueprint -from flask import render_template - -from typing import Dict -from typing import List - -glossary_blueprint = Blueprint('glossary_blueprint', __name__) -references_blueprint = Blueprint("references_blueprint", __name__) -environments_blueprint = Blueprint("environments_blueprint", __name__) -links_blueprint = Blueprint("links_blueprint", __name__) -policies_blueprint = Blueprint("policies_blueprint", __name__) -facilities_blueprint = Blueprint("facilities_blueprint", __name__) -news_blueprint = Blueprint("news_blueprint", __name__) - -blogs_blueprint = Blueprint("blogs_blueprint", __name__) - - -def render_markdown(file_name, is_remote_file=True): - """Try to fetch the file name from Github and if that fails, try to -look for it inside the file system """ - github_url = ("https://raw.githubusercontent.com/" - "genenetwork/gn-docs/master/") - - if not is_remote_file: - text = "" - with open(file_name, "r", encoding="utf-8") as input_file: - text = input_file.read() - return markdown.markdown(text, - extensions=['tables']) - - md_content = requests.get(f"{github_url}{file_name}") - - if md_content.status_code == 200: - return markdown.markdown(md_content.content.decode("utf-8"), - extensions=['tables']) - - return (f"\nContent for {file_name} not available. " - "Please check " - "(here to see where content exists)" - "[https://github.com/genenetwork/gn-docs]. " - "Please reach out to the gn2 team to have a look at this") - - -def get_file_from_python_search_path(pathname_suffix): - cands = [os.path.join(d, pathname_suffix) for d in sys.path] - try: - return list(filter(os.path.exists, cands))[0] - except IndexError: - return None - - -def get_blogs(user: str = "genenetwork", - repo_name: str = "gn-docs") -> dict: - - blogs: Dict[int, List] = {} - github_url = f"https://api.github.com/repos/{user}/{repo_name}/git/trees/master?recursive=1" - - repo_tree = requests.get(github_url).json()["tree"] - - for data in repo_tree: - path_name = data["path"] - if path_name.startswith("blog") and path_name.endswith(".md"): - split_path = path_name.split("/")[1:] - try: - year, title, file_name = split_path - except Exception as e: - year, file_name = split_path - title = "" - - subtitle = os.path.splitext(file_name)[0] - - blog = { - "title": title, - "subtitle": subtitle, - "full_path": path_name - } - - if year in blogs: - blogs[int(year)].append(blog) - else: - blogs[int(year)] = [blog] - - return dict(sorted(blogs.items(), key=lambda x: x[0], reverse=True)) - - -@glossary_blueprint.route('/') -def glossary(): - return render_template( - "glossary.html", - rendered_markdown=render_markdown("general/glossary/glossary.md")), 200 - - -@references_blueprint.route('/') -def references(): - return render_template( - "references.html", - rendered_markdown=render_markdown("general/references/references.md")), 200 - - -@news_blueprint.route('/') -def news(): - return render_template( - "news.html", - rendered_markdown=render_markdown("general/news/news.md")), 200 - - -@environments_blueprint.route("/") -def environments(): - - md_file = get_file_from_python_search_path("wqflask/DEPENDENCIES.md") - svg_file = get_file_from_python_search_path( - "wqflask/dependency-graph.html") - svg_data = None - if svg_file: - with open(svg_file, 'r') as f: - svg_data = "".join( - BeautifulSoup(f.read(), - 'lxml').body.script.contents) - - if md_file is not None: - return ( - render_template("environment.html", - svg_data=svg_data, - rendered_markdown=render_markdown( - md_file, - is_remote_file=False)), - 200 - ) - # Fallback: Fetch file from server - return (render_template( - "environment.html", - svg_data=None, - rendered_markdown=render_markdown( - "general/environments/environments.md")), - 200) - - -@environments_blueprint.route('/svg-dependency-graph') -def svg_graph(): - directory, file_name, _ = get_file_from_python_search_path( - "wqflask/dependency-graph.svg").partition("dependency-graph.svg") - return send_from_directory(directory, file_name) - - -@links_blueprint.route("/") -def links(): - return render_template( - "links.html", - rendered_markdown=render_markdown("general/links/links.md")), 200 - - -@policies_blueprint.route("/") -def policies(): - return render_template( - "policies.html", - rendered_markdown=render_markdown("general/policies/policies.md")), 200 - - -@facilities_blueprint.route("/") -def facilities(): - return render_template("facilities.html", rendered_markdown=render_markdown("general/help/facilities.md")), 200 - - -@blogs_blueprint.route("/") -def display_blog(blog_path): - return render_template("blogs.html", rendered_markdown=render_markdown(blog_path)) - - -@blogs_blueprint.route("/") -def blogs_list(): - blogs = get_blogs() - - return render_template("blogs_list.html", blogs=blogs) -- cgit v1.2.3