Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for json-based widgets/mashups #540

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add json support
dmunozv04 committed Mar 25, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit fb76d2c1ba353f2bdb1e286d388a3629a7d82698
1 change: 1 addition & 0 deletions src/requirements.txt
Original file line number Diff line number Diff line change
@@ -17,3 +17,4 @@ pyScss>=1.3.4,<2.0
Pygments
pillow
jsonpatch
jsonschema
14 changes: 7 additions & 7 deletions src/wirecloud/catalogue/fixtures/catalogue_search_data.json
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@
"popularity": "0",
"vendor": "Wirecloud",
"short_name": "Test",
"json_description": "{\"name\": \"Test\", \"vendor\": \"Wirecloud\", \"version\": \"1.5\", \"type\": \"widget\", \"title\": \"Incredible Test\", \"description\": \"This widget contains keywords like term mashable application component.\", \"wiring\": {\"inputs\": [{\"friendcode\": \"test-data\", \"actionlabel\": \"\", \"name\": \"inputendpoint\", \"label\": \"Input\", \"type\": \"text\", \"description\": \"input type text\"}], \"outputs\": [{\"friendcode\": \"test-data\", \"description\": \"output digit\", \"type\": \"text\", \"name\": \"outputendpoint\", \"label\": \"Output\"}]}, \"contents\": {\"src\": \"test.html\"}}",
"json_description": "{\"name\": \"Test\", \"vendor\": \"Wirecloud\", \"version\": \"1.5\", \"type\": \"widget\", \"title\": \"Incredible Test\", \"description\": \"This widget contains keywords like term mashable application component.\", \"wiring\": {\"inputs\": [{\"friendcode\": \"test-data\", \"actionlabel\": \"\", \"name\": \"inputendpoint\", \"label\": \"Input\", \"type\": \"text\", \"description\": \"input type text\"}], \"outputs\": [{\"friendcode\": \"test-data\", \"description\": \"output digit\", \"type\": \"text\", \"name\": \"outputendpoint\", \"label\": \"Output\"}]}, \"contents\": {\"src\": \"test.html\"}, \"widget_width\": \"4\", \"widget_height\": \"4\"}",
"creator": 80,
"creation_date": "2011-05-12T11:24:03Z",
"version": "1.5",
@@ -95,7 +95,7 @@
"popularity": "0",
"vendor": "Wirecloud",
"short_name": "Test",
"json_description": "{\"name\": \"Test\", \"vendor\": \"Wirecloud\", \"version\": \"2.0\", \"type\": \"widget\", \"title\": \"New Incredible Test\", \"description\": \"This widget contains keywords like prefix mashable application component.\", \"contents\": {\"src\": \"test.html\"}}",
"json_description": "{\"name\": \"Test\", \"vendor\": \"Wirecloud\", \"version\": \"2.0\", \"type\": \"widget\", \"title\": \"New Incredible Test\", \"description\": \"This widget contains keywords like prefix mashable application component.\", \"contents\": {\"src\": \"test.html\"}, \"widget_width\": \"4\", \"widget_height\": \"4\"}",
"creator": 80,
"creation_date": "2011-05-13T11:24:03Z",
"version": "2.0",
@@ -113,7 +113,7 @@
"popularity": "0",
"vendor": "Wirecloud",
"short_name": "Test",
"json_description": "{\"name\": \"Test\", \"vendor\": \"Wirecloud\", \"version\": \"2.5\", \"type\": \"widget\", \"title\": \"The Best Incredible Test\", \"description\": \"This widget contains keywords regex mashable application component.\", \"contents\": {\"src\": \"test.html\"}}",
"json_description": "{\"name\": \"Test\", \"vendor\": \"Wirecloud\", \"version\": \"2.5\", \"type\": \"widget\", \"title\": \"The Best Incredible Test\", \"description\": \"This widget contains keywords regex mashable application component.\", \"contents\": {\"src\": \"test.html\"}, \"widget_width\": \"4\", \"widget_height\": \"4\"}",
"creator": 80,
"creation_date": "2011-05-14T11:24:03Z",
"version": "2.5",
@@ -131,7 +131,7 @@
"popularity": "0",
"vendor": "CoNWeT-Lab",
"short_name": "Clock_Now",
"json_description": "{\"name\": \"Clock_Now\", \"vendor\": \"CoNWeT-Lab\", \"version\": \"1.5\", \"type\": \"widget\", \"title\": \"Clock Now\", \"description\": \"This WireCloud widget contains keywords like free button bluetooth.\", \"contents\": {\"src\": \"test.html\"}}",
"json_description": "{\"name\": \"Clock_Now\", \"vendor\": \"CoNWeT-Lab\", \"version\": \"1.5\", \"type\": \"widget\", \"title\": \"Clock Now\", \"description\": \"This WireCloud widget contains keywords like free button bluetooth.\", \"contents\": {\"src\": \"test.html\"}, \"widget_width\": \"4\", \"widget_height\": \"4\"}",
"creator": 80,
"creation_date": "2011-05-15T11:24:03Z",
"version": "1.5",
@@ -149,7 +149,7 @@
"popularity": "0",
"vendor": "CoNWeT-Lab",
"short_name": "Clock_Now",
"json_description": "{\"name\": \"Clock_Now\", \"vendor\": \"CoNWeT-Lab\", \"version\": \"1.11\", \"type\": \"widget\", \"title\": \"Last Clock Now\", \"description\": \"This WireCloud widget contains keywords like free button bluetooth.\", \"contents\": {\"src\": \"test.html\"}}",
"json_description": "{\"name\": \"Clock_Now\", \"vendor\": \"CoNWeT-Lab\", \"version\": \"1.11\", \"type\": \"widget\", \"title\": \"Last Clock Now\", \"description\": \"This WireCloud widget contains keywords like free button bluetooth.\", \"contents\": {\"src\": \"test.html\"}, \"widget_width\": \"4\", \"widget_height\": \"4\"}",
"creator": 80,
"creation_date": "2011-05-16T11:24:03Z",
"version": "1.11",
@@ -347,7 +347,7 @@
"popularity": "0",
"vendor": "Wirecloud",
"short_name": "Book-Reader",
"json_description": "{\"name\": \"Book-Reader\", \"vendor\": \"Wirecloud\", \"version\": \"1.5\", \"type\": \"widget\", \"title\": \"The Best Incredible Test\", \"description\": \"This widget contains keywords wiredrawers wiretappers wirephoto wirework wireway wired wireless.\", \"contents\": {\"src\": \"test.html\"}}",
"json_description": "{\"name\": \"Book-Reader\", \"vendor\": \"Wirecloud\", \"version\": \"1.5\", \"type\": \"widget\", \"title\": \"The Best Incredible Test\", \"description\": \"This widget contains keywords wiredrawers wiretappers wirephoto wirework wireway wired wireless.\", \"contents\": {\"src\": \"test.html\"}, \"widget_width\": \"4\", \"widget_height\": \"4\"}",
"creator": 80,
"creation_date": "2011-05-27T11:24:03Z",
"version": "1.5",
@@ -365,7 +365,7 @@
"popularity": "0",
"vendor": "CoNWeT-Lab",
"short_name": "Live_Sports",
"json_description": "{\"name\": \"Live_Sports\", \"vendor\": \"CoNWeT-Lab\", \"version\": \"1.0\", \"type\": \"widget\", \"title\": \"Live Sports\", \"description\": \"This widget contains keywords like free button bluetooth.\", \"contents\": {\"src\": \"test.html\"}}",
"json_description": "{\"name\": \"Live_Sports\", \"vendor\": \"CoNWeT-Lab\", \"version\": \"1.0\", \"type\": \"widget\", \"title\": \"Live Sports\", \"description\": \"This widget contains keywords like free button bluetooth.\", \"contents\": {\"src\": \"test.html\"}, \"widget_width\": \"4\", \"widget_height\": \"4\"}",
"creator": 80,
"creation_date": "2011-05-28T11:24:03Z",
"version": "1.0",
6 changes: 5 additions & 1 deletion src/wirecloud/commons/utils/template/parsers/json.py
Original file line number Diff line number Diff line change
@@ -19,13 +19,17 @@
# along with Wirecloud. If not, see <http://www.gnu.org/licenses/>.

