From 4c1664295357fb33cfdbbceb4254da8a7588fa99 Mon Sep 17 00:00:00 2001 From: Alessio Izzo Date: Wed, 31 Jul 2024 10:24:04 +0200 Subject: [PATCH 1/5] refactor DatasetScript by adding a base class that is going to be used also for system scripts --- scrunch/datasets.py | 8 +++----- scrunch/scripts.py | 23 +++++++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/scrunch/datasets.py b/scrunch/datasets.py index 1c17c51..7d58b91 100644 --- a/scrunch/datasets.py +++ b/scrunch/datasets.py @@ -33,14 +33,13 @@ from scrunch.expressions import parse_expr, prettify, process_expr from scrunch.folders import DatasetFolders from scrunch.views import DatasetViews -from scrunch.scripts import DatasetScripts, ScriptExecutionError +from scrunch.scripts import ScriptExecutionError from scrunch.helpers import (ReadOnly, _validate_category_rules, abs_url, case_expr, download_file, shoji_entity_wrapper, subvar_alias, validate_categories, shoji_catalog_wrapper, get_else_case, else_case_not_selected, SELECTED_ID, NOT_SELECTED_ID, NO_DATA_ID, valid_categorical_date, - shoji_view_wrapper, make_unique, - generate_subvariable_codes) + shoji_view_wrapper, generate_subvariable_codes) from scrunch.order import DatasetVariablesOrder, ProjectDatasetsOrder from scrunch.subentity import Deck, Filter, Multitable from scrunch.variables import (combinations_from_map, combine_categories_expr, @@ -836,7 +835,6 @@ def __init__(self, resource): # of the multiple inheritance, we just initiate self._vars here self._reload_variables() self.folders = DatasetFolders(self) - self.scripts = DatasetScripts(self.resource) def __getattr__(self, item): if item in self._ENTITY_ATTRIBUTES: @@ -2224,7 +2222,7 @@ def export(self, path, format='csv', filter=None, variables=None, % (format, ','.join(k)) ) if 'var_label_field' in options \ - and not options['var_label_field'] in ('name', 'description'): + and options['var_label_field'] not in ('name', 'description'): raise ValueError( 'The "var_label_field" export option must be either "name" ' 'or "description".' diff --git a/scrunch/scripts.py b/scrunch/scripts.py index 6f924dd..20b6e29 100644 --- a/scrunch/scripts.py +++ b/scrunch/scripts.py @@ -17,12 +17,12 @@ def __repr__(self): DEFAULT_SUBVARIABLE_SYNTAX = False -class DatasetScripts: - def __init__(self, dataset_resource): +class Scripts: + def __init__(self, resource): """ - :param dataset_resource: Pycrunch Entity for the dataset. + :param resource: Pycrunch Entity. """ - self.dataset_resource = dataset_resource + self.resource = resource def get_default_syntax_flag(self, strict_subvariable_syntax): """ @@ -44,19 +44,22 @@ def get_default_syntax_flag(self, strict_subvariable_syntax): """ if strict_subvariable_syntax is not None: return strict_subvariable_syntax - flags = self.dataset_resource.session.feature_flags + flags = self.resource.session.feature_flags return flags.get("clients_strict_subvariable_syntax", DEFAULT_SUBVARIABLE_SYNTAX) + +class DatasetScripts(Scripts): + def execute(self, script_body, strict_subvariable_syntax=None, dry_run=False): strict_subvariable_syntax = self.get_default_syntax_flag(strict_subvariable_syntax) payload = { "body": script_body, "strict_subvariable_syntax": strict_subvariable_syntax } - method = self.dataset_resource.scripts.create + method = self.resource.scripts.create if dry_run: payload["dry_run"] = True - method = self.dataset_resource.scripts.post + method = self.resource.scripts.post try: method({'element': 'shoji:entity', 'body': payload}) except pycrunch.ClientError as err: @@ -79,10 +82,10 @@ def collapse(self): all the previously executed scripts into one the first. It will delete all savepoints associated with the collapsed scripts. """ - self.dataset_resource.scripts.collapse.post({}) + self.resource.scripts.collapse.post({}) def all(self): - scripts_index = self.dataset_resource.scripts.index + scripts_index = self.resource.scripts.index scripts = [] for s_url, s in scripts_index.items(): scripts.append(s.entity) @@ -101,4 +104,4 @@ def revert_to(self, id=None, script_number=None): raise ValueError("Must indicate either ID or script number") resp = script.revert.post({}) # Asynchronous request - pycrunch.shoji.wait_progress(resp, self.dataset_resource.session) + pycrunch.shoji.wait_progress(resp, self.resource.session) From 98c4702d0a6935a2a4c3ca956134900369675631 Mon Sep 17 00:00:00 2001 From: Alessio Izzo Date: Wed, 31 Jul 2024 12:24:33 +0200 Subject: [PATCH 2/5] add execute for system scripts with strict_subvariable_syntax flag --- scrunch/accounts.py | 19 +++++-------------- scrunch/datasets.py | 24 +++++------------------- scrunch/scripts.py | 34 ++++++++++++++++++++++++++++++++-- scrunch/tests/test_accounts.py | 17 +++++++++++++++++ 4 files changed, 59 insertions(+), 35 deletions(-) diff --git a/scrunch/accounts.py b/scrunch/accounts.py index dea5859..afc227f 100644 --- a/scrunch/accounts.py +++ b/scrunch/accounts.py @@ -2,7 +2,7 @@ import pycrunch from scrunch.helpers import shoji_view_wrapper -from scrunch.scripts import ScriptExecutionError +from scrunch.scripts import ScriptExecutionError, SystemScript from scrunch.connections import _default_connection from scrunch.datasets import Project @@ -50,20 +50,11 @@ def current_account(cls, connection=None): act_res = site_root.account return cls(act_res) - def execute(self, script_body): - """ - Will run a system script on this account. - - System scripts do not have a return value. If they execute correctly - they'll finish silently. Otherwise an error will raise. - """ + def execute(self, script_body, strict_subvariable_syntax=None): + """Will run a system script on this account.""" # The account execution endpoint is a shoji:view - payload = shoji_view_wrapper(script_body) - try: - self.resource.execute.post(payload) - except pycrunch.ClientError as err: - resolutions = err.args[2]["resolutions"] - raise ScriptExecutionError(err, resolutions) + system_script = SystemScript(self.resource) + system_script.execute(script_body, strict_subvariable_syntax) @property def projects(self): diff --git a/scrunch/datasets.py b/scrunch/datasets.py index 7d58b91..ae151ce 100644 --- a/scrunch/datasets.py +++ b/scrunch/datasets.py @@ -33,7 +33,7 @@ from scrunch.expressions import parse_expr, prettify, process_expr from scrunch.folders import DatasetFolders from scrunch.views import DatasetViews -from scrunch.scripts import ScriptExecutionError +from scrunch.scripts import ScriptExecutionError, SystemScript from scrunch.helpers import (ReadOnly, _validate_category_rules, abs_url, case_expr, download_file, shoji_entity_wrapper, subvar_alias, validate_categories, shoji_catalog_wrapper, @@ -453,25 +453,11 @@ def __repr__(self): def __str__(self): return self.name - def execute(self, script_body): - """ - Will run a system script on this project. - - System scripts do not have a return value. If they execute correctly - they'll finish silently. Otherwise an error will raise. - """ + def execute(self, script_body, strict_subvariable_syntax=None): + """Will run a system script on this project.""" # The project execution endpoint is a shoji:view - payload = shoji_view_wrapper(script_body) - if "run" in self.resource.views: - exc_res = self.resource.run # Backwards compat og API - else: - exc_res = self.resource.execute - - try: - exc_res.post(payload) - except pycrunch.ClientError as err: - resolutions = err.args[2]["resolutions"] - raise ScriptExecutionError(err, resolutions) + system_script = SystemScript(self.resource) + system_script.execute(script_body, strict_subvariable_syntax) @property def members(self): diff --git a/scrunch/scripts.py b/scrunch/scripts.py index 20b6e29..2d98d13 100644 --- a/scrunch/scripts.py +++ b/scrunch/scripts.py @@ -4,6 +4,8 @@ import pycrunch from pycrunch.shoji import TaskError +from scrunch.helpers import shoji_view_wrapper + class ScriptExecutionError(Exception): def __init__(self, client_error, resolutions): @@ -17,7 +19,7 @@ def __repr__(self): DEFAULT_SUBVARIABLE_SYNTAX = False -class Scripts: +class BaseScript: def __init__(self, resource): """ :param resource: Pycrunch Entity. @@ -47,8 +49,36 @@ def get_default_syntax_flag(self, strict_subvariable_syntax): flags = self.resource.session.feature_flags return flags.get("clients_strict_subvariable_syntax", DEFAULT_SUBVARIABLE_SYNTAX) + def execute(self, script_body, strict_subvariable_syntax=None): + pass + + +class SystemScript(BaseScript): + + def format_request_url(self, execute, strict_subvariable_syntax=None): + strict_subvariable_syntax_flag = self.get_default_syntax_flag(strict_subvariable_syntax) + if strict_subvariable_syntax_flag: + execute.self = "{}?strict_subvariable_syntax=true".format(self.resource.self) + + def execute(self, script_body, strict_subvariable_syntax=None): + """ + Will run a system script on this. + + System scripts do not have a return value. If they execute correctly + they'll finish silently. Otherwise, an error will raise. + """ + # The project execution endpoint is a shoji:view + payload = shoji_view_wrapper(script_body) + try: + execute = self.resource.execute + self.format_request_url(execute, strict_subvariable_syntax) + execute.post(payload) + except pycrunch.ClientError as err: + resolutions = err.args[2]["resolutions"] + raise ScriptExecutionError(err, resolutions) + -class DatasetScripts(Scripts): +class DatasetScripts(BaseScript): def execute(self, script_body, strict_subvariable_syntax=None, dry_run=False): strict_subvariable_syntax = self.get_default_syntax_flag(strict_subvariable_syntax) diff --git a/scrunch/tests/test_accounts.py b/scrunch/tests/test_accounts.py index 3c097e2..5158da4 100644 --- a/scrunch/tests/test_accounts.py +++ b/scrunch/tests/test_accounts.py @@ -71,6 +71,23 @@ def test_execute(self): "value": "NOOP;" } + def test_execute_script_with_syntax_subvariable_flag(self): + session = self.make_session() + + response = Response() + response.status_code = 204 + + session.add_post_response(response) + current_act = Account.current_account(session.root) + + current_act.execute("NOOP;", strict_subvariable_syntax=True) + post_request = session.requests[-1] + assert json.loads(post_request.body) == { + "element": "shoji:view", + "value": "NOOP;" + } + assert "?strict_subvariable_syntax=true" in post_request.url + def test_projects(self): session = self.make_session() projects_url = "http://host/api/account/projects/" From 86b3b7337d498c057c8f1af443d5aa056cc1073e Mon Sep 17 00:00:00 2001 From: Alessio Izzo Date: Wed, 31 Jul 2024 16:09:47 +0200 Subject: [PATCH 3/5] add integration tests for system script with flag --- integration/test_scripts.py | 178 ++++++++++++++++++++++++++++++------ scrunch/datasets.py | 7 +- scrunch/scripts.py | 4 +- 3 files changed, 158 insertions(+), 31 deletions(-) diff --git a/integration/test_scripts.py b/integration/test_scripts.py index 625d452..49e425f 100644 --- a/integration/test_scripts.py +++ b/integration/test_scripts.py @@ -1,14 +1,136 @@ # coding: utf-8 +import os +from datetime import datetime + import pytest -from pycrunch.shoji import as_entity +from pycrunch.shoji import as_entity, wait_progress, TaskError +from scrunch.datasets import Project +from scrunch.helpers import shoji_entity_wrapper from scrunch.scripts import ScriptExecutionError from scrunch.mutable_dataset import get_mutable_dataset from fixtures import BaseIntegrationTestCase -class TestScripts(BaseIntegrationTestCase): +@pytest.mark.skipif(os.environ.get("LOCAL_INTEGRATION") is None, reason="Do not run this test during CI/CD") +class TestSystemScripts(BaseIntegrationTestCase): + def new_project(self, name): + res = self.site.projects.create(shoji_entity_wrapper({ + "name": name + datetime.now().strftime("%Y%m%d%H%M%S") + })).refresh() + return Project(res) + + def test_define_view_strict_subvariable_syntax(self): + project = self.new_project("test_view_strict_subvariable") + ds = self.site.datasets.create(as_entity({"name": "test_dataset_script"})).refresh() + categories = [ + {"id": 2, "name": "Home"}, + {"id": 3, "name": "Work"}, + {"id": -1, "name": "No Data", "missing": True}, + ] + subvariables = [ + {"alias": "cat", "name": "Cat"}, + {"alias": "dog", "name": "Dog"}, + {"alias": "bird", "name": "Bird"}, + ] + + ds.variables.create( + as_entity( + dict( + alias="pets", + name="Pets", + type="categorical_array", + categories=categories, + subvariables=subvariables, + values=[[2, 3, 3], [3, 3, 2], [2, -1, 3], [3, 2, -1]], + ) + ) + ) + ds.variables.create( + as_entity( + dict( + alias="pets_2", + name="Pets 2", + type="categorical_array", + categories=categories, + subvariables=subvariables, + values=[[2, 3, 3], [3, 3, 2], [2, -1, 3], [3, 2, -1]], + ) + ) + ) + script_body = """ + DEFINE VIEW FROM DATASET_ID(`{}`) + VARIABLES pets, pets_2 + NAME "My view"; + """.format(ds.body.id) + + scrunch_dataset = get_mutable_dataset(ds.body.id, self.site) + project.move_here([scrunch_dataset]) + project.execute(script_body, strict_subvariable_syntax=True) + view = scrunch_dataset.views.get_by_name("My view") + assert view.project.name == project.name + + def test_define_view_strict_subvariable_syntax_error(self): + project = self.new_project("test_view_strict_subvariable_false") + ds = self.site.datasets.create(as_entity({"name": "test_dataset_script_false"})).refresh() + categories = [ + {"id": 2, "name": "Home"}, + {"id": 3, "name": "Work"}, + {"id": -1, "name": "No Data", "missing": True}, + ] + subvariables = [ + {"alias": "cat", "name": "Cat"}, + {"alias": "dog", "name": "Dog"}, + {"alias": "bird", "name": "Bird"}, + ] + + ds.variables.create( + as_entity( + dict( + alias="pets", + name="Pets", + type="categorical_array", + categories=categories, + subvariables=subvariables, + values=[[2, 3, 3], [3, 3, 2], [2, -1, 3], [3, 2, -1]], + ) + ) + ) + ds.variables.create( + as_entity( + dict( + alias="pets_2", + name="Pets 2", + type="categorical_array", + categories=categories, + subvariables=subvariables, + values=[[2, 3, 3], [3, 3, 2], [2, -1, 3], [3, 2, -1]], + ) + ) + ) + script_body = """ + DEFINE VIEW FROM DATASET_ID(`{}`) + VARIABLES pets, pets_2 + NAME "My view"; + """.format(ds.body.id) + + try: + scrunch_dataset = get_mutable_dataset(ds.body.id, self.site) + project.move_here([scrunch_dataset]) + resp = project.execute(script_body) + with pytest.raises(TaskError) as err: + wait_progress(resp, self.site.session) + err_value = err.value[0] + err_value["type"] == "script:validation" + err_value["description"] == "Errors processing the script" + err_value["resolutions"][0]["message"] == "The following subvariables: bird, cat, dog exist in multiple arrays: pets, pets_2" + finally: + ds.delete() + project.delete() + + +class TestDatasetScripts(BaseIntegrationTestCase): def _create_ds(self): ds = self.site.datasets.create(as_entity({"name": "test_script"})).refresh() variable = ds.variables.create( @@ -24,17 +146,19 @@ def _create_ds(self): def test_execute(self): ds, variable = self._create_ds() - scrunch_dataset = get_mutable_dataset(ds.body.id, self.site, editor=True) - script = """ - RENAME pk TO varA; + try: + scrunch_dataset = get_mutable_dataset(ds.body.id, self.site, editor=True) + script = """ + RENAME pk TO varA; - CHANGE TITLE IN varA WITH "Variable A"; - """ - scrunch_dataset.scripts.execute(script) - variable.refresh() - assert variable.body["alias"] == "varA" - assert variable.body["name"] == "Variable A" - ds.delete() + CHANGE TITLE IN varA WITH "Variable A"; + """ + scrunch_dataset.scripts.execute(script) + variable.refresh() + assert variable.body["alias"] == "varA" + assert variable.body["name"] == "Variable A" + finally: + ds.delete() def test_handle_error(self): ds, variable = self._create_ds() @@ -79,23 +203,25 @@ def test_revert_script(self): assert variable.body["name"] == "pk" ds.delete() + @pytest.mark.skip(reason="Collapse is 504ing in the server.") def test_fetch_all_and_collapse(self): - raise self.skipTest("Collapse is 504ing in the server.") ds, variable = self._create_ds() - scrunch_dataset = get_mutable_dataset(ds.body.id, self.site) - s1 = "RENAME pk TO varA;" - s2 = 'CHANGE TITLE IN varA WITH "Variable A";' + try: + scrunch_dataset = get_mutable_dataset(ds.body.id, self.site) + s1 = "RENAME pk TO varA;" + s2 = 'CHANGE TITLE IN varA WITH "Variable A";' - scrunch_dataset.scripts.execute(s1) - scrunch_dataset.scripts.execute(s2) + scrunch_dataset.scripts.execute(s1) + scrunch_dataset.scripts.execute(s2) - r = scrunch_dataset.scripts.all() - assert len(r) == 2 - assert r[0].body["body"] == s1 - assert r[1].body["body"] == s2 + r = scrunch_dataset.scripts.all() + assert len(r) == 2 + assert r[0].body["body"] == s1 + assert r[1].body["body"] == s2 - scrunch_dataset.scripts.collapse() + scrunch_dataset.scripts.collapse() - r = scrunch_dataset.scripts.all() - assert len(r) == 1 - ds.delete() + r = scrunch_dataset.scripts.all() + assert len(r) == 1 + finally: + ds.delete() diff --git a/scrunch/datasets.py b/scrunch/datasets.py index ae151ce..9e932d5 100644 --- a/scrunch/datasets.py +++ b/scrunch/datasets.py @@ -33,13 +33,13 @@ from scrunch.expressions import parse_expr, prettify, process_expr from scrunch.folders import DatasetFolders from scrunch.views import DatasetViews -from scrunch.scripts import ScriptExecutionError, SystemScript +from scrunch.scripts import DatasetScripts, SystemScript from scrunch.helpers import (ReadOnly, _validate_category_rules, abs_url, case_expr, download_file, shoji_entity_wrapper, subvar_alias, validate_categories, shoji_catalog_wrapper, get_else_case, else_case_not_selected, SELECTED_ID, NOT_SELECTED_ID, NO_DATA_ID, valid_categorical_date, - shoji_view_wrapper, generate_subvariable_codes) + generate_subvariable_codes) from scrunch.order import DatasetVariablesOrder, ProjectDatasetsOrder from scrunch.subentity import Deck, Filter, Multitable from scrunch.variables import (combinations_from_map, combine_categories_expr, @@ -457,7 +457,7 @@ def execute(self, script_body, strict_subvariable_syntax=None): """Will run a system script on this project.""" # The project execution endpoint is a shoji:view system_script = SystemScript(self.resource) - system_script.execute(script_body, strict_subvariable_syntax) + return system_script.execute(script_body, strict_subvariable_syntax) @property def members(self): @@ -821,6 +821,7 @@ def __init__(self, resource): # of the multiple inheritance, we just initiate self._vars here self._reload_variables() self.folders = DatasetFolders(self) + self.scripts = DatasetScripts(self.resource) def __getattr__(self, item): if item in self._ENTITY_ATTRIBUTES: diff --git a/scrunch/scripts.py b/scrunch/scripts.py index 2d98d13..2ceba66 100644 --- a/scrunch/scripts.py +++ b/scrunch/scripts.py @@ -58,7 +58,7 @@ class SystemScript(BaseScript): def format_request_url(self, execute, strict_subvariable_syntax=None): strict_subvariable_syntax_flag = self.get_default_syntax_flag(strict_subvariable_syntax) if strict_subvariable_syntax_flag: - execute.self = "{}?strict_subvariable_syntax=true".format(self.resource.self) + execute.self += "?strict_subvariable_syntax=true" def execute(self, script_body, strict_subvariable_syntax=None): """ @@ -72,7 +72,7 @@ def execute(self, script_body, strict_subvariable_syntax=None): try: execute = self.resource.execute self.format_request_url(execute, strict_subvariable_syntax) - execute.post(payload) + return execute.post(payload) except pycrunch.ClientError as err: resolutions = err.args[2]["resolutions"] raise ScriptExecutionError(err, resolutions) From 0fc82b930c2431394d296f1b0b5c1767c263a0f5 Mon Sep 17 00:00:00 2001 From: Alessio Izzo Date: Thu, 1 Aug 2024 10:57:10 +0200 Subject: [PATCH 4/5] refactor based on code review + dataset scripts improvements --- scrunch/accounts.py | 2 +- scrunch/helpers.py | 6 +++--- scrunch/scripts.py | 14 ++++++++++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/scrunch/accounts.py b/scrunch/accounts.py index afc227f..4a2fef9 100644 --- a/scrunch/accounts.py +++ b/scrunch/accounts.py @@ -54,7 +54,7 @@ def execute(self, script_body, strict_subvariable_syntax=None): """Will run a system script on this account.""" # The account execution endpoint is a shoji:view system_script = SystemScript(self.resource) - system_script.execute(script_body, strict_subvariable_syntax) + return system_script.execute(script_body, strict_subvariable_syntax) @property def projects(self): diff --git a/scrunch/helpers.py b/scrunch/helpers.py index 1990e54..e2e8041 100644 --- a/scrunch/helpers.py +++ b/scrunch/helpers.py @@ -212,7 +212,7 @@ def _validate_category_rules(categories, rules): def shoji_view_wrapper(value, **kwargs): """ receives a dictionary and wraps its content on a body keyed dictionary - with the appropiate shoji: attribute + with the appropriate shoji: attribute """ payload = { 'element': 'shoji:view', @@ -225,7 +225,7 @@ def shoji_view_wrapper(value, **kwargs): def shoji_entity_wrapper(body, **kwargs): """ receives a dictionary and wraps its content on a body keyed dictionary - with the appropiate shoji: attribute + with the appropriate shoji: attribute """ payload = { 'element': 'shoji:entity', @@ -238,7 +238,7 @@ def shoji_entity_wrapper(body, **kwargs): def shoji_catalog_wrapper(index, **kwargs): """ receives a dictionary and wraps its content on a body keyed dictionary - with the appropiate shoji: attribute + with the appropriate shoji: attribute """ payload = { 'element': 'shoji:catalog', diff --git a/scrunch/scripts.py b/scrunch/scripts.py index 2ceba66..50a3103 100644 --- a/scrunch/scripts.py +++ b/scrunch/scripts.py @@ -4,7 +4,7 @@ import pycrunch from pycrunch.shoji import TaskError -from scrunch.helpers import shoji_view_wrapper +from scrunch.helpers import shoji_view_wrapper, shoji_entity_wrapper class ScriptExecutionError(Exception): @@ -67,7 +67,7 @@ def execute(self, script_body, strict_subvariable_syntax=None): System scripts do not have a return value. If they execute correctly they'll finish silently. Otherwise, an error will raise. """ - # The project execution endpoint is a shoji:view + # The script execution endpoint is a shoji:view payload = shoji_view_wrapper(script_body) try: execute = self.resource.execute @@ -86,12 +86,18 @@ def execute(self, script_body, strict_subvariable_syntax=None, dry_run=False): "body": script_body, "strict_subvariable_syntax": strict_subvariable_syntax } - method = self.resource.scripts.create + if dry_run: payload["dry_run"] = True method = self.resource.scripts.post + else: + method = self.resource.scripts.create + + # The dataset script execution endpoint is a shoji:entity + body = shoji_entity_wrapper(payload) + try: - method({'element': 'shoji:entity', 'body': payload}) + method(body) except pycrunch.ClientError as err: if isinstance(err, TaskError): # For async script validation error From 47c520c8510e4b6f4f749f54c032383ac6c696b9 Mon Sep 17 00:00:00 2001 From: Alessio Izzo Date: Thu, 1 Aug 2024 16:51:51 +0200 Subject: [PATCH 5/5] refactor how system scrypt make the call to cr.server --- integration/test_scripts.py | 3 ++- scrunch/scripts.py | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/integration/test_scripts.py b/integration/test_scripts.py index 49e425f..e3b05e6 100644 --- a/integration/test_scripts.py +++ b/integration/test_scripts.py @@ -67,7 +67,8 @@ def test_define_view_strict_subvariable_syntax(self): scrunch_dataset = get_mutable_dataset(ds.body.id, self.site) project.move_here([scrunch_dataset]) - project.execute(script_body, strict_subvariable_syntax=True) + resp = project.execute(script_body, strict_subvariable_syntax=True) + wait_progress(resp, self.site.session) view = scrunch_dataset.views.get_by_name("My view") assert view.project.name == project.name diff --git a/scrunch/scripts.py b/scrunch/scripts.py index 50a3103..412e2b4 100644 --- a/scrunch/scripts.py +++ b/scrunch/scripts.py @@ -55,10 +55,11 @@ def execute(self, script_body, strict_subvariable_syntax=None): class SystemScript(BaseScript): - def format_request_url(self, execute, strict_subvariable_syntax=None): + def format_request_url(self, request_url, strict_subvariable_syntax=None): strict_subvariable_syntax_flag = self.get_default_syntax_flag(strict_subvariable_syntax) if strict_subvariable_syntax_flag: - execute.self += "?strict_subvariable_syntax=true" + request_url += "?strict_subvariable_syntax=true" + return request_url def execute(self, script_body, strict_subvariable_syntax=None): """ @@ -70,9 +71,8 @@ def execute(self, script_body, strict_subvariable_syntax=None): # The script execution endpoint is a shoji:view payload = shoji_view_wrapper(script_body) try: - execute = self.resource.execute - self.format_request_url(execute, strict_subvariable_syntax) - return execute.post(payload) + execute_url = self.format_request_url(self.resource.views['execute'], strict_subvariable_syntax) + return self.resource.session.post(execute_url, json=payload) except pycrunch.ClientError as err: resolutions = err.args[2]["resolutions"] raise ScriptExecutionError(err, resolutions)