Skip to content

Commit

Permalink
Merge pull request #132 from FlickerSoul/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
FlickerSoul authored Jan 16, 2021
2 parents f768993 + 1053dea commit ab12e36
Show file tree
Hide file tree
Showing 18 changed files with 362 additions and 1,816 deletions.
86 changes: 86 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
version: 2.1

orbs:
# The python orb contains a set of prepackaged circleci configuration you can use repeatedly in your configurations files
# Orb commands and jobs help you with common scripting around a language/tool
# so you dont have to copy and paste it everywhere.
# See the orb documentation here: https://circleci.com/developer/orbs/orb/circleci/python
python: circleci/[email protected]
node: circleci/[email protected]

workflows:
graphery-build: # This is the name of the workflow, feel free to change it to better match your workflow.
# Inside the workflow, you define the jobs you want to run.
# For more details on extending your workflow, see the configuration docs: https://circleci.com/docs/2.0/configuration-reference/#workflows
jobs:
- build-backend
- build-frontend


jobs:
build-backend: # This is the name of the job, feel free to change it to better match what you're trying to do!
# These next lines defines a docker executors: https://circleci.com/docs/2.0/executor-types/
# You can specify an image from dockerhub or use one of the convenience images from CircleCI's Developer Hub
# A list of available CircleCI docker convenience images are available here: https://circleci.com/developer/images/image/cimg/python
# The executor is the environment in which the steps below will be executed - below will use a python 3.9 container
# Change the version below to your required version of python
working_directory: ~/Graphery/backend
docker:
- image: cimg/python:3.9
- image: circleci/postgres:13-postgis-ram
environment:
POSTGRES_USER: graphery
POSTGRES_PASSWORD: graphery
POSTGRES_DB: graphery
# Checkout the code as the first step. This is a dedicated CircleCI step.
# The python orb's install-packages step will install the dependencies from a Pipfile via Pipenv by default.
# Here we're making sure we use just use the system-wide pip. By default it uses the project root's requirements.txt.
# Then run your tests!
# CircleCI will report the results back to your VCS provider.
steps:
- checkout:
path: ~/Graphery
- python/install-packages:
pkg-manager: pipenv
# app-dir: ~/project/package-directory/ # If you're requirements.txt isn't in the root directory.
# pip-dependency-file: test-requirements.txt # if you have a different name for your requirements file, maybe one that combines your runtime and test requirements.
- run:
command: pipenv install -d
- run:
name: Bundle Test
command: cd ./bundle && pipenv run pytest -vv -ra -s
- run:
name: Server Test
command: cd ./server && pipenv run pytest -vv -ra -s
environment:
GRAPHERY_NORMAL_LOG_PATH: graphery_normal.log
GRAPHERY_EXECUTION_LOG_PATH: graphery_execution.log
GRAPHERY_API_LOG_PATH: graphery_api.log
environment:
PIPENV_IGNORE_VIRTUALENVS: 1

build-frontend:
working_directory: ~/Graphery/graphery
docker:
- image: cimg/python:3.9.1-node
steps:
- checkout:
path: ~/Graphery
# - restore_cache:
# name: Restore Yarn Package Cache
# keys:
# - yarn-packages-{{ checksum "yarn.lock" }}
- node/install-packages:
pkg-manager: yarn
# - run:
# name: Install Dependencies
# command: yarn install --immutable
# - save_cache:
# name: Save Yarn Package Cache
# key: yarn-packages-{{ checksum "yarn.lock" }}
# paths:
# - ~/.cache/yarn
- run:
name: Build Frontend
command: yarn run build

Empty file added backend/server/__init__.py
Empty file.
17 changes: 12 additions & 5 deletions backend/server/backend/graphql/admin_mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from typing import List, Sequence, Mapping, Type, Optional, MutableMapping

import graphene
from django.db import transaction
from django.db.models import QuerySet
from graphene.types.generic import GenericScalar
from graphql import GraphQLError

