mirror of
https://github.com/infeeeee/dyn2py
synced 2025-12-16 22:16:18 +01:00
Tests, documentation, fixes
This commit is contained in:
@@ -92,11 +92,19 @@ class File():
|
|||||||
def write(self, options: Options) -> None:
|
def write(self, options: Options) -> None:
|
||||||
"""Prepare writing file to the disk:
|
"""Prepare writing file to the disk:
|
||||||
create backup, process dry-run, call filetype specific write_file() methods
|
create backup, process dry-run, call filetype specific write_file() methods
|
||||||
|
Should be called on subclasses!
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
options(Options): Run options.
|
options(Options): Run options.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: If called on a File object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# This should only work on subclasses:
|
||||||
|
if type(self).__name__ == "File":
|
||||||
|
raise TypeError("This method shouldn't be called on File objects!")
|
||||||
|
|
||||||
if not self.modified:
|
if not self.modified:
|
||||||
logging.debug("File not modified, not saving")
|
logging.debug("File not modified, not saving")
|
||||||
return
|
return
|
||||||
@@ -126,16 +134,16 @@ class DynamoFile(File):
|
|||||||
"""A Dynamo file, subclass of File()"""
|
"""A Dynamo file, subclass of File()"""
|
||||||
|
|
||||||
full_dict: dict
|
full_dict: dict
|
||||||
"""The contents of the Dynamo file, as dict."""
|
"""The contents of the Dynamo file, as dict. Initialized with read()"""
|
||||||
uuid: str
|
uuid: str
|
||||||
"""The uuid of the graph"""
|
"""The uuid of the graph. Initialized with read()"""
|
||||||
name: str
|
name: str
|
||||||
"""The name of the graph, read from the file. Not the name of the file"""
|
"""The name of the graph, read from the file. Initialized with read()"""
|
||||||
python_nodes: list["PythonNode"]
|
python_nodes: list["PythonNode"]
|
||||||
"""Python node objects, read from this file"""
|
"""Python node objects, read from this file. Initialized with get_python_nodes()"""
|
||||||
|
|
||||||
open_files: set["DynamoFile"] = set()
|
open_files: set["DynamoFile"] = set()
|
||||||
"""A set of open Dynamo files, before saving"""
|
"""A set of open Dynamo files, before saving. Self added by read()"""
|
||||||
|
|
||||||
def extract_python(self, options: Options | None = None) -> None:
|
def extract_python(self, options: Options | None = None) -> None:
|
||||||
"""Extract and write python files
|
"""Extract and write python files
|
||||||
@@ -174,6 +182,7 @@ class DynamoFile(File):
|
|||||||
"""Read Dynamo graph to parameters
|
"""Read Dynamo graph to parameters
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
|
FileNotFoundError: The file does not exist
|
||||||
DynamoFileException: If the file is a Dynamo 1 file
|
DynamoFileException: If the file is a Dynamo 1 file
|
||||||
json.JSONDecodeError: If there are any other problem with the file
|
json.JSONDecodeError: If there are any other problem with the file
|
||||||
"""
|
"""
|
||||||
@@ -204,6 +213,9 @@ class DynamoFile(File):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[PythonNode]: A list of PythonNodes in the file
|
list[PythonNode]: A list of PythonNodes in the file
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
DynamoFileException: If no Python nodes in the file
|
||||||
"""
|
"""
|
||||||
if not self in self.open_files:
|
if not self in self.open_files:
|
||||||
self.read()
|
self.read()
|
||||||
@@ -211,8 +223,13 @@ class DynamoFile(File):
|
|||||||
full_python_nodes = [n for n in self.full_dict["Nodes"]
|
full_python_nodes = [n for n in self.full_dict["Nodes"]
|
||||||
if n["NodeType"] == "PythonScriptNode"]
|
if n["NodeType"] == "PythonScriptNode"]
|
||||||
|
|
||||||
|
# Check if it was already read:
|
||||||
|
try:
|
||||||
|
self.python_nodes
|
||||||
|
except AttributeError:
|
||||||
self.python_nodes = []
|
self.python_nodes = []
|
||||||
|
|
||||||
|
if not self.python_nodes:
|
||||||
for p_node in full_python_nodes:
|
for p_node in full_python_nodes:
|
||||||
# The name of the node is stored here:
|
# The name of the node is stored here:
|
||||||
node_views = self.full_dict["View"]["NodeViews"]
|
node_views = self.full_dict["View"]["NodeViews"]
|
||||||
@@ -326,14 +343,14 @@ class PythonFile(File):
|
|||||||
"""A Python file, subclass of File()"""
|
"""A Python file, subclass of File()"""
|
||||||
|
|
||||||
code: str
|
code: str
|
||||||
"""The python code as a string"""
|
"""The python code as a string. Initialized with read()"""
|
||||||
header_data: dict
|
header_data: dict
|
||||||
"""Parsed dict from the header of a python file"""
|
"""Parsed dict from the header of a python file. Initialized with read()"""
|
||||||
text: str
|
text: str
|
||||||
"""Full contents of the file before writing"""
|
"""Full contents of the file before writing. Initialized with generate_text()"""
|
||||||
|
|
||||||
open_files: set["PythonFile"] = set()
|
open_files: set["PythonFile"] = set()
|
||||||
"""A set of open Python files"""
|
"""A set of open Python files. Self added by read()"""
|
||||||
|
|
||||||
def generate_text(self, dynamo_file: DynamoFile, python_node: "PythonNode") -> None:
|
def generate_text(self, dynamo_file: DynamoFile, python_node: "PythonNode") -> None:
|
||||||
"""Generate full text to write with header
|
"""Generate full text to write with header
|
||||||
@@ -348,12 +365,17 @@ class PythonFile(File):
|
|||||||
Do not edit this section, if you want to update the Dynamo graph!\
|
Do not edit this section, if you want to update the Dynamo graph!\
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Double escape path:
|
||||||
|
dyn_path_string = str(dynamo_file.realpath)
|
||||||
|
if "\\" in dyn_path_string:
|
||||||
|
dyn_path_string = dyn_path_string.replace("\\", "\\\\")
|
||||||
|
|
||||||
self.header_data = {
|
self.header_data = {
|
||||||
"dyn2py_version": METADATA["Version"],
|
"dyn2py_version": METADATA["Version"],
|
||||||
"dyn2py_extracted": datetime.now().isoformat(),
|
"dyn2py_extracted": datetime.now().isoformat(),
|
||||||
"dyn_uuid": dynamo_file.uuid,
|
"dyn_uuid": dynamo_file.uuid,
|
||||||
"dyn_name": dynamo_file.name,
|
"dyn_name": dynamo_file.name,
|
||||||
"dyn_path": dynamo_file.realpath,
|
"dyn_path": dyn_path_string,
|
||||||
"dyn_modified": dynamo_file.mtimeiso,
|
"dyn_modified": dynamo_file.mtimeiso,
|
||||||
"py_id": python_node.id,
|
"py_id": python_node.id,
|
||||||
"py_engine": python_node.engine
|
"py_engine": python_node.engine
|
||||||
@@ -486,7 +508,7 @@ class PythonFile(File):
|
|||||||
|
|
||||||
def write_file(self) -> None:
|
def write_file(self) -> None:
|
||||||
"""Write this file to the disk. Should be called only from File.write()"""
|
"""Write this file to the disk. Should be called only from File.write()"""
|
||||||
with open(self.filepath, "w", encoding="utf-8") as output_file:
|
with open(self.filepath, "w", encoding="utf-8", newline='') as output_file:
|
||||||
output_file.write(self.text)
|
output_file.write(self.text)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
200
tests/input_files/no_python.dyn
Normal file
200
tests/input_files/no_python.dyn
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
{
|
||||||
|
"Uuid": "76de5c79-17c5-4c74-9f90-ad99a213d339",
|
||||||
|
"IsCustomNode": false,
|
||||||
|
"Description": "",
|
||||||
|
"Name": "no_python",
|
||||||
|
"ElementResolver": {
|
||||||
|
"ResolutionMap": {}
|
||||||
|
},
|
||||||
|
"Inputs": [],
|
||||||
|
"Outputs": [],
|
||||||
|
"Nodes": [
|
||||||
|
{
|
||||||
|
"ConcreteType": "Dynamo.Graph.Nodes.ZeroTouch.DSFunction, DynamoCore",
|
||||||
|
"NodeType": "FunctionNode",
|
||||||
|
"FunctionSignature": "+@var[]..[],var[]..[]",
|
||||||
|
"Id": "f8f4d3310211429ea8f301284983849e",
|
||||||
|
"Inputs": [
|
||||||
|
{
|
||||||
|
"Id": "264e2d2a3442445180048463a555399a",
|
||||||
|
"Name": "x",
|
||||||
|
"Description": "Integer value, double value or string\n\nvar[]..[]",
|
||||||
|
"UsingDefaultValue": false,
|
||||||
|
"Level": 2,
|
||||||
|
"UseLevels": false,
|
||||||
|
"KeepListStructure": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "f627c4088ee943aeba708e81f9945f1e",
|
||||||
|
"Name": "y",
|
||||||
|
"Description": "Integer value, double value or string\n\nvar[]..[]",
|
||||||
|
"UsingDefaultValue": false,
|
||||||
|
"Level": 2,
|
||||||
|
"UseLevels": false,
|
||||||
|
"KeepListStructure": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Outputs": [
|
||||||
|
{
|
||||||
|
"Id": "72975df34c2542ff949630ef7253bed5",
|
||||||
|
"Name": "var",
|
||||||
|
"Description": "The sum of two input numbers, or the concatenation of two strings",
|
||||||
|
"UsingDefaultValue": false,
|
||||||
|
"Level": 2,
|
||||||
|
"UseLevels": false,
|
||||||
|
"KeepListStructure": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Replication": "Auto",
|
||||||
|
"Description": "Returns addition of x and y\n\n+ (x: var[]..[], y: var[]..[]): var[]..[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ConcreteType": "Dynamo.Graph.Nodes.CodeBlockNodeModel, DynamoCore",
|
||||||
|
"NodeType": "CodeBlockNode",
|
||||||
|
"Code": "1;",
|
||||||
|
"Id": "24cee4b3934f46309d34386a1b5a674a",
|
||||||
|
"Inputs": [],
|
||||||
|
"Outputs": [
|
||||||
|
{
|
||||||
|
"Id": "dffa5271656d49e0b61ba8133b92a05e",
|
||||||
|
"Name": "",
|
||||||
|
"Description": "Value of expression at line 1",
|
||||||
|
"UsingDefaultValue": false,
|
||||||
|
"Level": 2,
|
||||||
|
"UseLevels": false,
|
||||||
|
"KeepListStructure": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Replication": "Disabled",
|
||||||
|
"Description": "Allows for DesignScript code to be authored directly"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ConcreteType": "CoreNodeModels.Watch, CoreNodeModels",
|
||||||
|
"NodeType": "ExtensionNode",
|
||||||
|
"Id": "26fc878922fd425a89112c6b14c9779b",
|
||||||
|
"Inputs": [
|
||||||
|
{
|
||||||
|
"Id": "1587eb8d7d8f41e6833e2b90f95b63fb",
|
||||||
|
"Name": "",
|
||||||
|
"Description": "Node to show output from",
|
||||||
|
"UsingDefaultValue": false,
|
||||||
|
"Level": 2,
|
||||||
|
"UseLevels": false,
|
||||||
|
"KeepListStructure": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Outputs": [
|
||||||
|
{
|
||||||
|
"Id": "d70e73be40114b9cb129a91cd4777c4a",
|
||||||
|
"Name": "",
|
||||||
|
"Description": "Node output",
|
||||||
|
"UsingDefaultValue": false,
|
||||||
|
"Level": 2,
|
||||||
|
"UseLevels": false,
|
||||||
|
"KeepListStructure": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Replication": "Disabled",
|
||||||
|
"Description": "Visualizes a node's output"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Connectors": [
|
||||||
|
{
|
||||||
|
"Start": "72975df34c2542ff949630ef7253bed5",
|
||||||
|
"End": "1587eb8d7d8f41e6833e2b90f95b63fb",
|
||||||
|
"Id": "8d017b34cb5b47f1b900c1c6ed8fd8d0",
|
||||||
|
"IsHidden": "False"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Start": "dffa5271656d49e0b61ba8133b92a05e",
|
||||||
|
"End": "264e2d2a3442445180048463a555399a",
|
||||||
|
"Id": "46f9099ffb1a4e08ad78d7e13d36d8bc",
|
||||||
|
"IsHidden": "False"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Start": "dffa5271656d49e0b61ba8133b92a05e",
|
||||||
|
"End": "f627c4088ee943aeba708e81f9945f1e",
|
||||||
|
"Id": "f167bc9b5eed4d5c96bac03015664979",
|
||||||
|
"IsHidden": "False"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Dependencies": [],
|
||||||
|
"NodeLibraryDependencies": [],
|
||||||
|
"Thumbnail": "",
|
||||||
|
"GraphDocumentationURL": null,
|
||||||
|
"ExtensionWorkspaceData": [
|
||||||
|
{
|
||||||
|
"ExtensionGuid": "28992e1d-abb9-417f-8b1b-05e053bee670",
|
||||||
|
"Name": "Properties",
|
||||||
|
"Version": "2.17",
|
||||||
|
"Data": {}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Author": "",
|
||||||
|
"Linting": {
|
||||||
|
"activeLinter": "None",
|
||||||
|
"activeLinterId": "7b75fb44-43fd-4631-a878-29f4d5d8399a",
|
||||||
|
"warningCount": 0,
|
||||||
|
"errorCount": 0
|
||||||
|
},
|
||||||
|
"Bindings": [],
|
||||||
|
"View": {
|
||||||
|
"Dynamo": {
|
||||||
|
"ScaleFactor": 1.0,
|
||||||
|
"HasRunWithoutCrash": true,
|
||||||
|
"IsVisibleInDynamoLibrary": true,
|
||||||
|
"Version": "2.17.0.3472",
|
||||||
|
"RunType": "Automatic",
|
||||||
|
"RunPeriod": "1000"
|
||||||
|
},
|
||||||
|
"Camera": {
|
||||||
|
"Name": "_Background Preview",
|
||||||
|
"EyeX": -17.0,
|
||||||
|
"EyeY": 24.0,
|
||||||
|
"EyeZ": 50.0,
|
||||||
|
"LookX": 12.0,
|
||||||
|
"LookY": -13.0,
|
||||||
|
"LookZ": -58.0,
|
||||||
|
"UpX": 0.0,
|
||||||
|
"UpY": 1.0,
|
||||||
|
"UpZ": 0.0
|
||||||
|
},
|
||||||
|
"ConnectorPins": [],
|
||||||
|
"NodeViews": [
|
||||||
|
{
|
||||||
|
"Name": "+",
|
||||||
|
"ShowGeometry": true,
|
||||||
|
"Id": "f8f4d3310211429ea8f301284983849e",
|
||||||
|
"IsSetAsInput": false,
|
||||||
|
"IsSetAsOutput": false,
|
||||||
|
"Excluded": false,
|
||||||
|
"X": 779.0,
|
||||||
|
"Y": 566.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Code Block",
|
||||||
|
"ShowGeometry": true,
|
||||||
|
"Id": "24cee4b3934f46309d34386a1b5a674a",
|
||||||
|
"IsSetAsInput": false,
|
||||||
|
"IsSetAsOutput": false,
|
||||||
|
"Excluded": false,
|
||||||
|
"X": 402.0,
|
||||||
|
"Y": 500.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Watch",
|
||||||
|
"ShowGeometry": true,
|
||||||
|
"Id": "26fc878922fd425a89112c6b14c9779b",
|
||||||
|
"IsSetAsInput": false,
|
||||||
|
"IsSetAsOutput": false,
|
||||||
|
"Excluded": false,
|
||||||
|
"X": 1102.0,
|
||||||
|
"Y": 587.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Annotations": [],
|
||||||
|
"X": 127.12026168573345,
|
||||||
|
"Y": 129.76719880218047,
|
||||||
|
"Zoom": 0.7658293928515516
|
||||||
|
}
|
||||||
|
}
|
||||||
106
tests/input_files/single_node.dyn
Normal file
106
tests/input_files/single_node.dyn
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
{
|
||||||
|
"Uuid": "76de5c79-17c5-4c74-9f90-ad99a213d339",
|
||||||
|
"IsCustomNode": false,
|
||||||
|
"Description": "",
|
||||||
|
"Name": "single_node",
|
||||||
|
"ElementResolver": {
|
||||||
|
"ResolutionMap": {}
|
||||||
|
},
|
||||||
|
"Inputs": [],
|
||||||
|
"Outputs": [],
|
||||||
|
"Nodes": [
|
||||||
|
{
|
||||||
|
"ConcreteType": "PythonNodeModels.PythonNode, PythonNodeModels",
|
||||||
|
"NodeType": "PythonScriptNode",
|
||||||
|
"Code": "# Load the Python Standard and DesignScript Libraries\r\nimport sys\r\nimport clr\r\nclr.AddReference('ProtoGeometry')\r\nfrom Autodesk.DesignScript.Geometry import *\r\n\r\n# The inputs to this node will be stored as a list in the IN variables.\r\ndataEnteringNode = IN\r\n\r\noutput = {\r\n \"python_version\": sys.version,\r\n \"asd_string\": \"asd_string\"\r\n}\r\n\r\n\r\n# Assign your output to the OUT variable.\r\nOUT = output",
|
||||||
|
"Engine": "CPython3",
|
||||||
|
"EngineName": "CPython3",
|
||||||
|
"VariableInputPorts": true,
|
||||||
|
"Id": "1c5d99792882409e97e132b3e9f814b0",
|
||||||
|
"Inputs": [
|
||||||
|
{
|
||||||
|
"Id": "7a29134d5d35492b80cd49a3ebac1847",
|
||||||
|
"Name": "IN[0]",
|
||||||
|
"Description": "Input #0",
|
||||||
|
"UsingDefaultValue": false,
|
||||||
|
"Level": 2,
|
||||||
|
"UseLevels": false,
|
||||||
|
"KeepListStructure": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Outputs": [
|
||||||
|
{
|
||||||
|
"Id": "a6a87605c777416bb759eaa87c976285",
|
||||||
|
"Name": "OUT",
|
||||||
|
"Description": "Result of the python script",
|
||||||
|
"UsingDefaultValue": false,
|
||||||
|
"Level": 2,
|
||||||
|
"UseLevels": false,
|
||||||
|
"KeepListStructure": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Replication": "Disabled",
|
||||||
|
"Description": "Runs an embedded Python script."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Connectors": [],
|
||||||
|
"Dependencies": [],
|
||||||
|
"NodeLibraryDependencies": [],
|
||||||
|
"Thumbnail": "",
|
||||||
|
"GraphDocumentationURL": null,
|
||||||
|
"ExtensionWorkspaceData": [
|
||||||
|
{
|
||||||
|
"ExtensionGuid": "28992e1d-abb9-417f-8b1b-05e053bee670",
|
||||||
|
"Name": "Properties",
|
||||||
|
"Version": "2.17",
|
||||||
|
"Data": {}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Author": "",
|
||||||
|
"Linting": {
|
||||||
|
"activeLinter": "None",
|
||||||
|
"activeLinterId": "7b75fb44-43fd-4631-a878-29f4d5d8399a",
|
||||||
|
"warningCount": 0,
|
||||||
|
"errorCount": 0
|
||||||
|
},
|
||||||
|
"Bindings": [],
|
||||||
|
"View": {
|
||||||
|
"Dynamo": {
|
||||||
|
"ScaleFactor": 1.0,
|
||||||
|
"HasRunWithoutCrash": true,
|
||||||
|
"IsVisibleInDynamoLibrary": true,
|
||||||
|
"Version": "2.17.0.3472",
|
||||||
|
"RunType": "Automatic",
|
||||||
|
"RunPeriod": "1000"
|
||||||
|
},
|
||||||
|
"Camera": {
|
||||||
|
"Name": "_Background Preview",
|
||||||
|
"EyeX": -17.0,
|
||||||
|
"EyeY": 24.0,
|
||||||
|
"EyeZ": 50.0,
|
||||||
|
"LookX": 12.0,
|
||||||
|
"LookY": -13.0,
|
||||||
|
"LookZ": -58.0,
|
||||||
|
"UpX": 0.0,
|
||||||
|
"UpY": 1.0,
|
||||||
|
"UpZ": 0.0
|
||||||
|
},
|
||||||
|
"ConnectorPins": [],
|
||||||
|
"NodeViews": [
|
||||||
|
{
|
||||||
|
"Name": "Python Script",
|
||||||
|
"ShowGeometry": true,
|
||||||
|
"Id": "1c5d99792882409e97e132b3e9f814b0",
|
||||||
|
"IsSetAsInput": false,
|
||||||
|
"IsSetAsOutput": false,
|
||||||
|
"Excluded": false,
|
||||||
|
"X": 208.0,
|
||||||
|
"Y": 367.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Annotations": [],
|
||||||
|
"X": 84.425000000000011,
|
||||||
|
"Y": -8.4125000000000227,
|
||||||
|
"Zoom": 1.1575
|
||||||
|
}
|
||||||
|
}
|
||||||
12
tests/support.py
Normal file
12
tests/support.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import pathlib
|
||||||
|
|
||||||
|
INPUT_DIR = "tests/input_files"
|
||||||
|
OUTPUT_DIR = "tests/output_files"
|
||||||
|
|
||||||
|
def cleanup_output_dir():
|
||||||
|
output_dir = pathlib.Path(OUTPUT_DIR)
|
||||||
|
if output_dir.exists():
|
||||||
|
for f in output_dir.iterdir():
|
||||||
|
f.unlink()
|
||||||
|
else:
|
||||||
|
output_dir.mkdir()
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import subprocess
|
import subprocess
|
||||||
import platform
|
|
||||||
|
|
||||||
|
|
||||||
class TestCommandLine(unittest.TestCase):
|
class TestCommandLine(unittest.TestCase):
|
||||||
|
|||||||
@@ -2,16 +2,8 @@ import unittest
|
|||||||
import dyn2py
|
import dyn2py
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
INPUT_DIR = "tests/input_files"
|
from tests.support import *
|
||||||
OUTPUT_DIR = "tests/output_files"
|
|
||||||
|
|
||||||
def cleanup_output_dir():
|
|
||||||
output_dir = pathlib.Path(OUTPUT_DIR)
|
|
||||||
if output_dir.exists():
|
|
||||||
for f in output_dir.iterdir():
|
|
||||||
f.unlink()
|
|
||||||
else:
|
|
||||||
output_dir.mkdir()
|
|
||||||
|
|
||||||
class TestDynamoFile(unittest.TestCase):
|
class TestDynamoFile(unittest.TestCase):
|
||||||
|
|
||||||
@@ -21,7 +13,7 @@ class TestDynamoFile(unittest.TestCase):
|
|||||||
# update_python_node
|
# update_python_node
|
||||||
# write
|
# write
|
||||||
|
|
||||||
def test_read(self):
|
def test_read_and_variables(self):
|
||||||
dyn = dyn2py.DynamoFile(f"{INPUT_DIR}/python_nodes.dyn")
|
dyn = dyn2py.DynamoFile(f"{INPUT_DIR}/python_nodes.dyn")
|
||||||
dyn.read()
|
dyn.read()
|
||||||
|
|
||||||
@@ -38,7 +30,7 @@ class TestDynamoFile(unittest.TestCase):
|
|||||||
dyn2.read()
|
dyn2.read()
|
||||||
|
|
||||||
|
|
||||||
def test_get_python_node(self):
|
def test_get_python_nodes(self):
|
||||||
dyn = dyn2py.DynamoFile(f"{INPUT_DIR}/python_nodes.dyn")
|
dyn = dyn2py.DynamoFile(f"{INPUT_DIR}/python_nodes.dyn")
|
||||||
py_nodes = dyn.get_python_nodes()
|
py_nodes = dyn.get_python_nodes()
|
||||||
py_node = dyn.get_python_node_by_id("d7704617c75e4bf1a5c387b7c3f001ea")
|
py_node = dyn.get_python_node_by_id("d7704617c75e4bf1a5c387b7c3f001ea")
|
||||||
@@ -46,11 +38,19 @@ class TestDynamoFile(unittest.TestCase):
|
|||||||
self.assertEqual(len(py_nodes), 6)
|
self.assertEqual(len(py_nodes), 6)
|
||||||
self.assertTrue(py_node)
|
self.assertTrue(py_node)
|
||||||
self.assertTrue(py_node in py_nodes)
|
self.assertTrue(py_node in py_nodes)
|
||||||
|
self.assertTrue(py_node in dyn.python_nodes)
|
||||||
self.assertEqual(py_node.checksum, "1f3d9e6153804fe1ed37571a9cda8e26")
|
self.assertEqual(py_node.checksum, "1f3d9e6153804fe1ed37571a9cda8e26")
|
||||||
|
|
||||||
with self.assertRaises(dyn2py.PythonNodeNotFoundException):
|
with self.assertRaises(dyn2py.PythonNodeNotFoundException):
|
||||||
dyn.get_python_node_by_id("wrongid")
|
dyn.get_python_node_by_id("wrongid")
|
||||||
|
|
||||||
|
dyn2 = dyn2py.DynamoFile(f"{INPUT_DIR}/no_python.dyn")
|
||||||
|
|
||||||
|
# Raise error on file without python nodes:
|
||||||
|
with self.assertRaises(dyn2py.DynamoFileException):
|
||||||
|
dyn2.get_python_nodes()
|
||||||
|
|
||||||
|
|
||||||
def test_extract_python(self):
|
def test_extract_python(self):
|
||||||
cleanup_output_dir()
|
cleanup_output_dir()
|
||||||
|
|
||||||
|
|||||||
92
tests/test_File.py
Normal file
92
tests/test_File.py
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import unittest
|
||||||
|
import dyn2py
|
||||||
|
import pathlib
|
||||||
|
import platform
|
||||||
|
|
||||||
|
from tests.support import *
|
||||||
|
|
||||||
|
|
||||||
|
class TestFile(unittest.TestCase):
|
||||||
|
|
||||||
|
# Methods to test:
|
||||||
|
# is_dynamo_file
|
||||||
|
# is_python_file
|
||||||
|
|
||||||
|
def test_init(self):
|
||||||
|
paths = [
|
||||||
|
f"{INPUT_DIR}/python_nodes.dyn",
|
||||||
|
pathlib.Path(f"{INPUT_DIR}/python_nodes.dyn")
|
||||||
|
]
|
||||||
|
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
paths.extend([
|
||||||
|
fr"{INPUT_DIR}\python_nodes.dyn",
|
||||||
|
pathlib.Path(fr"{INPUT_DIR}\python_nodes.dyn")
|
||||||
|
])
|
||||||
|
|
||||||
|
for path in paths:
|
||||||
|
the_file = dyn2py.File(path)
|
||||||
|
|
||||||
|
self.assertEqual(the_file.filepath,
|
||||||
|
pathlib.Path(f"{INPUT_DIR}/python_nodes.dyn"))
|
||||||
|
self.assertEqual(the_file.basename, "python_nodes")
|
||||||
|
self.assertEqual(the_file.dirpath, pathlib.Path(INPUT_DIR))
|
||||||
|
self.assertEqual(the_file.realpath, pathlib.Path(path).resolve())
|
||||||
|
|
||||||
|
self.assertEqual(the_file.mtime, 1678287111.4672492)
|
||||||
|
self.assertEqual(the_file.mtimeiso, "2023-03-08T15:51:51.467249")
|
||||||
|
self.assertTrue(the_file.exists)
|
||||||
|
self.assertEqual(the_file.extension, ".dyn")
|
||||||
|
self.assertFalse(the_file.modified)
|
||||||
|
|
||||||
|
def test_init_newfile(self):
|
||||||
|
paths = [
|
||||||
|
f"{INPUT_DIR}/new_file.dyn",
|
||||||
|
pathlib.Path(f"{INPUT_DIR}/new_file.dyn")
|
||||||
|
]
|
||||||
|
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
paths.extend([
|
||||||
|
fr"{INPUT_DIR}\new_file.dyn",
|
||||||
|
pathlib.Path(fr"{INPUT_DIR}\new_file.dyn")
|
||||||
|
])
|
||||||
|
|
||||||
|
for path in paths:
|
||||||
|
the_file = dyn2py.File(path)
|
||||||
|
|
||||||
|
self.assertEqual(the_file.filepath,
|
||||||
|
pathlib.Path(f"{INPUT_DIR}/new_file.dyn"))
|
||||||
|
self.assertEqual(the_file.basename, "new_file")
|
||||||
|
self.assertEqual(the_file.dirpath, pathlib.Path(INPUT_DIR))
|
||||||
|
self.assertEqual(the_file.realpath, pathlib.Path(path).resolve())
|
||||||
|
|
||||||
|
self.assertEqual(the_file.mtime, 0.0)
|
||||||
|
self.assertEqual(the_file.mtimeiso, "")
|
||||||
|
self.assertFalse(the_file.exists)
|
||||||
|
self.assertEqual(the_file.extension, ".dyn")
|
||||||
|
self.assertFalse(the_file.modified)
|
||||||
|
|
||||||
|
def test_newer(self):
|
||||||
|
older_file = dyn2py.File(f"{INPUT_DIR}/python_nodes.dyn")
|
||||||
|
newer_file = dyn2py.File(f"{INPUT_DIR}/no_python.dyn")
|
||||||
|
nonexisting_file = dyn2py.File(f"{INPUT_DIR}/new_file.dyn")
|
||||||
|
|
||||||
|
self.assertTrue(newer_file.is_newer(older_file))
|
||||||
|
self.assertTrue(newer_file.is_newer(nonexisting_file))
|
||||||
|
|
||||||
|
self.assertFalse(older_file.is_newer(newer_file))
|
||||||
|
self.assertTrue(older_file.is_newer(nonexisting_file))
|
||||||
|
|
||||||
|
self.assertFalse(nonexisting_file.is_newer(older_file))
|
||||||
|
self.assertFalse(nonexisting_file.is_newer(newer_file))
|
||||||
|
|
||||||
|
def test_write(self):
|
||||||
|
existing_file = dyn2py.File(f"{INPUT_DIR}/python_nodes.dyn")
|
||||||
|
nonexisting_file = dyn2py.File(f"{INPUT_DIR}/new_file.dyn")
|
||||||
|
options = dyn2py.Options()
|
||||||
|
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
existing_file.write(options)
|
||||||
|
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
nonexisting_file.write(options)
|
||||||
19
tests/test_PythonFile.py
Normal file
19
tests/test_PythonFile.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from tests.support import *
|
||||||
|
|
||||||
|
class TestPythonFile(unittest.TestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Missing variables:
|
||||||
|
# code
|
||||||
|
# header_data
|
||||||
|
# text
|
||||||
|
# open_files
|
||||||
|
|
||||||
|
# Missing methods:
|
||||||
|
# generate_text()
|
||||||
|
# update_dynamo()
|
||||||
|
# get_source_dynamo_file()
|
||||||
|
# read()
|
||||||
|
# write()
|
||||||
63
tests/test_PythonNode.py
Normal file
63
tests/test_PythonNode.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import unittest
|
||||||
|
import dyn2py
|
||||||
|
import hashlib
|
||||||
|
from tests.support import *
|
||||||
|
|
||||||
|
|
||||||
|
class TestPythonNode(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_init_from_dyn(self):
|
||||||
|
dyn = dyn2py.DynamoFile(f"{INPUT_DIR}/single_node.dyn")
|
||||||
|
dyn.read()
|
||||||
|
node_dict = next((n for n in dyn.full_dict["Nodes"]
|
||||||
|
if n["NodeType"] == "PythonScriptNode"), {})
|
||||||
|
|
||||||
|
# Found a node:
|
||||||
|
self.assertTrue(node_dict)
|
||||||
|
|
||||||
|
node_views = dyn.full_dict["View"]["NodeViews"]
|
||||||
|
|
||||||
|
node = dyn2py.PythonNode(
|
||||||
|
node_dict_from_dyn=node_dict,
|
||||||
|
full_nodeviews_dict_from_dyn=node_views,
|
||||||
|
source_dynamo_file=dyn
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(node.id, "1c5d99792882409e97e132b3e9f814b0")
|
||||||
|
self.assertEqual(node.engine, "CPython3")
|
||||||
|
self.assertEqual(node.checksum, "ec2c85a11ddbf8375da03f11272d427a")
|
||||||
|
self.assertEqual(node.name, "Python Script")
|
||||||
|
self.assertEqual(
|
||||||
|
node.filename, "single_node_1c5d99792882409e97e132b3e9f814b0.py")
|
||||||
|
|
||||||
|
def test_init_from_py(self):
|
||||||
|
|
||||||
|
cleanup_output_dir()
|
||||||
|
|
||||||
|
# Extract py:
|
||||||
|
options = dyn2py.Options(python_folder=OUTPUT_DIR)
|
||||||
|
dyn = dyn2py.DynamoFile(f"{INPUT_DIR}/single_node.dyn")
|
||||||
|
dyn.extract_python(options)
|
||||||
|
|
||||||
|
# Open the extracted file and replace a string:
|
||||||
|
with open(f"{OUTPUT_DIR}/single_node_1c5d99792882409e97e132b3e9f814b0.py") as orig_py, \
|
||||||
|
open(f"{OUTPUT_DIR}/single_node_mod.py", "w") as mod_py:
|
||||||
|
for line in orig_py:
|
||||||
|
if "asd_string" in line:
|
||||||
|
line = line.replace("asd_string", "qwe_string")
|
||||||
|
mod_py.write(line)
|
||||||
|
|
||||||
|
py = dyn2py.PythonFile(f"{OUTPUT_DIR}/single_node_mod.py")
|
||||||
|
py.read()
|
||||||
|
|
||||||
|
node = dyn2py.PythonNode(
|
||||||
|
node_id=py.header_data["py_id"],
|
||||||
|
engine=py.header_data["py_engine"],
|
||||||
|
code=py.code,
|
||||||
|
checksum=hashlib.md5(py.code.encode()).hexdigest()
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(node.id, "1c5d99792882409e97e132b3e9f814b0")
|
||||||
|
self.assertEqual(node.engine, "CPython3")
|
||||||
|
self.assertEqual(node.checksum, "bf0f039ef6f11c3043e0821143801d48")
|
||||||
|
|
||||||
Reference in New Issue
Block a user