Skip to content

Commit 3a6d279

Browse files
committed
replaces library
1 parent 0a16428 commit 3a6d279

File tree

2 files changed

+208
-1
lines changed

2 files changed

+208
-1
lines changed

services/web/server/src/simcore_service_webserver/publications/_handlers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from aiohttp import MultipartReader, hdrs, web
44
from common_library.json_serialization import json_dumps
5-
from json2html import json2html # type: ignore[import-untyped]
65
from servicelib.aiohttp import status
76
from servicelib.mimetype_constants import (
87
MIMETYPE_APPLICATION_JSON,
@@ -15,6 +14,7 @@
1514
from ..login.storage import AsyncpgStorage, get_plugin_storage
1615
from ..login.utils_email import AttachmentTuple, send_email_from_template, themed
1716
from ..products import products_web
17+
from ._utils import json2html
1818

1919
_logger = logging.getLogger(__name__)
2020

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
"""
2+
JSON 2 HTML Converter
3+
=====================
4+
5+
(c) Varun Malhotra 2013
6+
Source Code: https://github.com/softvar/json2html
7+
8+
9+
Contributors:
10+
-------------
11+
1. Michel Müller (@muellermichel), https://github.com/softvar/json2html/pull/2
12+
2. Daniel Lekic (@lekic), https://github.com/softvar/json2html/pull/17
13+
14+
LICENSE: MIT
15+
--------
16+
"""
17+
18+
# NOTE:
19+
#
20+
# Snapshot of https://github.com/softvar/json2html/blob/0a223c7b3e5dce286811fb12bbab681e7212ebfe/json2html/jsonconv.py
21+
# to avoid failure to install this module with `setuptools 78.0.1` due to
22+
# deprecated feature that this library still uses
23+
#
24+
25+
import sys
26+
27+
if sys.version_info[:2] < (2, 7):
28+
import simplejson as json_parser
29+
from ordereddict import OrderedDict
30+
else:
31+
import json as json_parser
32+
from collections import OrderedDict
33+
34+
if sys.version_info[:2] < (3, 0):
35+
from cgi import escape as html_escape
36+
37+
text = unicode
38+
text_types = (unicode, str)
39+
else:
40+
from html import escape as html_escape
41+
42+
text = str
43+
text_types = (str,)
44+
45+
46+
class Json2Html:
47+
def convert(
48+
self,
49+
json="",
50+
table_attributes='border="1"',
51+
clubbing=True,
52+
encode=False,
53+
escape=True,
54+
):
55+
"""
56+
Convert JSON to HTML Table format
57+
"""
58+
# table attributes such as class, id, data-attr-*, etc.
59+
# eg: table_attributes = 'class = "table table-bordered sortable"'
60+
self.table_init_markup = "<table %s>" % table_attributes
61+
self.clubbing = clubbing
62+
self.escape = escape
63+
json_input = None
64+
if not json:
65+
json_input = {}
66+
elif type(json) in text_types:
67+
try:
68+
json_input = json_parser.loads(json, object_pairs_hook=OrderedDict)
69+
except ValueError as e:
70+
# so the string passed here is actually not a json string
71+
# - let's analyze whether we want to pass on the error or use the string as-is as a text node
72+
if "Expecting property name" in text(e):
73+
# if this specific json loads error is raised, then the user probably actually wanted to pass json, but made a mistake
74+
raise e
75+
json_input = json
76+
else:
77+
json_input = json
78+
converted = self.convert_json_node(json_input)
79+
if encode:
80+
return converted.encode("ascii", "xmlcharrefreplace")
81+
return converted
82+
83+
def column_headers_from_list_of_dicts(self, json_input):
84+
"""
85+
This method is required to implement clubbing.
86+
It tries to come up with column headers for your input
87+
"""
88+
if (
89+
not json_input
90+
or not hasattr(json_input, "__getitem__")
91+
or not hasattr(json_input[0], "keys")
92+
):
93+
return None
94+
column_headers = json_input[0].keys()
95+
for entry in json_input:
96+
if (
97+
not hasattr(entry, "keys")
98+
or not hasattr(entry, "__iter__")
99+
or len(entry.keys()) != len(column_headers)
100+
):
101+
return None
102+
for header in column_headers:
103+
if header not in entry:
104+
return None
105+
return column_headers
106+
107+
def convert_json_node(self, json_input):
108+
"""
109+
Dispatch JSON input according to the outermost type and process it
110+
to generate the super awesome HTML format.
111+
We try to adhere to duck typing such that users can just pass all kinds
112+
of funky objects to json2html that *behave* like dicts and lists and other
113+
basic JSON types.
114+
"""
115+
if type(json_input) in text_types:
116+
if self.escape:
117+
return html_escape(text(json_input))
118+
else:
119+
return text(json_input)
120+
if hasattr(json_input, "items"):
121+
return self.convert_object(json_input)
122+
if hasattr(json_input, "__iter__") and hasattr(json_input, "__getitem__"):
123+
return self.convert_list(json_input)
124+
return text(json_input)
125+
126+
def convert_list(self, list_input):
127+
"""
128+
Iterate over the JSON list and process it
129+
to generate either an HTML table or a HTML list, depending on what's inside.
130+
If suppose some key has array of objects and all the keys are same,
131+
instead of creating a new row for each such entry,
132+
club such values, thus it makes more sense and more readable table.
133+
134+
@example:
135+
jsonObject = {
136+
"sampleData": [
137+
{"a":1, "b":2, "c":3},
138+
{"a":5, "b":6, "c":7}
139+
]
140+
}
141+
OUTPUT:
142+
_____________________________
143+
| | | | |
144+
| | a | c | b |
145+
| sampleData |---|---|---|
146+
| | 1 | 3 | 2 |
147+
| | 5 | 7 | 6 |
148+
-----------------------------
149+
150+
@contributed by: @muellermichel
151+
"""
152+
if not list_input:
153+
return ""
154+
converted_output = ""
155+
column_headers = None
156+
if self.clubbing:
157+
column_headers = self.column_headers_from_list_of_dicts(list_input)
158+
if column_headers is not None:
159+
converted_output += self.table_init_markup
160+
converted_output += "<thead>"
161+
converted_output += (
162+
"<tr><th>" + "</th><th>".join(column_headers) + "</th></tr>"
163+
)
164+
converted_output += "</thead>"
165+
converted_output += "<tbody>"
166+
for list_entry in list_input:
167+
converted_output += "<tr><td>"
168+
converted_output += "</td><td>".join(
169+
[
170+
self.convert_json_node(list_entry[column_header])
171+
for column_header in column_headers
172+
]
173+
)
174+
converted_output += "</td></tr>"
175+
converted_output += "</tbody>"
176+
converted_output += "</table>"
177+
return converted_output
178+
179+
# so you don't want or need clubbing eh? This makes @muellermichel very sad... ;(
180+
# alright, let's fall back to a basic list here...
181+
converted_output = "<ul><li>"
182+
converted_output += "</li><li>".join(
183+
[self.convert_json_node(child) for child in list_input]
184+
)
185+
converted_output += "</li></ul>"
186+
return converted_output
187+
188+
def convert_object(self, json_input):
189+
"""
190+
Iterate over the JSON object and process it
191+
to generate the super awesome HTML Table format
192+
"""
193+
if not json_input:
194+
return "" # avoid empty tables
195+
converted_output = self.table_init_markup + "<tr>"
196+
converted_output += "</tr><tr>".join(
197+
[
198+
"<th>%s</th><td>%s</td>"
199+
% (self.convert_json_node(k), self.convert_json_node(v))
200+
for k, v in json_input.items()
201+
]
202+
)
203+
converted_output += "</tr></table>"
204+
return converted_output
205+
206+
207+
json2html = Json2Html()

0 commit comments

Comments
 (0)