Expand All @@ -16,7 +18,7 @@
from backend.graphql.utils import process_model_wrapper, get_wrappers_by_ids, get_wrapper_by_id
from backend.intel_wrappers.intel_wrapper import CategoryWrapper, \
TutorialAnchorWrapper, UserWrapper, GraphWrapper, CodeWrapper, TutorialTranslationContentWrapper, \
GraphTranslationContentWrapper, ExecResultJsonWrapper, UploadsWrapper
GraphTranslationContentWrapper, ExecResultJsonWrapper, UploadsWrapper, _result_json_updater
from backend.intel_wrappers.wrapper_bases import AbstractWrapper
from backend.model.TranslationModels import TranslationBase, GraphTranslationBase
from backend.model.TutorialRelatedModel import GraphPriority, Graph
Expand Down Expand Up @@ -176,12 +178,17 @@ def mutate(self, _, lang: str, content: MutableMapping):
content['authors'] = get_wrappers_by_ids(UserWrapper, content['authors'])
content['tutorial_anchor'] = get_wrapper_by_id(TutorialAnchorWrapper, content['tutorial_anchor'])

graph_set: List[str] = content.pop('graph_set')
graph_set: QuerySet[Graph] = Graph.objects.filter(id__in=content.pop('graph_set'))

tutorial_content_wrapper = process_model_wrapper(TutorialTranslationContentWrapper,
model_class=translation_table, **content)
with transaction.atomic():
tutorial_content_wrapper = process_model_wrapper(TutorialTranslationContentWrapper,
model_class=translation_table, **content)

tutorial_content_wrapper.model.tutorial_anchor.graph_set.set(Graph.objects.filter(id__in=graph_set))
tutorial_content_wrapper.model.tutorial_anchor.graph_set.set(graph_set)

if hasattr(tutorial_content_wrapper.model, 'code'):
code_list = [tutorial_content_wrapper.model.code]
_result_json_updater(code_list, graph_set)

return UpdateTutorialContent(success=True, model=tutorial_content_wrapper.model)

Expand Down
49 changes: 45 additions & 4 deletions backend/server/backend/intel_wrappers/intel_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import json
from random import random
from typing import Optional, Iterable, Mapping, Type, Union, Any, TypeVar, Generic
from typing import Optional, Iterable, Mapping, Type, Union, Any, TypeVar, Generic, List, Tuple

from django.core.files import File
from django.db.models import Model
from django.db import transaction
from django.db.models import Model, QuerySet

from backend.intel_wrappers.validators import dummy_validator, category_validator, name_validator, url_validator, \
categories_validator, code_validator, wrapper_validator, authors_validator, non_empty_text_validator, \
Expand All @@ -17,13 +18,40 @@
from backend.model.TutorialRelatedModel import Category, Tutorial, Graph, Code, ExecResultJson, Uploads, FAKE_UUID
from backend.model.UserModel import User
from backend.intel_wrappers.wrapper_bases import AbstractWrapper, PublishedWrapper, VariedContentWrapper
from bundle.server_utils.main_functions import time_out_execute


def finalize_prerequisite_wrapper_iter(model_wrappers: Iterable[AbstractWrapper]) -> None:
for model_wrapper in model_wrappers:
model_wrapper.finalize_model(overwrite=False)


def _result_json_updater(code_list: Iterable[Code], graph_list: Iterable[Graph]) -> List[Tuple]:
failed_code_and_graph = []
for code in code_list:
for graph in graph_list:
try:
response = time_out_execute(code=code.code, graph_json=graph.cyjs)
if 'data' not in response or 'errors' in response:
raise ValueError('Execution went wrong with response: {}'.format(response))

with transaction.atomic():
try:
exec_result_json: ExecResultJson = ExecResultJson.objects.get(code=code, graph=graph)
except ExecResultJson.DoesNotExist:
exec_result_json: ExecResultJson = ExecResultJson(code=code, graph=graph)

result_json: List[Mapping] = response['data']['execResult']
exec_result_json.json = result_json
exec_result_json.save()
except Exception as e:
failed_code_and_graph.append(
(code, graph, e)
)

return failed_code_and_graph