import json
import os

from django.utils.translation import ugettext as _

from wirecloud.commons.utils.template.base import is_valid_name, is_valid_vendor, is_valid_version, parse_contacts_info, TemplateParseException
from wirecloud.commons.utils.translation import get_trans_index
from wirecloud.platform.wiring.utils import get_wiring_skeleton, parse_wiring_old_version
from jsonschema import validate

with open(os.path.join(os.path.dirname(__file__), '../schemas/json_schema.schema.json'), 'r') as JSONSCHEMA_FILE:
JSONSCHEMA = json.load(JSONSCHEMA_FILE)

class JSONTemplateParser(object):

@@ -189,7 +193,7 @@ def _add_translation_index(self, value, **kwargs):
self._info['translation_index_usage'][index].append(kwargs)

def _init(self):

validate(self._info, JSONSCHEMA)
self._check_string_fields(('title', 'description', 'longdescription', 'email', 'homepage', 'doc', 'changelog', 'image', 'smartphoneimage', 'license', 'licenseurl', 'issuetracker'))
self._check_contacts_fields(('authors', 'contributors'))
self._check_integer_fields(('macversion', ), default = 1)
1,218 changes: 1,218 additions & 0 deletions src/wirecloud/commons/utils/template/schemas/json_schema.schema.json

