Skip to content

Commit

Permalink
Merge pull request #3 from nodedge/code-generation
Browse files Browse the repository at this point in the history
Code generation
  • Loading branch information
nodedge committed Oct 4, 2020
2 parents 6451688 + 201b78c commit a2e522f
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 30 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ recursive-include nodedge/qss *
recursive-include nodedge/resources *
recursive-include tests *
recursive-include examples *
recursive-include tools *
recursive-exclude * __pycache__
recursive-exclude * *.py[co]

Expand Down
13 changes: 8 additions & 5 deletions nodedge/blocks/add_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ class AddBlock(Block):
evalString = "add"

def evalImplementation(self):
i0 = self.inputNodeAt(0)
i1 = self.inputNodeAt(1)
inputs = []
for i in range(len(self.inputSockets)):
inputs.append(self.inputNodeAt(i))

try:
operation = f"{AddBlock.evalString}({i0.eval()}, {i1.eval()})"
operation = f"{AddBlock.evalString}("
for curr_input in inputs:
operation += f"{curr_input.eval()},"
operation = operation[:-1] + ")"
result = eval(operation)
except TypeError as e:
raise EvaluationError(e)
Expand All @@ -30,7 +34,6 @@ def evalImplementation(self):
return self.value


# TODO: make evalImplementation generic with respect to number of inputs
# TODO: use join method instead ','.join(list_of_strings)
# TODO: Find a way to extract exceptions from evalImplementation
# TODO: Create a script to generate blocks from a dictionary (JSON / CSV / whatever)
# TODO: Create a script to generate tests for blocks: list of Inputs and list of expected Outputs
5 changes: 3 additions & 2 deletions nodedge/blocks/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ def eval(self, index=0):

try:
self.checkInputsValidity()
# TODO: Implement evalInputs and checkInputsConsistency methods
# TODO: Implement evalInputs (to avoid repeating eval in specific blocks implementations)
# TODO: Implement checkInputsConsistency (to avoid division by 0, ...)
# self.evalInputs()
# self.checkInputsConsistency()
self.value = self.evalImplementation()
Expand Down Expand Up @@ -137,7 +138,7 @@ class EvaluationError(Exception):
"""
:class:`~nodedge.block.EvaluationError` class
If a not cannot be evaluated, raise this error.
If a block cannot be evaluated, raise this error.
"""

pass
Expand Down
3 changes: 2 additions & 1 deletion nodedge/mdi_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import Any, Callable, List, Optional, cast

from pyqtconsole.console import PythonConsole
from PySide2.QtCore import QSignalMapper, Qt, QTimer, Slot
from PySide2.QtCore import QSignalMapper, QSize, Qt, QTimer, Slot
from PySide2.QtGui import QCloseEvent, QIcon, QKeySequence
from PySide2.QtWidgets import (
QAction,
Expand Down Expand Up @@ -81,6 +81,7 @@ def initUI(self) -> None:
os.path.join(os.path.dirname(__file__), "resources/nodedge_logo.png")
)
self.setWindowIcon(self.icon)
self.setMinimumSize(QSize(880, 600))

self.styleSheetFilename = os.path.join(
os.path.dirname(__file__), "qss/nodedge_style.qss"
Expand Down
52 changes: 30 additions & 22 deletions nodedge/qss/nodedge_style.qss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ background:palette(dark);
color:palette(window-text);
}


QTabWidget{
border:0;
}
Expand Down Expand Up @@ -59,14 +60,14 @@ image:url("close_window_100.png");
}

QDockWidget{
font-size: 14px;
color:palette(window-text);
/*font-weight:bold;*/
titlebar-close-icon:url("resources/iconsModified/close_window_100.png");
titlebar-normal-icon:url(":icons/docktitle-normal-btn-light.png");
icon-size:25px;
width:25px;
border: 1px solid palette(highlight);
font-size: 16px;
color: palette(window-text);
/*font-weight:bold;*/
titlebar-close-icon: url("resources/iconsModified/close_window_100.png");
titlebar-normal-icon: url(":icons/docktitle-normal-btn-light.png");
icon-size: 25px;
width: 25px;
border: 1px solid palette(highlight);
}

QDockWidget::title{
Expand All @@ -92,14 +93,16 @@ background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,
stop : 1 palette(dark));
}