class UserWrapper(AbstractWrapper[User]):
model_class: Type[User] = User

Expand Down Expand Up @@ -156,7 +184,14 @@ def __init__(self):
'priority': graph_priority_validator,
'cyjs': json_validator,
'tutorials': tutorial_anchors_validator
})
}, post_actions=[self._execute_code_after_submission])

def _execute_code_after_submission(self) -> None:
code_list: List[Code] = list(tutorial.code
for tutorial in self.model.tutorials.filter(code__isnull=False))
graph_list: List[Graph] = [self.model]
failed_missions = _result_json_updater(code_list, graph_list)
print(failed_missions)

def load_model_var(self, loaded_model: Graph) -> None:
super().load_model_var(loaded_model)
Expand Down Expand Up @@ -205,7 +240,13 @@ def __init__(self):
'name': non_empty_text_validator,
'tutorial': wrapper_validator,
'code': code_validator
})
}, post_actions=[self._execute_code_after_submission])

def _execute_code_after_submission(self) -> None:
code_list: List[Code] = [self.model]
graph_list: QuerySet[Graph] = self.tutorial.model.graph_set.all()
failed_missions = _result_json_updater(code_list, graph_list)
print(failed_missions)

def load_model_var(self, loaded_model: Code) -> None:
super().load_model_var(loaded_model)
Expand Down
34 changes: 25 additions & 9 deletions backend/server/backend/intel_wrappers/wrapper_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from abc import abstractmethod, ABC

from typing import Optional, Iterable, Mapping, Callable, Any, Type, Union, MutableMapping, TypeVar, Generic
from typing import Optional, Iterable, Mapping, Callable, Any, Type, Union, MutableMapping, TypeVar, Generic, Sequence

from django.core.exceptions import ValidationError
from django.db import models, IntegrityError, transaction
Expand Down Expand Up @@ -56,7 +56,7 @@ def load_model_var(self, loaded_model: _T) -> None:
pass

def load_model(self, loaded_model: _T, load_var: bool = True) -> ModelWrapperBase:
self.model = loaded_model
self.model: _T = loaded_model

if load_var:
self.load_model_var(loaded_model)
Expand Down Expand Up @@ -115,17 +115,31 @@ def get_var_from_kwargs(kwargs: Mapping, var_name: str) -> Optional[Any]:
return kwargs.get(var_name, None)


class PostActionWrapper(ABC):
def __init__(self, actions: Sequence[Callable] = ()) -> None:
self.actions_ = actions

def set_actions(self, actions: Sequence[Callable]) -> None:
self.actions_ = actions

def _perform_post_actions(self) -> None:
for action in self.actions_:
action()


_S = TypeVar('_S', bound=UUIDMixin)


class AbstractWrapper(IntelWrapperBase, ModelWrapperBase[_S], SettableBase, Generic[_S], ABC):
def __init__(self, validators: MutableMapping[str, Callable]):
class AbstractWrapper(IntelWrapperBase, ModelWrapperBase[_S], SettableBase, PostActionWrapper, Generic[_S], ABC):
def __init__(self, validators: MutableMapping[str, Callable],
post_actions: Sequence[Callable] = ()) -> None:
self.id: Optional[str] = None
validators['id'] = dummy_validator

IntelWrapperBase.__init__(self, validators)
ModelWrapperBase.__init__(self)
SettableBase.__init__(self)
PostActionWrapper.__init__(self, post_actions)

self.field_names = [*self.validators.keys()]

Expand Down Expand Up @@ -213,23 +227,25 @@ def finalize_model(self, overwrite: bool = True, validate: bool = True) -> None:
if overwrite and validate:
self.save_model()

self._perform_post_actions()


_V = TypeVar('_V', bound=PublishedMixin)


class PublishedWrapper(AbstractWrapper[_V], Generic[_V], ABC):
def __init__(self, validators: MutableMapping[str, Callable]):
def __init__(self, validators: MutableMapping[str, Callable], post_actions: Sequence[Callable] = ()):
self.is_published: bool = False
validators['is_published'] = is_published_validator
super(PublishedWrapper, self).__init__(validators)
super(PublishedWrapper, self).__init__(validators, post_actions)