Large diffs are not rendered by default.

22 changes: 15 additions & 7 deletions src/wirecloud/commons/utils/wgt.py
Original file line number Diff line number Diff line change
@@ -38,8 +38,8 @@ def __str__(self):


class WgtFile(object):

_template_filename = 'config.xml'
_possible_template_filenames = ['config.xml', 'config.json']
_template_filename = None

def __init__(self, _file):
self._zip = zipfile.ZipFile(_file)
@@ -49,6 +49,7 @@ def __init__(self, _file):
raise ValueError('Invalid file name: %s', filename)
if normalized_filename.startswith('/'):
raise ValueError('Invalid absolute file name: %s', filename)
self._set_template_filename()

@property
def namelist(self):
@@ -60,11 +61,18 @@ def get_underlying_file(self):
def read(self, path):
return self._zip.read(path)

def _set_template_filename(self):
for possible_template_file in self._possible_template_filenames:
if possible_template_file in self._zip.namelist():
self._template_filename = possible_template_file
return

def get_template(self):
try:
return self.read(self._template_filename)
template_file_content = self.read(self._template_filename)
return template_file_content
except KeyError:
raise InvalidContents('Missing config.xml at the root of the zipfile (wgt)')
raise InvalidContents('Missing config.xml or config.json at the root of the zipfile (wgt)')

def extract_file(self, file_name, output_path, recreate_=False):
contents = self.read(file_name)
@@ -147,13 +155,13 @@ def update_config(self, contents):
new_fp = BytesIO()

# Copy every file from the original zipfile to the new one
# excluding the config.xml file, that will be replaced
filename = 'config.xml'
# excluding the config file, that will be replaced
filename = self._template_filename
with zipfile.ZipFile(new_fp, 'w') as zout:
zout.comment = self._zip.comment # preserve the comment

for item in self._zip.infolist():
# Copy new config.xml contents
# Copy new config contents
if item.filename == filename:
zout.writestr(item, contents)
# Copy original files
5 changes: 3 additions & 2 deletions src/wirecloud/platform/workspace/mashupTemplateGenerator.py
Original file line number Diff line number Diff line change
@@ -180,12 +180,12 @@ def build_json_template_from_workspace(options, workspace, user):
options['description'] = get_workspace_description(workspace)

if 'authors' not in options:
options['authors'] = ({'name': str(user)},)
options['authors'] = [{'name': str(user)}]
elif isinstance(options['authors'], str):
options['authors'] = parse_contacts_info(options['authors'])

if 'contributors' not in options:
options['contributors'] = ()
options['contributors'] = []
elif isinstance(options['contributors'], str):
options['contributors'] = parse_contacts_info(options['contributors'])

@@ -252,6 +252,7 @@ def build_json_template_from_workspace(options, workspace, user):
options['wiring']['operators'] = {}
for operator_id, operator in wiring_status['operators'].items():
operator_data = {
'id': operator_id,
'name': operator['name'],
'preferences': {},
}
4 changes: 2 additions & 2 deletions src/wirecloud/platform/workspace/views.py
Original file line number Diff line number Diff line change
@@ -483,12 +483,12 @@ def create(self, request, workspace_id):
extra_files.append(('DESCRIPTION.md', BytesIO(options['longdescription'].encode('utf-8'))))
options['longdescription'] = 'DESCRIPTION.md'

description = build_xml_template_from_workspace(options, workspace, request.user)
description = build_json_template_from_workspace(options, workspace, request.user)

# Build mashup wgt file
f = BytesIO()
zf = zipfile.ZipFile(f, 'w')
zf.writestr('config.xml', description.encode('utf-8'))
zf.writestr('config.json', json.dumps(description, indent = 4))
for filename, extra_file in extra_files:
zf.writestr(filename, extra_file.read())
for resource_info in options['embedded']:

Unchanged files with check annotations Beta

parsed_url = urlparse(url)
if parsed_url.scheme not in self._servers or parsed_url.netloc not in self._servers[parsed_url.scheme]:
raise URLError('not valid')

Check failure on line 251 in src/wirecloud/commons/utils/testcases.py

GitHub Actions / django-selenium-tests

not valid

Check failure on line 251 in src/wirecloud/commons/utils/testcases.py

GitHub Actions / django-selenium-tests

not valid

Check failure on line 251 in src/wirecloud/commons/utils/testcases.py

GitHub Actions / django-selenium-tests

not valid

Check failure on line 251 in src/wirecloud/commons/utils/testcases.py

GitHub Actions / django-selenium-tests

not valid

Check failure on line 251 in src/wirecloud/commons/utils/testcases.py

GitHub Actions / django-selenium-tests

not valid
server = self._servers[parsed_url.scheme][parsed_url.netloc]
return server.request(method, url, *args, **kwargs)