QDockWidget::close-button{
image:url("resources/iconsModified/close_window_100.png");
icon-size: 25px;
padding: 0px;
QDockWidget::close-button {
image: url("resources/iconsModified/close_window_100.png");
icon-size: 25px;
padding: 0px;
margin: 0px;
}

QMenuBar{
background:palette(dark);
QMenuBar {
background: palette(dark);
font-size: 16px;
}

QMenuBar::item{
Expand Down Expand Up @@ -132,9 +135,9 @@ height:1px;
background:palette(light);
}

QToolButton{
padding: 0px 1px;
font-size: 14px;
QToolButton {
padding: 0px 1px;
font-size: 16px;
}

QMenu:disabled,
Expand Down Expand Up @@ -174,11 +177,16 @@ QTableView::item:active:hover{
color:palette(text);
}

QTableView::item:selected,QTableView::item:active:selected{
color:palette(text);
background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,
stop : 0 palette(base),stop : 1 palette(highlight));
border:0;}
QTableView::item:selected,QTableView::item:active:selected {
color: palette(text);
background: qlineargradient(x1:0,
y1: 0,
x2: 0,
y2: 1,
stop: 0 palette(highlight),
stop: 1 palette(highlight));
border: 0;
}

QPushButton{
border: 1px solid palette(light);
Expand Down
8 changes: 8 additions & 0 deletions tools/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
"""
<ModuleName> module containing :class:`~nodedge.<Name>.<ClassName>` class.
"""


class MyClass:
""":class:`~nodedge.<ModuleName>.<ClassName>` class ."""
8 changes: 8 additions & 0 deletions tools/block_generator/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
"""
<ModuleName> module containing :class:`~nodedge.<Name>.<ClassName>` class.
"""


class MyClass:
""":class:`~nodedge.<ModuleName>.<ClassName>` class ."""
12 changes: 12 additions & 0 deletions tools/block_generator/block_config.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
library,function,op_block_string,operation_name,block_name,operation_symbol
operator,add,OP_NODE_ADD,add,Addition,+
operator,sub,OP_NODE_SUBTRACT,sub,Subtraction,-
operator,mul,OP_NODE_MULTIPLY,mul,Multiplication,*
operator,truediv,OP_NODE_DIVIDE,truediv,Division,/
operator,mod,OP_NODE_MODULO,mod,Modulo,%
operator,pow,OP_NODE_POWER,pow,Power,**
operator,lt,OP_NODE_LESS,lt,Less,<
operator,le,OP_NODE_LESS_EQUAL,le,Less or Equal,<=
operator,eq,OP_NODE_EQUAL,eq,Equal,==
operator,gt,OP_NODE_GREATER,gt,Greater,>
operator,ge,OP_NODE_GREATER_EQUAL,ge,Greater or Equal,>=
29 changes: 29 additions & 0 deletions tools/block_generator/generate_pi_block.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import csv
import os.path
from string import Template

config_file = "block_config.csv"
save_path = "../../nodedge/tools/block_generator/generated_blocks/"

if __name__ == "__main__":

# Read one line of the csv
with open(config_file) as infile:
reader = csv.DictReader(infile, delimiter=",")

for row in reader:

# Generate code
with open("pi_block_template.txt") as template_file:
input_data = template_file.read()
template = Template(input_data)

output_data = template.substitute(**row)
file_name = f"{row['operation_name']}_block.py"
file_path = os.path.join(save_path, file_name)
output_file = open(file_path, "w")
output_file.write(output_data)
output_file.close()

template_file.close()
infile.close()
37 changes: 37 additions & 0 deletions tools/block_generator/pi_block_template.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-

from ${library} import ${function}

from nodedge.blocks.block import Block, EvaluationError
from nodedge.blocks.block_config import BLOCKS_ICONS_PATH, registerNode
try:
from nodedge.blocks.block_config import ${op_block_string}
except:
op_block_string = -1

@registerNode(${op_block_string})
class ${block_name}Block(Block):
icon = f"{BLOCKS_ICONS_PATH}/${operation_name}.png"
operationCode = ${op_block_string}
operationTitle = "${block_name}"
contentLabel = "${operation_symbol}"
contentLabelObjectName = "BlockBackground"
evalString = "${operation_name}"

def evalImplementation(self):
inputs = []
for i in range(len(self.inputSockets)):
inputs.append(self.inputNodeAt(i))

try:
operation = f"{${block_name}Block.evalString}("
for curr_input in inputs:
operation += f"{curr_input.eval()},"
operation = operation[:-1] + f")"
result = eval(operation)
except TypeError as e:
raise EvaluationError(e)

self.value = result

return self.value

0 comments on commit a2e522f

Please sign in to comment.