def load_model_var(self, loaded_model: _V) -> None:
super().load_model_var(loaded_model)
self.is_published = loaded_model.is_published


class VariedContentWrapper(PublishedWrapper[_V], Generic[_V], ABC):
def __init__(self, validators: MutableMapping[str, Callable]):
super(VariedContentWrapper, self).__init__(validators)
def __init__(self, validators: MutableMapping[str, Callable], post_actions: Sequence[Callable] = ()):
super(VariedContentWrapper, self).__init__(validators, post_actions)

self.model_class: _V = self.model_class
self.model_class: Type[_V] = self.model_class
2 changes: 1 addition & 1 deletion backend/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def read_file(filename):

setuptools.setup(
name="Graphery Servers",
version="0.24.2",
version="0.24.3",
packages=setuptools.find_packages(exclude=['tests*']),
install_requires=read_file('requirements.txt'),
author="Heyuan Zeng",
Expand Down
6 changes: 1 addition & 5 deletions graphery/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "graphery",
"version": "0.24.2",
"version": "0.24.3",
"private": true,
"repository": {
"type": "git",
Expand Down Expand Up @@ -67,15 +67,13 @@
"vuex-persistedstate": "^3.1.0"
},
"devDependencies": {
"@types/jest": "^24.0.19",
"@types/webpack": "^4.41.21",
"@typescript-eslint/eslint-plugin": "^2.26.0",
"@typescript-eslint/parser": "^2.26.0",
"@vue/cli-plugin-babel": "^4.5.10",
"@vue/cli-plugin-eslint": "^4.5.10",
"@vue/cli-plugin-router": "^4.5.10",
"@vue/cli-plugin-typescript": "^4.5.10",
"@vue/cli-plugin-unit-jest": "^4.5.10",
"@vue/cli-plugin-vuex": "^4.5.10",
"@vue/cli-service": "^4.5.10",
"@vue/eslint-config-prettier": "^6.0.0",
Expand All @@ -89,11 +87,9 @@
"prettier": "^1.19.1",
"sass": "^1.26.10",
"sass-loader": "^8.0.0",
"ts-jest": "^26.1.1",
"typescript": "^3.9.7",
"vue-cli-plugin-i18n": "~1.0.1",
"vue-cli-plugin-quasar": "~2.0.2",
"vue-jest": "^3.0.6",
"vue-template-compiler": "^2.6.12"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
})
.then((editor) => {
editor.getModel().onDidChangeContent(
debounce((_) => {
debounce(() => {
this.codeObject.code = this.editor.getValue();
}, 30)
);
Expand Down
13 changes: 7 additions & 6 deletions graphery/src/components/framework/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,21 @@
);
this.editor.getModel().onDidChangeContent(
debounce((_) => {
debounce(() => {
const codeContent = this.editor.getValue();
this.content = codeContent;
this.$emit('editorContentChanged', codeContent);
}, 100)
);
this.editor.onKeyUp((__) => {
debounce((__) => {
this.clearDecoration();
this.editor.onKeyUp(() => {
debounce(() => {
if (!this.isReadOnly) {
this.clearDecoration();
}
this.$emit('editorUserTyped');
}, 20)();
throttle((__) => {
throttle(() => {
if (this.isReadOnly) {
errorDialog(
{
Expand Down Expand Up @@ -174,7 +176,6 @@
}
},
moveToLine(line, message = 'Executing this line') {
// TODO scroll into view
this.changeDecoration(this.generateDecoration(line, message));
this.focusToLine(line);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@
for (const codeId of codeIds) {
resultJsonPositions[
this.getIdFromGraphIdAndCodeId(graphId, codeId)
] = { position: 0 };
] = {
position: 0,
variableListInfo: {
variableHighlightToggle: {},
variableListOrder: [],
},
};
}
}
this.$store.commit('rj/LOAD_JSON_LOCATIONS', resultJsonPositions);
Expand Down
Loading

0 comments on commit ab12e36

Please sign in to comment.